6430553: MouseClick event should not be fired if MouseRelease happened without MousePress

Verify that the there was a PRESS event before sending CLICK event

Reviewed-by: son, dcherepanov
This commit is contained in:
Andrei Dmitriev 2008-04-15 14:00:29 +04:00
parent e1d1e39f49
commit bcbd82060a
5 changed files with 53 additions and 35 deletions

View file

@ -103,12 +103,14 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
return defaultFont; return defaultFont;
} }
/* /* A bitmask keeps the button's numbers as Button1Mask, Button2Mask, Button3Mask
* Keeps all buttons which were pressed at the time of the last mouse * which are allowed to
* drag until all buttons will be released, contains state as bit masks * generate the CLICK event after the RELEASE has happened.
* Button1Mask, Button2Mask, Button3Mask * 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 mouseDragState = 0; private int mouseButtonClickAllowed = 0;
native int getNativeColor(Color clr, GraphicsConfiguration gc); native int getNativeColor(Color clr, GraphicsConfiguration gc);
native void getWMInsets(long window, long left, long top, long right, long bottom, long border); native void getWMInsets(long window, long left, long top, long right, long bottom, long border);
@ -660,6 +662,8 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
} }
if (type == XConstants.ButtonPress) { 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); XWindow lastWindow = (lastWindowRef != null) ? ((XWindow)lastWindowRef.get()):(null);
/* /*
multiclick checking multiclick checking
@ -715,8 +719,8 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
postEventToEventQueue(me); postEventToEventQueue(me);
if (((mouseDragState & getButtonMask(lbutton)) == 0) && // No up-button in the drag-state if ((type == XConstants.ButtonRelease) &&
(type == XConstants.ButtonRelease)) ((mouseButtonClickAllowed & getButtonMask(lbutton)) != 0) ) // No up-button in the drag-state
{ {
postEventToEventQueue(me = new MouseEvent((Component)getEventSource(), postEventToEventQueue(me = new MouseEvent((Component)getEventSource(),
MouseEvent.MOUSE_CLICKED, MouseEvent.MOUSE_CLICKED,
@ -743,7 +747,11 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
} }
} }
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) { public void handleMotionNotify(XEvent xev) {
@ -776,7 +784,7 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
Math.abs(lastY - y) < AWT_MULTICLICK_SMUDGE))) { Math.abs(lastY - y) < AWT_MULTICLICK_SMUDGE))) {
clickCount = 0; clickCount = 0;
lastWindowRef = null; lastWindowRef = null;
mouseDragState = mouseKeyState; mouseButtonClickAllowed = 0;
lastTime = 0; lastTime = 0;
lastX = 0; lastX = 0;
lastY = 0; lastY = 0;

View file

@ -234,6 +234,7 @@ int AwtComponent::sm_wheelRotationAmount = 0;
AwtComponent::AwtComponent() AwtComponent::AwtComponent()
{ {
m_mouseButtonClickAllowed = 0;
m_callbacksEnabled = FALSE; m_callbacksEnabled = FALSE;
m_hwnd = NULL; m_hwnd = NULL;
@ -246,7 +247,6 @@ AwtComponent::AwtComponent()
m_nextControlID = 1; m_nextControlID = 1;
m_childList = NULL; m_childList = NULL;
m_myControlID = 0; m_myControlID = 0;
m_mouseDragState = 0;
m_hdwp = NULL; m_hdwp = NULL;
m_validationNestCount = 0; m_validationNestCount = 0;
@ -2514,9 +2514,11 @@ MsgRouting AwtComponent::WmMouseDown(UINT flags, int x, int y, int button)
lastClickX = x; lastClickX = x;
lastClickY = y; lastClickY = y;
} }
/*
*Set appropriate bit of the mask on WM_MOUSE_DOWN message.
*/
m_mouseButtonClickAllowed |= GetButtonMK(button);
lastTime = now; lastTime = now;
// it's needed only if WM_LBUTTONUP doesn't come for some reason
m_mouseDragState &= ~GetButtonMK(button);
MSG msg; MSG msg;
InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
@ -2554,14 +2556,17 @@ MsgRouting AwtComponent::WmMouseUp(UINT flags, int x, int y, int button)
(GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ? (GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ?
TRUE : FALSE), GetButton(button), &msg); 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, SendMouseEvent(java_awt_event_MouseEvent_MOUSE_CLICKED,
TimeHelper::getMessageTimeUTC(), x, y, GetJavaModifiers(), TimeHelper::getMessageTimeUTC(), x, y, GetJavaModifiers(),
clickCount, JNI_FALSE, GetButton(button)); 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) { if ((flags & ALL_MK_BUTTONS) == 0) {
// only update if all buttons have been released // only update if all buttons have been released
@ -2605,7 +2610,8 @@ MsgRouting AwtComponent::WmMouseMove(UINT flags, int x, int y)
SendMouseEvent(java_awt_event_MouseEvent_MOUSE_DRAGGED, TimeHelper::getMessageTimeUTC(), x, y, SendMouseEvent(java_awt_event_MouseEvent_MOUSE_DRAGGED, TimeHelper::getMessageTimeUTC(), x, y,
GetJavaModifiers(), 0, JNI_FALSE, GetJavaModifiers(), 0, JNI_FALSE,
java_awt_event_MouseEvent_NOBUTTON, &msg); 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 { } else {
MSG msg; MSG msg;
InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);

View file

@ -707,13 +707,6 @@ protected:
BOOL m_backgroundColorSet; BOOL m_backgroundColorSet;
BOOL m_visible; /* copy of Component.visible */ 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 BOOL sm_suppressFocusAndActivation;
static HWND sm_realFocusOpposite; static HWND sm_realFocusOpposite;
@ -725,6 +718,15 @@ protected:
static UINT sm_95WheelSupport; static UINT sm_95WheelSupport;
private: 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; BOOL m_bSubclassed;
COLORREF m_colorForeground; COLORREF m_colorForeground;

View file

@ -84,7 +84,7 @@ AwtTrayIcon::AwtTrayIcon() {
if (sm_instCount++ == 0 && AwtTrayIcon::sm_msgWindow == NULL) { if (sm_instCount++ == 0 && AwtTrayIcon::sm_msgWindow == NULL) {
sm_msgWindow = AwtTrayIcon::CreateMessageWindow(); sm_msgWindow = AwtTrayIcon::CreateMessageWindow();
} }
m_mouseDragState = 0; m_mouseButtonClickAllowed = 0;
} }
AwtTrayIcon::~AwtTrayIcon() { AwtTrayIcon::~AwtTrayIcon() {
@ -349,7 +349,7 @@ MsgRouting AwtTrayIcon::WmMouseDown(UINT flags, int x, int y, int button)
} }
lastTime = now; lastTime = now;
// it's needed only if WM_LBUTTONUP doesn't come for some reason // 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; MSG msg;
AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
@ -371,12 +371,12 @@ MsgRouting AwtTrayIcon::WmMouseUp(UINT flags, int x, int y, int button)
(AwtComponent::GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ? (AwtComponent::GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ?
TRUE : FALSE), AwtComponent::GetButton(button), &msg); 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, SendMouseEvent(java_awt_event_MouseEvent_MOUSE_CLICKED,
TimeHelper::windowsToUTC(::GetTickCount()), x, y, AwtComponent::GetJavaModifiers(), TimeHelper::windowsToUTC(::GetTickCount()), x, y, AwtComponent::GetJavaModifiers(),
clickCount, JNI_FALSE, AwtComponent::GetButton(button)); 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; return mrConsume;
} }
@ -398,7 +398,7 @@ MsgRouting AwtTrayIcon::WmMouseMove(UINT flags, int x, int y)
lastY = y; lastY = y;
AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
if ((flags & AwtComponent::ALL_MK_BUTTONS) != 0) { if ((flags & AwtComponent::ALL_MK_BUTTONS) != 0) {
m_mouseDragState = flags; m_mouseButtonClickAllowed = 0;
} else { } else {
SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, TimeHelper::windowsToUTC(::GetTickCount()), x, y, SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, TimeHelper::windowsToUTC(::GetTickCount()), x, y,
AwtComponent::GetJavaModifiers(), 0, JNI_FALSE, AwtComponent::GetJavaModifiers(), 0, JNI_FALSE,

View file

@ -176,12 +176,14 @@ public:
private: private:
AWT_NOTIFYICONDATA m_nid; AWT_NOTIFYICONDATA m_nid;
/* /* A bitmask keeps the button's numbers as MK_LBUTTON, MK_MBUTTON, MK_RBUTTON
* Keeps all buttons which were pressed at the time of the last mouse * which are allowed to
* drag until all buttons will be released, contains state as bit masks * generate the CLICK event after the RELEASE has happened.
* MK_LBUTTON, MK_MBUTTON, MK_RBUTTON * 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_mouseDragState; UINT m_mouseButtonClickAllowed;
class TrayIconListItem { class TrayIconListItem {
public: public: