summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@theqtcompany.com>2015-02-24 17:19:40 +0100
committerFrederik Gladhorn <frederik.gladhorn@theqtcompany.com>2015-02-24 21:02:08 +0100
commit34b14a8472f44f8517577756e033b92ebd4c5912 (patch)
tree66a0575156d0a17a835430137e218e2b3f04cc65 /src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
parentd34353a065c443aac20376cbd88323480d769183 (diff)
parentedd555425a08f9e074f0a4d9333862636ccaae8d (diff)
Merge remote-tracking branch 'origin/5.4' into 5.5
Conflicts: examples/xml/htmlinfo/simpleexample.html examples/xml/rsslisting/rsslisting.cpp qmake/generators/win32/msbuild_objectmodel.cpp src/3rdparty/harfbuzz-ng/src/hb-private.hh src/corelib/global/qlogging.cpp src/corelib/io/qstorageinfo_unix.cpp src/corelib/thread/qwaitcondition_unix.cpp src/gui/kernel/qguiapplication.cpp src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp src/testlib/doc/src/qt-webpages.qdoc tests/auto/other/qaccessibility/tst_qaccessibility.cpp Change-Id: Ib272ff0bc30a1a5d51275eb3cd2f201dc82c11ff
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbconnection_xi2.cpp')
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp76
1 files changed, 66 insertions, 10 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index f225518cb9..e9fb47dabd 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -348,6 +348,7 @@ void QXcbConnection::xi2Select(xcb_window_t window)
// Listen for hotplug events
XIEventMask xiEventMask;
bitMask = XI_HierarchyChangedMask;
+ bitMask |= XI_DeviceChangedMask;
xiEventMask.deviceid = XIAllDevices;
xiEventMask.mask_len = sizeof(bitMask);
xiEventMask.mask = xiBitMask;
@@ -468,6 +469,11 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
xi2HandleHierachyEvent(xiEvent);
return;
}
+ if (xiEvent->evtype == XI_DeviceChanged) {
+ xi2HandleDeviceChangedEvent(xiEvent);
+ return;
+ }
+
#ifndef QT_NO_TABLETEVENT
for (int i = 0; i < m_tabletData.count(); ++i) {
if (m_tabletData.at(i).deviceId == xiEvent->deviceid) {
@@ -628,6 +634,64 @@ void QXcbConnection::xi2HandleHierachyEvent(void *event)
}
}
+void QXcbConnection::xi2HandleDeviceChangedEvent(void *event)
+{
+ xXIDeviceChangedEvent *xiEvent = reinterpret_cast<xXIDeviceChangedEvent *>(event);
+
+ // ### If a slave device changes (XIDeviceChange), we should probably run setup on it again.
+ if (xiEvent->reason != XISlaveSwitch)
+ return;
+
+#ifdef XCB_USE_XINPUT21
+ // This code handles broken scrolling device drivers that reset absolute positions
+ // when they are made active. Whenever a new slave device is made active the
+ // primary pointer sends a DeviceChanged event with XISlaveSwitch, and the new
+ // active slave in sourceid.
+
+ QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(xiEvent->sourceid);
+ if (device == m_scrollingDevices.end())
+ return;
+
+ int nrDevices = 0;
+ XIDeviceInfo* xiDeviceInfo = XIQueryDevice(static_cast<Display *>(m_xlib_display), xiEvent->sourceid, &nrDevices);
+ if (nrDevices <= 0) {
+ qCDebug(lcQpaXInputDevices, "scrolling device %d no longer present", xiEvent->sourceid);
+ return;
+ }
+ updateScrollingDevice(*device, xiDeviceInfo->num_classes, xiDeviceInfo->classes);
+ XIFreeDeviceInfo(xiDeviceInfo);
+#endif
+}
+
+void QXcbConnection::updateScrollingDevice(ScrollingDevice &scrollingDevice, int num_classes, void *classInfo)
+{
+#ifdef XCB_USE_XINPUT21
+ XIAnyClassInfo **classes = reinterpret_cast<XIAnyClassInfo**>(classInfo);
+ QPointF lastScrollPosition;
+ if (lcQpaXInput().isDebugEnabled())
+ lastScrollPosition = scrollingDevice.lastScrollPosition;
+ for (int c = 0; c < num_classes; ++c) {
+ if (classes[c]->type == XIValuatorClass) {
+ XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classes[c]);
+ const int valuatorAtom = qatom(vci->label);
+ if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
+ scrollingDevice.lastScrollPosition.setX(vci->value);
+ else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
+ scrollingDevice.lastScrollPosition.setY(vci->value);
+ }
+ }
+ if (lcQpaXInput().isDebugEnabled() && lastScrollPosition != scrollingDevice.lastScrollPosition)
+ qCDebug(lcQpaXInput, "scrolling device %d moved from (%f, %f) to (%f, %f)", scrollingDevice.deviceId,
+ lastScrollPosition.x(), lastScrollPosition.y(),
+ scrollingDevice.lastScrollPosition.x(),
+ scrollingDevice.lastScrollPosition.y());
+#else
+ Q_UNUSED(scrollingDevice);
+ Q_UNUSED(num_classes);
+ Q_UNUSED(classInfo);
+#endif
+}
+
void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *)
{
#ifdef XCB_USE_XINPUT21
@@ -638,19 +702,11 @@ void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *)
int nrDevices = 0;
XIDeviceInfo* xiDeviceInfo = XIQueryDevice(static_cast<Display *>(m_xlib_display), scrollingDevice.deviceId, &nrDevices);
if (nrDevices <= 0) {
+ qCDebug(lcQpaXInputDevices, "scrolling device %d no longer present", scrollingDevice.deviceId);
it = m_scrollingDevices.erase(it);
continue;
}
- for (int c = 0; c < xiDeviceInfo->num_classes; ++c) {
- if (xiDeviceInfo->classes[c]->type == XIValuatorClass) {
- XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(xiDeviceInfo->classes[c]);
- const int valuatorAtom = qatom(vci->label);
- if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
- scrollingDevice.lastScrollPosition.setX(vci->value);
- else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
- scrollingDevice.lastScrollPosition.setY(vci->value);
- }
- }
+ updateScrollingDevice(scrollingDevice, xiDeviceInfo->num_classes, xiDeviceInfo->classes);
XIFreeDeviceInfo(xiDeviceInfo);
++it;
}