diff options
Diffstat (limited to 'src/newt/native')
-rw-r--r-- | src/newt/native/MacWindow.m | 89 | ||||
-rw-r--r-- | src/newt/native/NewtMacWindow.h | 27 | ||||
-rw-r--r-- | src/newt/native/NewtMacWindow.m | 257 | ||||
-rw-r--r-- | src/newt/native/X11Window.c | 166 |
4 files changed, 362 insertions, 177 deletions
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index ddd59f0a1..6d96e01fb 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -44,6 +44,10 @@ #import <stdio.h> +#ifdef DBG_PERF + #include "timespec.h" +#endif + static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point"; static const char * const ClazzAnyCstrName = "<init>"; static const char * const ClazzNamePointCstrSignature = "(II)V"; @@ -315,11 +319,60 @@ static long GetDictionaryLong(CFDictionaryRef theDict, const void* key) /* * Class: jogamp_newt_driver_macosx_MacScreen + * Method: getScreenSizeMM0 + * Signature: (I)[I + */ +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenSizeMM0 + (JNIEnv *env, jobject obj, jint scrn_idx) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + +#ifdef DBG_PERF + struct timespec t0, t1, td; + long td_ms; + timespec_now(&t0); +#endif + + NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx); +#ifdef DBG_PERF + timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td); + fprintf(stderr, "MacScreen_getScreenSizeMM0.1: %ld ms\n", td_ms); fflush(NULL); +#endif + + CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); +#ifdef DBG_PERF + timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td); + fprintf(stderr, "MacScreen_getScreenSizeMM0.2: %ld ms\n", td_ms); fflush(NULL); +#endif + + CGSize screenDim = CGDisplayScreenSize(display); +#ifdef DBG_PERF + timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td); + fprintf(stderr, "MacScreen_getScreenSizeMM0.3: %ld ms\n", td_ms); fflush(NULL); +#endif + + jint prop[ 2 ]; + prop[0] = (jint) screenDim.width; + prop[1] = (jint) screenDim.height; + + jintArray properties = (*env)->NewIntArray(env, 2); + if (properties == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size 2"); + } + (*env)->SetIntArrayRegion(env, properties, 0, 2, prop); + + [pool release]; + + return properties; +} + +/* + * Class: jogamp_newt_driver_macosx_MacScreen * Method: getScreenMode0 - * Signature: (II)[I + * Signature: (IIII)[I */ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMode0 - (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx) + (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx, jint widthMM, jint heightMM) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -360,7 +413,6 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMo } // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef - CGSize screenDim = CGDisplayScreenSize(display); int mWidth = CGDDGetModeWidth(mode); int mHeight = CGDDGetModeHeight(mode); @@ -383,8 +435,8 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMo prop[propIndex++] = mWidth; prop[propIndex++] = mHeight; prop[propIndex++] = CGDDGetModeBitsPerPixel(mode); - prop[propIndex++] = (jint) screenDim.width; - prop[propIndex++] = (jint) screenDim.height; + prop[propIndex++] = widthMM; + prop[propIndex++] = heightMM; prop[propIndex++] = CGDDGetModeRefreshRate(mode); prop[propIndex++] = ccwRot; prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL @@ -421,9 +473,10 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacScreen_setScreenMod CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); CFArrayRef availableModes = CGDisplayAvailableModes(display); +#ifdef VERBOSE_ON CFIndex numberOfAvailableModes = CFArrayGetCount(availableModes); CFIndex numberOfAvailableModesRots = ROTMODES_PER_REALMODE * numberOfAvailableModes; - +#endif CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, mode_idx / ROTMODES_PER_REALMODE); // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef @@ -525,7 +578,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_createWindow0 styleMask: (NSUInteger) styleMask backing: (NSBackingStoreType) bufferingType defer: NO - screen: myScreen]; + screen: myScreen + isFullscreenWindow: fullscreen]; [myWindow setReleasedWhenClosed: YES]; // default [myWindow setPreservesContentDuringLiveResize: NO]; @@ -645,6 +699,19 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_close0 DBG_PRINT( "windowClose.0 - %p,%d view %p,%d, parent %p\n", mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin); + if(NULL!=mView) { + jobject javaWindowObject = [mView getJavaWindowObject]; + if( false == [mView getDestroyNotifySent] ) { + [mView setDestroyNotifySent: true]; + } else if(NULL!=javaWindowObject) { + DBG_PRINT( "windowClose.Error: javaWindowObject not NULL (%p), destroyNotifySent==true\n", javaWindowObject); + } + if(NULL!=javaWindowObject) { + (*env)->DeleteGlobalRef(env, javaWindowObject); + [mView setJavaWindowObject: NULL]; + } + } + NS_DURING if(NULL!=mView) { // Available >= 10.5 - Makes the menubar disapear @@ -670,7 +737,8 @@ NS_ENDHANDLER // This probably happens b/c it sends events to the main loop // but our resources are gone ?! // However, issuing a simple release seems to work quite well. - [mWin release]; + // [mWin release]; + [mWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO]; DBG_PRINT( "windowClose.X - %p,%d view %p,%d, parent %p\n", mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin); @@ -991,10 +1059,11 @@ JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_MacWindow_getLocationOn * Signature: (JZ)Z */ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setPointerVisible0 - (JNIEnv *env, jclass clazz, jlong window, jboolean mouseVisible) + (JNIEnv *env, jclass clazz, jlong window, jboolean hasFocus, jboolean mouseVisible) { NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); - [mWin setMouseVisible: ( JNI_TRUE == mouseVisible ) ? YES : NO]; + [mWin setMouseVisible: ( JNI_TRUE == mouseVisible ) ? YES : NO + hasFocus: ( JNI_TRUE == hasFocus ) ? YES : NO]; return JNI_TRUE; } diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index 3ba89de1e..f576f75f7 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -104,6 +104,7 @@ @interface NewtMacWindow : NSWindow #endif { + BOOL isFullscreenWindow; BOOL mouseConfined; BOOL mouseVisible; BOOL mouseInside; @@ -119,7 +120,8 @@ styleMask: (NSUInteger) windowStyle backing: (NSBackingStoreType) bufferingType defer: (BOOL) deferCreation - screen:(NSScreen *)screen; + screen:(NSScreen *)screen + isFullscreenWindow:(BOOL)isfs; - (void) updateInsets: (JNIEnv*) env; - (void) attachToParent: (NSWindow*) parent; @@ -130,17 +132,36 @@ - (NSPoint) getLocationOnScreen: (NSPoint) p; - (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p; +- (BOOL) isMouseInside; - (void) cursorHide:(BOOL)v; -- (void) setMouseVisible:(BOOL)v; +- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus; - (void) setMouseConfined:(BOOL)v; - (void) setMousePosition:(NSPoint)p; +- (void) sendKeyEvent: (NSEvent*) event eventType: (jint) evType; +- (void) sendMouseEvent: (NSEvent*) event eventType: (jint) evType; +- (void) focusChanged: (BOOL) gained; + - (BOOL) becomeFirstResponder; - (BOOL) resignFirstResponder; +- (BOOL) canBecomeKeyWindow; - (void) becomeKeyWindow; - (void) resignKeyWindow; - (void) windowDidBecomeKey: (NSNotification *) notification; - (void) windowDidResignKey: (NSNotification *) notification; -- (void) focusChanged: (BOOL) gained; +- (void) keyDown: (NSEvent*) theEvent; +- (void) keyUp: (NSEvent*) theEvent; +- (void) mouseEntered: (NSEvent*) theEvent; +- (void) mouseExited: (NSEvent*) theEvent; +- (void) mouseMoved: (NSEvent*) theEvent; +- (void) scrollWheel: (NSEvent*) theEvent; +- (void) mouseDown: (NSEvent*) theEvent; +- (void) mouseDragged: (NSEvent*) theEvent; +- (void) mouseUp: (NSEvent*) theEvent; +- (void) rightMouseDown: (NSEvent*) theEvent; +- (void) rightMouseDragged: (NSEvent*) theEvent; +- (void) rightMouseUp: (NSEvent*) theEvent; +- (void) otherMouseDown: (NSEvent*) theEvent; +- (void) otherMouseUp: (NSEvent*) theEvent; @end diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index ce41673c4..402389e71 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -238,10 +238,14 @@ static jmethodID windowRepaintID = NULL; DBG_PRINT("*************** dirtyRect: %p %lf/%lf %lfx%lf\n", javaWindowObject, dirtyRect.origin.x, dirtyRect.origin.y, dirtyRect.size.width, dirtyRect.size.height); + if(NULL==javaWindowObject) { + DBG_PRINT("drawRect: null javaWindowObject\n"); + return; + } int shallBeDetached = 0; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); if(NULL==env) { - DBG_PRINT("viewDidHide: null JNIEnv\n"); + DBG_PRINT("drawRect: null JNIEnv\n"); return; } @@ -258,6 +262,10 @@ static jmethodID windowRepaintID = NULL; - (void) viewDidHide { + if(NULL==javaWindowObject) { + DBG_PRINT("viewDidHide: null javaWindowObject\n"); + return; + } int shallBeDetached = 0; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); if(NULL==env) { @@ -276,10 +284,14 @@ static jmethodID windowRepaintID = NULL; - (void) viewDidUnhide { + if(NULL==javaWindowObject) { + DBG_PRINT("viewDidUnhide: null javaWindowObject\n"); + return; + } int shallBeDetached = 0; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); if(NULL==env) { - DBG_PRINT("viewDidHide: null JNIEnv\n"); + DBG_PRINT("viewDidUnhide: null JNIEnv\n"); return; } @@ -328,12 +340,14 @@ static jmethodID windowRepaintID = NULL; backing: (NSBackingStoreType) bufferingType defer: (BOOL) deferCreation screen:(NSScreen *)screen + isFullscreenWindow:(BOOL)isfs { id res = [super initWithContentRect: contentRect styleMask: windowStyle backing: bufferingType defer: deferCreation screen: screen]; + isFullscreenWindow = isfs; // Why is this necessary? Without it we don't get any of the // delegate methods like resizing and window movement. [self setDelegate: self]; @@ -389,8 +403,10 @@ static jmethodID windowRepaintID = NULL; { DBG_PRINT( "detachFromParent.1\n"); [self setParentWindow: nil]; - DBG_PRINT( "detachFromParent.2\n"); - [parent removeChildWindow: self]; + if(NULL != parent) { + DBG_PRINT( "detachFromParent.2\n"); + [parent removeChildWindow: self]; + } DBG_PRINT( "detachFromParent.X\n"); } @@ -463,15 +479,60 @@ static jmethodID windowRepaintID = NULL; // NSRect rS = [win convertRectFromScreen: r]; // 10.7 NSPoint oS = [self convertScreenToBase: r.origin]; oS.y = viewFrame.size.height - oS.y; // y-flip - return oS; } -- (BOOL) canBecomeKeyWindow +- (BOOL) isMouseInside { - // Even if the window is borderless, we still want it to be able - // to become the key window to receive keyboard events - return YES; + NSView* view = [self contentView]; + NSRect viewFrame = [view frame]; + NSPoint l1 = [NSEvent mouseLocation]; + NSPoint l0 = [self screenPos2NewtClientWinPos: l1]; + return viewFrame.origin.x <= l0.x && l0.x < (viewFrame.origin.x+viewFrame.size.width) && + viewFrame.origin.y <= l0.y && l0.y < (viewFrame.origin.y+viewFrame.size.height) ; +} + +- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus +{ + mouseVisible = v; + mouseInside = [self isMouseInside]; + DBG_PRINT( "setMouseVisible: confined %d, visible %d (current: %d), mouseInside %d, hasFocus %d\n", + mouseConfined, mouseVisible, !cursorIsHidden, mouseInside, focus); + if(YES == focus && YES == mouseInside) { + [self cursorHide: !mouseVisible]; + } +} + +- (void) cursorHide:(BOOL)v +{ + DBG_PRINT( "cursorHide: %d -> %d\n", cursorIsHidden, v); + if(v) { + if(!cursorIsHidden) { + [NSCursor hide]; + cursorIsHidden = YES; + } + } else { + if(cursorIsHidden) { + [NSCursor unhide]; + cursorIsHidden = NO; + } + } +} + +- (void) setMouseConfined:(BOOL)v +{ + mouseConfined = v; + DBG_PRINT( "setMouseConfined: confined %d, visible %d\n", mouseConfined, mouseVisible); +} + +- (void) setMousePosition:(NSPoint)p +{ + NSScreen* screen = [self screen]; + NSRect screenRect = [screen frame]; + + CGPoint pt = { p.x, screenRect.size.height - p.y }; // y-flip (CG is top-left origin) + CGEventRef ev = CGEventCreateMouseEvent (NULL, kCGEventMouseMoved, pt, kCGMouseButtonLeft); + CGEventPost (kCGHIDEventTap, ev); } static jint mods2JavaMods(NSUInteger mods) @@ -538,17 +599,6 @@ static jint mods2JavaMods(NSUInteger mods) } } -- (void) keyDown: (NSEvent*) theEvent -{ - [self sendKeyEvent: theEvent eventType: EVENT_KEY_PRESSED]; -} - -- (void) keyUp: (NSEvent*) theEvent -{ - [self sendKeyEvent: theEvent eventType: EVENT_KEY_RELEASED]; - [self sendKeyEvent: theEvent eventType: EVENT_KEY_TYPED]; -} - - (void) sendMouseEvent: (NSEvent*) event eventType: (jint) evType { NSView* nsview = [self contentView]; @@ -624,53 +674,100 @@ static jint mods2JavaMods(NSUInteger mods) } } -- (void) setMouseVisible:(BOOL)v +- (void) focusChanged: (BOOL) gained { - mouseVisible = v; - DBG_PRINT( "setMouseVisible: confined %d, visible %d\n", mouseConfined, mouseVisible); - if(YES == mouseInside) { - [self cursorHide: !mouseVisible]; + DBG_PRINT( "focusChanged: gained %d\n", gained); + NSView* nsview = [self contentView]; + if( ! [nsview isMemberOfClass:[NewtView class]] ) { + return; + } + NewtView* view = (NewtView *) nsview; + jobject javaWindowObject = [view getJavaWindowObject]; + if (javaWindowObject == NULL) { + DBG_PRINT("focusChanged: null javaWindowObject\n"); + return; + } + int shallBeDetached = 0; + JavaVM *jvmHandle = [view getJVMHandle]; + JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); + if(NULL==env) { + DBG_PRINT("focusChanged: null JNIEnv\n"); + return; + } + + (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE); + + if (shallBeDetached) { + (*jvmHandle)->DetachCurrentThread(jvmHandle); } } -- (void) cursorHide:(BOOL)v +- (BOOL) becomeFirstResponder { - if(v) { - if(!cursorIsHidden) { - [NSCursor hide]; - cursorIsHidden = YES; - } - } else { - if(cursorIsHidden) { - [NSCursor unhide]; - cursorIsHidden = NO; - } + DBG_PRINT( "*************** becomeFirstResponder\n"); + return [super becomeFirstResponder]; +} + +- (BOOL) resignFirstResponder +{ + DBG_PRINT( "*************** resignFirstResponder\n"); + return [super resignFirstResponder]; +} + +- (BOOL) canBecomeKeyWindow +{ + // Even if the window is borderless, we still want it to be able + // to become the key window to receive keyboard events + return YES; +} + +- (void) becomeKeyWindow +{ + DBG_PRINT( "*************** becomeKeyWindow\n"); + [super becomeKeyWindow]; +} + +- (void) resignKeyWindow +{ + DBG_PRINT( "*************** resignKeyWindow: isFullscreen %d\n", (int)isFullscreenWindow); + if(!isFullscreenWindow) { + [super resignKeyWindow]; } } -- (void) setMouseConfined:(BOOL)v +- (void) windowDidBecomeKey: (NSNotification *) notification { - mouseConfined = v; - DBG_PRINT( "setMouseConfined: confined %d, visible %d\n", mouseConfined, mouseVisible); + DBG_PRINT( "*************** windowDidBecomeKey\n"); + mouseInside = [self isMouseInside]; + if(YES == mouseInside) { + [self cursorHide: !mouseVisible]; + } + [self focusChanged: YES]; } -- (void) setMousePosition:(NSPoint)p +- (void) windowDidResignKey: (NSNotification *) notification { - NSScreen* screen = [self screen]; - NSRect screenRect = [screen frame]; + DBG_PRINT( "*************** windowDidResignKey\n"); + // Implicit mouse exit by OS X + [self focusChanged: NO]; +} - CGPoint pt = { p.x, screenRect.size.height - p.y }; // y-flip (CG is top-left origin) - CGEventRef ev = CGEventCreateMouseEvent (NULL, kCGEventMouseMoved, pt, kCGMouseButtonLeft); - CGEventPost (kCGHIDEventTap, ev); - NSPoint l0 = [NSEvent mouseLocation]; - [self screenPos2NewtClientWinPos: l0]; +- (void) keyDown: (NSEvent*) theEvent +{ + [self sendKeyEvent: theEvent eventType: EVENT_KEY_PRESSED]; +} + +- (void) keyUp: (NSEvent*) theEvent +{ + [self sendKeyEvent: theEvent eventType: EVENT_KEY_RELEASED]; + [self sendKeyEvent: theEvent eventType: EVENT_KEY_TYPED]; } - (void) mouseEntered: (NSEvent*) theEvent { DBG_PRINT( "mouseEntered: confined %d, visible %d\n", mouseConfined, mouseVisible); mouseInside = YES; - [self setMouseVisible: mouseVisible]; + [self cursorHide: !mouseVisible]; if(NO == mouseConfined) { [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_ENTERED]; } @@ -859,68 +956,4 @@ static jint mods2JavaMods(NSUInteger mods) [pool release]; } -- (BOOL) becomeFirstResponder -{ - DBG_PRINT( "*************** becomeFirstResponder\n"); - return [super becomeFirstResponder]; -} - -- (BOOL) resignFirstResponder -{ - DBG_PRINT( "*************** resignFirstResponder\n"); - return [super resignFirstResponder]; -} - -- (void) becomeKeyWindow -{ - DBG_PRINT( "*************** becomeKeyWindow\n"); - [super becomeKeyWindow]; -} - -- (void) resignKeyWindow -{ - DBG_PRINT( "*************** resignKeyWindow\n"); - [super resignKeyWindow]; -} - -- (void) windowDidBecomeKey: (NSNotification *) notification -{ - DBG_PRINT( "*************** windowDidBecomeKey\n"); - [self focusChanged: YES]; -} - -- (void) windowDidResignKey: (NSNotification *) notification -{ - DBG_PRINT( "*************** windowDidResignKey\n"); - [self focusChanged: NO]; -} - -- (void) focusChanged: (BOOL) gained -{ - DBG_PRINT( "focusChanged: gained %d\n", gained); - NSView* nsview = [self contentView]; - if( ! [nsview isMemberOfClass:[NewtView class]] ) { - return; - } - NewtView* view = (NewtView *) nsview; - jobject javaWindowObject = [view getJavaWindowObject]; - if (javaWindowObject == NULL) { - DBG_PRINT("focusChanged: null javaWindowObject\n"); - return; - } - int shallBeDetached = 0; - JavaVM *jvmHandle = [view getJVMHandle]; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); - if(NULL==env) { - DBG_PRINT("focusChanged: null JNIEnv\n"); - return; - } - - (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE); - - if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } -} - @end diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 0a7e1cf77..6953140c0 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -169,16 +169,21 @@ static Window NewtWindows_getParent (Display *dpy, Window w) { } return 0; // Error } -static Status NewtWindows_getParentPosition (Display *dpy, Window w, int *x_return, int *y_return) { +static void NewtWindows_setCWAbove(Display *dpy, Window w) { + XWindowChanges xwc; + 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; unsigned int width_return, height_return; unsigned int border_width_return; unsigned int depth_return; - Window parent = NewtWindows_getParent(dpy, w); - if(0 != parent) { - XGetGeometry(dpy, parent, &root_return, x_return, y_return, &width_return, - &height_return, &border_width_return, &depth_return); + if(0 != XGetGeometry(dpy, w, &root_return, x_return, y_return, &width_return, + &height_return, &border_width_return, &depth_return)) { return 1; // OK } return 0; // Error @@ -224,52 +229,6 @@ static Status NewtWindows_getFrameExtends(Display *dpy, Window window, int *left return 1; // Ok } -Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Window window, int *left, int *right, int *top, int *bottom) { - if(0 != NewtWindows_getFrameExtends(dpy, window, 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, jwindow, insetsChangedID, JNI_FALSE, *left, *right, *top, *bottom); - return 1; // OK - } else if(0 != NewtWindows_getParentPosition (dpy, window, left, top)) { - *right = *left; *bottom = *left; - DBG_PRINT( "NewtWindows_updateInsets: insets by parent position [ l %d, r %d, t %d, b %d ]\n", - *left, *right, *top, *bottom); - (*env)->CallVoidMethod(env, jwindow, insetsChangedID, JNI_FALSE, *left, *right, *top, *bottom); - return 1; // OK - } - return 0; // Error -} - -static void NewtWindows_setCWAbove(Display *dpy, Window w) { - XWindowChanges xwc; - memset(&xwc, 0, sizeof(XWindowChanges)); - xwc.stack_mode = Above; - XConfigureWindow(dpy, w, CWStackMode, &xwc); - XSync(dpy, False); -} - -static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, Window w, jboolean force) { - XWindowAttributes xwa; - Window focus_return; - int revert_to_return; - - XGetInputFocus(dpy, &focus_return, &revert_to_return); - DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d, hasFocus %d\n", dpy, (void*)w, force, focus_return==w); - - if( JNI_TRUE==force || focus_return!=w) { - DBG_PRINT( "X11: XRaiseWindow dpy %p, win %p\n", dpy, (void*)w); - XRaiseWindow(dpy, w); - NewtWindows_setCWAbove(dpy, w); - // Avoid 'BadMatch' errors from XSetInputFocus, ie if window is not viewable - XGetWindowAttributes(dpy, w, &xwa); - if(xwa.map_state == IsViewable) { - DBG_PRINT( "X11: XSetInputFocus dpy %p,win %pd\n", dpy, (void*)w); - XSetInputFocus(dpy, w, RevertToParent, CurrentTime); - } - } - DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d - FIN\n", dpy, (void*)w, force); - XSync(dpy, False); -} #define DECOR_USE_MWM 1 // works for known WMs // #define DECOR_USE_EWMH 1 // haven't seen this to work (NORMAL->POPUP, never gets undecorated) @@ -307,6 +266,29 @@ static void NewtWindows_setDecorations (Display *dpy, Window w, Bool decorated) XSync(dpy, False); } +static Bool NewtWindows_hasDecorations (Display *dpy, Window w) { + Bool decor = False; + +#ifdef DECOR_USE_MWM + Atom _MOTIF_WM_HINTS = XInternAtom( dpy, "_MOTIF_WM_HINTS", False ); + unsigned char *wm_data; + Atom wm_type; + int wm_format; + unsigned long wm_nitems, wm_bytes_after; + + if( Success == XGetWindowProperty(dpy, w, _MOTIF_WM_HINTS, 0, PROP_MWM_HINTS_ELEMENTS, False, AnyPropertyType, + &wm_type, &wm_format, &wm_nitems, &wm_bytes_after, &wm_data) ) { + if(wm_type != None) { + // unsigned long mwmhints[PROP_MWM_HINTS_ELEMENTS] = { MWM_HINTS_DECORATIONS, 0, decorated, 0, 0 }; // flags, functions, decorations, input_mode, status + unsigned long *hints = (unsigned long *) wm_data; + decor = ( 0 != (hints[0] & MWM_HINTS_DECORATIONS) ) && ( 0 != hints[2] ); + } + } +#endif + + return decor; +} + static void NewtWindows_setNormalWindowEWMH (Display *dpy, Window w) { Atom _NET_WM_WINDOW_TYPE = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE", False ); Atom types[1]={0}; @@ -430,6 +412,56 @@ static Bool NewtWindows_setFullscreenEWMH (Display *dpy, Window root, Window w, return res; } + +Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Window window, int *left, int *right, int *top, int *bottom) { + if(0 != NewtWindows_getFrameExtends(dpy, window, 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, jwindow, insetsChangedID, JNI_FALSE, *left, *right, *top, *bottom); + return 1; // OK + } + + Bool hasDecor = NewtWindows_hasDecorations (dpy, window); + if(hasDecor) { + // The following logic only works if window is top-level _and_ the WM + // has 'decorated' our client window w/ another parent window _within_ the actual 'framed' window. + Window parent = NewtWindows_getParent(dpy, 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, jwindow, insetsChangedID, JNI_FALSE, *left, *right, *top, *bottom); + return 1; // OK + } + } + DBG_PRINT( "NewtWindows_updateInsets: cannot determine insets - hasDecor %d\n", hasDecor); + return 0; // Error +} + +static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, Window w, jboolean force) { + XWindowAttributes xwa; + 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*)w, force, focus_return==w); + + if( JNI_TRUE==force || focus_return!=w) { + DBG_PRINT( "X11: XRaiseWindow dpy %p, win %p\n", dpy, (void*)w); + XRaiseWindow(dpy, w); + NewtWindows_setCWAbove(dpy, w); + // Avoid 'BadMatch' errors from XSetInputFocus, ie if window is not viewable + XGetWindowAttributes(dpy, w, &xwa); + DBG_PRINT( "X11: XSetInputFocus dpy %p,win %p, isViewable %d\n", dpy, (void*)w, (xwa.map_state == IsViewable)); + if(xwa.map_state == IsViewable) { + XSetInputFocus(dpy, w, RevertToParent, CurrentTime); + } + } + DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d - FIN\n", dpy, (void*)w, force); + XSync(dpy, False); +} + /** * Window */ @@ -601,11 +633,13 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 // we can pre-map the window here to be able to gather the insets and position. { XEvent event; - int left, right, top, bottom; + int left=0, right=0, top=0, bottom=0; XMapWindow(dpy, window); XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) window ); // wait to get proper insets values + XSync(dpy, False); + // send insets before visibility, allowing java code a proper sync point! NewtWindows_updateInsets(env, jwindow, dpy, window, &left, &right, &top, &bottom); (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); @@ -683,6 +717,15 @@ static Bool WaitForReparentNotify( Display *dpy, XEvent *event, XPointer arg ) { } #endif +/** + * KDE cause lost input focus in fullscreen mode. + * Using 'XGrabKeyboard(..)' would prevent the loss, + * but also would disable WM task switcher etc. + * + * #define FS_GRAB_KEYBOARD 1 + * + */ + /* * Class: jogamp_newt_driver_x11_X11Window * Method: reconfigureWindow0 @@ -730,6 +773,17 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 Bool enable = TST_FLAG_CHANGE_FULLSCREEN(flags) ? TST_FLAG_IS_FULLSCREEN(flags) : TST_FLAG_IS_ALWAYSONTOP(flags) ; if( NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, enable) ) { NewtDisplay_displayDispatchErrorHandlerEnable(0, env); + #ifdef FS_GRAB_KEYBOARD + if(TST_FLAG_CHANGE_FULLSCREEN(flags)) { + if(TST_FLAG_IS_FULLSCREEN(flags)) { + XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime); + } else { + XUngrabKeyboard(dpy, CurrentTime); + } + } else if(TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags)) { + XUngrabKeyboard(dpy, CurrentTime); + } + #endif return; } } @@ -744,6 +798,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) || ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // FS off NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, False); + #ifdef FS_GRAB_KEYBOARD + XUngrabKeyboard(dpy, CurrentTime); + #endif } if( TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_HAS_PARENT(flags) ) { @@ -791,6 +848,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) || ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // FS on NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, True); + #ifdef FS_GRAB_KEYBOARD + if(TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags)) { + XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime); + } + #endif } NewtDisplay_displayDispatchErrorHandlerEnable(0, env); |