aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2011-10-16 07:30:09 +0200
committerSven Gothel <[email protected]>2011-10-16 07:30:09 +0200
commitcac4e2e3f2d6c69a207077fd5e0ebec803afb6b0 (patch)
treef9e47f3ba7ac704f8c14bfe83f64122b883af49c
parentaf332515f76a4017e7a52ebec920e794a5398db4 (diff)
NEWT/OSX: Proper impl. of NEWT's focus management (fixes NEWT/AWT focus behavior/tests)
- Old code was just requesting the focus and made the window upfront and notifying a gained focus to WindowImpl. (hack) - Using proper requestFocus impl. issuing focusAction() and utilizing native focus gained/lost messages. This distinguish between 'makeKey' and 'orderFront'. Also requesting and accepting (view) first responder role, which is a precursor to proper gained/lost focus handling on OSX. - NEWTCanvasAWT: Adding 'steal AWT focus': +++ void requestFocus() { super.requestFocus(); // AWT < steal AWT focus > NEWTChild.requestFocus() } +++ Helps make the focus traversal between NEWT/AWT more reliable. Happend on OSX that AWT (NewtCanvasAWT instance) didn't release the focus after NEWT child gained the same. We are not able to use the 'focusAction()' here (disabled in this code path) due to AWT-EDT blocking and recursive focus changes. The latter is also intendend to request the AWT focus first .. - AWT/NEWT focus test 01 passes on OSX
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java4
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java16
-rw-r--r--src/newt/native/MacWindow.m54
-rw-r--r--src/newt/native/NewtMacWindow.h13
-rw-r--r--src/newt/native/NewtMacWindow.m43
5 files changed, 96 insertions, 34 deletions
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
index b2d97c7d5..47977610f 100644
--- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
+++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
@@ -307,6 +307,10 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
final void requestFocusNEWTChild() {
if(null!=newtChild) {
newtChild.setFocusAction(null);
+ // FIXME: Experimental 'steal AWT focus',
+ // since we have to disable the focus action due to recursion and AWT EDT blocking.
+ KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ kfm.clearGlobalFocusOwner();
newtChild.requestFocus();
newtChild.setFocusAction(focusAction);
}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java
index 0bb0b6b13..8886cf630 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java
@@ -181,8 +181,8 @@ public class MacWindow extends WindowImpl {
setTitle0(getWindowHandle(), title);
}
- protected void requestFocusImpl(boolean reparented) {
- makeKeyAndOrderFront0(getWindowHandle());
+ protected void requestFocusImpl(boolean force) {
+ requestFocus0(getWindowHandle(), force);
}
protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
@@ -196,17 +196,14 @@ public class MacWindow extends WindowImpl {
if( getWindowHandle() == 0 ) {
if( 0 != ( FLAG_IS_VISIBLE & flags) ) {
createWindow(false, pS, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags));
- makeKeyAndOrderFront0(getWindowHandle());
// no native event ..
visibleChanged(true, true);
- focusChanged(true, true);
} /* else { ?? } */
} else {
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 == ( FLAG_IS_VISIBLE & flags) ) {
orderOut0(getWindowHandle());
// no native event ..
visibleChanged(true, false);
- focusChanged(true, false);
}
if( 0 != ( FLAG_CHANGE_DECORATION & flags) ||
0 != ( FLAG_CHANGE_PARENTING & flags) ||
@@ -225,10 +222,9 @@ public class MacWindow extends WindowImpl {
sizeChanged(true, width, height, false); // incl. validation (incl. repositioning)
}
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 != ( FLAG_IS_VISIBLE & flags) ) {
- makeKeyAndOrderFront0(getWindowHandle());
+ orderFront0(getWindowHandle());
// no native event ..
- visibleChanged(true, true);
- focusChanged(true, true);
+ visibleChanged(true, true);
}
setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags));
}
@@ -447,10 +443,10 @@ public class MacWindow extends WindowImpl {
boolean opaque, boolean fullscreen, int windowStyle,
int backingStoreType,
int screen_idx, long view);
- private native void makeKeyAndOrderFront0(long window);
- private native void makeKey0(long window);
+ private native void requestFocus0(long window, boolean force);
/** in case of a child window, it actually only issues orderBack(..) */
private native void orderOut0(long window);
+ private native void orderFront0(long window);
private native void close0(long window);
private native void setTitle0(long window, String title);
private native long contentView0(long window);
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m
index fa555d119..871370b0d 100644
--- a/src/newt/native/MacWindow.m
+++ b/src/newt/native/MacWindow.m
@@ -48,6 +48,7 @@ static const char * const ClazzAnyCstrName = "<init>";
static const char * const ClazzNamePointCstrSignature = "(II)V";
static jclass pointClz = NULL;
static jmethodID pointCstr = NULL;
+static jmethodID focusActionID = NULL;
static NSString* jstringToNSString(JNIEnv* env, jstring jstr)
{
@@ -243,6 +244,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_initIDs0
ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
}
+ focusActionID = (*env)->GetMethodID(env, clazz, "focusAction", "()Z");
+ if(NULL==focusActionID) {
+ NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch method focusAction()Z");
+ }
+
// Need this when debugging, as it is necessary to attach gdb to
// the running java process -- "gdb java" doesn't work
// printf("Going to sleep for 10 seconds\n");
@@ -336,8 +342,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_createWindow0
// Immediately re-position the window based on an upper-left coordinate system
setFrameTopLeftPoint(parentWindow, myWindow, x, y);
- // [myWindow makeKeyAndOrderFront: myWindow];
- [myWindow performSelectorOnMainThread:@selector(makeKeyAndOrderFront:) withObject:myWindow waitUntilDone:YES];
+ [myWindow orderFront: myWindow];
NS_DURING
// Available >= 10.5 - Makes the menubar disapear
@@ -361,42 +366,50 @@ NS_ENDHANDLER
/*
* Class: jogamp_newt_driver_macosx_MacWindow
- * Method: makeKeyAndOrderFront
- * Signature: (J)V
+ * Method: requestFocus0
+ * Signature: (JZ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_makeKeyAndOrderFront0
- (JNIEnv *env, jobject unused, jlong window)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0
+ (JNIEnv *env, jobject window, jlong w, jboolean force)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSWindow* win = (NSWindow*) ((intptr_t) window);
-
- DBG_PRINT( "makeKeyAndOrderFront0 - window: %p (START)\n", win);
-
- [win performSelectorOnMainThread:@selector(makeKeyAndOrderFront:) withObject:win waitUntilDone:YES];
- // [win makeKeyAndOrderFront: win];
+ NSWindow* win = (NSWindow*) ((intptr_t) w);
+ BOOL hasFocus = [win isKeyWindow];
+
+ DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", win, force, hasFocus);
+
+ if( JNI_TRUE==force || !hasFocus ) {
+ if( JNI_TRUE==force || JNI_FALSE == (*env)->CallBooleanMethod(env, window, focusActionID) ) {
+ DBG_PRINT( "makeKeyWindow win %p\n", win);
+ // [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES];
+ // [win performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES];
+ [win orderFrontRegardless];
+ [win makeKeyWindow];
+ [win makeFirstResponder: nil];
+ }
+ }
- DBG_PRINT( "makeKeyAndOrderFront0 - window: %p (END)\n", win);
+ DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", win, force);
[pool release];
}
/*
* Class: jogamp_newt_driver_macosx_MacWindow
- * Method: makeKey
+ * Method: orderFront0
* Signature: (J)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_makeKey0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderFront0
(JNIEnv *env, jobject unused, jlong window)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* win = (NSWindow*) ((intptr_t) window);
- DBG_PRINT( "makeKey0 - window: %p (START)\n", win);
+ DBG_PRINT( "orderFront0 - window: %p (START)\n", win);
- [win performSelectorOnMainThread:@selector(makeKeyWindow:) withObject:nil waitUntilDone:YES];
- // [win makeKeyWindow];
+ [win orderFrontRegardless];
- DBG_PRINT( "makeKey0 - window: %p (END)\n", win);
+ DBG_PRINT( "orderFront0 - window: %p (END)\n", win);
[pool release];
}
@@ -415,7 +428,6 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderOut0
DBG_PRINT( "orderOut0 - window: (parent %p) %p (START)\n", pWin, mWin);
- // [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO];
if(NULL == pWin) {
[mWin orderOut: mWin];
} else {
@@ -458,7 +470,6 @@ NS_ENDHANDLER
}
[mWin orderOut: mWin];
- // [mWin performSelectorOnMainThread:@selector(close:) withObject:nil waitUntilDone:NO];
[mWin close]; // performs release!
DBG_PRINT( "*************** windowClose.X: %p (parent %p)\n", mWin, pWin);
@@ -481,7 +492,6 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setTitle0
NSString* str = jstringToNSString(env, title);
[str autorelease];
- // [win performSelectorOnMainThread:@selector(setTitle:) withObject:str waitUntilDone:NO];
[win setTitle: str];
DBG_PRINT( "setTitle0 - window: %p (END)\n", win);
diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h
index 532eba6b4..648b68275 100644
--- a/src/newt/native/NewtMacWindow.h
+++ b/src/newt/native/NewtMacWindow.h
@@ -80,6 +80,8 @@
- (void) rightMouseDown: (NSEvent*) theEvent;
- (void) resetCursorRects;
+- (BOOL) acceptsFirstResponder;
+
@end
#if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
@@ -100,10 +102,8 @@
+ (BOOL) initNatives: (JNIEnv*) env forClass: (jobject) clazz;
- (NSPoint) newtScreenWinPos2OSXScreenPos: (NSPoint) p;
-
- (NSPoint) newtClientWinPos2OSXScreenPos: (NSPoint) p;
- (NSPoint) getLocationOnScreen: (NSPoint) p;
-
- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p;
- (void) cursorHide:(BOOL)v;
@@ -113,6 +113,15 @@
- (void) updateInsets: (JNIEnv*) env;
+- (BOOL) becomeFirstResponder;
+- (BOOL) resignFirstResponder;
+- (void) becomeKeyWindow;
+- (void) windowDidBecomeKey: (NSNotification *) notification;
+- (void) sendFocusGained;
+- (void) resignKeyWindow;
+- (void) windowDidResignKey: (NSNotification *) notification;
+- (void) sendFocusLost;
+
- (id) initWithContentRect: (NSRect) contentRect
styleMask: (NSUInteger) windowStyle
backing: (NSBackingStoreType) bufferingType
diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m
index d4e2c2b6d..bb7fddb60 100644
--- a/src/newt/native/NewtMacWindow.m
+++ b/src/newt/native/NewtMacWindow.m
@@ -213,6 +213,11 @@ static jmethodID windowDestroyNotifyID = NULL;
[super viewDidUnhide];
}
+- (BOOL)acceptsFirstResponder
+{
+ return YES;
+}
+
@end
@implementation NewtMacWindow
@@ -742,8 +747,33 @@ 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) windowDidBecomeKey: (NSNotification *) notification
{
+ DBG_PRINT( "*************** windowDidBecomeKey\n");
+ [self sendFocusGained];
+}
+
+- (void) sendFocusGained
+{
+ DBG_PRINT( "sendFocusGained\n");
NSView* nsview = [self contentView];
if( ! [nsview isMemberOfClass:[NewtView class]] ) {
return;
@@ -769,8 +799,21 @@ static jint mods2JavaMods(NSUInteger mods)
}
}
+- (void) resignKeyWindow
+{
+ DBG_PRINT( "*************** becomeKeyWindow\n");
+ [super becomeKeyWindow];
+}
+
- (void) windowDidResignKey: (NSNotification *) notification
{
+ DBG_PRINT( "*************** windowDidResignKey\n");
+ [self sendFocusLost];
+}
+
+- (void) sendFocusLost
+{
+ DBG_PRINT( "sendFocusLost\n");
NSView* nsview = [self contentView];
if( ! [nsview isMemberOfClass:[NewtView class]] ) {
return;