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
--- 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: