--- old/src/macosx/native/sun/awt/AWTWindow.m 2012-08-10 16:51:43.000000000 +0400 +++ new/src/macosx/native/sun/awt/AWTWindow.m 2012-08-10 16:51:42.000000000 +0400 @@ -238,10 +238,12 @@ return self; } -// checks that this window is under the mouse cursor and this point is not overlapped by others windows -- (BOOL) isTopmostWindowUnderMouse { ++ (BOOL) isAWTWindow:(NSWindow *)window { + return [window isKindOfClass: [AWTWindow_Panel class]] || [window isKindOfClass: [AWTWindow_Normal class]]; +} - int currentWinID = [self.nsWindow windowNumber]; +// returns id for the topmost window under mouse ++ (NSInteger) getTopmostWindowUnderMouseID { NSRect screenRect = [[NSScreen mainScreen] frame]; NSPoint nsMouseLocation = [NSEvent mouseLocation]; @@ -249,53 +251,91 @@ NSMutableArray *windows = (NSMutableArray *)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID); - for (NSDictionary *window in windows) { - int layer = [[window objectForKey:(id)kCGWindowLayer] intValue]; + NSInteger layer = [[window objectForKey:(id)kCGWindowLayer] integerValue]; if (layer == 0) { - int winID = [[window objectForKey:(id)kCGWindowNumber] intValue]; CGRect rect; CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect); if (CGRectContainsPoint(rect, cgMouseLocation)) { - return currentWinID == winID; - } else if (currentWinID == winID) { - return NO; + return [[window objectForKey:(id)kCGWindowNumber] integerValue]; } } } - return NO; + return -1; } -- (void) synthesizeMouseEnteredExitedEvents { +// checks that this window is under the mouse cursor and this point is not overlapped by others windows +- (BOOL) isTopmostWindowUnderMouse { + return [self.nsWindow windowNumber] == [AWTWindow getTopmostWindowUnderMouseID]; +} - int eventType = 0; - BOOL isUnderMouse = [self isTopmostWindowUnderMouse]; - BOOL mouseIsOver = [[self.nsWindow contentView] mouseIsOver]; - - if (isUnderMouse && !mouseIsOver) { - eventType = NSMouseEntered; - } else if (!isUnderMouse && mouseIsOver) { - eventType = NSMouseExited; - } else { - return; - } ++ (AWTWindow *) getTopmostWindowUnderMouse { + NSEnumerator *windowEnumerator = [[NSApp windows] objectEnumerator]; + NSWindow *window; + + NSInteger topmostWindowUnderMouseID = [AWTWindow getTopmostWindowUnderMouseID]; + + while ((window = [windowEnumerator nextObject]) != nil) { + if ([window windowNumber] == topmostWindowUnderMouseID) { + BOOL isAWTWindow = [AWTWindow isAWTWindow: window]; + return isAWTWindow ? (AWTWindow *) [window delegate] : nil; + } + } + return nil; +} - NSPoint screenLocation = [NSEvent mouseLocation]; - NSPoint windowLocation = [self.nsWindow convertScreenToBase: screenLocation]; - int modifierFlags = (eventType == NSMouseEntered) ? NSMouseEnteredMask : NSMouseExitedMask; ++ (void) synthesizeMouseEnteredExitedEventsForAllWindows { - NSEvent *mouseEvent = [NSEvent enterExitEventWithType: eventType - location: windowLocation - modifierFlags: modifierFlags + NSPoint screenLocation = [NSEvent mouseLocation]; + NSInteger topmostWindowUnderMouseID = [AWTWindow getTopmostWindowUnderMouseID]; + NSArray *windows = [NSApp windows]; + NSWindow *window; + + // synthesize mouse exited event + NSEnumerator *windowEnumerator = [windows objectEnumerator]; + while ((window = [windowEnumerator nextObject]) != nil) { + if ([AWTWindow isAWTWindow: window]) { + NSInteger windowID = [window windowNumber]; + BOOL isUnderMouse = (windowID == topmostWindowUnderMouseID); + BOOL mouseIsOver = [[window contentView] mouseIsOver]; + if (!isUnderMouse && mouseIsOver) { + NSEvent *mouseEvent = [NSEvent enterExitEventWithType: NSMouseExited + location: [window convertScreenToBase: screenLocation] + modifierFlags: NSMouseExitedMask timestamp: 0 - windowNumber: [self.nsWindow windowNumber] + windowNumber: windowID context: nil eventNumber: 0 trackingNumber: 0 userData: nil ]; + [[window contentView] deliverJavaMouseEvent: mouseEvent]; + } + } + } - [[self.nsWindow contentView] deliverJavaMouseEvent: mouseEvent]; + // synthesize mouse entered event + windowEnumerator = [windows objectEnumerator]; + while ((window = [windowEnumerator nextObject]) != nil) { + if ([AWTWindow isAWTWindow: window]) { + NSInteger windowID = [window windowNumber]; + BOOL isUnderMouse = (windowID == topmostWindowUnderMouseID); + BOOL mouseIsOver = [[window contentView] mouseIsOver]; + if (isUnderMouse && !mouseIsOver) { + NSEvent *mouseEvent = [NSEvent enterExitEventWithType: NSMouseEntered + location: [window convertScreenToBase: screenLocation] + modifierFlags: NSMouseEnteredMask + timestamp: 0 + windowNumber: windowID + context: nil + eventNumber: 0 + trackingNumber: 0 + userData: nil + ]; + [[window contentView] deliverJavaMouseEvent: mouseEvent]; + } + } + } } - (void) dealloc { @@ -825,7 +865,7 @@ // (this will also re-enable screen updates, which were disabled above) // TODO: send PaintEvent - [window synthesizeMouseEnteredExitedEvents]; + [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows]; }]; JNF_COCOA_EXIT(env); @@ -1040,6 +1080,30 @@ /* * Class: sun_lwawt_macosx_CPlatformWindow + * Method: nativeGetTopmostPlatformWindowUnderMouse + * Signature: (J)V + */ +JNIEXPORT jobject +JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetTopmostPlatformWindowUnderMouse +(JNIEnv *env, jclass clazz) +{ + jobject topmostWindowUnderMouse = nil; + + JNF_COCOA_ENTER(env); + AWT_ASSERT_APPKIT_THREAD; + + AWTWindow *awtWindow = [AWTWindow getTopmostWindowUnderMouse]; + if (awtWindow != nil) { + topmostWindowUnderMouse = [awtWindow.javaPlatformWindow jObject]; + } + + JNF_COCOA_EXIT(env); + + return topmostWindowUnderMouse; +} + +/* + * Class: sun_lwawt_macosx_CPlatformWindow * Method: nativeSynthesizeMouseEnteredExitedEvents * Signature: (J)V */ @@ -1055,7 +1119,7 @@ AWTWindow *window = (AWTWindow*)[nsWindow delegate]; - [window synthesizeMouseEnteredExitedEvents]; + [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows]; }]; JNF_COCOA_EXIT(env);