src/macosx/classes/sun/lwawt/LWWindowPeer.java

Print this page

        

@@ -86,14 +86,20 @@
 //    private VolatileImage backBuffer;
     private volatile BufferedImage backBuffer;
 
     private volatile int windowState = Frame.NORMAL;
 
-    // A peer where the last mouse event came to. Used to generate
-    // MOUSE_ENTERED/EXITED notifications and by cursor manager to
+    // check that the mouse is over the window
+    private volatile boolean isMouseOver = false;
+
+    // A peer where the last mouse event came to. Used by cursor manager to
     // find the component under cursor
-    private static volatile LWComponentPeer lastMouseEventPeer = null;
+    private static volatile LWComponentPeer lastCommonMouseEventPeer = null;
+
+    // A peer where the last mouse event came to. Used to generate
+    // MOUSE_ENTERED/EXITED notifications
+    private volatile LWComponentPeer lastMouseEventPeer;
 
     // Peers where all dragged/released events should come to,
     // depending on what mouse button is being dragged according to Cocoa
     private static LWComponentPeer mouseDownTarget[] = new LWComponentPeer[3];
 

@@ -674,70 +680,69 @@
     {
         // TODO: fill "bdata" member of AWTEvent
         Rectangle r = getBounds();
         // findPeerAt() expects parent coordinates
         LWComponentPeer targetPeer = findPeerAt(r.x + x, r.y + y);
-        LWWindowPeer lastWindowPeer =
-            (lastMouseEventPeer != null) ? lastMouseEventPeer.getWindowPeerOrSelf() : null;
-        LWWindowPeer curWindowPeer =
-            (targetPeer != null) ? targetPeer.getWindowPeerOrSelf() : null;
 
         if (id == MouseEvent.MOUSE_EXITED) {
-            // Sometimes we may get MOUSE_EXITED after lastMouseEventPeer is switched
-            // to a peer from another window. So we must first check if this peer is
-            // the same as lastWindowPeer
-            if (lastWindowPeer == this) {
-                if (isEnabled()) {
+            isMouseOver = false;
+            if (lastMouseEventPeer != null) {
+                if (lastMouseEventPeer.isEnabled()) {
                     Point lp = lastMouseEventPeer.windowToLocal(x, y,
-                                                                lastWindowPeer);
+                            this);
                     postEvent(new MouseEvent(lastMouseEventPeer.getTarget(),
                                              MouseEvent.MOUSE_EXITED, when,
                                              modifiers, lp.x, lp.y, screenX,
                                              screenY, clickCount, popupTrigger,
                                              button));
                 }
-                lastMouseEventPeer = null;
-            }
-        } else {
-            if (targetPeer != lastMouseEventPeer) {
 
-                if (id != MouseEvent.MOUSE_DRAGGED || lastMouseEventPeer == null) {
-                    // lastMouseEventPeer may be null if mouse was out of Java windows
-                    if (lastMouseEventPeer != null && lastMouseEventPeer.isEnabled()) {
-                        // Sometimes, MOUSE_EXITED is not sent by delegate (or is sent a bit
-                        // later), in which case lastWindowPeer is another window
-                        if (lastWindowPeer != this) {
-                            Point oldp = lastMouseEventPeer.windowToLocal(x, y, lastWindowPeer);
-                            // Additionally translate from this to lastWindowPeer coordinates
-                            Rectangle lr = lastWindowPeer.getBounds();
-                            oldp.x += r.x - lr.x;
-                            oldp.y += r.y - lr.y;
-                            postEvent(new MouseEvent(lastMouseEventPeer.getTarget(),
-                                                     MouseEvent.MOUSE_EXITED,
-                                                     when, modifiers,
-                                                     oldp.x, oldp.y, screenX, screenY,
-                                                     clickCount, popupTrigger, button));
-                        } else {
-                            Point oldp = lastMouseEventPeer.windowToLocal(x, y, this);
-                            postEvent(new MouseEvent(lastMouseEventPeer.getTarget(),
-                                                     MouseEvent.MOUSE_EXITED,
-                                                     when, modifiers,
-                                                     oldp.x, oldp.y, screenX, screenY,
-                                                     clickCount, popupTrigger, button));
+                // Sometimes we may get MOUSE_EXITED after lastCommonMouseEventPeer is switched
+                // to a peer from another window. So we must first check if this peer is
+                // the same as lastWindowPeer
+                if (lastCommonMouseEventPeer != null && lastCommonMouseEventPeer.getWindowPeerOrSelf() == this) {
+                    lastCommonMouseEventPeer = null;
                         }
+                lastMouseEventPeer = null;
                     }
-                    if (targetPeer != null && targetPeer.isEnabled() && id != MouseEvent.MOUSE_ENTERED) {
-                        Point newp = targetPeer.windowToLocal(x, y, curWindowPeer);
+        } else if(id == MouseEvent.MOUSE_ENTERED) {
+            isMouseOver = true;
+            if (targetPeer != null) {
+                if (targetPeer.isEnabled()) {
+                    Point lp = targetPeer.windowToLocal(x, y, this);
                         postEvent(new MouseEvent(targetPeer.getTarget(),
-                                                 MouseEvent.MOUSE_ENTERED,
-                                                 when, modifiers,
-                                                 newp.x, newp.y, screenX, screenY,
-                                                 clickCount, popupTrigger, button));
-                    }
+                            MouseEvent.MOUSE_ENTERED, when,
+                            modifiers, lp.x, lp.y, screenX,
+                            screenY, clickCount, popupTrigger,
+                            button));
                 }
+                lastCommonMouseEventPeer = targetPeer;
                 lastMouseEventPeer = targetPeer;
             }
+        } else {
+            PlatformWindow topmostPlatforWindow =
+                    platformWindow.getTopmostPlatformWindowUnderMouse();
+
+            LWWindowPeer topmostWindowPeer =
+                    topmostPlatforWindow != null ? topmostPlatforWindow.getPeer() : null;
+
+            // topmostWindowPeer == null condition is added for the backward
+            // compatibility with applets. It can be removed when the
+            // getTopmostPlatformWindowUnderMouse() method will be properly
+            // implemented in CPlatformEmbeddedFrame class
+            if (topmostWindowPeer == this || topmostWindowPeer == null) {
+                generateMouseEnterExitEventsForComponents(when, button, x, y,
+                        screenX, screenY, modifiers, clickCount, popupTrigger,
+                        targetPeer);
+            } else {
+                LWComponentPeer topmostTargetPeer =
+                        topmostWindowPeer != null ? topmostWindowPeer.findPeerAt(r.x + x, r.y + y) : null;
+                topmostWindowPeer.generateMouseEnterExitEventsForComponents(when, button, x, y,
+                        screenX, screenY, modifiers, clickCount, popupTrigger,
+                        topmostTargetPeer);
+            }
+
             // TODO: fill "bdata" member of AWTEvent
 
             int eventButtonMask = (button > 0)? MouseEvent.getMaskForButton(button) : 0;
             int otherButtonsPressed = modifiers & ~eventButtonMask;
 

@@ -783,23 +788,17 @@
                 }
 
                 // mouseClickButtons is updated below, after MOUSE_CLICK is sent
             }
 
-            // check if we receive mouseEvent from outside the window's bounds
-            // it can be either mouseDragged or mouseReleased
-            if (curWindowPeer == null) {
-                //TODO This can happen if this window is invisible. this is correct behavior in this case?
-                curWindowPeer = this;
-            }
             if (targetPeer == null) {
                 //TODO This can happen if this window is invisible. this is correct behavior in this case?
                 targetPeer = this;
             }
 
 
-            Point lp = targetPeer.windowToLocal(x, y, curWindowPeer);
+            Point lp = targetPeer.windowToLocal(x, y, this);
             if (targetPeer.isEnabled()) {
                 MouseEvent event = new MouseEvent(targetPeer.getTarget(), id,
                                                   when, modifiers, lp.x, lp.y,
                                                   screenX, screenY, clickCount,
                                                   popupTrigger, button);

@@ -819,10 +818,42 @@
             }
         }
         notifyUpdateCursor();
     }
 
+    private void generateMouseEnterExitEventsForComponents(long when,
+            int button, int x, int y, int screenX, int screenY,
+            int modifiers, int clickCount, boolean popupTrigger,
+            LWComponentPeer targetPeer) {
+
+        if (!isMouseOver || targetPeer == lastMouseEventPeer) {
+            return;
+        }
+
+        // Generate Mouse Exit for components
+        if (lastMouseEventPeer != null && lastMouseEventPeer.isEnabled()) {
+            Point oldp = lastMouseEventPeer.windowToLocal(x, y, this);
+            postEvent(new MouseEvent(lastMouseEventPeer.getTarget(),
+                    MouseEvent.MOUSE_EXITED,
+                    when, modifiers,
+                    oldp.x, oldp.y, screenX, screenY,
+                    clickCount, popupTrigger, button));
+        }
+        lastCommonMouseEventPeer = targetPeer;
+        lastMouseEventPeer = targetPeer;
+
+        // Generate Mouse Enter for components
+        if (targetPeer != null && targetPeer.isEnabled()) {
+            Point newp = targetPeer.windowToLocal(x, y, this);
+            postEvent(new MouseEvent(targetPeer.getTarget(),
+                    MouseEvent.MOUSE_ENTERED,
+                    when, modifiers,
+                    newp.x, newp.y, screenX, screenY,
+                    clickCount, popupTrigger, button));
+        }
+    }
+
     public void dispatchMouseWheelEvent(long when, int x, int y, int modifiers,
                                         int scrollType, int scrollAmount,
                                         int wheelRotation, double preciseWheelRotation,
                                         byte[] bdata)
     {

@@ -1063,15 +1094,15 @@
 
         return changed;
     }
 
     public static LWWindowPeer getWindowUnderCursor() {
-        return lastMouseEventPeer != null ? lastMouseEventPeer.getWindowPeerOrSelf() : null;
+        return lastCommonMouseEventPeer != null ? lastCommonMouseEventPeer.getWindowPeerOrSelf() : null;
     }
 
     public static LWComponentPeer<?, ?> getPeerUnderCursor() {
-        return lastMouseEventPeer;
+        return lastCommonMouseEventPeer;
     }
 
     /*
      * Requests platform to set native focus on a frame/dialog.
      * In case of a simple window, triggers appropriate java focus change.