jdk/src/macosx/native/sun/awt/AWTWindow.m
changeset 12535 6d2ee83614e8
parent 12402 f3903de3fd9e
child 12640 5ea775607d72
--- a/jdk/src/macosx/native/sun/awt/AWTWindow.m	Wed May 02 13:53:06 2012 +0400
+++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m	Wed May 02 17:54:18 2012 +0400
@@ -170,6 +170,66 @@
     return self;
 }
 
+// checks that this window is under the mouse cursor and this point is not overlapped by others windows 
+- (BOOL) isTopmostWindowUnderMouse {
+    
+    int currentWinID = [self windowNumber]; 
+    
+    NSRect screenRect = [[NSScreen mainScreen] frame];    
+    NSPoint nsMouseLocation = [NSEvent mouseLocation];
+    CGPoint cgMouseLocation = CGPointMake(nsMouseLocation.x, screenRect.size.height - nsMouseLocation.y);    
+    
+    NSMutableArray *windows = (NSMutableArray *)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
+    
+    
+    for (NSDictionary *window in windows) {
+        int layer = [[window objectForKey:(id)kCGWindowLayer] intValue];
+        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 NO;
+}
+
+- (void) synthesizeMouseEnteredExitedEvents {
+    
+    int eventType = 0;
+    BOOL isUnderMouse = [self isTopmostWindowUnderMouse];
+    BOOL mouseIsOver = [[self contentView] mouseIsOver];
+    
+    if (isUnderMouse && !mouseIsOver) {
+        eventType = NSMouseEntered;
+    } else if (!isUnderMouse && mouseIsOver) {
+        eventType = NSMouseExited;        
+    } else {
+        return;
+    }
+    
+    NSPoint screenLocation = [NSEvent mouseLocation];        
+    NSPoint windowLocation = [self convertScreenToBase: screenLocation];        
+    int modifierFlags = (eventType == NSMouseEntered) ? NSMouseEnteredMask : NSMouseExitedMask;
+    
+    NSEvent *mouseEvent = [NSEvent enterExitEventWithType: eventType
+                                                  location: windowLocation
+                                             modifierFlags: modifierFlags
+                                                 timestamp: 0
+                                              windowNumber: [self windowNumber]
+                                                   context: nil
+                                               eventNumber: 0
+                                            trackingNumber: 0
+                                                  userData: nil
+                            ];
+    
+    [[self contentView] deliverJavaMouseEvent: mouseEvent];
+}
+
 - (void) dealloc {
 AWT_ASSERT_APPKIT_THREAD;
 
@@ -669,6 +729,8 @@
         // ensure we repaint the whole window after the resize operation
         // (this will also re-enable screen updates, which were disabled above)
         // TODO: send PaintEvent
+        
+        [window synthesizeMouseEnteredExitedEvents];
     }];
 
 JNF_COCOA_EXIT(env);
@@ -899,6 +961,27 @@
 
 /*
  * Class:     sun_lwawt_macosx_CPlatformWindow
+ * Method:    nativeSynthesizeMouseEnteredExitedEvents
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents
+(JNIEnv *env, jclass clazz, jlong windowPtr)
+{
+    JNF_COCOA_ENTER(env);
+    AWT_ASSERT_NOT_APPKIT_THREAD;
+    
+    AWTWindow *window = OBJC(windowPtr);
+    [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
+        AWT_ASSERT_APPKIT_THREAD;
+        
+        [window synthesizeMouseEnteredExitedEvents];
+    }];
+    
+    JNF_COCOA_EXIT(env);
+}
+
+/*
+ * Class:     sun_lwawt_macosx_CPlatformWindow
  * Method:    nativeGetScreenNSWindowIsOn_AppKitThread
  * Signature: (J)I
  */