changeset 6075:b9336793e998

2223192: [macosx] "opposite" seems always null in focus events Reviewed-by: anthony
author leonidr
date Wed, 15 May 2013 15:29:39 +0400
parents 889f9b9f79b4
children e4c0c70ce3bd
files src/macosx/classes/sun/lwawt/LWWindowPeer.java src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java src/macosx/native/sun/awt/AWTWindow.h src/macosx/native/sun/awt/AWTWindow.m
diffstat 6 files changed, 72 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/src/macosx/classes/sun/lwawt/LWWindowPeer.java	Tue May 14 20:10:10 2013 +0100
+++ b/src/macosx/classes/sun/lwawt/LWWindowPeer.java	Wed May 15 15:29:39 2013 +0400
@@ -701,8 +701,9 @@
         getLWToolkit().getCursorManager().updateCursorLater(this);
     }
 
-    public void notifyActivation(boolean activation) {
-        changeFocusedWindow(activation);
+    public void notifyActivation(boolean activation, LWWindowPeer opposite) {
+        Window oppositeWindow = (opposite == null)? null : opposite.getTarget();
+        changeFocusedWindow(activation, oppositeWindow);
     }
 
     // MouseDown in non-client area
@@ -1135,6 +1136,9 @@
         Window currentActive = KeyboardFocusManager.
             getCurrentKeyboardFocusManager().getActiveWindow();
 
+        Window opposite = LWKeyboardFocusManagerPeer.getInstance().
+            getCurrentFocusedWindow();
+
         // Make the owner active window.
         if (isSimpleWindow()) {
             LWWindowPeer owner = getOwnerFrameDialog(this);
@@ -1161,16 +1165,17 @@
             }
 
             // DKFM will synthesize all the focus/activation events correctly.
-            changeFocusedWindow(true);
+            changeFocusedWindow(true, opposite);
             return true;
 
         // In case the toplevel is active but not focused, change focus directly,
         // as requesting native focus on it will not have effect.
         } else if (getTarget() == currentActive && !getTarget().hasFocus()) {
 
-            changeFocusedWindow(true);
+            changeFocusedWindow(true, opposite);
             return true;
         }
+
         return platformWindow.requestWindowFocus();
     }
 
@@ -1200,7 +1205,7 @@
     /*
      * Changes focused window on java level.
      */
-    private void changeFocusedWindow(boolean becomesFocused) {
+    private void changeFocusedWindow(boolean becomesFocused, Window opposite) {
         if (focusLog.isLoggable(PlatformLogger.FINE)) {
             focusLog.fine((becomesFocused?"gaining":"loosing") + " focus window: " + this);
         }
@@ -1224,9 +1229,6 @@
             }
         }
 
-        KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
-        Window oppositeWindow = becomesFocused ? kfmPeer.getCurrentFocusedWindow() : null;
-
         // Note, the method is not called:
         // - when the opposite (gaining focus) window is an owned/owner window.
         // - for a simple window in any case.
@@ -1238,10 +1240,11 @@
             grabbingWindow.ungrab();
         }
 
+        KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
         kfmPeer.setCurrentFocusedWindow(becomesFocused ? getTarget() : null);
 
         int eventID = becomesFocused ? WindowEvent.WINDOW_GAINED_FOCUS : WindowEvent.WINDOW_LOST_FOCUS;
-        WindowEvent windowEvent = new WindowEvent(getTarget(), eventID, oppositeWindow);
+        WindowEvent windowEvent = new WindowEvent(getTarget(), eventID, opposite);
 
         // TODO: wrap in SequencedEvent
         postEvent(windowEvent);
--- a/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java	Tue May 14 20:10:10 2013 +0100
+++ b/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java	Wed May 15 15:29:39 2013 +0400
@@ -121,7 +121,7 @@
             clipboard.checkPasteboard();
         }
         if (parentWindowActive) {
-            responder.handleWindowFocusEvent(focused);
+            responder.handleWindowFocusEvent(focused, null);
         }
     }
 
@@ -130,7 +130,7 @@
         // ignore focus "lost" native request as it may mistakenly
         // deactivate active window (see 8001161)
         if (focused && parentWindowActive) {
-            responder.handleWindowFocusEvent(parentWindowActive);
+            responder.handleWindowFocusEvent(parentWindowActive, null);
         }
     }
 
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java	Tue May 14 20:10:10 2013 +0100
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java	Wed May 15 15:29:39 2013 +0400
@@ -218,7 +218,7 @@
         }
     }
 
-    void handleWindowFocusEvent(boolean gained) {
-        peer.notifyActivation(gained);
+    void handleWindowFocusEvent(boolean gained, LWWindowPeer opposite) {
+        peer.notifyActivation(gained, opposite);
     }
 }
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Tue May 14 20:10:10 2013 +0100
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Wed May 15 15:29:39 2013 +0400
@@ -902,13 +902,15 @@
     /*************************************************************
      * Callbacks from the AWTWindow and AWTView objc classes.
      *************************************************************/
-    private void deliverWindowFocusEvent(boolean gained){
+    private void deliverWindowFocusEvent(boolean gained, CPlatformWindow opposite){
         // Fix for 7150349: ingore "gained" notifications when the app is inactive.
         if (gained && !((LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive()) {
             focusLogger.fine("the app is inactive, so the notification is ignored");
             return;
         }
-        responder.handleWindowFocusEvent(gained);
+
+        LWWindowPeer oppositePeer = (opposite == null)? null : opposite.getPeer();
+        responder.handleWindowFocusEvent(gained, oppositePeer);
     }
 
     private void deliverMoveResizeEvent(int x, int y, int width, int height,
--- a/src/macosx/native/sun/awt/AWTWindow.h	Tue May 14 20:10:10 2013 +0100
+++ b/src/macosx/native/sun/awt/AWTWindow.h	Wed May 15 15:29:39 2013 +0400
@@ -72,6 +72,9 @@
 - (BOOL) worksWhenModal;
 - (void)sendEvent:(NSEvent *)event;
 
++ (void) setLastKeyWindow:(AWTWindow *)window;
++ (AWTWindow *) lastKeyWindow;
+
 @end
 
 @interface AWTWindow_Normal : NSWindow
--- a/src/macosx/native/sun/awt/AWTWindow.m	Tue May 14 20:10:10 2013 +0100
+++ b/src/macosx/native/sun/awt/AWTWindow.m	Wed May 15 15:29:39 2013 +0400
@@ -70,6 +70,14 @@
 }
 @end
 
+// Cocoa windowDidBecomeKey/windowDidResignKey notifications
+// doesn't provide information about "opposite" window, so we
+// have to do a bit of tracking. This variable points to a window
+// which had been the key window just before a new key window
+// was set. It would be nil if the new key window isn't an AWT
+// window or the app currently has no key window.
+static AWTWindow* lastKeyWindow = nil;
+
 // --------------------------------------------------------------
 // NSWindow/NSPanel descendants implementation
 #define AWT_NS_WINDOW_IMPLEMENTATION                            \
@@ -298,6 +306,10 @@
     return self;
 }
 
++ (BOOL) isAWTWindow:(NSWindow *)window {
+    return [window isKindOfClass: [AWTWindow_Panel class]] || [window isKindOfClass: [AWTWindow_Normal class]];
+}
+
 // checks that this window is under the mouse cursor and this point is not overlapped by others windows
 - (BOOL) isTopmostWindowUnderMouse {
 
@@ -551,15 +563,17 @@
     [self _deliverIconify:JNI_FALSE];
 }
 
-- (void) _deliverWindowFocusEvent:(BOOL)focused {
+- (void) _deliverWindowFocusEvent:(BOOL)focused oppositeWindow:(AWTWindow *)opposite {
 //AWT_ASSERT_APPKIT_THREAD;
-
     JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
     if (platformWindow != NULL) {
-        static JNF_MEMBER_CACHE(jm_deliverWindowFocusEvent, jc_CPlatformWindow, "deliverWindowFocusEvent", "(Z)V");
-        JNFCallVoidMethod(env, platformWindow, jm_deliverWindowFocusEvent, (jboolean)focused);
+        jobject oppositeWindow = [opposite.javaPlatformWindow jObjectWithEnv:env];
+
+        static JNF_MEMBER_CACHE(jm_deliverWindowFocusEvent, jc_CPlatformWindow, "deliverWindowFocusEvent", "(ZLsun/lwawt/macosx/CPlatformWindow;)V");
+        JNFCallVoidMethod(env, platformWindow, jm_deliverWindowFocusEvent, (jboolean)focused, oppositeWindow);
         (*env)->DeleteLocalRef(env, platformWindow);
+        (*env)->DeleteLocalRef(env, oppositeWindow);
     }
 }
 
@@ -568,7 +582,10 @@
 AWT_ASSERT_APPKIT_THREAD;
     [AWTToolkit eventCountPlusPlus];
     [CMenuBar activate:self.javaMenuBar modallyDisabled:NO];
-    [self _deliverWindowFocusEvent:YES];
+    AWTWindow *opposite = [AWTWindow lastKeyWindow];
+    [AWTWindow setLastKeyWindow:nil];
+
+    [self _deliverWindowFocusEvent:YES oppositeWindow: opposite];
 }
 
 - (void) windowDidResignKey: (NSNotification *) notification {
@@ -576,7 +593,18 @@
 AWT_ASSERT_APPKIT_THREAD;
     [AWTToolkit eventCountPlusPlus];
     [self.javaMenuBar deactivate];
-    [self _deliverWindowFocusEvent:NO];
+
+    // the new key window
+    NSWindow *keyWindow = [NSApp keyWindow];
+    AWTWindow *opposite = nil;
+    if ([AWTWindow isAWTWindow: keyWindow]) {
+        opposite = (AWTWindow *)[keyWindow delegate];
+        [AWTWindow setLastKeyWindow: self];
+    } else {
+        [AWTWindow setLastKeyWindow: nil];
+    }
+
+    [self _deliverWindowFocusEvent:NO oppositeWindow: opposite];
 }
 
 - (void) windowDidBecomeMain: (NSNotification *) notification {
@@ -735,6 +763,17 @@
     }
 }
 
++ (void) setLastKeyWindow:(AWTWindow *)window {
+    [window retain];
+    [lastKeyWindow release];
+    lastKeyWindow = window;
+}
+
++ (AWTWindow *) lastKeyWindow {
+    return lastKeyWindow;
+}
+
+
 @end // AWTWindow
 
 
@@ -1141,6 +1180,10 @@
     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
         AWTWindow *window = (AWTWindow*)[nsWindow delegate];
 
+        if ([AWTWindow lastKeyWindow] == window) {
+            [AWTWindow setLastKeyWindow: nil];
+        }
+
         // AWTWindow holds a reference to the NSWindow in its nsWindow
         // property. Unsetting the delegate allows it to be deallocated
         // which releases the reference. This, in turn, allows the window