summaryrefslogtreecommitdiffstats
path: root/src/newt/native
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt/native')
-rw-r--r--src/newt/native/MacWindow.m89
-rw-r--r--src/newt/native/NewtMacWindow.h27
-rw-r--r--src/newt/native/NewtMacWindow.m257
-rw-r--r--src/newt/native/X11Window.c166
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);