diff options
author | Sven Gothel <[email protected]> | 2012-01-18 03:42:52 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-01-18 03:42:52 +0100 |
commit | bc933c6e18a68d9cd94b0349fb516852ac0c7457 (patch) | |
tree | 17a1ff55ece6b7d124c9d34c569052306ad6675f /src | |
parent | d8bbddaea08bd6ae75bc5255ab33cbf15cf3a7be (diff) |
NEWT/OSX: Cleanup 'javaWindowObject' @ window-close & avoid NPE; Disable lostFocus (resignKeyWindow) when in fullscreen mode; Ignore invalid key release/type events.
- Cleanup 'javaWindowObject' @ window-close & avoid NPE
Ensure that the direct window.close() impl. removes the global reference
and that all use cases check for NULL pointer.
- Disable lostFocus (resignKeyWindow) when in fullscreen mode
Similar to the X11 KDE bug, OS X delivers a lostFocus event
which we prevent from being processed in fullscreen mode.
- Ignore invalid key release/type events
In case of offscreen/onscreen switching (fullscreen/reparenting) via destroy/create,
the still pressed key would be send to the new window and repeat the action (key typed).
State validation discards the double processing.
Diffstat (limited to 'src')
-rw-r--r-- | src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java | 44 | ||||
-rw-r--r-- | src/newt/native/MacWindow.m | 16 | ||||
-rw-r--r-- | src/newt/native/NewtMacWindow.h | 4 | ||||
-rw-r--r-- | src/newt/native/NewtMacWindow.m | 30 |
4 files changed, 78 insertions, 16 deletions
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java index f879ad86c..32e76ec00 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java @@ -296,10 +296,13 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl // Note that we send the key char for the key code on this // platform -- we do not get any useful key codes out of the system final int keyCode2 = MacKeyUtil.validateKeyCode(keyCode, keyChar); - if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.sendKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)); - // only deliver keyChar on key Typed events, harmonizing platform behavior - keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1; - super.sendKeyEvent(eventType, modifiers, keyCode2, keyChar); + final boolean valid = validateKeyEvent(eventType, modifiers, keyCode); + if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.sendKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)+", valid "+valid); + if(valid) { + // only deliver keyChar on key Typed events, harmonizing platform behavior + keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1; + super.sendKeyEvent(eventType, modifiers, keyCode2, keyChar); + } } @Override @@ -307,12 +310,37 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl // Note that we send the key char for the key code on this // platform -- we do not get any useful key codes out of the system final int keyCode2 = MacKeyUtil.validateKeyCode(keyCode, keyChar); - if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.enqueueKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)); - // only deliver keyChar on key Typed events, harmonizing platform behavior - keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1; - super.enqueueKeyEvent(wait, eventType, modifiers, keyCode2, keyChar); + final boolean valid = validateKeyEvent(eventType, modifiers, keyCode); + if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.enqueueKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)+", valid "+valid); + if(valid) { + // only deliver keyChar on key Typed events, harmonizing platform behavior + keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1; + super.enqueueKeyEvent(wait, eventType, modifiers, keyCode2, keyChar); + } } + private int keyDownModifiers = 0; + private int keyDownCode = 0; + + private boolean validateKeyEvent(int eventType, int modifiers, int keyCode) { + switch(eventType) { + case KeyEvent.EVENT_KEY_PRESSED: + keyDownModifiers = modifiers; + keyDownCode = keyCode; + return true; + case KeyEvent.EVENT_KEY_RELEASED: + return keyDownModifiers == modifiers && keyDownCode == keyCode; + case KeyEvent.EVENT_KEY_TYPED: + final boolean matchKeyDown = keyDownModifiers == modifiers && keyDownCode == keyCode; + keyDownModifiers = 0; + keyDownCode = 0; + return matchKeyDown; + default: + throw new NativeWindowException("Unexpected key event type " + eventType); + } + } + + //---------------------------------------------------------------------- // Internals only // diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 5470be5ae..015295931 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -578,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]; @@ -698,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 diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index 24a7cd632..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; diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 539672f2b..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"); } @@ -713,8 +729,10 @@ static jint mods2JavaMods(NSUInteger mods) - (void) resignKeyWindow { - DBG_PRINT( "*************** resignKeyWindow\n"); - [super resignKeyWindow]; + DBG_PRINT( "*************** resignKeyWindow: isFullscreen %d\n", (int)isFullscreenWindow); + if(!isFullscreenWindow) { + [super resignKeyWindow]; + } } - (void) windowDidBecomeKey: (NSNotification *) notification |