7124310: [macosx] "opposite" seems always null in focus events

Reviewed-by: anthony
This commit is contained in:
Leonid Romanov 2012-11-02 19:20:03 +04:00
parent 1aa03d0b50
commit c0c03f17ce
6 changed files with 68 additions and 21 deletions

@ -675,8 +675,9 @@ public class LWWindowPeer
getLWToolkit().getCursorManager().updateCursorLater(this); getLWToolkit().getCursorManager().updateCursorLater(this);
} }
public void notifyActivation(boolean activation) { public void notifyActivation(boolean activation, LWWindowPeer opposite) {
changeFocusedWindow(activation); Window oppositeWindow = (opposite == null)? null : opposite.getTarget();
changeFocusedWindow(activation, oppositeWindow);
} }
// MouseDown in non-client area // MouseDown in non-client area
@ -1151,6 +1152,9 @@ public class LWWindowPeer
Window currentActive = KeyboardFocusManager. Window currentActive = KeyboardFocusManager.
getCurrentKeyboardFocusManager().getActiveWindow(); getCurrentKeyboardFocusManager().getActiveWindow();
Window opposite = LWKeyboardFocusManagerPeer.getInstance().
getCurrentFocusedWindow();
// Make the owner active window. // Make the owner active window.
if (isSimpleWindow()) { if (isSimpleWindow()) {
LWWindowPeer owner = getOwnerFrameDialog(this); LWWindowPeer owner = getOwnerFrameDialog(this);
@ -1177,16 +1181,17 @@ public class LWWindowPeer
} }
// DKFM will synthesize all the focus/activation events correctly. // DKFM will synthesize all the focus/activation events correctly.
changeFocusedWindow(true); changeFocusedWindow(true, opposite);
return true; return true;
// In case the toplevel is active but not focused, change focus directly, // In case the toplevel is active but not focused, change focus directly,
// as requesting native focus on it will not have effect. // as requesting native focus on it will not have effect.
} else if (getTarget() == currentActive && !getTarget().hasFocus()) { } else if (getTarget() == currentActive && !getTarget().hasFocus()) {
changeFocusedWindow(true); changeFocusedWindow(true, opposite);
return true; return true;
} }
return platformWindow.requestWindowFocus(); return platformWindow.requestWindowFocus();
} }
@ -1216,7 +1221,7 @@ public class LWWindowPeer
/* /*
* Changes focused window on java level. * Changes focused window on java level.
*/ */
private void changeFocusedWindow(boolean becomesFocused) { private void changeFocusedWindow(boolean becomesFocused, Window opposite) {
if (focusLog.isLoggable(PlatformLogger.FINE)) { if (focusLog.isLoggable(PlatformLogger.FINE)) {
focusLog.fine((becomesFocused?"gaining":"loosing") + " focus window: " + this); focusLog.fine((becomesFocused?"gaining":"loosing") + " focus window: " + this);
} }
@ -1240,9 +1245,6 @@ public class LWWindowPeer
} }
} }
KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
Window oppositeWindow = becomesFocused ? kfmPeer.getCurrentFocusedWindow() : null;
// Note, the method is not called: // Note, the method is not called:
// - when the opposite (gaining focus) window is an owned/owner window. // - when the opposite (gaining focus) window is an owned/owner window.
// - for a simple window in any case. // - for a simple window in any case.
@ -1254,10 +1256,11 @@ public class LWWindowPeer
grabbingWindow.ungrab(); grabbingWindow.ungrab();
} }
KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
kfmPeer.setCurrentFocusedWindow(becomesFocused ? getTarget() : null); kfmPeer.setCurrentFocusedWindow(becomesFocused ? getTarget() : null);
int eventID = becomesFocused ? WindowEvent.WINDOW_GAINED_FOCUS : WindowEvent.WINDOW_LOST_FOCUS; int eventID = becomesFocused ? WindowEvent.WINDOW_GAINED_FOCUS : WindowEvent.WINDOW_LOST_FOCUS;
WindowEvent windowEvent = new TimedWindowEvent(getTarget(), eventID, oppositeWindow, System.currentTimeMillis()); WindowEvent windowEvent = new TimedWindowEvent(getTarget(), eventID, opposite, System.currentTimeMillis());
// TODO: wrap in SequencedEvent // TODO: wrap in SequencedEvent
postEvent(windowEvent); postEvent(windowEvent);

@ -113,14 +113,14 @@ public class CEmbeddedFrame extends EmbeddedFrame {
public void handleFocusEvent(boolean focused) { public void handleFocusEvent(boolean focused) {
this.focused = focused; this.focused = focused;
if (parentWindowActive) { if (parentWindowActive) {
responder.handleWindowFocusEvent(focused); responder.handleWindowFocusEvent(focused, null);
} }
} }
public void handleWindowFocusEvent(boolean parentWindowActive) { public void handleWindowFocusEvent(boolean parentWindowActive) {
this.parentWindowActive = parentWindowActive; this.parentWindowActive = parentWindowActive;
if (focused) { if (focused) {
responder.handleWindowFocusEvent(parentWindowActive); responder.handleWindowFocusEvent(parentWindowActive, null);
} }
} }

@ -218,7 +218,7 @@ final class CPlatformResponder {
} }
} }
void handleWindowFocusEvent(boolean gained) { void handleWindowFocusEvent(boolean gained, LWWindowPeer opposite) {
peer.notifyActivation(gained); peer.notifyActivation(gained, opposite);
} }
} }

@ -878,13 +878,15 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor
/************************************************************* /*************************************************************
* Callbacks from the AWTWindow and AWTView objc classes. * 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. // Fix for 7150349: ingore "gained" notifications when the app is inactive.
if (gained && !((LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive()) { if (gained && !((LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive()) {
focusLogger.fine("the app is inactive, so the notification is ignored"); focusLogger.fine("the app is inactive, so the notification is ignored");
return; 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) { private void deliverMoveResizeEvent(int x, int y, int width, int height) {

@ -69,6 +69,9 @@
- (BOOL) worksWhenModal; - (BOOL) worksWhenModal;
- (void)sendEvent:(NSEvent *)event; - (void)sendEvent:(NSEvent *)event;
+ (void) setLastKeyWindow:(AWTWindow *)window;
+ (AWTWindow *) lastKeyWindow;
@end @end
@interface AWTWindow_Normal : NSWindow @interface AWTWindow_Normal : NSWindow

@ -51,6 +51,14 @@
static JNF_CLASS_CACHE(jc_CPlatformWindow, "sun/lwawt/macosx/CPlatformWindow"); static JNF_CLASS_CACHE(jc_CPlatformWindow, "sun/lwawt/macosx/CPlatformWindow");
// 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 // NSWindow/NSPanel descendants implementation
#define AWT_NS_WINDOW_IMPLEMENTATION \ #define AWT_NS_WINDOW_IMPLEMENTATION \
@ -505,15 +513,17 @@ AWT_ASSERT_APPKIT_THREAD;
[self _deliverIconify:JNI_FALSE]; [self _deliverIconify:JNI_FALSE];
} }
- (void) _deliverWindowFocusEvent:(BOOL)focused { - (void) _deliverWindowFocusEvent:(BOOL)focused oppositeWindow:(AWTWindow *)opposite {
//AWT_ASSERT_APPKIT_THREAD; //AWT_ASSERT_APPKIT_THREAD;
JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env]; jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
if (platformWindow != NULL) { if (platformWindow != NULL) {
static JNF_MEMBER_CACHE(jm_deliverWindowFocusEvent, jc_CPlatformWindow, "deliverWindowFocusEvent", "(Z)V"); jobject oppositeWindow = [opposite.javaPlatformWindow jObjectWithEnv:env];
JNFCallVoidMethod(env, platformWindow, jm_deliverWindowFocusEvent, (jboolean)focused);
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, platformWindow);
(*env)->DeleteLocalRef(env, oppositeWindow);
} }
} }
@ -522,7 +532,10 @@ AWT_ASSERT_APPKIT_THREAD;
AWT_ASSERT_APPKIT_THREAD; AWT_ASSERT_APPKIT_THREAD;
[AWTToolkit eventCountPlusPlus]; [AWTToolkit eventCountPlusPlus];
[CMenuBar activate:self.javaMenuBar modallyDisabled:NO]; [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 { - (void) windowDidResignKey: (NSNotification *) notification {
@ -530,7 +543,18 @@ AWT_ASSERT_APPKIT_THREAD;
AWT_ASSERT_APPKIT_THREAD; AWT_ASSERT_APPKIT_THREAD;
[AWTToolkit eventCountPlusPlus]; [AWTToolkit eventCountPlusPlus];
[self.javaMenuBar deactivate]; [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 { - (void) windowDidBecomeMain: (NSNotification *) notification {
@ -684,6 +708,17 @@ AWT_ASSERT_APPKIT_THREAD;
} }
} }
+ (void) setLastKeyWindow:(AWTWindow *)window {
[window retain];
[lastKeyWindow release];
lastKeyWindow = window;
}
+ (AWTWindow *) lastKeyWindow {
return lastKeyWindow;
}
@end // AWTWindow @end // AWTWindow
@ -1208,6 +1243,10 @@ JNF_COCOA_ENTER(env);
[JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){ [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
AWTWindow *window = (AWTWindow*)[nsWindow delegate]; AWTWindow *window = (AWTWindow*)[nsWindow delegate];
if ([AWTWindow lastKeyWindow] == window) {
[AWTWindow setLastKeyWindow: nil];
}
// AWTWindow holds a reference to the NSWindow in its nsWindow // AWTWindow holds a reference to the NSWindow in its nsWindow
// property. Unsetting the delegate allows it to be deallocated // property. Unsetting the delegate allows it to be deallocated
// which releases the reference. This, in turn, allows the window // which releases the reference. This, in turn, allows the window