Windows QPA: Fix multiple mouse button presses detection
The detection of multiple mouse button presses was broken in the new WM_POINTER-based implementation. The bug was due to the incorrect assumption that the press/release of a second mouse button (while another one is held) would also send WM_POINTERDOWN/WM_POINTERUP, while in fact it sends a WM_POINTERUPDATE with the actual event type given by pointerInfo->ButtonChangeType. Task-number: QTBUG-70787 Change-Id: Ib6776ab7f3d0b8eb5e832a0c863a15bde456e0dd Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
This commit is contained in:
parent
18be2337ea
commit
4840668994
@ -61,6 +61,8 @@
|
|||||||
#include <QtCore/qloggingcategory.h>
|
#include <QtCore/qloggingcategory.h>
|
||||||
#include <QtCore/qoperatingsystemversion.h>
|
#include <QtCore/qoperatingsystemversion.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -184,41 +186,65 @@ static void getMouseEventInfo(UINT message, POINTER_BUTTON_CHANGE_TYPE changeTyp
|
|||||||
{POINTER_CHANGE_FIFTHBUTTON_UP, Qt::XButton2},
|
{POINTER_CHANGE_FIFTHBUTTON_UP, Qt::XButton2},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const QHash<UINT, QEvent::Type> eventMapping {
|
static const POINTER_BUTTON_CHANGE_TYPE downChanges[] = {
|
||||||
{WM_POINTERUPDATE, QEvent::MouseMove},
|
POINTER_CHANGE_FIRSTBUTTON_DOWN,
|
||||||
{WM_POINTERDOWN, QEvent::MouseButtonPress},
|
POINTER_CHANGE_SECONDBUTTON_DOWN,
|
||||||
{WM_POINTERUP, QEvent::MouseButtonRelease},
|
POINTER_CHANGE_THIRDBUTTON_DOWN,
|
||||||
{WM_NCPOINTERUPDATE, QEvent::NonClientAreaMouseMove},
|
POINTER_CHANGE_FOURTHBUTTON_DOWN,
|
||||||
{WM_NCPOINTERDOWN, QEvent::NonClientAreaMouseButtonPress},
|
POINTER_CHANGE_FIFTHBUTTON_DOWN,
|
||||||
{WM_NCPOINTERUP, QEvent::NonClientAreaMouseButtonRelease},
|
};
|
||||||
{WM_POINTERWHEEL, QEvent::Wheel},
|
|
||||||
{WM_POINTERHWHEEL, QEvent::Wheel},
|
static const POINTER_BUTTON_CHANGE_TYPE upChanges[] = {
|
||||||
|
POINTER_CHANGE_FIRSTBUTTON_UP,
|
||||||
|
POINTER_CHANGE_SECONDBUTTON_UP,
|
||||||
|
POINTER_CHANGE_THIRDBUTTON_UP,
|
||||||
|
POINTER_CHANGE_FOURTHBUTTON_UP,
|
||||||
|
POINTER_CHANGE_FIFTHBUTTON_UP,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!eventType || !mouseButton)
|
if (!eventType || !mouseButton)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (message == WM_POINTERDOWN || message == WM_POINTERUP || message == WM_NCPOINTERDOWN || message == WM_NCPOINTERUP)
|
const bool nonClient = message == WM_NCPOINTERUPDATE ||
|
||||||
*mouseButton = buttonMapping.value(changeType, Qt::NoButton);
|
message == WM_NCPOINTERDOWN ||
|
||||||
else
|
message == WM_NCPOINTERUP;
|
||||||
*mouseButton = Qt::NoButton;
|
|
||||||
|
|
||||||
*eventType = eventMapping.value(message, QEvent::None);
|
if (std::find(std::begin(downChanges),
|
||||||
|
std::end(downChanges), changeType) < std::end(downChanges)) {
|
||||||
|
*eventType = nonClient ? QEvent::NonClientAreaMouseButtonPress :
|
||||||
|
QEvent::MouseButtonPress;
|
||||||
|
} else if (std::find(std::begin(upChanges),
|
||||||
|
std::end(upChanges), changeType) < std::end(upChanges)) {
|
||||||
|
*eventType = nonClient ? QEvent::NonClientAreaMouseButtonRelease :
|
||||||
|
QEvent::MouseButtonRelease;
|
||||||
|
} else if (message == WM_POINTERWHEEL || message == WM_POINTERHWHEEL) {
|
||||||
|
*eventType = QEvent::Wheel;
|
||||||
|
} else {
|
||||||
|
*eventType = nonClient ? QEvent::NonClientAreaMouseMove :
|
||||||
|
QEvent::MouseMove;
|
||||||
|
}
|
||||||
|
|
||||||
|
*mouseButton = buttonMapping.value(changeType, Qt::NoButton);
|
||||||
|
|
||||||
// Pointer messages lack a double click indicator. Check if this is the case here.
|
// Pointer messages lack a double click indicator. Check if this is the case here.
|
||||||
if (message == WM_POINTERDOWN) {
|
if (*eventType == QEvent::MouseButtonPress ||
|
||||||
|
*eventType == QEvent::NonClientAreaMouseButtonPress) {
|
||||||
static LONG lastTime = 0;
|
static LONG lastTime = 0;
|
||||||
static Qt::MouseButton lastButton = Qt::NoButton;
|
static Qt::MouseButton lastButton = Qt::NoButton;
|
||||||
|
static QEvent::Type lastEvent = QEvent::None;
|
||||||
static QPoint lastPos;
|
static QPoint lastPos;
|
||||||
LONG messageTime = GetMessageTime();
|
LONG messageTime = GetMessageTime();
|
||||||
if (*mouseButton == lastButton
|
if (*mouseButton == lastButton
|
||||||
|
&& *eventType == lastEvent
|
||||||
&& messageTime - lastTime < (LONG)GetDoubleClickTime()
|
&& messageTime - lastTime < (LONG)GetDoubleClickTime()
|
||||||
&& qAbs(globalPos.x() - lastPos.x()) < GetSystemMetrics(SM_CXDOUBLECLK)
|
&& qAbs(globalPos.x() - lastPos.x()) < GetSystemMetrics(SM_CXDOUBLECLK)
|
||||||
&& qAbs(globalPos.y() - lastPos.y()) < GetSystemMetrics(SM_CYDOUBLECLK)) {
|
&& qAbs(globalPos.y() - lastPos.y()) < GetSystemMetrics(SM_CYDOUBLECLK)) {
|
||||||
*eventType = QEvent::MouseButtonDblClick;
|
*eventType = nonClient ? QEvent::NonClientAreaMouseButtonDblClick :
|
||||||
|
QEvent::MouseButtonDblClick;
|
||||||
}
|
}
|
||||||
lastTime = messageTime;
|
lastTime = messageTime;
|
||||||
lastButton = *mouseButton;
|
lastButton = *mouseButton;
|
||||||
|
lastEvent = *eventType;
|
||||||
lastPos = globalPos;
|
lastPos = globalPos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user