summaryrefslogtreecommitdiffstats
path: root/src/newt/native
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt/native')
-rw-r--r--src/newt/native/MacWindow.m149
-rw-r--r--src/newt/native/NewtMacWindow.h9
-rw-r--r--src/newt/native/NewtMacWindow.m135
-rw-r--r--src/newt/native/Window.h4
-rw-r--r--src/newt/native/WindowsEDID.c10
-rw-r--r--src/newt/native/WindowsWindow.c361
-rw-r--r--src/newt/native/X11Common.h71
-rw-r--r--src/newt/native/X11Display.c293
-rw-r--r--src/newt/native/X11Window.c300
9 files changed, 979 insertions, 353 deletions
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m
index b59e19e4e..ee012add3 100644
--- a/src/newt/native/MacWindow.m
+++ b/src/newt/native/MacWindow.m
@@ -832,8 +832,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow
}
JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getDisplayID0(JNIEnv *env, jobject jthis, jlong window) {
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window);
+ if( NULL == myWindow ) {
+ DBG_PRINT( "getDisplayID0 - NULL NEWT win - abort\n");
+ return 0;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSScreen *screen = [myWindow screen];
int32_t displayID = (int32_t)NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
[pool release];
@@ -849,16 +853,16 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getDisplayID0
*/
JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initWindow0
(JNIEnv *env, jobject jthis, jlong parent, jlong window, jint x, jint y, jint w, jint h, jfloat reqPixelScale,
- jboolean opaque, jboolean visible, jlong jview)
+ jboolean opaque, jboolean atop, jboolean abottom, jboolean visible, jlong jview)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window);
NewtView* myView = (NewtView*) (intptr_t) jview ;
BOOL fullscreen = myWindow->isFullscreenWindow;
- DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, reqPixScale %f, opaque %d, fs %d, visible %d, view %p (START)\n",
+ DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, reqPixScale %f, opaque %d, atop %d, abottom %d, fs %d, visible %d, view %p (START)\n",
(void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, (int)x, (int)y, (int)w, (int)h, (float)reqPixelScale,
- (int) opaque, (int)fullscreen, (int)visible, myView);
+ (int) opaque, (int)atop, (int)abottom, (int)fullscreen, (int)visible, myView);
NS_DURING
// HiDPI scaling: Setup - Available >= 10.7
@@ -921,6 +925,7 @@ NS_ENDHANDLER
[myWindow setOpaque: NO];
[myWindow setBackgroundColor: [NSColor clearColor]];
}
+ [myWindow setAlwaysOn: atop bottom:abottom];
// specify we want mouse-moved events
[myWindow setAcceptsMouseMovedEvents:YES];
@@ -1035,8 +1040,12 @@ NS_ENDHANDLER
JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPixelScale0
(JNIEnv *env, jobject jthis, jlong window, jlong view, jfloat reqPixelScale)
{
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window);
+ if( NULL == myWindow ) {
+ DBG_PRINT( "setPixelScale0 - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtView* myView = (NewtView*) (intptr_t) view ;
#ifdef VERBOSE_ON
int dbgIdx = 1;
@@ -1195,8 +1204,12 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_unlockSur
JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_requestFocus0
(JNIEnv *env, jobject window, jlong w, jboolean force)
{
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* mWin = (NSWindow*) ((intptr_t) w);
+ if( NULL == mWin ) {
+ DBG_PRINT( "requestFocus - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
#ifdef VERBOSE_ON
BOOL hasFocus = [mWin isKeyWindow];
#endif
@@ -1220,12 +1233,16 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_requestFocus0
JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_resignFocus0
(JNIEnv *env, jobject window, jlong w)
{
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* mWin = (NSWindow*) ((intptr_t) w);
+ if( NULL == mWin ) {
+ DBG_PRINT( "resignFocus0 - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* pWin = [mWin parentWindow];
BOOL hasFocus = [mWin isKeyWindow];
- DBG_PRINT( "requestFocusParent0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus );
+ DBG_PRINT( "resignFocus0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus );
if( hasFocus ) {
if(NULL != pWin) {
// [mWin makeFirstResponder: pWin];
@@ -1234,7 +1251,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_resignFocus0
[pWin resignKeyWindow];
}
}
- DBG_PRINT( "requestFocusParent0 - window: %p (END)\n", mWin);
+ DBG_PRINT( "resignFocus0 - window: %p (END)\n", mWin);
[pool release];
}
@@ -1247,8 +1264,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_resignFocus0
JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderFront0
(JNIEnv *env, jobject unused, jlong window)
{
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* mWin = (NSWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "orderFront0 - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* pWin = [mWin parentWindow];
DBG_PRINT( "orderFront0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]);
@@ -1272,8 +1293,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderFront0
JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderOut0
(JNIEnv *env, jobject unused, jlong window)
{
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* mWin = (NSWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "orderOut0 - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* pWin = [mWin parentWindow];
DBG_PRINT( "orderOut0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]);
@@ -1297,8 +1322,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderOut0
JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setTitle0
(JNIEnv *env, jobject unused, jlong window, jstring title)
{
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* win = (NSWindow*) ((intptr_t) window);
+ if( NULL == win ) {
+ DBG_PRINT( "setTitle0 - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
DBG_PRINT( "setTitle0 - window: %p (START)\n", win);
@@ -1374,88 +1403,64 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeContent
/*
* Class: jogamp_newt_driver_macosx_WindowDriver
- * Method: setWindowClientTopLeftPointAndSize0
- * Signature: (JIIIIZ)V
+ * Method: updateSizePosInsets0
+ * Signature: (JZ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPointAndSize0
- (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jint w, jint h, jboolean display)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_updateSizePosInsets0
+ (JNIEnv *env, jobject jthis, jlong window, jboolean defer)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window);
- DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (START)\n", mWin);
+ DBG_PRINT( "updateSizePosInsets - window: %p, defer %d (START)\n", mWin, (int)defer);
- setWindowClientTopLeftPointAndSize(mWin, x, y, w, h, display);
+ [mWin updateSizePosInsets: env jwin:jthis defer:defer];
- DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (END)\n", mWin);
+ DBG_PRINT( "updateSizePosInsets - window: %p, defer %d (END)\n", mWin, (int)defer);
[pool release];
}
/*
* Class: jogamp_newt_driver_macosx_WindowDriver
- * Method: setWindowClientTopLeftPoint0
- * Signature: (JIIZ)V
+ * Method: setWindowClientTopLeftPointAndSize0
+ * Signature: (JIIIIZ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPoint0
- (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jboolean display)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPointAndSize0
+ (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jint w, jint h, jboolean display)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window);
- DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (START)\n", mWin);
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (START)\n", mWin);
- setWindowClientTopLeftPoint(mWin, x, y, display);
+ setWindowClientTopLeftPointAndSize(mWin, x, y, w, h, display);
- DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (END)\n", mWin);
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (END)\n", mWin);
[pool release];
}
/*
* Class: jogamp_newt_driver_macosx_WindowDriver
- * Method: setAlwaysOnTop0
- * Signature: (JZ)V
+ * Method: setWindowClientTopLeftPoint0
+ * Signature: (JIIZ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnTop0
- (JNIEnv *env, jobject unused, jlong window, jboolean atop)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPoint0
+ (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jboolean display)
{
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSWindow* win = (NSWindow*) ((intptr_t) window);
-
- DBG_PRINT( "setAlwaysOnTop0 - window: %p, atop %d (START)\n", win, (int)atop);
-
- if(atop) {
- [win setLevel:NSFloatingWindowLevel];
- } else {
- [win setLevel:NSNormalWindowLevel];
+ NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "setWindowClientTopLeftPoint - NULL NEWT win - abort\n");
+ return;
}
-
- DBG_PRINT( "setAlwaysOnTop0 - window: %p, atop %d (END)\n", win, (int)atop);
-
- [pool release];
-}
-
-/*
- * Class: jogamp_newt_driver_macosx_WindowDriver
- * Method: setAlwaysOnBottom0
- * Signature: (JZ)V
- */
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnBottom0
- (JNIEnv *env, jobject unused, jlong window, jboolean abottom)
-{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSWindow* win = (NSWindow*) ((intptr_t) window);
- DBG_PRINT( "setAlwaysOnBottom0 - window: %p, abottom %d (START)\n", win, (int)abottom);
+ DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (START)\n", mWin);
- if(abottom) {
- [win setLevel:NSScreenSaverWindowLevel]; // ??
- } else {
- [win setLevel:NSNormalWindowLevel];
- }
+ setWindowClientTopLeftPoint(mWin, x, y, display);
- DBG_PRINT( "setAlwaysOnBottom0 - window: %p, abottom %d (END)\n", win, (int)abottom);
+ DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (END)\n", mWin);
[pool release];
}
@@ -1469,6 +1474,10 @@ JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getLocatio
(JNIEnv *env, jclass unused, jlong win, jint src_x, jint src_y)
{
NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) win;
+ if( NULL == mWin ) {
+ DBG_PRINT( "getLocationOnScreen0 - NULL NEWT win - abort\n");
+ return NULL;
+ }
if( ![mWin isKindOfClass:[NewtMacWindow class]] ) {
NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
return NULL;
@@ -1480,12 +1489,16 @@ JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getLocatio
JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerIcon0
(JNIEnv *env, jobject unused, jlong window, jlong handle)
{
+ NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) window;
+ if( NULL == mWin ) {
+ DBG_PRINT( "setPointerIcon0 - NULL NEWT win - abort\n");
+ return;
+ }
NSCursor *c = (NSCursor*) (intptr_t) handle ;
if ( NULL != c && NO == [c isKindOfClass:[NSCursor class]] ) {
NewtCommon_throwNewRuntimeException(env, "Not a NSCursor %p", c);
return;
}
- NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) window;
if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) {
NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
return;
@@ -1509,6 +1522,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerVis
(JNIEnv *env, jclass clazz, jlong window, jboolean hasFocus, jboolean mouseVisible)
{
NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "setPointerVisible0 - NULL NEWT win - abort\n");
+ return;
+ }
if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) {
NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
return;
@@ -1533,6 +1550,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_confinePointe
(JNIEnv *env, jclass clazz, jlong window, jboolean confine)
{
NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "confinePointer0 - NULL NEWT win - abort\n");
+ return;
+ }
if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) {
NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
return;
@@ -1556,6 +1577,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_warpPointer0
(JNIEnv *env, jclass clazz, jlong window, jint x, jint y)
{
NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "warpPointer0 - NULL NEWT win - abort\n");
+ return;
+ }
if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) {
NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
return;
diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h
index 7dc5c6e19..14474bc10 100644
--- a/src/newt/native/NewtMacWindow.h
+++ b/src/newt/native/NewtMacWindow.h
@@ -142,6 +142,7 @@ CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen);
#endif
{
BOOL realized;
+ jboolean withinLiveResize;
@public
BOOL hasPresentationSwitch;
NSUInteger defaultPresentationOptions;
@@ -164,7 +165,10 @@ CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen);
- (void) setRealized: (BOOL)v;
- (BOOL) isRealized;
+- (void) setAlwaysOn: (BOOL)top bottom:(BOOL)bottom;
+
- (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin;
+- (void) updateSizePosInsets: (JNIEnv*) env jwin: (jobject) javaWin defer: (jboolean)defer;
- (void) attachToParent: (NSWindow*) parent;
- (void) detachFromParent: (NSWindow*) parent;
@@ -189,7 +193,12 @@ CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen);
- (void) windowDidBecomeKey: (NSNotification *) notification;
- (void) windowDidResignKey: (NSNotification *) notification;
+- (void) windowWillStartLiveResize: (NSNotification *) notification;
+- (void) windowDidEndLiveResize: (NSNotification *) notification;
+- (NSSize) windowWillResize: (NSWindow *)sender toSize:(NSSize)frameSize;
- (void) windowDidResize: (NSNotification*) notification;
+- (void) sendResizeEvent;
+
- (void) windowDidMove: (NSNotification*) notification;
- (BOOL) windowClosingImpl: (BOOL) force;
- (BOOL) windowShouldClose: (id) sender;
diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m
index 7b3df391d..6024a90d4 100644
--- a/src/newt/native/NewtMacWindow.m
+++ b/src/newt/native/NewtMacWindow.m
@@ -54,7 +54,7 @@ static jfloat GetDelta(NSEvent *event, jint javaMods[]) {
deltaX = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis2);
deltaY = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1);
// fprintf(stderr, "WHEEL/PAD: %lf/%lf - 0x%X\n", (double)deltaX, (double)deltaY, javaMods[0]);
- if( fabsf(deltaX) > fabsf(deltaY) ) {
+ if( fabs(deltaX) > fabs(deltaY) ) {
javaMods[0] |= EVENT_SHIFT_MASK;
delta = deltaX;
} else {
@@ -179,9 +179,10 @@ static jmethodID requestFocusID = NULL;
static jmethodID insetsChangedID = NULL;
static jmethodID sizeChangedID = NULL;
+static jmethodID sizeScreenPosInsetsChangedID = NULL;
static jmethodID updatePixelScaleID = NULL;
static jmethodID visibleChangedID = NULL;
-static jmethodID positionChangedID = NULL;
+static jmethodID screenPositionChangedID = NULL;
static jmethodID focusChangedID = NULL;
static jmethodID windowDestroyNotifyID = NULL;
static jmethodID windowRepaintID = NULL;
@@ -649,31 +650,32 @@ static jmethodID windowRepaintID = NULL;
// convert to 1-based button number (or use zero if no button is involved)
// TODO: detect mouse button when mouse wheel scrolled
- jshort javaButtonNum = 0;
+ jshort javaButtonNum;
jfloat scrollDeltaY = 0.0f;
switch ([event type]) {
- case NSScrollWheel: {
- scrollDeltaY = GetDelta(event, javaMods);
- javaButtonNum = 1;
- break;
- }
- case NSLeftMouseDown:
- case NSLeftMouseUp:
- case NSLeftMouseDragged:
- javaButtonNum = 1;
- break;
- case NSRightMouseDown:
- case NSRightMouseUp:
- case NSRightMouseDragged:
- javaButtonNum = 3;
- break;
- case NSOtherMouseDown:
- case NSOtherMouseUp:
- case NSOtherMouseDragged:
- javaButtonNum = 2;
- break;
+ case NSScrollWheel:
+ scrollDeltaY = GetDelta(event, javaMods);
+ javaButtonNum = 1;
+ break;
+ case NSLeftMouseDown:
+ case NSLeftMouseUp:
+ case NSLeftMouseDragged:
+ javaButtonNum = 1;
+ break;
+ case NSRightMouseDown:
+ case NSRightMouseUp:
+ case NSRightMouseDragged:
+ javaButtonNum = 3;
+ break;
+ case NSOtherMouseDown:
+ case NSOtherMouseUp:
+ case NSOtherMouseDragged:
+ javaButtonNum = 2;
+ break;
+ default:
+ javaButtonNum = 0;
+ break;
}
-
if (evType == EVENT_MOUSE_WHEEL_MOVED && scrollDeltaY == 0) {
// ignore 0 increment wheel scroll events
return;
@@ -830,13 +832,15 @@ NS_ENDHANDLER
updatePixelScaleID = (*env)->GetMethodID(env, clazz, "updatePixelScale", "(ZFF)V");
visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V");
- positionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V");
+ sizeScreenPosInsetsChangedID = (*env)->GetMethodID(env, clazz, "sizeScreenPosInsetsChanged", "(ZIIIIIIIIZZ)V");
+ screenPositionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V");
focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V");
windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V");
requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V");
- if (enqueueMouseEventID && enqueueKeyEventID && sizeChangedID && updatePixelScaleID && visibleChangedID && insetsChangedID &&
- positionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID)
+ if (enqueueMouseEventID && enqueueKeyEventID && sizeChangedID && updatePixelScaleID && visibleChangedID &&
+ insetsChangedID && sizeScreenPosInsetsChangedID &&
+ screenPositionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID)
{
CKCH_CreateDictionaries();
return YES;
@@ -889,6 +893,7 @@ NS_ENDHANDLER
cachedInsets[3] = 0; // b
realized = YES;
+ withinLiveResize = JNI_FALSE;
DBG_PRINT("NewtWindow::create: %p, realized %d, hasPresentationSwitch %d[defaultOptions 0x%X, fullscreenOptions 0x%X], (refcnt %d)\n",
res, realized, (int)hasPresentationSwitch, (int)defaultPresentationOptions, (int)fullscreenPresentationOptions, (int)[res retainCount]);
return res;
@@ -928,6 +933,20 @@ NS_ENDHANDLER
return realized;
}
+- (void) setAlwaysOn: (BOOL)top bottom:(BOOL)bottom
+{
+ if( top ) {
+ DBG_PRINT( "*************** setAlwaysOn -> top\n");
+ [self setLevel: kCGMaximumWindowLevel];
+ } else if ( bottom ) {
+ DBG_PRINT( "*************** setAlwaysOn -> bottom\n");
+ [self setLevel: kCGDesktopIconWindowLevel]; // w/ input
+ } else {
+ DBG_PRINT( "*************** setAlwaysOn -> normal\n");
+ [self setLevel:NSNormalWindowLevel];
+ }
+}
+
- (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin
{
NSRect frameRect = [self frame];
@@ -948,6 +967,33 @@ NS_ENDHANDLER
}
}
+- (void) updateSizePosInsets: (JNIEnv*) env jwin: (jobject) javaWin defer: (jboolean)defer
+{
+ // update insets on every window resize for lack of better hook place
+ [self updateInsets: NULL jwin:NULL];
+
+ NSRect frameRect = [self frame];
+ NSRect contentRect = [self contentRectForFrameRect: frameRect];
+
+ DBG_PRINT( "updateSize: [ w %d, h %d ], liveResize %d\n", (jint) contentRect.size.width, (jint) contentRect.size.height, (jint)withinLiveResize);
+
+ NSPoint p0 = { 0, 0 };
+ p0 = [self getLocationOnScreen: p0];
+
+ DBG_PRINT( "updatePos: [ x %d, y %d ]\n", (jint) p0.x, (jint) p0.y);
+
+ if( NULL != env && NULL != javaWin ) {
+ (*env)->CallVoidMethod(env, javaWin, sizeScreenPosInsetsChangedID, defer,
+ (jint) p0.x, (jint) p0.y,
+ (jint) contentRect.size.width, (jint) contentRect.size.height,
+ cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3],
+ JNI_FALSE, // force
+ withinLiveResize
+ );
+ }
+}
+
+
- (void) attachToParent: (NSWindow*) parent
{
DBG_PRINT( "attachToParent.1\n");
@@ -1183,8 +1229,30 @@ NS_ENDHANDLER
[self focusChanged: NO];
}
+- (void) windowWillStartLiveResize: (NSNotification *) notification
+{
+ DBG_PRINT( "*************** windowWillStartLiveResize\n");
+ withinLiveResize = JNI_TRUE;
+}
+- (void) windowDidEndLiveResize: (NSNotification *) notification
+{
+ DBG_PRINT( "*************** windowDidEndLiveResize\n");
+ withinLiveResize = JNI_FALSE;
+ [self sendResizeEvent];
+}
+- (NSSize) windowWillResize: (NSWindow *)sender toSize:(NSSize)frameSize
+{
+ DBG_PRINT( "*************** windowWillResize %lfx%lf\n", frameSize.width, frameSize.height);
+ return frameSize;
+}
- (void)windowDidResize: (NSNotification*) notification
{
+ DBG_PRINT( "*************** windowDidResize\n");
+ [self sendResizeEvent];
+}
+
+- (void) sendResizeEvent
+{
jobject javaWindowObject = NULL;
int shallBeDetached = 0;
JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
@@ -1198,15 +1266,7 @@ NS_ENDHANDLER
javaWindowObject = [newtView getJavaWindowObject];
}
if( NULL != javaWindowObject ) {
- // update insets on every window resize for lack of better hook place
- [self updateInsets: env jwin:javaWindowObject];
-
- NSRect frameRect = [self frame];
- NSRect contentRect = [self contentRectForFrameRect: frameRect];
-
- (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, JNI_TRUE, // defer
- (jint) contentRect.size.width,
- (jint) contentRect.size.height, JNI_FALSE);
+ [self updateSizePosInsets: env jwin: javaWindowObject defer:JNI_TRUE];
}
// detaching thread not required - daemon
// NewtCommon_ReleaseJNIEnv(shallBeDetached);
@@ -1232,7 +1292,8 @@ NS_ENDHANDLER
NSPoint p0 = { 0, 0 };
p0 = [self getLocationOnScreen: p0];
- (*env)->CallVoidMethod(env, javaWindowObject, positionChangedID, JNI_FALSE, (jint) p0.x, (jint) p0.y);
+ DBG_PRINT( "windowDidMove: [ x %d, y %d ]\n", (jint) p0.x, (jint) p0.y);
+ (*env)->CallVoidMethod(env, javaWindowObject, screenPositionChangedID, JNI_TRUE, (jint) p0.x, (jint) p0.y);
// detaching thread not required - daemon
// NewtCommon_ReleaseJNIEnv(shallBeDetached);
diff --git a/src/newt/native/Window.h b/src/newt/native/Window.h
index ada886d24..f6aba4c83 100644
--- a/src/newt/native/Window.h
+++ b/src/newt/native/Window.h
@@ -53,7 +53,9 @@
#define FLAG_IS_MAXIMIZED_VERT ( 1 << 9 )
#define FLAG_IS_MAXIMIZED_HORZ ( 1 << 10 )
#define FLAG_IS_FULLSCREEN ( 1 << 11 )
-#define FLAG_IS_FULLSCREEN_SPAN ( 1 << 12 )
+#define FLAG_IS_POINTERVISIBLE ( 1 << 12 )
+#define FLAG_IS_POINTERCONFINED ( 1 << 13 )
+#define FLAG_IS_FULLSCREEN_SPAN ( 1 << 14 )
#define TST_FLAG_CHANGE_VISIBILITY(f) ( 0 != ( (f) & FLAG_CHANGE_VISIBILITY ) )
#define TST_FLAG_CHANGE_VISIBILITY_FAST(f) ( 0 != ( (f) & FLAG_CHANGE_VISIBILITY_FAST ) )
diff --git a/src/newt/native/WindowsEDID.c b/src/newt/native/WindowsEDID.c
index d84773dc6..5fc410a91 100644
--- a/src/newt/native/WindowsEDID.c
+++ b/src/newt/native/WindowsEDID.c
@@ -144,8 +144,14 @@ static _TCHAR* Get2ndSlashBlock(const _TCHAR* sIn, _TCHAR* sOut, size_t sOutLen)
size_t len = t - s;
if( len > 0 ) {
if( sOutLen >= len ) {
- _tcsncpy_s(sOut, sOutLen, s, len);
- return sOut;
+ // Bug 1196: Unresolved strncpy_s (MSVCRT) on WinXP.
+ // Mapped: _tcsncpy_s -> strncpy_s (!UNICODE).
+ // On WinXP MSVCRT has no strncpy_s.
+ // _tcsncpy_s(sOut, sOutLen, s, len);
+ if( len <= sOutLen-1 ) {
+ _tcsncpy(sOut, s, len);
+ return sOut;
+ }
}
}
}
diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c
index a9a5cac10..59e054516 100644
--- a/src/newt/native/WindowsWindow.c
+++ b/src/newt/native/WindowsWindow.c
@@ -181,6 +181,7 @@ static jmethodID maximizedChangedID = NULL;
static jmethodID positionChangedID = NULL;
static jmethodID focusChangedID = NULL;
static jmethodID visibleChangedID = NULL;
+static jmethodID sizePosInsetsFocusVisibleChangedID = NULL;
static jmethodID windowDestroyNotifyID = NULL;
static jmethodID windowRepaintID = NULL;
static jmethodID sendMouseEventID = NULL;
@@ -206,10 +207,18 @@ static int NewtEDID_avail = 0;
typedef struct {
JNIEnv* jenv;
jobject jinstance;
+ /* client x-pos */
+ int xpos;
+ /* client y-pos */
+ int ypos;
/* client size width */
int width;
/* client size height */
int height;
+ /* visible state */
+ BOOL visible;
+ /* focused state */
+ BOOL focused;
/* Insets left, right, top, bottom */
RECT insets;
/** Tristate: -1 HIDE, 0 NOP, 1 SHOW */
@@ -226,6 +235,10 @@ typedef struct {
BOOL isMinimized;
/** Bool: 0 NOP, 1 maximized */
BOOL isMaximized;
+ BOOL isOnBottom;
+ BOOL isOnTop;
+ /** Bug 1205: Clear Window Background -> security! */
+ BOOL isInCreation;
int pointerCaptured;
int pointerInside;
int touchDownCount;
@@ -608,21 +621,41 @@ static int WmKeyUp(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE s
static void NewtWindows_requestFocus (JNIEnv *env, jobject window, HWND hwnd, jboolean force) {
HWND pHwnd, current;
+ WindowUserData * wud;
BOOL isEnabled = IsWindowEnabled(hwnd);
pHwnd = GetParent(hwnd);
current = GetFocus();
- DBG_PRINT("*** WindowsWindow: requestFocus.S force %d, parent %p, window %p, isEnabled %d, isCurrent %d\n",
- (int)force, (void*)pHwnd, (void*)hwnd, isEnabled, current==hwnd);
+#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA);
+#else
+ wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#endif
+
+ DBG_PRINT("*** WindowsWindow: requestFocus.S force %d, parent %p, window %p, isEnabled %d, isCurrent %d, isOn[Top %d, Bottom %d]\n",
+ (int)force, (void*)pHwnd, (void*)hwnd, isEnabled, current==hwnd,
+ wud->isOnTop, wud->isOnBottom);
if( JNI_TRUE==force || current!=hwnd || !isEnabled ) {
UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
if(!isEnabled) {
EnableWindow(hwnd, TRUE);
}
- SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, flags);
- SetForegroundWindow(hwnd); // Slightly Higher Priority
+ BOOL frontWindow;
+ if( wud->isOnBottom ) {
+ SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
+ frontWindow = FALSE;
+ } else if( wud->isOnTop ) {
+ SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, flags);
+ frontWindow = TRUE;
+ } else {
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, flags);
+ frontWindow = TRUE;
+ }
+ if( frontWindow ) {
+ SetForegroundWindow(hwnd); // Slightly Higher Priority
+ }
SetFocus(hwnd);// Sets Keyboard Focus To Window (activates parent window if exist, or this window)
- if(NULL!=pHwnd) {
+ if( frontWindow && NULL!=pHwnd ) {
SetActiveWindow(hwnd);
}
current = GetFocus();
@@ -671,10 +704,11 @@ static void UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd) {
jobject window = wud->jinstance;
RECT outside;
RECT inside;
+ int strategy = 0;
if (IsIconic(hwnd)) {
wud->insets.left = wud->insets.top = wud->insets.right = wud->insets.bottom = -1;
- return FALSE;
+ return;
}
wud->insets.left = wud->insets.top = wud->insets.right = wud->insets.bottom = 0;
@@ -688,6 +722,7 @@ static void UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd) {
wud->insets.bottom = outside.bottom - inside.bottom;
wud->insets.left = inside.left - outside.left;
wud->insets.right = outside.right - inside.right;
+ strategy = 1;
} else {
wud->insets.top = -1;
}
@@ -713,18 +748,21 @@ static void UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd) {
/* Add in title. */
wud->insets.top += GetSystemMetrics(SM_CYCAPTION);
+ strategy += 10;
} else {
/* undo the -1 set above */
wud->insets.left = wud->insets.top = wud->insets.right = wud->insets.bottom = 0;
+ strategy += 20;
}
}
- DBG_PRINT("*** WindowsWindow: UpdateInsets window %p, [l %d, r %d - t %d, b %d - %dx%d]\n",
- (void*)hwnd, (int)wud->insets.left, (int)wud->insets.right, (int)wud->insets.top, (int)wud->insets.bottom,
- (int) ( wud->insets.left + wud->insets.right ), (int) (wud->insets.top + wud->insets.bottom));
-
- (*env)->CallVoidMethod(env, window, insetsChangedID, JNI_FALSE,
- (int)wud->insets.left, (int)wud->insets.right, (int)wud->insets.top, (int)wud->insets.bottom);
+ DBG_PRINT("*** WindowsWindow: UpdateInsets window %p, s %d, [l %d, r %d - t %d, b %d - %dx%d], at-init %d\n",
+ (void*)hwnd, strategy, (int)wud->insets.left, (int)wud->insets.right, (int)wud->insets.top, (int)wud->insets.bottom,
+ (int) ( wud->insets.left + wud->insets.right ), (int) (wud->insets.top + wud->insets.bottom), wud->isInCreation);
+ if( !wud->isInCreation ) {
+ (*env)->CallVoidMethod(env, window, insetsChangedID, JNI_FALSE,
+ (int)wud->insets.left, (int)wud->insets.right, (int)wud->insets.top, (int)wud->insets.bottom);
+ }
}
static void WmSize(JNIEnv *env, WindowUserData * wud, HWND wnd, UINT type)
@@ -763,14 +801,16 @@ static void WmSize(JNIEnv *env, WindowUserData * wud, HWND wnd, UINT type)
wud->width = (int) ( rc.right - rc.left );
wud->height = (int) ( rc.bottom - rc.top );
- DBG_PRINT("*** WindowsWindow: WmSize.X window %p, %dx%d, isMinimized %d, isMaximized %d (changed %d), visible %d\n",
- (void*)wnd, wud->width, wud->height, wud->isMinimized, wud->isMaximized, maxChanged, isVisible);
+ DBG_PRINT("*** WindowsWindow: WmSize.X window %p, %dx%d, isMinimized %d, isMaximized %d (changed %d), visible %d, at-init %d\n",
+ (void*)wnd, wud->width, wud->height, wud->isMinimized, wud->isMaximized, maxChanged, isVisible, wud->isInCreation);
- if( maxChanged ) {
- jboolean v = wud->isMaximized ? JNI_TRUE : JNI_FALSE;
- (*env)->CallVoidMethod(env, window, maximizedChangedID, v, v);
+ if( !wud->isInCreation ) {
+ if( maxChanged ) {
+ jboolean v = wud->isMaximized ? JNI_TRUE : JNI_FALSE;
+ (*env)->CallVoidMethod(env, window, maximizedChangedID, v, v);
+ }
+ (*env)->CallVoidMethod(env, window, sizeChangedID, JNI_FALSE, wud->width, wud->height, JNI_FALSE);
}
- (*env)->CallVoidMethod(env, window, sizeChangedID, JNI_FALSE, wud->width, wud->height, JNI_FALSE);
}
#ifdef TEST_MOUSE_HOOKS
@@ -896,6 +936,7 @@ static void sendTouchScreenEvent(JNIEnv *env, jobject window,
jNames, jX, jY, jPressure, (jfloat)maxPressure);
}
+// #define DO_ERASEBKGND 1
static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) {
LRESULT res = 0;
@@ -959,11 +1000,15 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
// Bug 916 - NEWT Fullscreen Mode on Windows ALT-TAB doesn't allow Application Switching
// Remedy for 'some' display drivers, i.e. Intel HD:
// Explicitly push fullscreen window to BOTTOM when inactive (ALT-TAB)
- UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
- if( inactive ) {
- SetWindowPos(wnd, HWND_BOTTOM, 0, 0, 0, 0, flags);
+ if( inactive || wud->isOnBottom ) {
+ SetWindowPos(wnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
} else {
- SetWindowPos(wnd, HWND_TOP, 0, 0, 0, 0, flags);
+ UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+ if( wud->isOnTop ) {
+ SetWindowPos(wnd, HWND_TOPMOST, 0, 0, 0, 0, flags);
+ } else {
+ SetWindowPos(wnd, HWND_TOP, 0, 0, 0, 0, flags);
+ }
SetForegroundWindow(wnd); // Slightly Higher Priority
}
}
@@ -971,6 +1016,34 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
}
break;
+ case WM_WINDOWPOSCHANGING: {
+ WINDOWPOS *p = (WINDOWPOS*)lParam;
+ BOOL isThis = wnd == p->hwnd;
+ BOOL isBottom = HWND_BOTTOM == p->hwndInsertAfter;
+ BOOL isTopMost = HWND_TOPMOST == p->hwndInsertAfter;
+ BOOL forceBottom = isThis && wud->isOnBottom && !isBottom;
+ BOOL forceTop = isThis && wud->isOnTop && !isTopMost;
+ #ifdef VERBOSE_ON
+ BOOL isNoTopMost = HWND_NOTOPMOST == p->hwndInsertAfter;
+ BOOL isTop = HWND_TOP == p->hwndInsertAfter;
+ BOOL isNoZ = 0 != ( SWP_NOZORDER & p->flags );
+ DBG_PRINT("*** WindowsWindow: WM_WINDOWPOSCHANGING window %p / %p (= %d), %p[bottom %d, notop %d, top %d, topmost %d, noZ %d, force[Top %d, Bottom %d], %d/%d %dx%d 0x%X\n",
+ wnd, p->hwnd, isThis,
+ p->hwndInsertAfter, isBottom, isNoTopMost, isTop, isTopMost, isNoZ,
+ forceTop, forceBottom,
+ p->x, p->y, p->cx, p->cy, p->flags);
+ #endif
+ if( forceTop ) {
+ p->hwndInsertAfter = HWND_TOPMOST;
+ p->flags &= ~SWP_NOZORDER;
+ } else if( forceBottom ) {
+ p->hwndInsertAfter = HWND_BOTTOM;
+ p->flags &= ~SWP_NOZORDER;
+ }
+ useDefWindowProc = 1;
+ }
+ break;
+
case WM_SETTINGCHANGE:
if (wParam == SPI_SETNONCLIENTMETRICS) {
// make sure insets are updated, we don't need to resize the window
@@ -986,33 +1059,79 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
break;
case WM_SHOWWINDOW:
- DBG_PRINT("*** WindowsWindow: WM_SHOWWINDOW window %p: %d\n", wnd, wParam==TRUE);
- (*env)->CallVoidMethod(env, window, visibleChangedID, JNI_FALSE, wParam==TRUE?JNI_TRUE:JNI_FALSE);
+ DBG_PRINT("*** WindowsWindow: WM_SHOWWINDOW window %p: %d, at-init %d\n", wnd, wParam==TRUE, wud->isInCreation);
+ wud->visible = wParam==TRUE;
+ if( !wud->isInCreation ) {
+ (*env)->CallVoidMethod(env, window, visibleChangedID, JNI_FALSE, wParam==TRUE?JNI_TRUE:JNI_FALSE);
+ }
break;
case WM_MOVE:
- DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d\n", wnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- (*env)->CallVoidMethod(env, window, positionChangedID, JNI_FALSE, (jint)GET_X_LPARAM(lParam), (jint)GET_Y_LPARAM(lParam));
+ wud->xpos = (int)GET_X_LPARAM(lParam);
+ wud->ypos = (int)GET_Y_LPARAM(lParam);
+ DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d, at-init %d\n", wnd, wud->xpos, wud->ypos, wud->isInCreation);
+ if( !wud->isInCreation ) {
+ (*env)->CallVoidMethod(env, window, positionChangedID, JNI_FALSE, (jint)wud->xpos, (jint)wud->ypos);
+ }
useDefWindowProc = 1;
break;
case WM_PAINT: {
- RECT r;
- if (GetUpdateRect(wnd, &r, FALSE /* do not erase background */)) {
- // clear the whole client area and issue repaint for it, w/o looping through erase background
- ValidateRect(wnd, NULL); // clear all!
- (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1);
+ if( wud->isInCreation ) {
+ #ifdef DO_ERASEBKGND
+ if (GetUpdateRect(wnd, NULL, TRUE /* erase background */)) {
+ DBG_PRINT("*** WindowsWindow: WM_PAINT.0 (dirty)\n");
+ // WM_ERASEBKGND sent!
+ #else
+ if (GetUpdateRect(wnd, NULL, FALSE /* do not erase background */)) {
+ DBG_PRINT("*** WindowsWindow: WM_PAINT.0 (dirty)\n");
+ ValidateRect(wnd, NULL); // clear all!
+ #endif
+ } else {
+ DBG_PRINT("*** WindowsWindow: WM_PAINT.0 (clean)\n");
+ }
} else {
- // shall not happen ?
- ValidateRect(wnd, NULL); // clear all!
+ if (GetUpdateRect(wnd, NULL, FALSE /* do not erase background */)) {
+ DBG_PRINT("*** WindowsWindow: WM_PAINT.1 (dirty)\n");
+ // Let NEWT render the whole client area by issueing repaint for it, w/o looping through erase background
+ ValidateRect(wnd, NULL); // clear all!
+ (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1);
+ } else {
+ DBG_PRINT("*** WindowsWindow: WM_PAINT.1 (clean)\n");
+ // shall not happen ?
+ ValidateRect(wnd, NULL); // clear all!
+ }
+ // return 0 == done
}
- // return 0 == done
break;
}
case WM_ERASEBKGND:
- // ignore erase background
- (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1);
- res = 1; // return 1 == done, OpenGL, etc .. erases the background, hence we claim to have just done this
+ if( wud->isInCreation ) {
+ #ifdef DO_ERASEBKGND
+ // On Windows the initial window is clean?!
+ // This fill destroys translucency on Windows 10
+ // (which only seem to work on undecorated windows)
+ PAINTSTRUCT ps;
+ HDC hdc;
+ hdc = BeginPaint(wnd, &ps);
+ DBG_PRINT("*** WindowsWindow: WM_ERASEBKGND.0 (erasure) l/b %d/%d r/t %d/%d\n",
+ ps.rcPaint.left, ps.rcPaint.bottom, ps.rcPaint.right, ps.rcPaint.top);
+ // FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW+1));
+ // FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_APPWORKSPACE+1));
+ // A black color also sets alpha to zero for translucency!
+ FillRect(hdc, &ps.rcPaint, (HBRUSH)GetStockObject(BLACK_PEN));
+ EndPaint(wnd, &ps);
+ #else
+ ValidateRect(wnd, NULL); // clear all!
+ #endif
+ res = 1; // return 1 == done
+ } else {
+ // ignore erase background, but let NEWT render the whole client area
+ DBG_PRINT("*** WindowsWindow: WM_ERASEBKGND.1 (repaint)\n");
+ ValidateRect(wnd, NULL); // clear all!
+ (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1);
+ res = 1; // return 1 == done, OpenGL, etc .. erases the background, hence we claim to have just done this
+ }
break;
case WM_SETCURSOR :
@@ -1061,8 +1180,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
break;
case WM_SETFOCUS:
- DBG_PRINT("*** WindowsWindow: WM_SETFOCUS window %p, lost %p\n", wnd, (HWND)wParam);
- (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_TRUE);
+ DBG_PRINT("*** WindowsWindow: WM_SETFOCUS window %p, lost %p, at-init %d\n", wnd, (HWND)wParam, wud->isInCreation);
+ wud->focused = TRUE;
+ if( !wud->isInCreation ) {
+ (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_TRUE);
+ }
useDefWindowProc = 1;
break;
@@ -1075,7 +1197,10 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
wud->pointerCaptured = 0;
ReleaseCapture();
}
- (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE);
+ wud->focused = FALSE;
+ if( !wud->isInCreation ) {
+ (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE);
+ }
useDefWindowProc = 1;
} else {
// quick focus .. we had it already, are enabled ..
@@ -2003,6 +2128,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0
positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZII)V");
focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V");
visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
+ sizePosInsetsFocusVisibleChangedID = (*env)->GetMethodID(env, clazz, "sizePosInsetsFocusVisibleChanged", "(ZIIIIIIIIIIZ)V");
windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V");
sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)V");
@@ -2016,6 +2142,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0
positionChangedID == NULL ||
focusChangedID == NULL ||
visibleChangedID == NULL ||
+ sizePosInsetsFocusVisibleChangedID == NULL ||
windowDestroyNotifyID == NULL ||
windowRepaintID == NULL ||
sendMouseEventID == NULL ||
@@ -2078,6 +2205,9 @@ static void NewtWindow_setVisiblePosSize(WindowUserData *wud, HWND hwnd, int jfl
if(visible) {
wflags = SWP_SHOWWINDOW;
+ if( abottom ) {
+ wflags |= SWP_NOACTIVATE;
+ }
} else {
wflags = SWP_NOACTIVATE | SWP_NOZORDER;
}
@@ -2085,6 +2215,8 @@ static void NewtWindow_setVisiblePosSize(WindowUserData *wud, HWND hwnd, int jfl
wflags |= SWP_NOSIZE;
}
+ wud->isOnTop = atop;
+ wud->isOnBottom = abottom;
if(atop) {
SetWindowPos(hwnd, HWND_TOP, x, y, width, height, wflags);
SetWindowPos(hwnd, HWND_TOPMOST, x, y, width, height, wflags);
@@ -2095,7 +2227,6 @@ static void NewtWindow_setVisiblePosSize(WindowUserData *wud, HWND hwnd, int jfl
SetWindowPos(hwnd, HWND_NOTOPMOST, x, y, width, height, wflags);
SetWindowPos(hwnd, HWND_TOP, x, y, width, height, wflags);
}
- // SetWindowPos(hwnd, atop ? HWND_TOPMOST : HWND_TOP, x, y, width, height, wflags);
if( TST_FLAG_CHANGE_MAXIMIZED_ANY(jflags) ) {
if( TST_FLAG_IS_MAXIMIZED_VERT(jflags) && TST_FLAG_IS_MAXIMIZED_HORZ(jflags) ) {
@@ -2122,16 +2253,15 @@ static void NewtWindow_setVisiblePosSize(WindowUserData *wud, HWND hwnd, int jfl
JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindow0
(JNIEnv *env, jobject obj,
jlong hInstance, jstring jWndClassName, jstring jWndName, jint winMajor, jint winMinor,
- jlong parent, jint jx, jint jy, jint defaultWidth, jint defaultHeight, jint flags)
+ jlong parent, jint jxpos, jint jypos, jint defaultWidth, jint defaultHeight, jint flags)
{
HWND parentWindow = (HWND) (intptr_t) parent;
const TCHAR* wndClassName = NULL;
const TCHAR* wndName = NULL;
- DWORD windowStyle = WS_DEFAULT_STYLES | WS_VISIBLE;
- int x=(int)jx, y=(int)jy;
+ DWORD windowStyle = WS_DEFAULT_STYLES;
+ int xpos=(int)jxpos, ypos=(int)jypos;
int width=(int)defaultWidth, height=(int)defaultHeight;
- HWND window = NULL;
- int _x = x, _y = y; // pos for CreateWindow, might be tweaked
+ HWND hwnd = NULL;
#ifdef UNICODE
wndClassName = NewtCommon_GetNullTerminatedStringChars(env, jWndClassName);
@@ -2147,10 +2277,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
return 0;
}
windowStyle |= WS_CHILD ;
- } else if ( TST_FLAG_IS_UNDECORATED(flags) ) {
- windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
} else {
- if ( TST_FLAG_IS_RESIZABLE(flags) ) {
+ if ( TST_FLAG_IS_UNDECORATED(flags) ) {
+ windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
+ } else if ( TST_FLAG_IS_RESIZABLE(flags) ) {
// WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
windowStyle |= WS_OVERLAPPEDWINDOW;
} else {
@@ -2158,31 +2288,32 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
}
if( TST_FLAG_IS_AUTOPOSITION(flags) ) {
// user didn't requested specific position, use WM default
- _x = CW_USEDEFAULT;
- _y = 0;
+ xpos = CW_USEDEFAULT;
+ ypos = 0;
}
}
- window = CreateWindow(wndClassName, wndName, windowStyle,
- _x, _y, width, height,
- parentWindow, NULL,
- (HINSTANCE) (intptr_t) hInstance,
- NULL);
+ hwnd = CreateWindow(wndClassName, wndName, windowStyle,
+ xpos, ypos, width, height,
+ parentWindow, NULL, (HINSTANCE) (intptr_t) hInstance, NULL);
- DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, win %d.%d parent %p, window %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n",
- (int)GetCurrentThreadId(), winMajor, winMinor, parentWindow, window, x, y, width, height,
+ DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, win %d.%d parent %p, window %p, %d/%d -> %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n",
+ (int)GetCurrentThreadId(), winMajor, winMinor, parentWindow, hwnd, jxpos, jypos, xpos, ypos, width, height,
TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags), TST_FLAG_IS_AUTOPOSITION(flags));
- if (NULL == window) {
+ if (NULL == hwnd) {
int lastError = (int) GetLastError();
DBG_PRINT("*** WindowsWindow: CreateWindow failure: 0x%X %d\n", lastError, lastError);
- return 0;
} else {
WindowUserData * wud = (WindowUserData *) malloc(sizeof(WindowUserData));
wud->jinstance = (*env)->NewGlobalRef(env, obj);
wud->jenv = env;
+ wud->xpos = xpos;
+ wud->ypos = ypos;
wud->width = width;
wud->height = height;
+ wud->visible = TRUE;
+ wud->focused = TRUE;
wud->setPointerVisible = 0;
wud->setPointerAction = 0;
wud->defPointerHandle = LoadCursor( NULL, IDC_ARROW);
@@ -2191,6 +2322,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
wud->isChildWindow = NULL!=parentWindow;
wud->isMinimized = FALSE;
wud->isMaximized = FALSE;
+ wud->isOnBottom = FALSE;
+ wud->isOnTop = FALSE;
+ wud->isInCreation = TRUE;
wud->pointerCaptured = 0;
wud->pointerInside = 0;
wud->touchDownCount = 0;
@@ -2209,32 +2343,26 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
DBG_PRINT("*** WindowsWindow: CreateWindow winTouchFuncAvail %d, supportsMTouch %d\n", WinTouch_func_avail, wud->supportsMTouch);
#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
- SetWindowLong(window, GWL_USERDATA, (intptr_t) wud);
+ SetWindowLong(hwnd, GWL_USERDATA, (intptr_t) wud);
#else
- SetWindowLongPtr(window, GWLP_USERDATA, (intptr_t) wud);
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (intptr_t) wud);
#endif
- // gather and adjust position and size
- {
- RECT rc;
-
- ShowWindow(window, SW_SHOW);
-
- // send insets before visibility, allowing java code a proper sync point!
- UpdateInsets(env, wud, window);
- (*env)->CallVoidMethod(env, wud->jinstance, visibleChangedID, JNI_FALSE, JNI_TRUE);
+ // send insets before visibility, allowing java code a proper sync point!
+ UpdateInsets(env, wud, hwnd);
- if( TST_FLAG_IS_AUTOPOSITION(flags) ) {
- GetWindowRect(window, &rc);
- x = rc.left + wud->insets.left; // client coords
- y = rc.top + wud->insets.top; // client coords
- }
- DBG_PRINT("*** WindowsWindow: CreateWindow client: %d/%d %dx%d (autoPosition %d)\n", x, y, width, height, TST_FLAG_IS_AUTOPOSITION(flags));
- NewtWindow_setVisiblePosSize(wud, window, flags, TRUE, x, y, width, height);
- }
- if( wud->supportsMTouch ) {
- WinTouch_RegisterTouchWindow(window, 0);
+ if( TST_FLAG_IS_AUTOPOSITION(flags) ) {
+ RECT rc;
+ GetWindowRect(hwnd, &rc);
+ xpos = rc.left + wud->insets.left; // client coords
+ ypos = rc.top + wud->insets.top; // client coords
+ wud->xpos = xpos;
+ wud->ypos = ypos;
}
+ DBG_PRINT("*** WindowsWindow: CreateWindow client: %d/%d %dx%d -> %d/%d %dx%d (autoPosition %d)\n",
+ xpos, ypos, width, height,
+ wud->xpos, wud->ypos, wud->width, wud->height,
+ TST_FLAG_IS_AUTOPOSITION(flags));
}
#ifdef UNICODE
@@ -2251,7 +2379,49 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
DBG_PRINT("**** LLMP Hook %p, MP Hook %p\n", hookLLMP, hookMP);
#endif
- return (jlong) (intptr_t) window;
+ DBG_PRINT("*** WindowsWindow: CreateWindow done\n");
+ return (jlong) (intptr_t) hwnd;
+}
+
+/*
+ * Class: jogamp_newt_driver_windows_WindowDriver
+ * Method: InitWindow
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_InitWindow0
+ (JNIEnv *env, jobject obj, jlong window, jint flags)
+{
+ HWND hwnd = (HWND) (intptr_t) window;
+ WindowUserData * wud;
+#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA);
+#else
+ wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#endif
+
+ DBG_PRINT("*** WindowsWindow: InitWindow start %d/%d %dx%d, focused %d, visible %d\n",
+ wud->xpos, wud->ypos, wud->width, wud->height, wud->focused, wud->visible);
+
+ NewtWindow_setVisiblePosSize(wud, hwnd, flags, TRUE, wud->xpos, wud->ypos, wud->width, wud->height);
+ wud->isInCreation = FALSE;
+
+ DBG_PRINT("*** WindowsWindow: InitWindow pos/size set: %d/%d %dx%d, focused %d, visible %d\n",
+ wud->xpos, wud->ypos, wud->width, wud->height, wud->focused, wud->visible);
+
+ if( wud->isMaximized ) {
+ (*env)->CallVoidMethod(env, wud->jinstance, maximizedChangedID, JNI_TRUE, JNI_TRUE);
+ }
+ (*env)->CallVoidMethod(env, wud->jinstance, sizePosInsetsFocusVisibleChangedID, JNI_FALSE,
+ (jint)wud->xpos, (jint)wud->ypos,
+ (jint)wud->width, (jint)wud->height,
+ (jint)wud->insets.left, (jint)wud->insets.right, (jint)wud->insets.top, (jint)wud->insets.bottom,
+ (jint)(wud->focused ? 1 : 0),
+ (jint)(wud->visible ? 1 : 0),
+ JNI_FALSE);
+ DBG_PRINT("*** WindowsWindow: InitWindow JNI callbacks done\n");
+
+ if( wud->supportsMTouch ) {
+ WinTouch_RegisterTouchWindow(hwnd, 0);
+ }
}
/*
@@ -2283,6 +2453,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
DWORD windowStyle = WS_DEFAULT_STYLES;
BOOL styleChange = TST_FLAG_CHANGE_DECORATION(flags) || TST_FLAG_CHANGE_FULLSCREEN(flags) ||
TST_FLAG_CHANGE_PARENTING(flags) || TST_FLAG_CHANGE_RESIZABLE(flags);
+ BOOL atop = TST_FLAG_IS_ALWAYSONTOP(flags);
+ BOOL abottom = TST_FLAG_IS_ALWAYSONBOTTOM(flags);
WindowUserData * wud;
#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA);
@@ -2290,12 +2462,13 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
#endif
- DBG_PRINT( "*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, isChild %d, undecoration[change %d, val %d], fullscreen[change %d, val %d], alwaysOnTop[change %d, val %d], visible[change %d, val %d], resizable[change %d, val %d] -> styleChange %d, isChild %d, isMinimized %d, isMaximized %d, isFullscreen %d\n",
+ DBG_PRINT( "*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, isChild %d, undecoration[change %d, val %d], fullscreen[change %d, val %d], alwaysOnTop[change %d, val %d], alwaysOnBottom[change %d, val %d], visible[change %d, val %d], resizable[change %d, val %d] -> styleChange %d, isChild %d, isMinimized %d, isMaximized %d, isFullscreen %d\n",
parent, window, x, y, width, height,
TST_FLAG_CHANGE_PARENTING(flags), TST_FLAG_IS_CHILD(flags),
TST_FLAG_CHANGE_DECORATION(flags), TST_FLAG_IS_UNDECORATED(flags),
TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(flags),
TST_FLAG_CHANGE_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONTOP(flags),
+ TST_FLAG_CHANGE_ALWAYSONBOTTOM(flags), TST_FLAG_IS_ALWAYSONBOTTOM(flags),
TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags),
TST_FLAG_CHANGE_RESIZABLE(flags), TST_FLAG_CHANGE_RESIZABLE(flags), styleChange,
wud->isChildWindow, wud->isMinimized, wud->isMaximized, wud->isFullscreen);
@@ -2305,6 +2478,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
return;
}
+ wud->isOnTop = atop;
+ wud->isOnBottom = abottom;
+
if (NULL!=hwndP && !IsWindow(hwndP)) {
DBG_PRINT("*** WindowsWindow: reconfigureWindow0 failure: Passed parent window %p is invalid\n", (void*)hwndP);
return;
@@ -2329,10 +2505,15 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
SetParent(hwnd, NULL);
}
- if( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) { // FS on
- // TOP: in -> out
- wud->isFullscreen = TRUE;
- NewtWindows_setFullScreen(JNI_TRUE);
+ if( TST_FLAG_IS_FULLSCREEN(flags) ) {
+ if( TST_FLAG_CHANGE_FULLSCREEN(flags) ) { // FS on
+ wud->isFullscreen = TRUE;
+ if( !abottom ) {
+ NewtWindows_setFullScreen(JNI_TRUE);
+ }
+ } else if( TST_FLAG_CHANGE_ALWAYSONBOTTOM(flags) ) { // FS BOTTOM toggle
+ NewtWindows_setFullScreen( abottom ? JNI_FALSE : JNI_TRUE);
+ }
}
if ( styleChange ) {
@@ -2351,7 +2532,6 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
}
if( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off
- // CHILD: out -> in
wud->isFullscreen = FALSE;
NewtWindows_setFullScreen(JNI_FALSE);
}
@@ -2365,9 +2545,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
if( TST_FLAG_CHANGE_VISIBILITY(flags) ) {
if( TST_FLAG_IS_VISIBLE(flags) ) {
- int cmd = wud->isMinimized ? SW_RESTORE : SW_SHOW;
+ int cmd = wud->isMinimized ? SW_RESTORE : ( abottom ? SW_SHOWNA : SW_SHOW );
wud->isMinimized = FALSE;
ShowWindow(hwnd, cmd);
+ if( abottom ) {
+ SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
+ }
} else if( !TST_FLAG_CHANGE_VISIBILITY_FAST(flags) && !TST_FLAG_IS_CHILD(flags) ) {
wud->isMinimized = TRUE;
ShowWindow(hwnd, SW_MINIMIZE);
diff --git a/src/newt/native/X11Common.h b/src/newt/native/X11Common.h
index cdfb65d50..978cfffed 100644
--- a/src/newt/native/X11Common.h
+++ b/src/newt/native/X11Common.h
@@ -42,6 +42,7 @@
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
+#include <X11/extensions/XInput2.h>
#include <X11/extensions/Xrandr.h>
@@ -71,7 +72,15 @@
extern jclass X11NewtWindowClazz;
extern jmethodID insetsChangedID;
extern jmethodID visibleChangedID;
-extern jmethodID sizePosMaxInsetsChanged;
+extern jmethodID insetsVisibleChangedID;
+
+typedef struct {
+ int id;
+ int x;
+ int y;
+} XITouchPosition;
+
+#define XI_TOUCHCOORD_COUNT 10
typedef struct {
Window window;
@@ -83,13 +92,71 @@ typedef struct {
uint32_t lastDesktop;
Bool maxHorz;
Bool maxVert;
+ /** flag whether window is mapped */
+ Bool isMapped;
+ int xiTouchDeviceId;
+ XITouchPosition xiTouchCoords[XI_TOUCHCOORD_COUNT];
} JavaWindow;
JavaWindow * getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning);
Status NewtWindows_getRootAndParent (Display *dpy, Window w, Window * root_return, Window * parent_return);
Bool NewtWindows_updateInsets(Display *dpy, JavaWindow * w, int *left, int *right, int *top, int *bottom);
-Bool NewtWindows_updateMaximized(Display *dpy, JavaWindow * w);
+Bool NewtWindows_updateMaximized(Display *dpy, JavaWindow * w, uint32_t netWMState);
+
+#define _MASK_NET_WM_STATE ( 1 << 0 )
+#define _MASK_NET_WM_STATE_MODAL ( 1 << 1 )
+#define _MASK_NET_WM_STATE_STICKY ( 1 << 2 )
+#define _MASK_NET_WM_STATE_MAXIMIZED_VERT ( 1 << 3 )
+#define _MASK_NET_WM_STATE_MAXIMIZED_HORZ ( 1 << 4 )
+#define _MASK_NET_WM_STATE_SHADED ( 1 << 5 )
+#define _MASK_NET_WM_STATE_HIDDEN ( 1 << 8 )
+#define _MASK_NET_WM_STATE_FULLSCREEN ( 1 << 9 )
+#define _MASK_NET_WM_STATE_ABOVE ( 1 << 10 )
+#define _MASK_NET_WM_STATE_BELOW ( 1 << 11 )
+#define _MASK_NET_WM_STATE_DEMANDS_ATTENTION ( 1 << 12 )
+#define _MASK_NET_WM_STATE_FOCUSED ( 1 << 13 )
+#define _MASK_NET_WM_BYPASS_COMPOSITOR ( 1 << 14 )
+#define _MASK_NET_WM_DESKTOP ( 1 << 15 )
+#define _MASK_NET_CURRENT_DESKTOP ( 1 << 16 )
+#define _MASK_NET_WM_WINDOW_TYPE ( 1 << 17 )
+#define _MASK_NET_WM_WINDOW_TYPE_NORMAL ( 1 << 18 )
+#define _MASK_NET_WM_WINDOW_TYPE_POPUP_MENU ( 1 << 19 )
+#define _MASK_NET_FRAME_EXTENTS ( 1 << 20 )
+#define _MASK_NET_SUPPORTED ( 1 << 21 )
+#define _MASK_NET_ACTIVE_WINDOW ( 1 << 22 )
+#define _MASK_WM_CHANGE_STATE ( 1 << 23 )
+#define _MASK_MOTIF_WM_HINTS ( 1 << 24 )
+
+#define _NET_WM_STATE_IDX 0
+#define _NET_WM_STATE_MODAL_IDX 1
+#define _NET_WM_STATE_STICKY_IDX 2
+#define _NET_WM_STATE_MAXIMIZED_VERT_IDX 3
+#define _NET_WM_STATE_MAXIMIZED_HORZ_IDX 4
+#define _NET_WM_STATE_SHADED_IDX 5
+#define _NET_WM_STATE_SKIP_TASKBAR_IDX 6
+#define _NET_WM_STATE_SKIP_PAGER_IDX 7
+#define _NET_WM_STATE_HIDDEN_IDX 8
+#define _NET_WM_STATE_FULLSCREEN_IDX 9
+#define _NET_WM_STATE_ABOVE_IDX 10
+#define _NET_WM_STATE_BELOW_IDX 11
+#define _NET_WM_STATE_DEMANDS_ATTENTION_IDX 12
+#define _NET_WM_STATE_FOCUSED_IDX 13
+#define _NET_WM_BYPASS_COMPOSITOR_IDX 14
+#define _NET_WM_DESKTOP_IDX 15
+#define _NET_CURRENT_DESKTOP_IDX 16
+#define _NET_WM_WINDOW_TYPE_IDX 17
+#define _NET_WM_WINDOW_TYPE_NORMAL_IDX 18
+#define _NET_WM_WINDOW_TYPE_POPUP_MENU_IDX 19
+#define _NET_FRAME_EXTENTS_IDX 20
+#define _NET_SUPPORTED_IDX 21
+#define _NET_ACTIVE_WINDOW_IDX 22
+#define _WM_CHANGE_STATE_IDX 23
+#define _MOTIF_WM_HINTS_IDX 24
+
+void NewtWindows_setUrgency(Display *dpy, Window window, Bool enable);
+void NewtWindows_sendNET_WM_STATE(Display *dpy, Window root, JavaWindow *w, int prop1Idx, int prop2Idx, Bool enable);
+uint32_t NewtWindows_getNET_WM_STATE(Display *dpy, JavaWindow *w);
#endif /* _X11COMMON_H_ */
diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c
index 7ac6e8639..7c6741839 100644
--- a/src/newt/native/X11Display.c
+++ b/src/newt/native/X11Display.c
@@ -35,7 +35,7 @@
jclass X11NewtWindowClazz = NULL;
jmethodID insetsChangedID = NULL;
jmethodID visibleChangedID = NULL;
-jmethodID sizePosMaxInsetsChangedID = NULL;
+jmethodID insetsVisibleChangedID = NULL;
static const char * const ClazzNameX11NewtWindow = "jogamp/newt/driver/x11/WindowDriver";
@@ -46,13 +46,17 @@ static jmethodID getCurrentThreadNameID = NULL;
static jmethodID dumpStackID = NULL;
static jmethodID sizeChangedID = NULL;
static jmethodID positionChangedID = NULL;
-static jmethodID focusChangedID = NULL;
+static jmethodID focusVisibleChangedID = NULL;
static jmethodID reparentNotifyID = NULL;
static jmethodID windowDestroyNotifyID = NULL;
static jmethodID windowRepaintID = NULL;
static jmethodID sendMouseEventID = NULL;
static jmethodID sendKeyEventID = NULL;
static jmethodID sendMouseEventRequestFocusID = NULL;
+static jmethodID visibleChangedWindowRepaintID = NULL;
+static jmethodID visibleChangedSendMouseEventID = NULL;
+static jmethodID sizePosMaxInsetsVisibleChangedID = NULL;
+static jmethodID sendTouchScreenEventID = NULL;
/**
* Keycode
@@ -244,22 +248,26 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
}
}
- // displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJJII)V"); // Variant using XKB
- displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJII)V");
+ // displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJJIII)V"); // Variant using XKB
+ displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJIII)V");
sendRRScreenChangeNotifyID = (*env)->GetMethodID(env, clazz, "sendRRScreenChangeNotify", "(J)V");
getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "getCurrentThreadName", "()Ljava/lang/String;");
dumpStackID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "dumpStack", "()V");
insetsChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsChanged", "(ZIIII)V");
sizeChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sizeChanged", "(ZIIZ)V");
positionChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "positionChanged", "(ZII)V");
- focusChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "focusChanged", "(ZZ)V");
+ focusVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "focusVisibleChanged", "(ZII)V");
visibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChanged", "(ZZ)V");
- sizePosMaxInsetsChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sizePosMaxInsetsChanged", "(ZIIIIZZIIIIZ)V");
+ insetsVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsVisibleChanged", "(ZIIIII)V");
+ sizePosMaxInsetsVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sizePosMaxInsetsVisibleChanged", "(ZIIIIIIIIIIIZ)V");
reparentNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "reparentNotify", "(J)V");
windowDestroyNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowDestroyNotify", "(Z)Z");
windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)V");
+ visibleChangedWindowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChangedWindowRepaint", "(ZIIIII)V");
sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(SIIISF)V");
sendMouseEventRequestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEventRequestFocus", "(SIIISF)V");
+ visibleChangedSendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChangedSendMouseEvent", "(ZISIIISF)V");
+ sendTouchScreenEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendTouchScreenEvent", "(SII[I[I[I[FF)V");
sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(SISSCLjava/lang/String;)V");
if (displayCompletedID == NULL ||
@@ -269,19 +277,22 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
insetsChangedID == NULL ||
sizeChangedID == NULL ||
positionChangedID == NULL ||
- focusChangedID == NULL ||
+ focusVisibleChangedID == NULL ||
visibleChangedID == NULL ||
- sizePosMaxInsetsChangedID == NULL ||
+ insetsVisibleChangedID == NULL ||
+ sizePosMaxInsetsVisibleChangedID == NULL ||
reparentNotifyID == NULL ||
windowDestroyNotifyID == NULL ||
windowRepaintID == NULL ||
+ visibleChangedWindowRepaintID == NULL ||
sendMouseEventID == NULL ||
sendMouseEventRequestFocusID == NULL ||
+ visibleChangedSendMouseEventID == NULL ||
+ sendTouchScreenEventID == NULL ||
sendKeyEventID == NULL) {
return JNI_FALSE;
}
-
return JNI_TRUE;
}
@@ -320,10 +331,13 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay
int randr_event_base, randr_error_base;
XRRQueryExtension(dpy, &randr_event_base, &randr_error_base);
+ int xi_opcode = -1, event, error;
+ XQueryExtension(dpy, "XInputExtension", &xi_opcode, &event, &error);
+
DBG_PRINT("X11: X11Display_completeDisplay dpy %p\n", dpy);
(*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom /*, kbdHandle*/, // XKB disabled for now
- randr_event_base, randr_error_base);
+ randr_event_base, randr_error_base, xi_opcode);
}
/*
@@ -353,14 +367,96 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0
DBG_PRINT("X11: X11Display_DisplayRelease dpy %p\n", dpy);
}
+static int NewtWindows_updateVisibility(JNIEnv *env, Display *dpy, JavaWindow *jw, uint32_t netWMState, const char *dbgs) {
+ int visibleChange;
+ if( jw->isMapped && 0 != ( _MASK_NET_WM_STATE_HIDDEN & jw->supportedAtoms ) ) {
+ if( 0 != ( _MASK_NET_WM_STATE_HIDDEN & netWMState ) ) {
+ visibleChange = 0;
+ } else {
+ visibleChange = 1;
+ }
+ } else {
+ visibleChange = -1;
+ }
+ #ifdef VERBOSE_ON
+ XWindowAttributes xwa;
+ memset(&xwa, 0, sizeof(XWindowAttributes));
+ XGetWindowAttributes(dpy, jw->window, &xwa);
+
+ // map_state: IsUnmapped(0), IsUnviewable(1), IsViewable(2)
+ DBG_PRINT( "X11: event . %s call %p - isMapped %d, visibleChanged %d, map_state %d\n",
+ dbgs, (void*)jw->window, jw->isMapped, visibleChange, xwa.map_state);
+ #endif
+ return visibleChange;
+}
+
+static void sendTouchScreenEvent(JNIEnv *env, JavaWindow *jw,
+ short eventType, // MouseEvent.EVENT_MOUSE_PRESSED, MouseEvent.EVENT_MOUSE_RELEASED, MouseEvent.EVENT_MOUSE_MOVED
+ int modifiers, // 0!
+ int actionId) // index of multiple-pointer arrays representing the pointer which triggered the event
+{
+ jint pointerNames[XI_TOUCHCOORD_COUNT];
+ jint x[XI_TOUCHCOORD_COUNT];
+ jint y[XI_TOUCHCOORD_COUNT];
+ jfloat pressure[] = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
+ jint actionIdx = -1;
+ int i, cnt;
+
+ for(i = 0, cnt = 0; i < XI_TOUCHCOORD_COUNT; i++) {
+ if( -1 != jw->xiTouchCoords[i].id ) {
+ x[cnt] = jw->xiTouchCoords[i].x;
+ y[cnt] = jw->xiTouchCoords[i].y;
+ pointerNames[cnt] = jw->xiTouchCoords[i].id;
+ if (jw->xiTouchCoords[i].id == actionId) {
+ actionIdx = cnt;
+ }
+ cnt++;
+ }
+ }
+ if( 0 > actionIdx ) {
+ NewtCommon_throwNewRuntimeException(env, "Internal Error: XI event (window %p) actionId %d not found in %d xiTouchCoords",
+ (void*)jw->window, actionId, cnt);
+ }
+ DBG_PRINT( "X11: XI event - sendTouchScreenEvent: Window %p, action-touchid[%d] %d of %d ptr: %d/%d\n",
+ (void*)jw->window, actionIdx, actionId, cnt, x[actionIdx], y[actionIdx]);
+
+ jintArray jNames = (*env)->NewIntArray(env, cnt);
+ if (jNames == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (names) of size %d", cnt);
+ }
+ (*env)->SetIntArrayRegion(env, jNames, 0, cnt, pointerNames);
+
+ jintArray jX = (*env)->NewIntArray(env, cnt);
+ if (jX == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (x) of size %d", cnt);
+ }
+ (*env)->SetIntArrayRegion(env, jX, 0, cnt, x);
+
+ jintArray jY = (*env)->NewIntArray(env, cnt);
+ if (jY == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (y) of size %d", cnt);
+ }
+ (*env)->SetIntArrayRegion(env, jY, 0, cnt, y);
+
+ jfloatArray jPressure = (*env)->NewFloatArray(env, cnt);
+ if (jPressure == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate float array (pressure) of size %d", cnt);
+ }
+ (*env)->SetFloatArrayRegion(env, jPressure, 0, cnt, pressure);
+
+ (*env)->CallVoidMethod(env, jw->jwindow, sendTouchScreenEventID,
+ (jshort)eventType, (jint)modifiers, (jint)actionIdx,
+ jNames, jX, jY, jPressure, (jfloat)1.0f);
+}
+
/*
* Class: jogamp_newt_driver_x11_DisplayDriver
* Method: DispatchMessages0
- * Signature: (JJJII)V
+ * Signature: (JJJIII)V
*/
JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0
(JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/,
- jint randr_event_base, jint randr_error_base)
+ jint randr_event_base, jint randr_error_base, jint xi_opcode)
{
Display * dpy = (Display *) (intptr_t) display;
Atom wm_delete_atom = (Atom)windowDeleteAtom;
@@ -411,17 +507,30 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
if( randr_event_base > 0 && RRScreenChangeNotify == ( evt.type - randr_event_base ) ) {
DBG_PRINT( "X11: DispatchMessages dpy %p, Event RRScreenChangeNotify %p\n", (void*)dpy, (void*)&evt);
(*env)->CallVoidMethod(env, obj, sendRRScreenChangeNotifyID, (jlong)(intptr_t)&evt);
- continue;
+ continue; // next event
}
if( 0==evt.xany.window ) {
DBG_PRINT( "X11: DispatchMessages dpy %p, Event %d - Window NULL, ignoring\n", (void*)dpy, (int)evt.type);
- continue;
+ continue; // next event
}
- // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type);
+ // Valid registered XI Event w/ cookie data (incl. the event Window name)?
+ // Here: https://www.x.org/wiki/Development/Documentation/Multitouch/
+ XGenericEventCookie *evtCookie = &evt.xcookie; // hacks: https://keithp.com/blogs/Cursor_tracking/
+ int isXiEvent = GenericEvent == evtCookie->type && xi_opcode == evtCookie->extension && XGetEventData(dpy, evtCookie);
+ XIDeviceEvent *xiDevEv;
+ Window windowPointer;
+ if( !isXiEvent ) {
+ xiDevEv = NULL;
+ windowPointer = evt.xany.window;
+ DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)windowPointer, (int)evt.type);
+ } else {
+ xiDevEv = evtCookie->data;
+ windowPointer = xiDevEv->event;
+ }
- jw = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom,
+ jw = getJavaWindowProperty(env, dpy, windowPointer, javaObjectAtom,
#ifdef VERBOSE_ON
True
#else
@@ -430,10 +539,62 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
);
if(NULL==jw) {
- fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)evt.xany.window);
- continue;
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)windowPointer);
+ continue; // next event
}
-
+
+ if ( isXiEvent ) {
+ if( xiDevEv->deviceid != jw->xiTouchDeviceId) {
+ DBG_PRINT( "X11: XI event - dpy %p, win %p, Event %d: DeviceID not matching: Window %d, this %d\n", (void*)dpy, (void*)windowPointer, (int)evt.type, xiDevEv->deviceid, jw->xiTouchDeviceId);
+ } else {
+ int i;
+ switch (xiDevEv->evtype) {
+ case XI_TouchBegin:
+ for (i = 0; i < XI_TOUCHCOORD_COUNT; i++) {
+ if (jw->xiTouchCoords[i].id == -1) {
+ jw->xiTouchCoords[i].id = xiDevEv->detail % 32767;
+ jw->xiTouchCoords[i].x = xiDevEv->event_x;
+ jw->xiTouchCoords[i].y = xiDevEv->event_y;
+ break;
+ }
+ }
+ DBG_PRINT( "X11: XI event - XI_TouchBegin Window %p, devid %d, touchid[%d] %d @ %d/%d\n", (void*)windowPointer, xiDevEv->deviceid,
+ i, jw->xiTouchCoords[i].id, jw->xiTouchCoords[i].x, jw->xiTouchCoords[i].y);
+ sendTouchScreenEvent(env, jw, EVENT_MOUSE_PRESSED, 0, xiDevEv->detail % 32767);
+ break;
+
+ case XI_TouchUpdate:
+ for (i = 0; i < XI_TOUCHCOORD_COUNT; i++) {
+ if (jw->xiTouchCoords[i].id == xiDevEv->detail % 32767) {
+ jw->xiTouchCoords[i].x = xiDevEv->event_x;
+ jw->xiTouchCoords[i].y = xiDevEv->event_y;
+ break;
+ }
+ }
+ DBG_PRINT( "X11: XI event - XI_TouchUpdate: Window %p, devid %d, touchid[%d] %d @ %d/%d\n", (void*)windowPointer, xiDevEv->deviceid,
+ i, jw->xiTouchCoords[i].id, jw->xiTouchCoords[i].x, jw->xiTouchCoords[i].y);
+ sendTouchScreenEvent(env, jw, EVENT_MOUSE_MOVED, 0, xiDevEv->detail % 32767);
+ break;
+
+ case XI_TouchEnd:
+ for (i = 0; i < XI_TOUCHCOORD_COUNT; i++) {
+ if (jw->xiTouchCoords[i].id == xiDevEv->detail % 32767) {
+ break;
+ }
+ }
+ DBG_PRINT( "X11: XI event - XI_TouchEnd: Window %p, devid %d, touchid[%d] %d @ %d/%d\n", (void*)windowPointer, xiDevEv->deviceid,
+ i, jw->xiTouchCoords[i].id, jw->xiTouchCoords[i].x, jw->xiTouchCoords[i].y);
+ sendTouchScreenEvent(env, jw, EVENT_MOUSE_RELEASED, 0, xiDevEv->detail % 32767);
+ if ( i < XI_TOUCHCOORD_COUNT ) {
+ jw->xiTouchCoords[i].id = -1;
+ }
+ break;
+ }
+ }
+ XFreeEventData(dpy, evtCookie);
+ continue; // next event, skip evt.type handling below
+ }
+
switch(evt.type) {
case KeyRelease:
if (XEventsQueued(dpy, QueuedAfterReading)) {
@@ -538,15 +699,23 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
break;
case EnterNotify:
DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
- (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_ENTERED,
- modifiers,
- (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/);
+ {
+ uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw);
+ int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "EnterNotify");
+ (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedSendMouseEventID, JNI_FALSE, (jint)visibleChange,
+ (jshort) EVENT_MOUSE_ENTERED, modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/);
+ }
break;
case LeaveNotify:
DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
- (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_EXITED,
- modifiers,
- (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/);
+ {
+ uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw);
+ int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "LeaveNotify");
+ (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedSendMouseEventID, JNI_FALSE, (jint)visibleChange,
+ (jshort) EVENT_MOUSE_EXITED, modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/);
+ }
break;
case MappingNotify:
DBG_PRINT( "X11: event . MappingNotify call %p type %d\n", (void*)evt.xmapping.window, evt.xmapping.type);
@@ -578,19 +747,25 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
evt.xconfigure.override_redirect, evt.xconfigure.window != evt.xconfigure.event);
if ( evt.xconfigure.window == evt.xconfigure.event ) {
// ignore child window change notification
- // update insets
+ // insets: negative values are ignored
int left=-1, right=-1, top=-1, bottom=-1;
+ uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw);
+ int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "ConfigureNotify");
NewtWindows_updateInsets(dpy, jw, &left, &right, &top, &bottom);
- NewtWindows_updateMaximized(dpy, jw);
- (*env)->CallVoidMethod(env, jw->jwindow, sizePosMaxInsetsChangedID, JNI_FALSE,
+ Bool maxChanged = NewtWindows_updateMaximized(dpy, jw, netWMState);
+ (*env)->CallVoidMethod(env, jw->jwindow, sizePosMaxInsetsVisibleChangedID, JNI_FALSE,
(jint) evt.xconfigure.x, (jint) evt.xconfigure.y,
(jint) evt.xconfigure.width, (jint) evt.xconfigure.height,
- (jboolean)jw->maxHorz, (jboolean)jw->maxVert,
+ (jint)(maxChanged ? ( jw->maxHorz ? 1 : 0 ) : -1),
+ (jint)(maxChanged ? ( jw->maxVert ? 1 : 0 ) : -1),
(jint)left, (jint)right, (jint)top, (jint)bottom,
+ (jint)visibleChange,
JNI_FALSE);
}
break;
case ClientMessage:
+ DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X, sendEvent %d\n",
+ (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type, evt.xclient.send_event);
if (evt.xclient.send_event==True && evt.xclient.data.l[0]==wm_delete_atom) { // windowDeleteAtom
jboolean closed;
DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X ..\n",
@@ -604,48 +779,76 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
break;
case FocusIn:
- DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window);
- (*env)->CallVoidMethod(env, jw->jwindow, focusChangedID, JNI_FALSE, JNI_TRUE);
+ DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xfocus.window);
+ {
+ uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw);
+ int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "FocusIn");
+ (*env)->CallVoidMethod(env, jw->jwindow, focusVisibleChangedID, JNI_FALSE, (jint)1, (jint)visibleChange);
+ }
break;
case FocusOut:
- DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window);
- (*env)->CallVoidMethod(env, jw->jwindow, focusChangedID, JNI_FALSE, JNI_FALSE);
+ DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xfocus.window);
+ {
+ uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw);
+ int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "FocusOut");
+ (*env)->CallVoidMethod(env, jw->jwindow, focusVisibleChangedID, JNI_FALSE, (jint)0, (jint)visibleChange);
+ }
break;
+ case VisibilityNotify:
+ DBG_PRINT( "X11: event . VisibilityNotify call %p\n", (void*)evt.xvisibility.window);
+ {
+ #if 0
+ uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw);
+ int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "VisibilityNotify");
+ if( 0 <= visibleChange ) {
+ (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE, 0 < visibleChange ? JNI_TRUE : JNI_FALSE);
+ }
+ #endif
+ }
+ break;
+
+
case Expose:
DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)evt.xexpose.window,
evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height, evt.xexpose.count);
-
if (evt.xexpose.count == 0 && evt.xexpose.width > 0 && evt.xexpose.height > 0) {
(*env)->CallVoidMethod(env, jw->jwindow, windowRepaintID, JNI_FALSE,
evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height);
+ #if 0
+ uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw);
+ int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "Expose");
+ (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedWindowRepaintID, JNI_FALSE, (jint)visibleChange,
+ evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height);
+ #endif
}
break;
case MapNotify:
- DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, override_redirect %d, child-event: %d\n",
- (void*)evt.xmap.event, (void*)evt.xmap.window, (int)evt.xmap.override_redirect,
+ DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, isMapped %d -> 1, override_redirect %d, child-event: %d\n",
+ (void*)evt.xmap.event, (void*)evt.xmap.window, jw->isMapped, (int)evt.xmap.override_redirect,
evt.xmap.event!=evt.xmap.window);
if( evt.xmap.event == evt.xmap.window ) {
// ignore child window notification
- {
- // update insets
- int left, right, top, bottom;
- if( NewtWindows_updateInsets(dpy, jw, &left, &right, &top, &bottom) ) {
- (*env)->CallVoidMethod(env, jw->jwindow, insetsChangedID, JNI_FALSE, left, right, top, bottom);
- }
+ jw->isMapped = True;
+ // insets: negative values are ignored
+ int left=-1, right=-1, top=-1, bottom=-1;
+ if( NewtWindows_updateInsets(dpy, jw, &left, &right, &top, &bottom) ) {
+ (*env)->CallVoidMethod(env, jw->jwindow, insetsVisibleChangedID, JNI_FALSE, left, right, top, bottom, 1);
+ } else {
+ (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
}
- (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
}
break;
case UnmapNotify:
- DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, from_configure %d, child-event: %d\n",
- (void*)evt.xunmap.event, (void*)evt.xunmap.window, (int)evt.xunmap.from_configure,
+ DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, isMapped %d -> 0, from_configure %d, child-event: %d\n",
+ (void*)evt.xunmap.event, (void*)evt.xunmap.window, jw->isMapped, (int)evt.xunmap.from_configure,
evt.xunmap.event!=evt.xunmap.window);
if( evt.xunmap.event == evt.xunmap.window ) {
// ignore child window notification
+ jw->isMapped = False;
(*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE);
}
break;
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index 6fa3cc195..1c2c8e80f 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -85,53 +85,7 @@ static uintptr_t getPtrOut32Long(unsigned long * src) {
#define _NET_WM_STATE_REMOVE 0
#define _NET_WM_STATE_ADD 1
-#define _MASK_NET_WM_STATE ( 1 << 0 )
-#define _MASK_NET_WM_STATE_MODAL ( 1 << 1 )
-#define _MASK_NET_WM_STATE_STICKY ( 1 << 2 )
-#define _MASK_NET_WM_STATE_MAXIMIZED_VERT ( 1 << 3 )
-#define _MASK_NET_WM_STATE_MAXIMIZED_HORZ ( 1 << 4 )
-#define _MASK_NET_WM_STATE_SHADED ( 1 << 5 )
-#define _MASK_NET_WM_STATE_HIDDEN ( 1 << 8 )
-#define _MASK_NET_WM_STATE_FULLSCREEN ( 1 << 9 )
-#define _MASK_NET_WM_STATE_ABOVE ( 1 << 10 )
-#define _MASK_NET_WM_STATE_BELOW ( 1 << 11 )
-#define _MASK_NET_WM_STATE_DEMANDS_ATTENTION ( 1 << 12 )
-#define _MASK_NET_WM_STATE_FOCUSED ( 1 << 13 )
-#define _MASK_NET_WM_BYPASS_COMPOSITOR ( 1 << 14 )
-#define _MASK_NET_WM_DESKTOP ( 1 << 15 )
-#define _MASK_NET_CURRENT_DESKTOP ( 1 << 16 )
-#define _MASK_NET_WM_WINDOW_TYPE ( 1 << 17 )
-#define _MASK_NET_WM_WINDOW_TYPE_NORMAL ( 1 << 18 )
-#define _MASK_NET_WM_WINDOW_TYPE_POPUP_MENU ( 1 << 19 )
-#define _MASK_NET_FRAME_EXTENTS ( 1 << 20 )
-#define _MASK_NET_SUPPORTED ( 1 << 21 )
-#define _MASK_WM_CHANGE_STATE ( 1 << 22 )
-#define _MASK_MOTIF_WM_HINTS ( 1 << 23 )
-
-#define _NET_WM_STATE_IDX 0
-#define _NET_WM_STATE_MODAL_IDX 1
-#define _NET_WM_STATE_STICKY_IDX 2
-#define _NET_WM_STATE_MAXIMIZED_VERT_IDX 3
-#define _NET_WM_STATE_MAXIMIZED_HORZ_IDX 4
-#define _NET_WM_STATE_SHADED_IDX 5
-#define _NET_WM_STATE_SKIP_TASKBAR_IDX 6
-#define _NET_WM_STATE_SKIP_PAGER_IDX 7
-#define _NET_WM_STATE_HIDDEN_IDX 8
-#define _NET_WM_STATE_FULLSCREEN_IDX 9
-#define _NET_WM_STATE_ABOVE_IDX 10
-#define _NET_WM_STATE_BELOW_IDX 11
-#define _NET_WM_STATE_DEMANDS_ATTENTION_IDX 12
-#define _NET_WM_STATE_FOCUSED_IDX 13
-#define _NET_WM_BYPASS_COMPOSITOR_IDX 14
-#define _NET_WM_DESKTOP_IDX 15
-#define _NET_CURRENT_DESKTOP_IDX 16
-#define _NET_WM_WINDOW_TYPE_IDX 17
-#define _NET_WM_WINDOW_TYPE_NORMAL_IDX 18
-#define _NET_WM_WINDOW_TYPE_POPUP_MENU_IDX 19
-#define _NET_FRAME_EXTENTS_IDX 20
-#define _NET_SUPPORTED_IDX 21
-#define _WM_CHANGE_STATE_IDX 22
-#define _MOTIF_WM_HINTS_IDX 23
+/** Sync w/ X11Common.h MASK and IDX */
static const char * _ALL_ATOM_NAMES[] = {
/* 0 */ "_NET_WM_STATE",
/* 1 */ "_NET_WM_STATE_MODAL",
@@ -155,8 +109,9 @@ static const char * _ALL_ATOM_NAMES[] = {
/* 19 */ "_NET_WM_WINDOW_TYPE_POPUP_MENU",
/* 20 */ "_NET_FRAME_EXTENTS",
/* 21 */ "_NET_SUPPORTED",
- /* 22 */ "WM_CHANGE_STATE",
- /* 23 */ "_MOTIF_WM_HINTS"
+ /* 22 */ "_NET_ACTIVE_WINDOW",
+ /* 23 */ "WM_CHANGE_STATE",
+ /* 24 */ "_MOTIF_WM_HINTS"
};
static const uint32_t _ALL_ATOM_COUNT = (uint32_t)(sizeof(_ALL_ATOM_NAMES)/sizeof(const char *));
@@ -185,7 +140,6 @@ static uint32_t NewtWindows_getSupportedFeaturesEWMH(Display *dpy, Window root,
uint32_t res = 0;
Status s;
- XSync(dpy, False);
if ( Success == (s = XGetWindowProperty(dpy, root, allAtoms[_NET_SUPPORTED_IDX], 0, 1024, False, AnyPropertyType,
&type, &form, &props_count, &remain, (unsigned char**)&properties)) ) {
if( NULL != properties ) {
@@ -202,7 +156,16 @@ static uint32_t NewtWindows_getSupportedFeaturesEWMH(Display *dpy, Window root,
}
return res;
}
-static uint32_t NewtWindows_getNET_WM_STATE(Display *dpy, Window window, Atom * allAtoms, Bool verbose) {
+uint32_t NewtWindows_getNET_WM_STATE(Display *dpy, JavaWindow *w) {
+ Bool verbose =
+#ifdef VERBOSE_ON
+ True
+#else
+ False
+#endif
+ ;
+ Window window = w->window;
+ Atom * allAtoms = w->allAtoms;
Atom * properties = NULL;
Atom type = 0;
unsigned long props_count = 0, remain = 0;
@@ -210,7 +173,6 @@ static uint32_t NewtWindows_getNET_WM_STATE(Display *dpy, Window window, Atom *
uint32_t res = 0;
Status s;
- XSync(dpy, False);
if ( Success == (s = XGetWindowProperty(dpy, window, allAtoms[_NET_WM_STATE_IDX], 0, 1024, False, AnyPropertyType,
&type, &form, &props_count, &remain, (unsigned char**)&properties)) ) {
if( NULL != properties ) {
@@ -220,7 +182,7 @@ static uint32_t NewtWindows_getNET_WM_STATE(Display *dpy, Window window, Atom *
XFree(properties);
}
if(verbose) {
- fprintf(stderr, "**************** X11: WM_STATE of %p: 0x%X\n", (void*)window, res);
+ fprintf(stderr, "**************** X11: WM_STATE of %p: %d props -> 0x%X\n", (void*)window, (int)props_count, res);
}
} else if(verbose) {
fprintf(stderr, "**************** X11: WM_STATE of %p: XGetWindowProperty failed: %d\n", (void*)window, s);
@@ -249,6 +211,12 @@ static JavaWindow* createJavaWindowProperty(JNIEnv *env, Display *dpy, Window ro
res->lastDesktop = 0; //undef
res->maxHorz = False;
res->maxVert = False;
+ res->isMapped = False;
+ int i;
+ for (i = 0; i < XI_TOUCHCOORD_COUNT; i++) {
+ res->xiTouchCoords[i].id = -1;
+ }
+ res->xiTouchDeviceId = -1;
}
unsigned long jogl_java_object_data[2]; // X11 is based on 'unsigned long'
int nitems_32 = putPtrIn32Long( jogl_java_object_data, (uintptr_t) res);
@@ -292,7 +260,7 @@ JavaWindow * getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlo
if ( Success != res ) {
if(True==showWarning) {
- fprintf(stderr, "Warning: NEWT X11Window: Could not fetch Atom NEWT_JAVA_OBJECT window property (res %d) nitems %ld, bytes_after %ld, result 0!\n", res, nitems, bytes_after);
+ fprintf(stderr, "Warning: NEWT X11Window: Could not fetch Atom NEWT_JAVA_OBJECT window %p property (res %d) nitems %ld, bytes_after %ld, result 0!\n", (void*)window, res, nitems, bytes_after);
}
return NULL;
}
@@ -302,8 +270,8 @@ JavaWindow * getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlo
XFree(jogl_java_object_data_pp);
}
if(True==showWarning) {
- fprintf(stderr, "Warning: NEWT X11Window: Fetched invalid Atom NEWT_JAVA_OBJECT window property (res %d) nitems %ld, bytes_after %ld, actual_type %ld, NEWT_JAVA_OBJECT %ld, result 0!\n",
- res, nitems, bytes_after, (long)actual_type, (long)javaObjectAtom);
+ fprintf(stderr, "Warning: NEWT X11Window: Fetched invalid Atom NEWT_JAVA_OBJECT window %p property (res %d) nitems %ld, bytes_after %ld, actual_type %ld, NEWT_JAVA_OBJECT %ld, result 0!\n",
+ (void *)window, res, nitems, bytes_after, (long)actual_type, (long)javaObjectAtom);
}
return NULL;
}
@@ -352,7 +320,6 @@ static void NewtWindows_setCWAbove(Display *dpy, Window w) {
memset(&xwc, 0, sizeof(XWindowChanges));
xwc.stack_mode = Above;
XConfigureWindow(dpy, w, CWStackMode, &xwc);
- XSync(dpy, False);
}
static Status NewtWindows_getWindowPositionRelative2Parent (Display *dpy, Window w, int *x_return, int *y_return) {
Window root_return;
@@ -440,8 +407,7 @@ static void NewtWindows_setDecorations (Display *dpy, JavaWindow *w, Bool decora
#ifdef DECOR_USE_EWMH
XChangeProperty( dpy, w->window, w->allAtoms[_NET_WM_WINDOW_TYPE_IDX], XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes);
#endif
-
- XSync(dpy, False);
+ XFlush(dpy);
}
static Bool NewtWindows_hasDecorations (Display *dpy, JavaWindow * w) {
@@ -473,7 +439,6 @@ static void NewtWindows_requestFocus (Display *dpy, JavaWindow * jw, Bool force)
Window focus_return;
int revert_to_return;
- XSync(dpy, False);
XGetInputFocus(dpy, &focus_return, &revert_to_return);
DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d, hasFocus %d\n", dpy, (void*)jw->window, force, focus_return==jw->window);
@@ -488,8 +453,8 @@ static void NewtWindows_requestFocus (Display *dpy, JavaWindow * jw, Bool force)
XSetInputFocus(dpy, jw->window, RevertToParent, CurrentTime);
}
}
+ XFlush(dpy);
DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d - FIN\n", dpy, (void*)jw->window, force);
- XSync(dpy, False);
}
Bool NewtWindows_updateInsets(Display *dpy, JavaWindow * w, int *left, int *right, int *top, int *bottom) {
@@ -513,16 +478,9 @@ Bool NewtWindows_updateInsets(Display *dpy, JavaWindow * w, int *left, int *righ
return False; // Error
}
-Bool NewtWindows_updateMaximized(Display *dpy, JavaWindow * w) {
- uint32_t state = NewtWindows_getNET_WM_STATE(dpy, w->window, w->allAtoms,
-#ifdef VERBOSE_ON
- True
-#else
- False
-#endif
- );
- Bool maxHorz = 0 != ( _MASK_NET_WM_STATE_MAXIMIZED_HORZ & state ) ;
- Bool maxVert = 0 != ( _MASK_NET_WM_STATE_MAXIMIZED_VERT & state ) ;
+Bool NewtWindows_updateMaximized(Display *dpy, JavaWindow * w, uint32_t netWMState) {
+ Bool maxHorz = 0 != ( _MASK_NET_WM_STATE_MAXIMIZED_HORZ & netWMState ) ;
+ Bool maxVert = 0 != ( _MASK_NET_WM_STATE_MAXIMIZED_VERT & netWMState ) ;
if( w->maxHorz != maxHorz || w->maxVert != maxVert ) {
w->maxHorz = maxHorz;
w->maxVert = maxVert;
@@ -558,11 +516,20 @@ static void NewtWindows_setWindowTypeEWMH (Display *dpy, JavaWindow * w, int typ
} // else { }
if( 0 != types[0] ) {
XChangeProperty( dpy, w->window, w->allAtoms[_NET_WM_WINDOW_TYPE_IDX], XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, 1);
- XSync(dpy, False);
+ XFlush(dpy);
}
}
-static void NewtWindows_sendNET_WM_STATE(Display *dpy, Window root, JavaWindow *w, int prop1Idx, int prop2Idx, Bool enable) {
+void NewtWindows_setUrgency(Display *dpy, Window window, Bool enable) {
+ XWMHints wmh;
+ memset ( &wmh, 0, sizeof(wmh) );
+ if( enable ) {
+ wmh.flags = XUrgencyHint;
+ }
+ XSetWMHints(dpy, window, &wmh);
+}
+
+void NewtWindows_sendNET_WM_STATE(Display *dpy, Window root, JavaWindow *w, int prop1Idx, int prop2Idx, Bool enable) {
XEvent xev;
int i=0;
@@ -694,7 +661,7 @@ static void NewtWindows_setStackingEWMHFlags (Display *dpy, Window root, JavaWin
changeMaxVert ? _NET_WM_STATE_MAXIMIZED_VERT_IDX : 0,
enable);
}
- XSync(dpy, False);
+ XFlush(dpy);
DBG_PRINT( "X11: setStackingEWMHFlags ON %d, change[Sticky %d, Fullscreen %d, Above %d, Below %d, MaxV %d, MaxH %d]\n",
enable, changeSticky, changeFullscreen, changeAbove, changeBelow, changeMaxVert, changeMaxHorz);
}
@@ -709,35 +676,47 @@ static Bool WaitForUnmapNotify( Display *dpy, XEvent *event, XPointer arg ) {
static void NewtWindows_setVisible(Display *dpy, Window root, JavaWindow* jw, Bool visible, Bool useWM, Bool waitForNotify) {
XEvent event;
- if( !visible && useWM && 0 != ( _MASK_NET_WM_STATE_HIDDEN & jw->supportedAtoms ) ) {
- DBG_PRINT( "X11: setVisible -> %d, method: IconicState, wait %d, window %p\n", (int)visible, (int)waitForNotify, (void*)jw->window);
- // It has been experienced that UnmapNotify is not sent for child windows when using IconicState!
+ DBG_PRINT( "X11: setVisible -> %d, useWM: %d, wait %d, window %p\n", (int)visible, (int)useWM, (int)waitForNotify, (void*)jw->window);
+ if( useWM && jw->isMapped && 0 != ( _MASK_NET_WM_STATE_HIDDEN & jw->supportedAtoms ) ) {
+ // It has been experienced that MapNotify/UnmapNotify is not sent for windows when using NormalState/IconicState!
+ // See X11Display.c::Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0 case ConfigureNotify
+ // NewtWindows_sendNET_WM_STATE(dpy, root, jw, _NET_WM_STATE_DEMANDS_ATTENTION_IDX, 0, True);
+ // NewtWindows_setUrgency(dpy, jw->window, True);
XEvent xev;
memset ( &xev, 0, sizeof(xev) );
- xev.type = ClientMessage;
- xev.xclient.window = jw->window;
- xev.xclient.message_type = jw->allAtoms[_WM_CHANGE_STATE_IDX];
- xev.xclient.format = 32;
- xev.xclient.data.l[0] = IconicState;
- XSendEvent ( dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &xev );
- // NewtWindows_sendNET_WM_STATE(dpy, root, jw, _NET_WM_STATE_HIDDEN_IDX, 0, !visible);
- if(waitForNotify) {
- XIfEvent( dpy, &event, WaitForUnmapNotify, (XPointer) jw->window );
+ if( visible ) {
+ // NormalState does not work on some WMs (Gnome, KDE)
+ xev.type = ClientMessage;
+ xev.xclient.window = jw->window;
+ xev.xclient.message_type = jw->allAtoms[_NET_ACTIVE_WINDOW_IDX];
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = 1; //source indication for normal applications
+ xev.xclient.data.l[1] = CurrentTime;
+ XSendEvent ( dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &xev );
+ } else {
+ xev.type = ClientMessage;
+ xev.xclient.window = jw->window;
+ xev.xclient.message_type = jw->allAtoms[_WM_CHANGE_STATE_IDX];
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = IconicState;
+ XSendEvent ( dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &xev );
}
} else {
- DBG_PRINT( "X11: setVisible -> %d, method: Map/Unmap, wait %d, window %p\n", (int)visible, (int)waitForNotify, (void*)jw->window);
if( visible ) {
XMapRaised(dpy, jw->window);
if(waitForNotify) {
XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) jw->window );
}
+ jw->isMapped=True;
} else {
XUnmapWindow(dpy, jw->window);
if(waitForNotify) {
XIfEvent( dpy, &event, WaitForUnmapNotify, (XPointer) jw->window );
}
+ jw->isMapped=False;
}
}
+ XFlush(dpy);
}
@@ -771,7 +750,7 @@ static void NewtWindows_setPosSize(Display *dpy, JavaWindow* w, jint x, jint y,
xwc.height=height;
}
XConfigureWindow(dpy, w->window, flags, &xwc);
- XSync(dpy, False);
+ XFlush(dpy);
}
}
@@ -787,7 +766,7 @@ static void NewtWindows_setIcon(Display *dpy, Window w, int data_size, const uns
JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
(JNIEnv *env, jobject obj, jlong parent, jlong display, jint screen_index,
jint visualID,
- jlong javaObjectAtom, jlong windowDeleteAtom,
+ jlong javaObjectAtom, jlong windowDeleteAtom, jint xi_opcode,
jint x, jint y, jint width, jint height, int flags,
jint pixelDataSize, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct,
jboolean verbose)
@@ -858,24 +837,23 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind
pVisualQuery=NULL;
}
- attrMask = ( CWBackingStore | CWBackingPlanes | CWBackingPixel | CWBackPixmap |
- CWBorderPixel | CWColormap | CWOverrideRedirect | CWEventMask ) ;
+ attrMask = ( CWBackingStore | CWBackingPlanes | CWBackingPixel |
+ CWBackPixmap | CWBackPixel | CWBorderPixel | CWColormap |
+ CWOverrideRedirect | CWEventMask ) ;
memset(&xswa, 0, sizeof(xswa));
- xswa.override_redirect = False; // use the window manager, always (default)
- xswa.border_pixel = 0;
- xswa.background_pixmap = None;
xswa.backing_store=NotUseful; /* NotUseful, WhenMapped, Always */
xswa.backing_planes=0; /* planes to be preserved if possible */
xswa.backing_pixel=0; /* value to use in restoring planes */
+ xswa.background_pixmap = None;
+ xswa.background_pixel = BlackPixel(dpy, scrn_idx);
+ xswa.border_pixel = 0;
+ xswa.colormap = XCreateColormap(dpy, windowParent, visual, AllocNone);
+ xswa.override_redirect = False; // use the window manager, always (default)
xswa.event_mask = X11_MOUSE_EVENT_MASK;
xswa.event_mask |= KeyPressMask | KeyReleaseMask ;
- xswa.event_mask |= FocusChangeMask | SubstructureNotifyMask | StructureNotifyMask | ExposureMask ;
-
- xswa.colormap = XCreateColormap(dpy,
- windowParent,
- visual,
- AllocNone);
+ xswa.event_mask |= FocusChangeMask | SubstructureNotifyMask | StructureNotifyMask | ExposureMask;
+ // xswa.event_mask |= VisibilityChangeMask;
{
int _x = x, _y = y; // pos for CreateWindow, might be tweaked
@@ -900,6 +878,7 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind
NewtCommon_throwNewRuntimeException(env, "could not create Window, bail out!");
return 0;
}
+ // XClearWindow(dpy, window);
XSetWMProtocols(dpy, window, &wm_delete_atom, 1); // windowDeleteAtom
javaWindow = createJavaWindowProperty(env, dpy, root, window, javaObjectAtom, windowDeleteAtom, obj, verbose);
@@ -911,7 +890,8 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind
// we can pre-map the window here to be able to gather the insets and position.
{
XEvent event;
- int left=0, right=0, top=0, bottom=0;
+ // insets: negative values are ignored
+ int left=-1, right=-1, top=-1, bottom=-1;
const unsigned char * pixelPtr = NULL;
// NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly!
@@ -926,18 +906,20 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind
XMapWindow(dpy, window);
XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) window ); // wait to get proper insets values
-
- XSync(dpy, False);
+ javaWindow->isMapped=True;
if( JNI_FALSE == pixels_is_direct && NULL != pixelPtr ) {
(*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
}
// send insets before visibility, allowing java code a proper sync point!
+ XSync(dpy, False);
if( NewtWindows_updateInsets(dpy, javaWindow, &left, &right, &top, &bottom) ) {
- (*env)->CallVoidMethod(env, javaWindow->jwindow, insetsChangedID, JNI_FALSE, left, right, top, bottom);
+ (*env)->CallVoidMethod(env, javaWindow->jwindow, insetsVisibleChangedID, JNI_FALSE, left, right, top, bottom, 1);
+ } else {
+ (*env)->CallVoidMethod(env, javaWindow->jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
+ left=0; right=0; top=0; bottom=0;
}
- (*env)->CallVoidMethod(env, javaWindow->jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
if( TST_FLAG_IS_AUTOPOSITION(flags) ) {
// get position from WM
@@ -975,6 +957,59 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind
NewtWindows_setMinMaxSize(dpy, javaWindow, width, height, width, height);
}
}
+
+ // Register X11 Multitouch Events for new Window
+ // https://www.x.org/wiki/Development/Documentation/Multitouch/
+ if( 0 <= xi_opcode ) {
+ XIDeviceInfo *di;
+ int cnt = 0;
+
+ DBG_PRINT( "X11: [CreateWindow]: XI: Window %p, Extension %d\n", (void*)window, xi_opcode);
+ di = XIQueryDevice(dpy, XIAllDevices, &cnt);
+
+ if( NULL != di && 0 < cnt ) {
+ int devid = -1;
+ int i, j;
+
+ // find the 1st XITouchClass device available
+ for (i = 0; i < cnt && -1 == devid; i ++) {
+ XIDeviceInfo *dev = &di[i];
+ for (j = 0; j < dev->num_classes; j ++) {
+ XITouchClassInfo *class = (XITouchClassInfo*)(dev->classes[j]);
+ DBG_PRINT( "X11: [CreateWindow]: XI: Scan Window %p, device[%d/%d].class[%d/%d]: devid %d, type %d (is XITouchClass %d)\n",
+ (void*)window, (i+1), cnt, (j+1), dev->num_classes, dev->deviceid, class->type, (XITouchClass == class->type));
+ if ( XITouchClass == class->type ) {
+ devid = dev->deviceid;
+ break;
+ }
+ }
+ }
+ XIFreeDeviceInfo(di);
+ di = NULL;
+
+ if( -1 != devid ) {
+ // register 1st XITouchClass device if available
+ XIEventMask mask = {
+ .deviceid = devid,
+ .mask_len = XIMaskLen(XI_TouchEnd) // in bytes
+ };
+
+ mask.mask = (unsigned char*)calloc(mask.mask_len, sizeof(unsigned char));
+ XISetMask(mask.mask, XI_TouchBegin);
+ XISetMask(mask.mask, XI_TouchUpdate);
+ XISetMask(mask.mask, XI_TouchEnd);
+
+ XISelectEvents(dpy, window, &mask, 1);
+
+ free(mask.mask);
+
+ javaWindow->xiTouchDeviceId = devid;
+ DBG_PRINT( "X11: [CreateWindow]: XI: Window %p, XITouchClass devid %d\n", (void*)window, devid);
+ }
+ }
+ }
+
+ XFlush(dpy);
handles[0] = (jlong)(intptr_t)window;
handles[1] = (jlong)(intptr_t)javaWindow;
jhandles = (*env)->NewLongArray(env, 2);
@@ -988,12 +1023,40 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind
/*
* Class: jogamp_newt_driver_x11_WindowDriver
+ * Method: GetSupportedReconfigMask0
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_WindowDriver_GetSupportedReconfigMask0
+ (JNIEnv *env, jclass clazz, jlong javaWindow)
+{
+ JavaWindow * jw = (JavaWindow*)(intptr_t)javaWindow;
+ uint32_t supported = jw->supportedAtoms;
+ return
+ FLAG_IS_VISIBLE |
+ FLAG_IS_AUTOPOSITION |
+ FLAG_IS_CHILD |
+ FLAG_IS_FOCUSED |
+ FLAG_IS_UNDECORATED |
+ ( ( 0 != ( _MASK_NET_WM_STATE_ABOVE & supported ) ) ? FLAG_IS_ALWAYSONTOP : 0 ) |
+ ( ( 0 != ( _MASK_NET_WM_STATE_BELOW & supported ) ) ? FLAG_IS_ALWAYSONBOTTOM : 0 ) |
+ ( ( 0 != ( _MASK_NET_WM_DESKTOP & supported ) ) ? FLAG_IS_STICKY : 0 ) |
+ FLAG_IS_RESIZABLE |
+ ( ( 0 != ( _MASK_NET_WM_STATE_MAXIMIZED_VERT & supported ) ) ? FLAG_IS_MAXIMIZED_VERT : 0 ) |
+ ( ( 0 != ( _MASK_NET_WM_STATE_MAXIMIZED_HORZ & supported ) ) ? FLAG_IS_MAXIMIZED_HORZ : 0 ) |
+ FLAG_IS_FULLSCREEN |
+ FLAG_IS_POINTERVISIBLE |
+ FLAG_IS_POINTERCONFINED |
+ FLAG_IS_FULLSCREEN_SPAN;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_WindowDriver
* Method: CloseWindow
* Signature: (JJ)V
*/
JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0
(JNIEnv *env, jobject obj, jlong display, jlong javaWindow /*, jlong kbdHandle*/, // XKB disabled for now
- jint randr_event_base, jint randr_error_base)
+ jint randr_event_base, jint randr_error_base, jint xi_opcode)
{
Display * dpy = (Display *) (intptr_t) display;
JavaWindow * jw, * jw0;
@@ -1008,7 +1071,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0
NewtCommon_FatalError(env, "invalid JavaWindow connection..");
}
jw0 = getJavaWindowProperty(env, dpy, jw->window, jw->javaObjectAtom, True);
- if(NULL==jw) {
+ if(NULL==jw0) {
NewtCommon_throwNewRuntimeException(env, "could not fetch Java Window object, bail out!");
return;
}
@@ -1026,11 +1089,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0
XGetWindowAttributes(dpy, jw->window, &xwa); // prefetch colormap to be destroyed after window destruction
XSelectInput(dpy, jw->window, 0);
XUnmapWindow(dpy, jw->window);
+ jw->isMapped=False;
// Drain all events related to this window ..
Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display,
(jlong)(intptr_t)jw->javaObjectAtom, (jlong)(intptr_t)jw->windowDeleteAtom /*, kbdHandle */, // XKB disabled for now
- randr_event_base, randr_error_base);
+ randr_event_base, randr_error_base, xi_opcode);
XDestroyWindow(dpy, jw->window);
if( None != xwa.colormap ) {
@@ -1065,7 +1129,7 @@ static Bool WaitForReparentNotify( Display *dpy, XEvent *event, XPointer arg ) {
* Signature: (JIJJIIIII)V
*/
JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindow0
- (JNIEnv *env, jobject obj, jlong jdisplay, jint screen_index,
+ (JNIEnv *env, jclass clazz, jlong jdisplay, jint screen_index,
jlong jparent, jlong javaWindow,
jint x, jint y, jint width, jint height, jint flags)
{
@@ -1121,6 +1185,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
TST_FLAG_CHANGE_STICKY(flags), TST_FLAG_IS_STICKY(flags),
fsEWMHFlags);
+ XSync(dpy, False);
+
// FS Note: To toggle FS, utilizing the _NET_WM_STATE_FULLSCREEN WM state should be enough.
// However, we have to consider other cases like reparenting and WM which don't support it.
#if 0 // Also doesn't work work properly w/ Unity WM
@@ -1162,8 +1228,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
XReparentWindow( dpy, jw->window, parent, x, y ); // actual reparent call
#ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY
XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) jw->window );
+ #else
+ XSync(dpy, False);
#endif
- XSync(dpy, False);
XSetWMProtocols(dpy, jw->window, &wm_delete_atom, 1); // windowDeleteAtom
// Fix for Unity WM, i.e. _remove_ persistent previous states
NewtWindows_setStackingEWMHFlags(dpy, root, jw, fsEWMHFlags, False);
@@ -1205,10 +1272,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
// CHILD: out -> in
DBG_PRINT( "X11: reconfigureWindow0 PARENTING out->in\n");
XReparentWindow( dpy, jw->window, parent, x, y ); // actual reparent call
+ XFlush(dpy);
#ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY
XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) jw->window );
+ #else
+ XSync(dpy, False);
#endif
- XSync(dpy, False);
}
if( tempInvisible ) {
@@ -1220,7 +1289,6 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
if( TST_FLAG_IS_VISIBLE(flags) ) {
DBG_PRINT( "X11: reconfigureWindow0 VISIBLE ON\n");
NewtWindows_setVisible(dpy, root, jw, True /* visible */, useWM, False /* wait */);
- XSync(dpy, False);
if( !TST_FLAG_IS_MAXIMIZED_ANY(flags) ) {
// WM may disregard pos/size XConfigureWindow requests for invisible windows!
DBG_PRINT( "X11: reconfigureWindow0 setPosSize.2 %d/%d %dx%d\n", x, y, width, height);
@@ -1229,7 +1297,6 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
} else {
DBG_PRINT( "X11: reconfigureWindow0 VISIBLE OFF\n");
NewtWindows_setVisible(dpy, root, jw, False /* visible */, useWM, False /* wait */);
- XSync(dpy, False);
}
}
@@ -1250,6 +1317,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
NewtWindows_setMinMaxSize(dpy, jw, -1, -1, -1, -1); // FIXME: ..
}
}
+ XFlush(dpy);
DBG_PRINT( "X11: reconfigureWindow0 X (full)\n");
}
@@ -1259,9 +1327,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
* Signature: (JJZ)V
*/
JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_requestFocus0
- (JNIEnv *env, jobject obj, jlong display, jlong javaWindow, jboolean force)
+ (JNIEnv *env, jclass clazz, jlong display, jlong javaWindow, jboolean force)
{
- NewtWindows_requestFocus ( (Display *) (intptr_t) display, (JavaWindow*)(intptr_t)javaWindow, JNI_TRUE==force?True:False ) ;
+ Display * dpy = (Display *) (intptr_t) display;
+ XSync(dpy, False);
+ NewtWindows_requestFocus ( dpy, (JavaWindow*)(intptr_t)javaWindow, JNI_TRUE==force?True:False ) ;
}
/*