Revert "xcb: handle XI2 input button and motion events from slave devices"

This reverts commit b71be292780b858f2c55ce92601452e2ea946de2, which causes a regression when using mouse wheel and moving cursor together
on scroll bar for some qt applications, like qutebrowser and
qbittorrent.

Fixes: QTBUG-129509
Fixes: QTBUG-129514
Task-number: QTBUG-110841
Change-Id: I703158874413a1306ea99217bced4ba38382f543
Reviewed-by: Liang Qi <liang.qi@qt.io>
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
(cherry picked from commit 5875da6d70303468eab85030a80f54c268f80b79)
This commit is contained in:
Liang Qi 2024-10-01 12:46:30 +02:00 committed by Jani Heikkinen
parent 063783b144
commit b839e9b36d

View File

@ -682,96 +682,23 @@ static inline qreal fixed1616ToReal(xcb_input_fp1616_t val)
return qreal(val) / 0x10000;
}
//implementation is ported from https://codereview.qt-project.org/c/qt/qtbase/+/231552/12/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp#558
namespace {
/*! \internal
Qt listens for XIAllDevices to avoid losing mouse events. This function
ensures that we don't process the same event twice: from a slave device and
then again from a master device.
In a normal use case (e.g. mouse press and release inside a window), we will
drop events from master devices as duplicates. Other advantage of processing
events from slave devices is that they don't share button state. All buttons
on a master device share the state.
Examples of special cases:
\list
\li During system move/resize, window manager (_NET_WM_MOVERESIZE) grabs the
master pointer, in this case we process the matching release from the slave
device. A master device event is not sent by the server, hence no duplicate
event to drop. If we listened for XIAllMasterDevices instead, we would never
see a release event in this case.
\li If we dismiss a context menu by clicking somewhere outside a Qt application,
we will process the mouse press from the master pointer as that is the
device we are grabbing. We are not grabbing slave devices (grabbing on the
slave device is buggy according to 19d289ab1b5bde3e136765e5432b5c7d004df3a4).
And since the event occurs outside our window, the slave device event is
not sent to us by the server, hence no duplicate event to drop.
\endlist
*/
bool isDuplicateEvent(xcb_ge_event_t *event)
{
Q_ASSERT(event);
struct qXIEvent {
bool isValid = false;
uint16_t sourceid;
uint8_t evtype;
uint32_t detail;
int32_t root_x;
int32_t root_y;
};
static qXIEvent lastSeenEvent;
bool isDuplicate = false;
auto *xiDeviceEvent = reinterpret_cast<qt_xcb_input_device_event_t *>(event);
if (lastSeenEvent.isValid) {
isDuplicate = lastSeenEvent.sourceid == xiDeviceEvent->sourceid &&
lastSeenEvent.evtype == xiDeviceEvent->event_type &&
lastSeenEvent.detail == xiDeviceEvent->detail &&
lastSeenEvent.root_x == xiDeviceEvent->root_x &&
lastSeenEvent.root_y == xiDeviceEvent->root_y;
} else {
lastSeenEvent.isValid = true;
}
lastSeenEvent.sourceid = xiDeviceEvent->sourceid;
lastSeenEvent.evtype = xiDeviceEvent->event_type;
lastSeenEvent.detail = xiDeviceEvent->detail;
lastSeenEvent.root_x = xiDeviceEvent->root_x;
lastSeenEvent.root_y = xiDeviceEvent->root_y;
if (isDuplicate) {
qCDebug(lcQpaXInputEvents, "Duplicate XI2 event %d", event->event_type);
// This sanity check ensures that special cases like QTBUG-59277 keep working.
lastSeenEvent.isValid = false; // An event can be a duplicate only once.
}
return isDuplicate;
}
} // namespace
void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
{
auto *xiEvent = reinterpret_cast<qt_xcb_input_device_event_t *>(event);
if (m_xiSlavePointerIds.contains(xiEvent->deviceid)) {
if (!(xiEvent->event_type == XCB_INPUT_BUTTON_PRESS
|| xiEvent->event_type == XCB_INPUT_BUTTON_RELEASE
|| xiEvent->event_type == XCB_INPUT_MOTION)) {
if (!m_duringSystemMoveResize)
return;
if (xiEvent->event == XCB_NONE)
return;
if (xiEvent->event_type == XCB_INPUT_TOUCH_END)
abortSystemMoveResize(xiEvent->event);
setTime(xiEvent->time);
if (m_xiSlavePointerIds.contains(xiEvent->deviceid) && xiEvent->event_type != XCB_INPUT_PROPERTY) {
if (!m_duringSystemMoveResize)
return;
if (xiEvent->event == XCB_NONE)
return;
if (xiEvent->event_type == XCB_INPUT_BUTTON_RELEASE
&& xiEvent->detail == XCB_BUTTON_INDEX_1 ) {
abortSystemMoveResize(xiEvent->event);
} else if (xiEvent->event_type == XCB_INPUT_TOUCH_END) {
abortSystemMoveResize(xiEvent->event);
return;
} else {
return;
}
}
@ -783,27 +710,11 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
switch (xiEvent->event_type) {
case XCB_INPUT_BUTTON_PRESS:
case XCB_INPUT_BUTTON_RELEASE:
case XCB_INPUT_MOTION: {
if (isDuplicateEvent(event))
return;
if (m_xiSlavePointerIds.contains(xiEvent->deviceid)) {
if (m_duringSystemMoveResize) {
if (xiEvent->event_type == XCB_INPUT_BUTTON_RELEASE
&& xiEvent->detail == XCB_BUTTON_INDEX_1 ) {
abortSystemMoveResize(xiEvent->event);
} else {
return;
}
}
}
xiDeviceEvent = xiEvent;
eventListener = windowEventListenerFromId(xiDeviceEvent->event);
sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master
break;
}
case XCB_INPUT_MOTION:
case XCB_INPUT_TOUCH_BEGIN:
case XCB_INPUT_TOUCH_UPDATE:
case XCB_INPUT_TOUCH_END: {
case XCB_INPUT_TOUCH_END:
{
xiDeviceEvent = xiEvent;
eventListener = windowEventListenerFromId(xiDeviceEvent->event);
sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master