diff options
Diffstat (limited to 'src/newt/native')
-rw-r--r-- | src/newt/native/MacWindow.m | 149 | ||||
-rw-r--r-- | src/newt/native/NewtMacWindow.h | 9 | ||||
-rw-r--r-- | src/newt/native/NewtMacWindow.m | 135 | ||||
-rw-r--r-- | src/newt/native/Window.h | 4 | ||||
-rw-r--r-- | src/newt/native/WindowsEDID.c | 10 | ||||
-rw-r--r-- | src/newt/native/WindowsWindow.c | 588 | ||||
-rw-r--r-- | src/newt/native/X11Common.h | 64 | ||||
-rw-r--r-- | src/newt/native/X11Display.c | 171 | ||||
-rw-r--r-- | src/newt/native/X11RandR13.c | 8 | ||||
-rw-r--r-- | src/newt/native/X11Window.c | 313 |
10 files changed, 957 insertions, 494 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 ad4111ec7..59e054516 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -177,9 +177,11 @@ static jmethodID insetsChangedID = NULL; static jmethodID sizeChangedID = NULL; +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; @@ -202,15 +204,23 @@ static UnregisterTouchWindowPROCADDR WinTouch_UnregisterTouchWindow = NULL; static int NewtEDID_avail = 0; -static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd); - 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 */ int setPointerVisible; /** Tristate: -1 RESET, 0 NOP, 1 SET-NEW */ @@ -218,9 +228,17 @@ typedef struct { HCURSOR setPointerHandle; HCURSOR defPointerHandle; /** Bool: 0 NOP, 1 FULLSCREEN */ - int isFullscreen; + BOOL isFullscreen; /** Bool: 0 TOP, 1 CHILD */ - int isChildWindow; + BOOL isChildWindow; + /** Bool: 0 NOP, 1 minimized/iconic */ + 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; @@ -228,6 +246,8 @@ typedef struct { int supportsMTouch; } WindowUserData; +static void UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd); + typedef struct { USHORT javaKey; USHORT windowsKey; @@ -601,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(); @@ -660,91 +700,34 @@ static jboolean NewtWindows_setFullScreen(jboolean fullscreen) return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, flags) ) ? JNI_TRUE : JNI_FALSE; } -#if 0 - -static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd) -{ - // being naughty here - static RECT m_insets = { 0, 0, 0, 0 }; - RECT outside; - RECT inside; - POINT *rp_inside = (POINT *) (void *) &inside; - int dx, dy, dw, dh; - - if (IsIconic(hwnd)) { - m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = -1; - return FALSE; - } - - m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = 0; - - GetClientRect(hwnd, &inside); - GetWindowRect(hwnd, &outside); - - DBG_PRINT("*** WindowsWindow: UpdateInsets (a1) window %p, Inside CC: %d/%d - %d/%d %dx%d\n", - (void*)hwnd, - (int)inside.left, (int)inside.top, (int)inside.right, (int)inside.bottom, - (int)(inside.right - inside.left), (int)(inside.bottom - inside.top)); - DBG_PRINT("*** WindowsWindow: UpdateInsets (a1) window %p, Outside SC: %d/%d - %d/%d %dx%d\n", - (void*)hwnd, - (int)outside.left, (int)outside.top, (int)outside.right, (int)outside.bottom, - (int)(outside.right - outside.left), (int)(outside.bottom - outside.top)); - - // xform client -> screen coord - ClientToScreen(hwnd, rp_inside); - ClientToScreen(hwnd, rp_inside+1); - - DBG_PRINT("*** WindowsWindow: UpdateInsets (a2) window %p, Inside SC: %d/%d - %d/%d %dx%d\n", - (void*)hwnd, - (int)inside.left, (int)inside.top, (int)inside.right, (int)inside.bottom, - (int)(inside.right - inside.left), (int)(inside.bottom - inside.top)); - - m_insets.top = inside.top - outside.top; - m_insets.bottom = outside.bottom - inside.bottom; - m_insets.left = inside.left - outside.left; - m_insets.right = outside.right - inside.right; - - DBG_PRINT("*** WindowsWindow: UpdateInsets (1.0) window %p, %d/%d - %d/%d %dx%d\n", - (void*)hwnd, - (int)m_insets.left, (int)m_insets.top, (int)m_insets.right, (int)m_insets.bottom, - (int)(m_insets.right-m_insets.left), (int)(m_insets.top-m_insets.bottom)); - - (*env)->CallVoidMethod(env, window, insetsChangedID, JNI_FALSE, - m_insets.left, m_insets.right, - m_insets.top, m_insets.bottom); - return &m_insets; -} - -#else - -static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd) -{ - // being naughty here - static RECT m_insets = { 0, 0, 0, 0 }; +static void UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd) { + jobject window = wud->jinstance; RECT outside; RECT inside; + int strategy = 0; if (IsIconic(hwnd)) { - m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = -1; - return FALSE; + wud->insets.left = wud->insets.top = wud->insets.right = wud->insets.bottom = -1; + return; } - m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = 0; + wud->insets.left = wud->insets.top = wud->insets.right = wud->insets.bottom = 0; GetClientRect(hwnd, &inside); GetWindowRect(hwnd, &outside); if (outside.right - outside.left > 0 && outside.bottom - outside.top > 0) { MapWindowPoints(hwnd, 0, (LPPOINT)&inside, 2); - m_insets.top = inside.top - outside.top; - m_insets.bottom = outside.bottom - inside.bottom; - m_insets.left = inside.left - outside.left; - m_insets.right = outside.right - inside.right; + wud->insets.top = inside.top - outside.top; + wud->insets.bottom = outside.bottom - inside.bottom; + wud->insets.left = inside.left - outside.left; + wud->insets.right = outside.right - inside.right; + strategy = 1; } else { - m_insets.top = -1; + wud->insets.top = -1; } - if (m_insets.left < 0 || m_insets.top < 0 || - m_insets.right < 0 || m_insets.bottom < 0) + if (wud->insets.left < 0 || wud->insets.top < 0 || + wud->insets.right < 0 || wud->insets.bottom < 0) { LONG style = GetWindowLong(hwnd, GWL_STYLE); @@ -752,49 +735,65 @@ static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd) if (!bIsUndecorated) { /* Get outer frame sizes. */ if (style & WS_THICKFRAME) { - m_insets.left = m_insets.right = + wud->insets.left = wud->insets.right = GetSystemMetrics(SM_CXSIZEFRAME); - m_insets.top = m_insets.bottom = + wud->insets.top = wud->insets.bottom = GetSystemMetrics(SM_CYSIZEFRAME); } else { - m_insets.left = m_insets.right = + wud->insets.left = wud->insets.right = GetSystemMetrics(SM_CXDLGFRAME); - m_insets.top = m_insets.bottom = + wud->insets.top = wud->insets.bottom = GetSystemMetrics(SM_CYDLGFRAME); } /* Add in title. */ - m_insets.top += GetSystemMetrics(SM_CYCAPTION); + wud->insets.top += GetSystemMetrics(SM_CYCAPTION); + strategy += 10; } else { /* undo the -1 set above */ - m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = 0; + 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)m_insets.left, (int)m_insets.right, (int)m_insets.top, (int)m_insets.bottom, - (int) ( m_insets.left + m_insets.right ), (int) (m_insets.top + m_insets.bottom)); - - (*env)->CallVoidMethod(env, window, insetsChangedID, JNI_FALSE, - (int)m_insets.left, (int)m_insets.right, (int)m_insets.top, (int)m_insets.bottom); - return &m_insets; + 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); + } } -#endif - static void WmSize(JNIEnv *env, WindowUserData * wud, HWND wnd, UINT type) { RECT rc; BOOL isVisible = IsWindowVisible(wnd); jobject window = wud->jinstance; + BOOL maxChanged = FALSE; + + DBG_PRINT("*** WindowsWindow: WmSize.0 window %p, %dx%d, isMinimized %d, isMaximized %d, visible %d\n", + (void*)wnd, wud->width, wud->height, wud->isMinimized, wud->isMaximized, isVisible); if (type == SIZE_MINIMIZED) { - // TODO: deal with minimized window sizing + wud->isMinimized = TRUE; return; } + if (type == SIZE_MAXIMIZED) { + if( !wud->isMaximized ) { + wud->isMaximized = 1; + maxChanged = TRUE; + } + } else if (type == SIZE_RESTORED) { + wud->isMinimized = FALSE; + if( wud->isMaximized ) { + wud->isMaximized = FALSE; + maxChanged = TRUE; + } + } // make sure insets are up to date - (void)UpdateInsets(env, window, wnd); + UpdateInsets(env, wud, wnd); GetClientRect(wnd, &rc); @@ -802,9 +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 window %p, %dx%d, visible %d\n", (void*)wnd, wud->width, wud->height, 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); - (*env)->CallVoidMethod(env, window, sizeChangedID, JNI_FALSE, wud->width, wud->height, JNI_FALSE); + 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); + } } #ifdef TEST_MOUSE_HOOKS @@ -930,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; @@ -993,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 } } @@ -1005,11 +1016,39 @@ 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 // because the size of the client area doesn't change - (void)UpdateInsets(env, window, wnd); + UpdateInsets(env, wud, wnd); } else { useDefWindowProc = 1; } @@ -1020,32 +1059,79 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP break; case WM_SHOWWINDOW: - (*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 : @@ -1094,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; @@ -1108,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 .. @@ -2032,9 +2124,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0 insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V"); + maximizedChangedID = (*env)->GetMethodID(env, clazz, "maximizedChanged", "(ZZ)V"); 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"); @@ -2044,9 +2138,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0 if (insetsChangedID == NULL || sizeChangedID == NULL || + maximizedChangedID == NULL || positionChangedID == NULL || focusChangedID == NULL || visibleChangedID == NULL || + sizePosInsetsFocusVisibleChangedID == NULL || windowDestroyNotifyID == NULL || windowRepaintID == NULL || sendMouseEventID == NULL || @@ -2088,32 +2184,61 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_getNewtWndP return (jlong) (intptr_t) wndProc; } -static void NewtWindow_setVisiblePosSize(HWND hwnd, BOOL atop, BOOL visible, +static void NewtWindow_setVisiblePosSize(WindowUserData *wud, HWND hwnd, int jflags, BOOL visible, int x, int y, int width, int height) { - UINT flags; - BOOL bRes; - - DBG_PRINT("*** WindowsWindow: NewtWindow_setVisiblePosSize %d/%d %dx%d, atop %d, visible %d\n", - x, y, width, height, atop, visible); + BOOL atop = TST_FLAG_IS_ALWAYSONTOP(jflags); + BOOL abottom = TST_FLAG_IS_ALWAYSONBOTTOM(jflags); + UINT wflags; + + DBG_PRINT("*** WindowsWindow: NewtWindow_setVisiblePosSize client %d/%d %dx%d, atop %d, abottom %d, max[change[%d %d], is[%d %d]], visible %d\n", + x, y, width, height, atop, abottom, + TST_FLAG_CHANGE_MAXIMIZED_VERT(jflags), TST_FLAG_CHANGE_MAXIMIZED_HORZ(jflags), + TST_FLAG_IS_MAXIMIZED_VERT(jflags), TST_FLAG_IS_MAXIMIZED_HORZ(jflags), + visible); + + x -= wud->insets.left; // top-level + y -= wud->insets.top; // top-level + width += wud->insets.left + wud->insets.right; // top-level + height += wud->insets.top + wud->insets.bottom; // top-level + DBG_PRINT("*** WindowsWindow: NewtWindow_setVisiblePosSize top-level %d/%d %dx%d\n", x, y, width, height); if(visible) { - flags = SWP_SHOWWINDOW; + wflags = SWP_SHOWWINDOW; + if( abottom ) { + wflags |= SWP_NOACTIVATE; + } } else { - flags = SWP_NOACTIVATE | SWP_NOZORDER; + wflags = SWP_NOACTIVATE | SWP_NOZORDER; } if(0>=width || 0>=height ) { - flags |= SWP_NOSIZE; + wflags |= SWP_NOSIZE; } + wud->isOnTop = atop; + wud->isOnBottom = abottom; if(atop) { - SetWindowPos(hwnd, HWND_TOP, x, y, width, height, flags); - SetWindowPos(hwnd, HWND_TOPMOST, x, y, width, height, flags); + SetWindowPos(hwnd, HWND_TOP, x, y, width, height, wflags); + SetWindowPos(hwnd, HWND_TOPMOST, x, y, width, height, wflags); + } else if(abottom) { + SetWindowPos(hwnd, HWND_NOTOPMOST, x, y, width, height, wflags); + SetWindowPos(hwnd, HWND_BOTTOM, x, y, width, height, wflags); } else { - SetWindowPos(hwnd, HWND_NOTOPMOST, x, y, width, height, flags); - SetWindowPos(hwnd, HWND_TOP, x, y, width, height, flags); + SetWindowPos(hwnd, HWND_NOTOPMOST, x, y, width, height, wflags); + SetWindowPos(hwnd, 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) ) { + wud->isMaximized = 1; + ShowWindow(hwnd, SW_MAXIMIZE); + } else if( !TST_FLAG_IS_MAXIMIZED_VERT(jflags) && !TST_FLAG_IS_MAXIMIZED_HORZ(jflags) ) { + if( wud->isMaximized ) { + ShowWindow(hwnd, SW_RESTORE); + wud->isMaximized = 0; + } + } } - // SetWindowPos(hwnd, atop ? HWND_TOPMOST : HWND_TOP, x, y, width, height, flags); InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); @@ -2128,16 +2253,15 @@ static void NewtWindow_setVisiblePosSize(HWND hwnd, BOOL atop, BOOL visible, 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, jboolean autoPosition, 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); @@ -2153,43 +2277,54 @@ 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 { - windowStyle |= WS_OVERLAPPEDWINDOW; - if(JNI_TRUE == autoPosition) { + 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 { + windowStyle |= WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; + } + 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, - TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags), autoPosition); + 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); wud->setPointerHandle = wud->defPointerHandle; - wud->isFullscreen = 0; + wud->isFullscreen = FALSE; 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; @@ -2208,40 +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; - RECT * insets; - - ShowWindow(window, SW_SHOW); - - // send insets before visibility, allowing java code a proper sync point! - insets = UpdateInsets(env, wud->jinstance, window); - (*env)->CallVoidMethod(env, wud->jinstance, visibleChangedID, JNI_FALSE, JNI_TRUE); - - if(JNI_TRUE == autoPosition) { - GetWindowRect(window, &rc); - x = rc.left + insets->left; // client coords - y = rc.top + insets->top; // client coords - } - DBG_PRINT("*** WindowsWindow: CreateWindow client: %d/%d %dx%d (autoPosition %d)\n", x, y, width, height, autoPosition); + // send insets before visibility, allowing java code a proper sync point! + UpdateInsets(env, wud, hwnd); - x -= insets->left; // top-level - y -= insets->top; // top-level - width += insets->left + insets->right; // top-level - height += insets->top + insets->bottom; // top-level - DBG_PRINT("*** WindowsWindow: CreateWindow top-level %d/%d %dx%d\n", x, y, width, height); - - NewtWindow_setVisiblePosSize(window, TST_FLAG_IS_ALWAYSONTOP(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 @@ -2258,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); + } } /* @@ -2288,7 +2451,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW HWND hwndP = (HWND) (intptr_t) parent; HWND hwnd = (HWND) (intptr_t) window; DWORD windowStyle = WS_DEFAULT_STYLES; - BOOL styleChange = TST_FLAG_CHANGE_DECORATION(flags) || TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_PARENTING(flags) ; + 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); @@ -2296,20 +2462,25 @@ 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, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d -> styleChange %d, isChild %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_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), styleChange, wud->isChildWindow, wud->isFullscreen); + 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); if (!IsWindow(hwnd)) { DBG_PRINT("*** WindowsWindow: reconfigureWindow0 failure: Passed window %p is invalid\n", (void*)hwnd); 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; @@ -2334,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 = 1; - 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 ) { @@ -2345,16 +2521,18 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW windowStyle |= WS_CHILD ; } else if ( TST_FLAG_IS_UNDECORATED(flags) ) { windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; - } else { + } 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 { + windowStyle |= WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; } SetWindowLong(hwnd, GWL_STYLE, windowStyle); SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER ); } if( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off - // CHILD: out -> in - wud->isFullscreen = 0; + wud->isFullscreen = FALSE; NewtWindows_setFullScreen(JNI_FALSE); } @@ -2363,17 +2541,25 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW SetParent(hwnd, hwndP ); } - NewtWindow_setVisiblePosSize(hwnd, TST_FLAG_IS_ALWAYSONTOP(flags), TST_FLAG_IS_VISIBLE(flags), x, y, width, height); + NewtWindow_setVisiblePosSize(wud, hwnd, flags, TST_FLAG_IS_VISIBLE(flags), x, y, width, height); if( TST_FLAG_CHANGE_VISIBILITY(flags) ) { if( TST_FLAG_IS_VISIBLE(flags) ) { - ShowWindow(hwnd, 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); } else { ShowWindow(hwnd, SW_HIDE); } } - DBG_PRINT("*** WindowsWindow: reconfigureWindow0.X isChild %d, isFullscreen %d\n", wud->isChildWindow, wud->isFullscreen); + DBG_PRINT("*** WindowsWindow: reconfigureWindow0.X isChild %d, isMinimized %d, isFullscreen %d\n", wud->isChildWindow, wud->isMinimized, wud->isFullscreen); } /* diff --git a/src/newt/native/X11Common.h b/src/newt/native/X11Common.h index 309e62683..f9254ab76 100644 --- a/src/newt/native/X11Common.h +++ b/src/newt/native/X11Common.h @@ -71,7 +71,7 @@ extern jclass X11NewtWindowClazz; extern jmethodID insetsChangedID; extern jmethodID visibleChangedID; -extern jmethodID minMaxSizeChangedID; +extern jmethodID insetsVisibleChangedID; typedef struct { Window window; @@ -81,13 +81,71 @@ typedef struct { Atom windowDeleteAtom; uint32_t supportedAtoms; uint32_t lastDesktop; + Bool maxHorz; + Bool maxVert; + /** flag whether window is mapped */ + Bool isMapped; } 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); -Status NewtWindows_updateInsets(JNIEnv *env, Display *dpy, JavaWindow * w, int *left, int *right, int *top, int *bottom); -void NewtWindows_updateMinMaxSize(JNIEnv *env, Display *dpy, JavaWindow * w); +Bool NewtWindows_updateInsets(Display *dpy, JavaWindow * w, int *left, int *right, int *top, int *bottom); +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 0ba454a00..32e0f8786 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 minMaxSizeChangedID = NULL; +jmethodID insetsVisibleChangedID = NULL; static const char * const ClazzNameX11NewtWindow = "jogamp/newt/driver/x11/WindowDriver"; @@ -46,13 +46,16 @@ 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 requestFocusID = NULL; +static jmethodID sendMouseEventRequestFocusID = NULL; +static jmethodID visibleChangedWindowRepaintID = NULL; +static jmethodID visibleChangedSendMouseEventID = NULL; +static jmethodID sizePosMaxInsetsVisibleChangedID = NULL; /** * Keycode @@ -222,7 +225,7 @@ static jint X11InputState2NewtModifiers(unsigned int xstate, jshort javaVKey, jb /* * Class: jogamp_newt_driver_x11_DisplayDriver - * Method: initIDs + * Method: initIDs0 * Signature: (Z)Z */ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0 @@ -252,15 +255,18 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0 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"); - minMaxSizeChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "minMaxSizeChanged", "(IIII)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"); sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(SISSCLjava/lang/String;)V"); - requestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "requestFocus", "(Z)V"); if (displayCompletedID == NULL || sendRRScreenChangeNotifyID == NULL || @@ -269,15 +275,18 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0 insetsChangedID == NULL || sizeChangedID == NULL || positionChangedID == NULL || - focusChangedID == NULL || + focusVisibleChangedID == NULL || visibleChangedID == NULL || - minMaxSizeChangedID == NULL || + insetsVisibleChangedID == NULL || + sizePosMaxInsetsVisibleChangedID == NULL || reparentNotifyID == NULL || windowDestroyNotifyID == NULL || windowRepaintID == NULL || + visibleChangedWindowRepaintID == NULL || sendMouseEventID == NULL || - sendKeyEventID == NULL || - requestFocusID == NULL) { + sendMouseEventRequestFocusID == NULL || + visibleChangedSendMouseEventID == NULL || + sendKeyEventID == NULL) { return JNI_FALSE; } @@ -287,7 +296,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0 /* * Class: jogamp_newt_driver_x11_DisplayDriver - * Method: CompleteDisplay + * Method: CompleteDisplay0 * Signature: (J)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay0 @@ -353,10 +362,33 @@ 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; +} + /* * Class: jogamp_newt_driver_x11_DisplayDriver - * Method: DispatchMessages - * Signature: (JJJ)V + * Method: DispatchMessages0 + * Signature: (JJJII)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0 (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/, @@ -522,8 +554,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage switch(evt.type) { case ButtonPress: - (*env)->CallVoidMethod(env, jw->jwindow, requestFocusID, JNI_FALSE); - (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_PRESSED, + (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventRequestFocusID, (jshort) EVENT_MOUSE_PRESSED, modifiers, (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/); break; @@ -539,15 +570,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); @@ -579,19 +618,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 - int left, right, top, bottom; - NewtWindows_updateInsets(env, dpy, jw, &left, &right, &top, &bottom); - } - NewtWindows_updateMinMaxSize(env, dpy, jw); - (*env)->CallVoidMethod(env, jw->jwindow, sizeChangedID, JNI_FALSE, - (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE); - (*env)->CallVoidMethod(env, jw->jwindow, positionChangedID, JNI_FALSE, - (jint) evt.xconfigure.x, (jint) evt.xconfigure.y); + // 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); + 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, + (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", @@ -605,46 +650,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; - NewtWindows_updateInsets(env, dpy, jw, &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; @@ -693,7 +768,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage /* * Class: Java_jogamp_newt_driver_x11_DisplayDriver * Method: createPointerIcon0 - * Signature: (JJILjava/lang/Object;I)V + * Signature: (JJIZIIII)J */ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_createPointerIcon0 (JNIEnv *env, jclass clazz, jlong display, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY) @@ -731,7 +806,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_createPointerI /* * Class: Java_jogamp_newt_driver_x11_DisplayDriver * Method: destroyPointerIcon0 - * Signature: (JJILjava/lang/Object;I)V + * Signature: (JJ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_destroyPointerIcon0 (JNIEnv *env, jclass clazz, jlong display, jlong handle) diff --git a/src/newt/native/X11RandR13.c b/src/newt/native/X11RandR13.c index 0dd53feb8..3f9dff289 100644 --- a/src/newt/native/X11RandR13.c +++ b/src/newt/native/X11RandR13.c @@ -39,6 +39,14 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR13_getScreenResources0 Display *dpy = (Display *) (intptr_t) display; Window root = RootWindow(dpy, (int)screen_idx); + /* Bug 1183 + * XRRGetScreenResourcesCurrent (or XRRGetScreenResources) + * _occasionally_ reports empty data + * unless XRRGetScreenSizeRange has been called once. + */ + int minWidth, minHeight, maxWidth, maxHeight; + XRRGetScreenSizeRange ( dpy, root, &minWidth, &minHeight, &maxWidth, &maxHeight); + XRRScreenResources *res = XRRGetScreenResourcesCurrent( dpy, root); // 1.3 // XRRScreenResources *res = XRRGetScreenResources( dpy, root); // 1.2 diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 778b71cc5..de2bddc86 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 *)); @@ -178,21 +133,20 @@ static uint32_t NewtWindows_getSupportedFeatureEWMH(Display *dpy, const Atom * a return 0; } static uint32_t NewtWindows_getSupportedFeaturesEWMH(Display *dpy, Window root, Atom * allAtoms, Bool verbose) { - Atom * actions = NULL; + Atom * properties = NULL; Atom type = 0; - unsigned long action_len = 0, remain = 0; + unsigned long props_count = 0, remain = 0; int form = 0, i = 0; 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, &action_len, &remain, (unsigned char**)&actions)) ) { - if( NULL != actions ) { - for(i=0; i<action_len; i++) { - res |= NewtWindows_getSupportedFeatureEWMH(dpy, allAtoms, actions[i], i, verbose); + &type, &form, &props_count, &remain, (unsigned char**)&properties)) ) { + if( NULL != properties ) { + for(i=0; i<props_count; i++) { + res |= NewtWindows_getSupportedFeatureEWMH(dpy, allAtoms, properties[i], i, verbose); } - XFree(actions); + XFree(properties); } if(verbose) { fprintf(stderr, "**************** X11: Feature EWMH CHECK: 0x%X\n", res); @@ -202,6 +156,39 @@ static uint32_t NewtWindows_getSupportedFeaturesEWMH(Display *dpy, Window root, } return res; } +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; + int form = 0, i = 0; + uint32_t res = 0; + Status s; + + 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 ) { + for(i=0; i<props_count; i++) { + res |= NewtWindows_getSupportedFeatureEWMH(dpy, allAtoms, properties[i], i, verbose); + } + XFree(properties); + } + if(verbose) { + 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); + } + return res; +} static JavaWindow* createJavaWindowProperty(JNIEnv *env, Display *dpy, Window root, Window window, jlong javaObjectAtom, jlong windowDeleteAtom, jobject obj, Bool verbose) { @@ -222,6 +209,9 @@ static JavaWindow* createJavaWindowProperty(JNIEnv *env, Display *dpy, Window ro res->windowDeleteAtom = (Atom)windowDeleteAtom; res->supportedAtoms = NewtWindows_getSupportedFeaturesEWMH(dpy, root, allAtoms, verbose); res->lastDesktop = 0; //undef + res->maxHorz = False; + res->maxVert = False; + res->isMapped = False; } unsigned long jogl_java_object_data[2]; // X11 is based on 'unsigned long' int nitems_32 = putPtrIn32Long( jogl_java_object_data, (uintptr_t) res); @@ -325,7 +315,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; @@ -413,8 +402,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) { @@ -446,7 +434,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); @@ -461,16 +448,14 @@ 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); } -Status NewtWindows_updateInsets(JNIEnv *env, Display *dpy, JavaWindow * w, int *left, int *right, int *top, int *bottom) { +Bool NewtWindows_updateInsets(Display *dpy, JavaWindow * w, int *left, int *right, int *top, int *bottom) { if(0 != NewtWindows_getFrameExtends(dpy, w, left, right, top, bottom)) { - DBG_PRINT( "NewtWindows_updateInsets: insets by _NET_FRAME_EXTENTS [ l %d, r %d, t %d, b %d ]\n", - *left, *right, *top, *bottom); - (*env)->CallVoidMethod(env, w->jwindow, insetsChangedID, JNI_FALSE, *left, *right, *top, *bottom); - return 1; // OK + DBG_PRINT( "NewtWindows_updateInsets: insets by _NET_FRAME_EXTENTS [ l %d, r %d, t %d, b %d ]\n", *left, *right, *top, *bottom); + return True; // OK } Bool hasDecor = NewtWindows_hasDecorations (dpy, w); @@ -480,43 +465,23 @@ Status NewtWindows_updateInsets(JNIEnv *env, Display *dpy, JavaWindow * w, int * Window parent = NewtWindows_getParent(dpy, w->window); if(0 != NewtWindows_getWindowPositionRelative2Parent (dpy, parent, left, top)) { *right = *left; *bottom = *top; - DBG_PRINT( "NewtWindows_updateInsets: insets by parent position [ l %d, r %d, t %d, b %d ]\n", - *left, *right, *top, *bottom); - (*env)->CallVoidMethod(env, w->jwindow, insetsChangedID, JNI_FALSE, *left, *right, *top, *bottom); - return 1; // OK + DBG_PRINT( "NewtWindows_updateInsets: insets by parent position [ l %d, r %d, t %d, b %d ]\n", *left, *right, *top, *bottom); + return True; // OK } } DBG_PRINT( "NewtWindows_updateInsets: cannot determine insets - hasDecor %d\n", hasDecor); - return 0; // Error + return False; // Error } -void NewtWindows_updateMinMaxSize(JNIEnv *env, Display *dpy, JavaWindow * w) { - XSizeHints * xsh = XAllocSizeHints(); - long xsh_bits = 0; - int min_width=-1, min_height=-1; - int max_width=-1, max_height=-1; - if( NULL != xsh ) { - xsh->flags = 0; - xsh->min_width=0; - xsh->min_height=0; - xsh->max_width=0; - xsh->max_height=0; - if( 0 != XGetWMNormalHints(dpy, w->window, xsh, &xsh_bits) ) { - // OK - if( 0 != ( xsh_bits & PMinSize ) ) { - min_width = xsh->min_width; - min_height = xsh->min_height; - } - if( 0 != ( xsh_bits & PMaxSize ) ) { - max_width = xsh->max_width; - max_height = xsh->max_height; - } - DBG_PRINT( "NewtWindows_updateMinMaxSize: XGetWMNormalHints 0x%X / 0x%X for window %p on display %p\n", xsh_bits, xsh->flags, (void*)w->window, dpy); - (*env)->CallVoidMethod(env, w->jwindow, minMaxSizeChangedID, min_width, min_height, max_width, max_height); - } else { - DBG_PRINT( "NewtWindows_updateMinMaxSize: XGetWMNormalHints failed (0x%X / 0x%X) for window %p on display %p\n", xsh_bits, xsh->flags, (void*)w->window, dpy); - } - XFree(xsh); +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; + return True; + } else { + return False; } } @@ -546,11 +511,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); + } +} + +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); } -static void NewtWindows_sendNET_WM_STATE(Display *dpy, Window root, JavaWindow *w, int prop1Idx, int prop2Idx, Bool enable) { +void NewtWindows_sendNET_WM_STATE(Display *dpy, Window root, JavaWindow *w, int prop1Idx, int prop2Idx, Bool enable) { XEvent xev; int i=0; @@ -671,12 +645,18 @@ static void NewtWindows_setStackingEWMHFlags (Display *dpy, Window root, JavaWin XChangeProperty( dpy, w->window, w->allAtoms[_NET_WM_BYPASS_COMPOSITOR_IDX], XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&value, 1); } } else if( changeMaxVert || changeMaxHorz ) { + if( changeMaxHorz ) { + w->maxHorz = enable; + } + if( changeMaxVert ) { + w->maxVert = enable; + } NewtWindows_sendNET_WM_STATE(dpy, root, w, - changeMaxVert ? _NET_WM_STATE_MAXIMIZED_VERT_IDX : 0, changeMaxHorz ? _NET_WM_STATE_MAXIMIZED_HORZ_IDX : 0, + 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); } @@ -691,35 +671,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); } @@ -753,7 +745,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); } } @@ -840,24 +832,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 @@ -882,6 +873,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); @@ -893,7 +885,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! @@ -908,16 +901,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! - NewtWindows_updateInsets(env, dpy, javaWindow, &left, &right, &top, &bottom); - (*env)->CallVoidMethod(env, javaWindow->jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); + XSync(dpy, False); + if( NewtWindows_updateInsets(dpy, javaWindow, &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; + } if( TST_FLAG_IS_AUTOPOSITION(flags) ) { // get position from WM @@ -955,6 +952,7 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind NewtWindows_setMinMaxSize(dpy, javaWindow, width, height, width, height); } } + XFlush(dpy); handles[0] = (jlong)(intptr_t)window; handles[1] = (jlong)(intptr_t)javaWindow; jhandles = (*env)->NewLongArray(env, 2); @@ -968,6 +966,34 @@ 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 */ @@ -1006,6 +1032,7 @@ 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, @@ -1045,7 +1072,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) { @@ -1101,6 +1128,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 @@ -1142,8 +1171,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); @@ -1185,10 +1215,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 ) { @@ -1200,7 +1232,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); @@ -1209,7 +1240,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); } } @@ -1230,6 +1260,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"); } @@ -1239,9 +1270,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 ) ; } /* |