6430553: MouseClick event should not be fired if MouseRelease happened without MousePress
authordav
Tue, 15 Apr 2008 14:00:29 +0400
changeset 447 0fb5f354ad70
parent 442 687798d7d7b6
child 448 e795e3ba11f8
6430553: MouseClick event should not be fired if MouseRelease happened without MousePress Summary: verify that the there was a PRESS event before sending CLICK event Reviewed-by: son, dcherepanov
jdk/src/solaris/classes/sun/awt/X11/XWindow.java
jdk/src/windows/native/sun/windows/awt_Component.cpp
jdk/src/windows/native/sun/windows/awt_Component.h
jdk/src/windows/native/sun/windows/awt_TrayIcon.cpp
jdk/src/windows/native/sun/windows/awt_TrayIcon.h
--- a/jdk/src/solaris/classes/sun/awt/X11/XWindow.java	Wed Apr 09 09:37:07 2008 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWindow.java	Tue Apr 15 14:00:29 2008 +0400
@@ -103,12 +103,14 @@
         return defaultFont;
     }
 
-    /*
-     * Keeps all buttons which were pressed at the time of the last mouse
-     * drag until all buttons will be released, contains state as bit masks
-     * Button1Mask, Button2Mask, Button3Mask
-     */
-    private int mouseDragState = 0;
+    /* A bitmask keeps the button's numbers as Button1Mask, Button2Mask, Button3Mask
+     * which are allowed to
+     * generate the CLICK event after the RELEASE has happened.
+     * There are conditions that must be true for that sending CLICK event:
+     * 1) button was initially PRESSED
+     * 2) no movement or drag has happened until RELEASE
+    */
+    private int mouseButtonClickAllowed = 0;
 
     native int getNativeColor(Color clr, GraphicsConfiguration gc);
     native void getWMInsets(long window, long left, long top, long right, long bottom, long border);
@@ -660,6 +662,8 @@
         }
 
         if (type == XConstants.ButtonPress) {
+            //Allow this mouse button to generate CLICK event on next ButtonRelease
+            mouseButtonClickAllowed |= getButtonMask(lbutton);
             XWindow lastWindow = (lastWindowRef != null) ? ((XWindow)lastWindowRef.get()):(null);
             /*
                multiclick checking
@@ -715,8 +719,8 @@
 
             postEventToEventQueue(me);
 
-            if (((mouseDragState & getButtonMask(lbutton)) == 0) && // No up-button in the drag-state
-                (type == XConstants.ButtonRelease))
+            if ((type == XConstants.ButtonRelease) &&
+                ((mouseButtonClickAllowed & getButtonMask(lbutton)) != 0) ) // No up-button in the drag-state
             {
                 postEventToEventQueue(me = new MouseEvent((Component)getEventSource(),
                                                      MouseEvent.MOUSE_CLICKED,
@@ -743,7 +747,11 @@
             }
         }
 
-        mouseDragState &= ~getButtonMask(lbutton); // Exclude the up-button from the drag-state
+        /* Update the state variable AFTER the CLICKED event post. */
+        if (type == XConstants.ButtonRelease) {
+            /* Exclude this mouse button from allowed list.*/
+            mouseButtonClickAllowed &= ~getButtonMask(lbutton);
+        }
     }
 
     public void handleMotionNotify(XEvent xev) {
@@ -776,7 +784,7 @@
                Math.abs(lastY - y) < AWT_MULTICLICK_SMUDGE))) {
           clickCount = 0;
           lastWindowRef = null;
-          mouseDragState = mouseKeyState;
+          mouseButtonClickAllowed = 0;
           lastTime = 0;
           lastX = 0;
           lastY = 0;
--- a/jdk/src/windows/native/sun/windows/awt_Component.cpp	Wed Apr 09 09:37:07 2008 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp	Tue Apr 15 14:00:29 2008 +0400
@@ -234,6 +234,7 @@
 
 AwtComponent::AwtComponent()
 {
+    m_mouseButtonClickAllowed = 0;
     m_callbacksEnabled = FALSE;
     m_hwnd = NULL;
 
@@ -246,7 +247,6 @@
     m_nextControlID = 1;
     m_childList = NULL;
     m_myControlID = 0;
-    m_mouseDragState = 0;
     m_hdwp = NULL;
     m_validationNestCount = 0;
 
@@ -2514,9 +2514,11 @@
         lastClickX = x;
         lastClickY = y;
     }
+    /*
+     *Set appropriate bit of the mask on WM_MOUSE_DOWN message.
+     */
+    m_mouseButtonClickAllowed |= GetButtonMK(button);
     lastTime = now;
-    // it's needed only if WM_LBUTTONUP doesn't come for some reason
-    m_mouseDragState &= ~GetButtonMK(button);
 
     MSG msg;
     InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
@@ -2554,14 +2556,17 @@
                    (GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ?
                     TRUE : FALSE), GetButton(button), &msg);
     /*
-     * If no movement, then report a click following the button release
+     * If no movement, then report a click following the button release.
+     * When WM_MOUSEUP comes to a window without previous WM_MOUSEDOWN,
+     * spurous MOUSE_CLICK is about to happen. See 6430553.
      */
-    if (!(m_mouseDragState & GetButtonMK(button))) { // No up-button in the drag-state
+    if ((m_mouseButtonClickAllowed & GetButtonMK(button)) != 0) { //CLICK allowed
         SendMouseEvent(java_awt_event_MouseEvent_MOUSE_CLICKED,
                        TimeHelper::getMessageTimeUTC(), x, y, GetJavaModifiers(),
                        clickCount, JNI_FALSE, GetButton(button));
     }
-    m_mouseDragState &= ~GetButtonMK(button); // Exclude the up-button from the drag-state
+    // Exclude button from allowed to generate CLICK messages
+    m_mouseButtonClickAllowed &= ~GetButtonMK(button);
 
     if ((flags & ALL_MK_BUTTONS) == 0) {
         // only update if all buttons have been released
@@ -2605,7 +2610,8 @@
             SendMouseEvent(java_awt_event_MouseEvent_MOUSE_DRAGGED, TimeHelper::getMessageTimeUTC(), x, y,
                            GetJavaModifiers(), 0, JNI_FALSE,
                            java_awt_event_MouseEvent_NOBUTTON, &msg);
-            m_mouseDragState = flags;
+            //dragging means no more CLICKs until next WM_MOUSE_DOWN/WM_MOUSE_UP message sequence
+            m_mouseButtonClickAllowed = 0;
         } else {
             MSG msg;
             InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
--- a/jdk/src/windows/native/sun/windows/awt_Component.h	Wed Apr 09 09:37:07 2008 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Component.h	Tue Apr 15 14:00:29 2008 +0400
@@ -707,13 +707,6 @@
     BOOL     m_backgroundColorSet;
     BOOL     m_visible;         /* copy of Component.visible */
 
-    /*
-     * Keeps all buttons which were pressed at the time of the last mouse
-     * drag until all buttons will be released, contains state as bit masks
-     * MK_LBUTTON, MK_MBUTTON, MK_RBUTTON
-     */
-    UINT     m_mouseDragState;
-
     static BOOL sm_suppressFocusAndActivation;
     static HWND sm_realFocusOpposite;
 
@@ -725,6 +718,15 @@
     static UINT sm_95WheelSupport;
 
 private:
+    /* A bitmask keeps the button's numbers as MK_LBUTTON, MK_MBUTTON, MK_RBUTTON
+     * which are allowed to
+     * generate the CLICK event after the RELEASE has happened.
+     * There are conditions that must be true for that sending CLICK event:
+     * 1) button was initially PRESSED
+     * 2) no movement or drag has happened until RELEASE
+    */
+    UINT m_mouseButtonClickAllowed;
+
     BOOL m_bSubclassed;
 
     COLORREF m_colorForeground;
--- a/jdk/src/windows/native/sun/windows/awt_TrayIcon.cpp	Wed Apr 09 09:37:07 2008 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_TrayIcon.cpp	Tue Apr 15 14:00:29 2008 +0400
@@ -84,7 +84,7 @@
     if (sm_instCount++ == 0 && AwtTrayIcon::sm_msgWindow == NULL) {
         sm_msgWindow = AwtTrayIcon::CreateMessageWindow();
     }
-    m_mouseDragState = 0;
+    m_mouseButtonClickAllowed = 0;
 }
 
 AwtTrayIcon::~AwtTrayIcon() {
@@ -349,7 +349,7 @@
     }
     lastTime = now;
     // it's needed only if WM_LBUTTONUP doesn't come for some reason
-    m_mouseDragState &= ~AwtComponent::GetButtonMK(button);
+    m_mouseButtonClickAllowed |= AwtComponent::GetButtonMK(button);
 
     MSG msg;
     AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
@@ -371,12 +371,12 @@
                    (AwtComponent::GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ?
                     TRUE : FALSE), AwtComponent::GetButton(button), &msg);
 
-    if (!(m_mouseDragState & AwtComponent::GetButtonMK(button))) { // No up-button in the drag-state
+    if ((m_mouseButtonClickAllowed & AwtComponent::GetButtonMK(button)) != 1) { // No up-button in the drag-state
         SendMouseEvent(java_awt_event_MouseEvent_MOUSE_CLICKED,
                        TimeHelper::windowsToUTC(::GetTickCount()), x, y, AwtComponent::GetJavaModifiers(),
                        clickCount, JNI_FALSE, AwtComponent::GetButton(button));
     }
-    m_mouseDragState &= ~AwtComponent::GetButtonMK(button); // Exclude the up-button from the drag-state
+    m_mouseButtonClickAllowed &= ~AwtComponent::GetButtonMK(button); // Exclude the up-button from the drag-state
 
     return mrConsume;
 }
@@ -398,7 +398,7 @@
         lastY = y;
         AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
         if ((flags & AwtComponent::ALL_MK_BUTTONS) != 0) {
-            m_mouseDragState = flags;
+            m_mouseButtonClickAllowed = 0;
         } else {
             SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, TimeHelper::windowsToUTC(::GetTickCount()), x, y,
                            AwtComponent::GetJavaModifiers(), 0, JNI_FALSE,
--- a/jdk/src/windows/native/sun/windows/awt_TrayIcon.h	Wed Apr 09 09:37:07 2008 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_TrayIcon.h	Tue Apr 15 14:00:29 2008 +0400
@@ -176,12 +176,14 @@
 private:
     AWT_NOTIFYICONDATA m_nid;
 
-    /*
-     * Keeps all buttons which were pressed at the time of the last mouse
-     * drag until all buttons will be released, contains state as bit masks
-     * MK_LBUTTON, MK_MBUTTON, MK_RBUTTON
-     */
-    UINT     m_mouseDragState;
+    /* A bitmask keeps the button's numbers as MK_LBUTTON, MK_MBUTTON, MK_RBUTTON
+     * which are allowed to
+     * generate the CLICK event after the RELEASE has happened.
+     * There are conditions that must be true for that sending CLICK event:
+     * 1) button was initially PRESSED
+     * 2) no movement or drag has happened until RELEASE
+    */
+    UINT m_mouseButtonClickAllowed;
 
     class TrayIconListItem {
       public: