diff options
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbconnection_xi2.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 110 |
1 files changed, 51 insertions, 59 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index b2dcf7c3e7..bfb3534879 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -52,12 +52,6 @@ void QXcbConnection::initializeXInput2() { - // TODO Qt 6 (or perhaps earlier): remove these redundant env variables - if (qEnvironmentVariableIsSet("QT_XCB_DEBUG_XINPUT")) - const_cast<QLoggingCategory&>(lcQpaXInput()).setEnabled(QtDebugMsg, true); - if (qEnvironmentVariableIsSet("QT_XCB_DEBUG_XINPUT_DEVICES")) - const_cast<QLoggingCategory&>(lcQpaXInputDevices()).setEnabled(QtDebugMsg, true); - Display *xDisplay = static_cast<Display *>(m_xlib_display); if (XQueryExtension(xDisplay, "XInputExtension", &m_xiOpCode, &m_xiEventBase, &m_xiErrorBase)) { int xiMajor = 2; @@ -325,12 +319,18 @@ void QXcbConnection::xi2SetupDevices() Display *xDisplay = static_cast<Display *>(m_xlib_display); int deviceCount = 0; XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount); + m_xiMasterPointerIds.clear(); for (int i = 0; i < deviceCount; ++i) { - // Only non-master pointing devices are relevant here. - if (devices[i].use != XISlavePointer) + XIDeviceInfo deviceInfo = devices[i]; + if (deviceInfo.use == XIMasterPointer) { + m_xiMasterPointerIds.append(deviceInfo.deviceid); continue; - xi2SetupDevice(&devices[i], false); + } + if (deviceInfo.use == XISlavePointer) // only slave pointer devices are relevant here + xi2SetupDevice(&deviceInfo, false); } + if (m_xiMasterPointerIds.size() > 1) + qCDebug(lcQpaXInputDevices) << "multi-pointer X detected"; XIFreeDeviceInfo(devices); } @@ -849,62 +849,54 @@ bool QXcbConnection::startSystemResizeForTouchBegin(xcb_window_t window, const Q bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab) { - if (grab && !canGrab()) - return false; - - int num_devices = 0; Display *xDisplay = static_cast<Display *>(xlib_display()); - XIDeviceInfo *info = XIQueryDevice(xDisplay, XIAllMasterDevices, &num_devices); - if (!info) - return false; - - XIEventMask evmask; - unsigned char mask[XIMaskLen(XI_LASTEVENT)]; - evmask.mask = mask; - evmask.mask_len = sizeof(mask); - memset(mask, 0, sizeof(mask)); - evmask.deviceid = XIAllMasterDevices; - - XISetMask(mask, XI_ButtonPress); - XISetMask(mask, XI_ButtonRelease); - XISetMask(mask, XI_Motion); - XISetMask(mask, XI_Enter); - XISetMask(mask, XI_Leave); - XISetMask(mask, XI_TouchBegin); - XISetMask(mask, XI_TouchUpdate); - XISetMask(mask, XI_TouchEnd); - - bool grabbed = true; - for (int i = 0; i < num_devices; i++) { - int id = info[i].deviceid, n = 0; - XIDeviceInfo *deviceInfo = XIQueryDevice(xDisplay, id, &n); - if (deviceInfo) { - const bool grabbable = deviceInfo->use != XIMasterKeyboard; - XIFreeDeviceInfo(deviceInfo); - if (!grabbable) - continue; - } - if (!grab) { - Status result = XIUngrabDevice(xDisplay, id, CurrentTime); - if (result != Success) { - grabbed = false; - qCDebug(lcQpaXInput, "XInput 2.2: failed to ungrab events for device %d (result %d)", id, result); - } - } else { - Status result = XIGrabDevice(xDisplay, id, w, CurrentTime, None, XIGrabModeAsync, - XIGrabModeAsync, False, &evmask); + bool ok = false; + + if (grab) { // grab + XIEventMask evmask; + unsigned char mask[XIMaskLen(XI_LASTEVENT)]; + evmask.mask = mask; + evmask.mask_len = sizeof(mask); + memset(mask, 0, sizeof(mask)); + XISetMask(mask, XI_ButtonPress); + XISetMask(mask, XI_ButtonRelease); + XISetMask(mask, XI_Motion); + XISetMask(mask, XI_Enter); + XISetMask(mask, XI_Leave); + XISetMask(mask, XI_TouchBegin); + XISetMask(mask, XI_TouchUpdate); + XISetMask(mask, XI_TouchEnd); + + for (int id : m_xiMasterPointerIds) { + evmask.deviceid = id; + Status result = XIGrabDevice(xDisplay, id, w, CurrentTime, None, + XIGrabModeAsync, XIGrabModeAsync, False, &evmask); if (result != Success) { - grabbed = false; - qCDebug(lcQpaXInput, "XInput 2.2: failed to grab events for device %d on window %x (result %d)", id, w, result); + qCDebug(lcQpaXInput, "failed to grab events for device %d on window %x" + "(result %d)", id, w, result); + } else { + // Managed to grab at least one of master pointers, that should be enough + // to properly dismiss windows that rely on mouse grabbing. + ok = true; } } + } else { // ungrab + for (int id : m_xiMasterPointerIds) { + Status result = XIUngrabDevice(xDisplay, id, CurrentTime); + if (result != Success) + qCDebug(lcQpaXInput, "XIUngrabDevice failed - id: %d (result %d)", id, result); + } + // XIUngrabDevice does not seem to wait for a reply from X server (similar to + // xcb_ungrab_pointer). Ungrabbing won't fail, unless NoSuchExtension error + // has occurred due to a programming error somewhere else in the stack. That + // would mean that things will crash soon anyway. + ok = true; } - XIFreeDeviceInfo(info); - - m_xiGrab = grabbed; + if (ok) + m_xiGrab = grab; - return grabbed; + return ok; } void QXcbConnection::xi2HandleHierarchyEvent(void *event) @@ -1340,7 +1332,7 @@ QXcbConnection::TabletData *QXcbConnection::tabletDataForDevice(int id) if (m_tabletData.at(i).deviceId == id) return &m_tabletData[i]; } - return Q_NULLPTR; + return nullptr; } #endif // QT_CONFIG(tabletevent) |