Skip to content

Commit

Permalink
Revert "xcb: handle XI2 input button and motion events from slave dev…
Browse files Browse the repository at this point in the history
…ices"

This reverts commit b71be29, 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
Pick-to: 6.8.0 6.8 6.7 6.5 6.2 5.15
Change-Id: I703158874413a1306ea99217bced4ba38382f543
Reviewed-by: Liang Qi <liang.qi@qt.io>
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
  • Loading branch information
liangqi committed Oct 1, 2024
1 parent c5ee1f6 commit 5875da6
Showing 1 changed file with 16 additions and 105 deletions.
121 changes: 16 additions & 105 deletions src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand All @@ -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
Expand Down

0 comments on commit 5875da6

Please sign in to comment.