xcb: when using XI2 for mouse, change state only on press and release
If the mouse event is synthesized from a touchscreen, since we're using XI2 we've already delivered the actual touch event by the time an XI_Motion event occurs. It's bogus to treat the XI_Motion event as a mouse press merely because XIMaskIsSet pretends that the mouse button is pressed. If the QPA motion event says that the button is pressed, then QGuiApplicationPrivate::processMouseEvent() will synthesize an extra mouse button event for the press, and another for the release. Task-number: QTBUG-56156 Change-Id: I937edfd8cc9aab5b21370036c4b42dc0c0a74b50 Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
parent
75aea3ff5e
commit
157ee01a8d
@ -2416,6 +2416,17 @@ static inline int fixed1616ToInt(FP1616 val)
|
||||
return int((qreal(val >> 16)) + (val & 0xFFFF) / (qreal)0xFFFF);
|
||||
}
|
||||
|
||||
void QXcbWindow::handleXIMouseButtonState(const xcb_ge_event_t *event)
|
||||
{
|
||||
QXcbConnection *conn = connection();
|
||||
const xXIDeviceEvent *ev = reinterpret_cast<const xXIDeviceEvent *>(event);
|
||||
if (ev->buttons_len > 0) {
|
||||
unsigned char *buttonMask = (unsigned char *) &ev[1];
|
||||
for (int i = 1; i <= 15; ++i)
|
||||
conn->setButton(conn->translateMouseButton(i), XIMaskIsSet(buttonMask, i));
|
||||
}
|
||||
}
|
||||
|
||||
// With XI 2.2+ press/release/motion comes here instead of the above handlers.
|
||||
void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource source)
|
||||
{
|
||||
@ -2431,12 +2442,6 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource
|
||||
|
||||
const Qt::MouseButton button = conn->xiToQtMouseButton(ev->detail);
|
||||
|
||||
if (ev->buttons_len > 0) {
|
||||
unsigned char *buttonMask = (unsigned char *) &ev[1];
|
||||
for (int i = 1; i <= 15; ++i)
|
||||
conn->setButton(conn->translateMouseButton(i), XIMaskIsSet(buttonMask, i));
|
||||
}
|
||||
|
||||
const char *sourceName = 0;
|
||||
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) {
|
||||
const QMetaObject *metaObject = qt_getEnumMetaObject(source);
|
||||
@ -2446,18 +2451,23 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource
|
||||
|
||||
switch (ev->evtype) {
|
||||
case XI_ButtonPress:
|
||||
handleXIMouseButtonState(event);
|
||||
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
|
||||
qCDebug(lcQpaXInputEvents, "XI2 mouse press, button %d, time %d, source %s", button, ev->time, sourceName);
|
||||
conn->setButton(button, true);
|
||||
handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, source);
|
||||
break;
|
||||
case XI_ButtonRelease:
|
||||
handleXIMouseButtonState(event);
|
||||
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
|
||||
qCDebug(lcQpaXInputEvents, "XI2 mouse release, button %d, time %d, source %s", button, ev->time, sourceName);
|
||||
conn->setButton(button, false);
|
||||
handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, source);
|
||||
break;
|
||||
case XI_Motion:
|
||||
// Here we do NOT call handleXIMouseButtonState because we don't expect button state change to be bundled with motion.
|
||||
// When a touchscreen is pressed, an XI_Motion event occurs in which XIMaskIsSet says the left button is pressed,
|
||||
// but we don't want QGuiApplicationPrivate::processMouseEvent() to react by generating a mouse press event.
|
||||
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
|
||||
qCDebug(lcQpaXInputEvents, "XI2 mouse motion %d,%d, time %d, source %s", event_x, event_y, ev->time, sourceName);
|
||||
handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time, source);
|
||||
|
@ -139,6 +139,7 @@ public:
|
||||
void handleFocusOutEvent(const xcb_focus_out_event_t *event) Q_DECL_OVERRIDE;
|
||||
void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) Q_DECL_OVERRIDE;
|
||||
#ifdef XCB_USE_XINPUT22
|
||||
void handleXIMouseButtonState(const xcb_ge_event_t *);
|
||||
void handleXIMouseEvent(xcb_ge_event_t *, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized) Q_DECL_OVERRIDE;
|
||||
void handleXIEnterLeave(xcb_ge_event_t *) Q_DECL_OVERRIDE;
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user