Search
SailfishOS Open Build Service
>
Projects
>
home:sbinner
:
qt481
>
qt
> qt-4.8.0-Adapted-XInput2.0-code-to-support-multiple-connected.patch
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File qt-4.8.0-Adapted-XInput2.0-code-to-support-multiple-connected.patch of Package qt
From 7abf94c5a7d5705abf08f3cb5b917eb9928694fa Mon Sep 17 00:00:00 2001 From: Robin Burchell <robin.burchell@collabora.com> Date: Sun, 13 Nov 2011 12:37:56 +0100 Subject: [PATCH] Adapted XInput2.0 code to support multiple connected input devices Pointer input is received from the first Virtual Core Pointer. Additional master pointers are ignored. Touch input is received from any touch device conntected to the first Virtual Core Pointer or which is not attached to any Pointer. Signed-off-by: James Ketrenos <jketreno@linux.intel.com> --- src/gui/kernel/qapplication_x11.cpp | 502 ++++++++++++++++++----------------- src/gui/kernel/qcursor_x11.cpp | 8 +- src/gui/kernel/qt_x11_p.h | 14 +- src/gui/kernel/qwidget_x11.cpp | 44 ++-- src/gui/kernel/qx11embed_x11.cpp | 10 +- 5 files changed, 295 insertions(+), 283 deletions(-) diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 2e1fe98..9c88476 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -4,6 +4,9 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** +** Code contributions to adapt XInput2.0 portions to support multiple +** connected input devices are Copyright (C) 2011 Intel Corporation +** ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ @@ -1654,6 +1657,110 @@ static void getXDefault(const char *group, const char *key, bool *val) } #endif +#if !defined(QT_NO_XINPUT2) +// xiFindActiveDevice +// Used to determine if an input event's reported device Id is for +// either the Master core pointer or one of the attached Touch +// devices +int xiFindActiveDevice(int deviceId) +{ + if (!X11->xiDeviceInfo) + return -1; + + foreach (int id, X11->xiActiveDevices) { + if (id == deviceId) { + for (int i = 0; i < X11->xiDeviceCount; i++) + if (X11->xiDeviceInfo[i].deviceid == deviceId) + return i; + } + } + + return -1; +} + +// xiFreeDevices +// Helper function to clean up a few duplications of code +void xiFreeDevices() +{ + if (X11->xiDeviceInfo) { + X11->xiIsTouch.clear(); + X11->xibuttonclassinfo = 0; + XIFreeDeviceInfo(X11->xiDeviceInfo); + } +} + +// xiEnumerateDevices +// Query X for the full set of all input devices and attach to +// the first Virtual Core Pointer found, recording it as the +// xiMasterDeviceId Additionally, attach to any Touch enabled device +// that is either a Slave of that Core Pointer or is Floating +void xiEnumerateDevices() +{ + xiFreeDevices(); + + XIDeviceInfo *info; + X11->xiDeviceInfo = XIQueryDevice(QX11Info::display(), XIAllDevices, &X11->xiDeviceCount); + X11->xiIsTouch.reserve(X11->xiDeviceCount); + + // We connect to only the first Master Pointer for Touch and Pointer events. + // We connect to any Floating Slave pointers for Touch + X11->xiMasterIndex = -1; + X11->xiMasterDeviceId = -1; + for (int i = 0; i < X11->xiDeviceCount; i++) { + info = &X11->xiDeviceInfo[i]; + X11->xiIsTouch << false; + + // We will only take the first slave pointers from the first master pointer we find; we do not + if (info->use == XIMasterPointer && X11->xiMasterIndex != -1) { + qDebug() << "Skipping additional Master Pointer:" << info->name << "(" << info->deviceid << ")"; + continue; + } + + if (info->use == XIMasterPointer) { + X11->xiMasterIndex = i; + X11->xiMasterDeviceId = info->deviceid; + X11->xiIsTouch[i] = false; + qDebug() << "Adding Master Pointer:" << info->name << "(" << info->deviceid << ")"; + X11->xiActiveDevices.append(info->deviceid); + for (int j = 0; j < info->num_classes; ++j) { + if (info->classes[j]->type == XIButtonClass) { + X11->xibuttonclassinfo = (XIButtonClassInfo *) info->classes[j]; + break; + } + } + continue; + } + + if (info->use == XIFloatingSlave || info->use == XISlavePointer) { + if (info->use == XISlavePointer && info->attachment != X11->xiMasterDeviceId) { + qDebug() << "Skipping Slave on non-Master:" << info->name << "(" << info->deviceid << ")"; + continue; + } + + for (int j = 0; j < info->num_classes; j++) { + if (info->classes[j]->type == XIValuatorClass) { + XIValuatorClassInfo *valuator = (XIValuatorClassInfo *)(info->classes[j]); + // If this device doesn't support the AbsMTTrackingID then we can't use it as a touch device + if (valuator->label == ATOM(AbsMTTrackingID)) { + X11->xiIsTouch[i] = true; + break; + } + } + } + + if (X11->xiIsTouch[i]) { + qDebug() << "Adding" << (info->use == XIFloatingSlave ? "FLOATING" : "ATTACHED") << "touch device:" << info->name << "(" << info->deviceid << ")"; + X11->xiActiveDevices.append(info->deviceid); + } else { + qDebug() << "Skipping non-Touch device:" << info->name << "(" << info->deviceid << ")"; + } + } + } +} + +#endif + + // ### This should be static but it isn't because of the friend declaration // ### in qpaintdevice.h which then should have a static too but can't have // ### it because "storage class specifiers invalid in friend function @@ -1690,9 +1797,9 @@ void qt_init(QApplicationPrivate *priv, int, X11->xinput_eventbase = 0; X11->xinput_errorbase = 0; #if !defined(QT_NO_XINPUT2) - X11->xideviceinfo = 0; - X11->xibuttonclassinfo = 0; - X11->xiMaxContacts = 0; + X11->xiDeviceInfo = 0; + X11->xiDeviceCount = 0; + X11->xiMasterIndex = 0; #endif X11->use_xkb = false; @@ -2187,61 +2294,7 @@ void qt_init(QApplicationPrivate *priv, int, XISelectEvents(X11->display, DefaultRootWindow(X11->display), &xieventmask, 1); - // find the first master pointer and use this throughout Qt - // when making XI2 calls that need a device id (rationale is that - // for the time being, most setups will only have one master - // pointer (despite having multiple slaves) - int deviceCount = 0; - XIDeviceInfo *devices = XIQueryDevice(X11->display, XIAllMasterDevices, &deviceCount); - if (devices) { - for (int i = 0; i < deviceCount; ++i) { - if (devices[i].use == XIMasterPointer) { - int unused = 0; - X11->xideviceinfo = XIQueryDevice(X11->display, devices[i].deviceid, &unused); - break; - } - } - XIFreeDeviceInfo(devices); - } - if (!X11->xideviceinfo) - qFatal("Qt: Internal error, no XI2 master pointer found."); - - // find the button info - X11->xibuttonclassinfo = 0; - for (int i = 0; i < X11->xideviceinfo->num_classes; ++i) { - if (X11->xideviceinfo->classes[i]->type == XIButtonClass) { - X11->xibuttonclassinfo = (XIButtonClassInfo *) X11->xideviceinfo->classes[i]; - break; - } - } - - // find the "Max Contacts" property on the device - Atom typeReturn; - int formatReturn; - ulong countReturn, bytesReturn; - uchar *data = 0; - if (XIGetProperty(X11->display, - X11->xibuttonclassinfo->sourceid, - ATOM(MaxContacts), - 0, 1, - False, - XA_INTEGER, - &typeReturn, - &formatReturn, - &countReturn, - &bytesReturn, - &data) == Success - && data != 0 - && typeReturn == XA_INTEGER - && formatReturn == 8 - && countReturn == 1) { - // multi-touch driver reported the max number of touch-points - X11->xiMaxContacts = data[0]; - } else { - X11->xiMaxContacts = 0; - } - if (data) - XFree(data); + xiEnumerateDevices(); } } #elif !defined(QT_NO_XINPUT) @@ -2770,11 +2823,7 @@ void qt_cleanup() if (qt_is_gui_used) { #if !defined(QT_NO_XINPUT2) - if (X11->xideviceinfo) - XIFreeDeviceInfo(X11->xideviceinfo); - X11->xideviceinfo = 0; - X11->xibuttonclassinfo = 0; - X11->xiMaxContacts = 0; + xiFreeDevices(); #endif QPixmapCache::clear(); @@ -3414,48 +3463,9 @@ int QApplication::x11ProcessEvent(XEvent* event) case XI_DeviceChanged: { XIDeviceChangedEvent *xidevicechangedevent = (XIDeviceChangedEvent *) event->xcookie.data; - - int unused = X11->xideviceinfo->deviceid; - XIFreeDeviceInfo(X11->xideviceinfo); - X11->xideviceinfo = XIQueryDevice(X11->display, unused, &unused); - if (xidevicechangedevent->reason == XISlaveSwitch) { - // device has changed capabilities, find the button class info - X11->xibuttonclassinfo = 0; - for (int i = 0; i < X11->xideviceinfo->num_classes; ++i) { - if (X11->xideviceinfo->classes[i]->type == XIButtonClass) { - X11->xibuttonclassinfo = (XIButtonClassInfo *) X11->xideviceinfo->classes[i]; - break; - } - } - - // is this still a multi-touch device? find the "Max Contacts" property on the device - Atom typeReturn; - int formatReturn; - ulong countReturn, bytesReturn; - uchar *data = 0; - if (XIGetProperty(X11->display, - X11->xibuttonclassinfo->sourceid, - ATOM(MaxContacts), - 0, 1, - False, - XA_INTEGER, - &typeReturn, - &formatReturn, - &countReturn, - &bytesReturn, - &data) == Success - && data != 0 - && typeReturn == XA_INTEGER - && formatReturn == 8 - && countReturn == 1) { - // multi-touch driver reported the max number of touch-points - X11->xiMaxContacts = data[0]; - } else { - X11->xiMaxContacts = 0; - } - if (data) - XFree(data); + qDebug("XISlaveSwitch"); + xiEnumerateDevices(); } else { // ### TODO: handle this type of event qDebug("XI_DeviceChanged, id %d, source %d, reason %d", @@ -3468,6 +3478,7 @@ int QApplication::x11ProcessEvent(XEvent* event) case XI_HierarchyChanged: // ### TODO: handle this type of event qDebug("XI_HierarchyChanged"); + xiEnumerateDevices(); break; case XI_ButtonPress: case XI_ButtonRelease: @@ -3852,8 +3863,9 @@ int QApplication::x11ProcessEvent(XEvent* event) if (isXI2Event) { XIEnterEvent *xienterevent = (XIEnterEvent *) event->xcookie.data; - if (X11->xideviceinfo->deviceid != xienterevent->deviceid) - qFatal("Qt: Internal error, don't know how to handle events from a different master pointer"); + if (X11->xiMasterIndex != -1 && + X11->xiMasterDeviceId == xienterevent->deviceid) + break; mode = xienterevent->mode; detail = xienterevent->detail; @@ -3918,8 +3930,9 @@ int QApplication::x11ProcessEvent(XEvent* event) if (isXI2Event) { XIEnterEvent *xienterevent = (XIEnterEvent *) event->xcookie.data; - if (X11->xideviceinfo->deviceid != xienterevent->deviceid) - qFatal("Qt: Internal error, don't know how to handle events from a different master pointer"); + if (X11->xiMasterIndex != -1 && + X11->xiMasterDeviceId == xienterevent->deviceid) + break; mode = xienterevent->mode; detail = xienterevent->detail; @@ -4465,7 +4478,7 @@ void QApplicationPrivate::openPopup(QWidget *popup) XIEventMask xieventmask; uchar bitmask[2] = { 0, 0 }; - xieventmask.deviceid = X11->xideviceinfo->deviceid; + xieventmask.deviceid = X11->xiMasterDeviceId; xieventmask.mask = bitmask; xieventmask.mask_len = sizeof(bitmask); @@ -4476,7 +4489,7 @@ void QApplicationPrivate::openPopup(QWidget *popup) XISetMask(bitmask, XI_Leave); r = XIGrabDevice(X11->display, - X11->xideviceinfo->deviceid, + xieventmask.deviceid, popup->effectiveWinId(), X11->time, XNone, @@ -4544,7 +4557,7 @@ void QApplicationPrivate::closePopup(QWidget *popup) } else { #if !defined(QT_NO_XINPUT2) if (X11->use_xinput) - XIUngrabDevice(X11->display, X11->xideviceinfo->deviceid, X11->time); + XIUngrabDevice(X11->display, X11->xiMasterDeviceId, X11->time); else #endif XUngrabPointer(dpy, X11->time); @@ -4589,7 +4602,7 @@ void QApplicationPrivate::closePopup(QWidget *popup) XIEventMask xieventmask; uchar bitmask[2] = { 0, 0 }; - xieventmask.deviceid = X11->xideviceinfo->deviceid; + xieventmask.deviceid = X11->xiMasterDeviceId; xieventmask.mask = bitmask; xieventmask.mask_len = sizeof(bitmask); @@ -4600,7 +4613,7 @@ void QApplicationPrivate::closePopup(QWidget *popup) XISetMask(bitmask, XI_Leave); r = XIGrabDevice(X11->display, - X11->xideviceinfo->deviceid, + xieventmask.deviceid, aw->effectiveWinId(), X11->time, XNone, @@ -5091,12 +5104,15 @@ bool QETWidget::translateXI2Event(const XIEvent *xievent) XIDeviceEvent *motionevent = (XIDeviceEvent *) xievent; XIDeviceEvent lastMotion = *motionevent; + int index = xiFindActiveDevice(motionevent->deviceid); + bool isTouch = (index == -1) ? false : X11->xiIsTouch[index]; + Qt::MouseButtons buttons; Qt::KeyboardModifiers modifiers; Qt::MouseButtons lastButtons; uint activeTouchPoints = 0; Qt::KeyboardModifiers lastModifiers = X11->translateModifiers(lastMotion.mods.effective); - if (X11->xiMaxContacts == 0) { // if mouse + if (!isTouch) { // if mouse lastButtons = translateXI2MouseButtons(&lastMotion.buttons); } else { // else touch // get a list of currently active touch points @@ -5129,73 +5145,58 @@ bool QETWidget::translateXI2Event(const XIEvent *xievent) (Atom)ev.xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST))))) { qApp->x11ProcessEvent(&ev); continue; - } else if (X11->xiMaxContacts == 0 // if mouse event - && ev.type == GenericEvent - && ev.xcookie.extension == X11->xinput_opcode - && ev.xcookie.evtype == XI_Motion - && XGetEventData(X11->display, &ev.xcookie)) { + } else if (ev.type == GenericEvent + && ev.xcookie.extension == X11->xinput_opcode + && ev.xcookie.evtype == XI_Motion + && XGetEventData(X11->display, &ev.xcookie)) { // this is an XI_Motion event... motionevent = (XIDeviceEvent *) ev.xcookie.data; - buttons = translateXI2MouseButtons(&motionevent->buttons); - modifiers = X11->translateModifiers(motionevent->mods.effective); - // .. can we compress it? - if (motionevent->event == lastMotion.event - && buttons == lastButtons - && modifiers == lastModifiers) { - // send event through filters - if (!qt_x11EventFilter(&ev) && !x11Event(&ev)) { - // compress this motion event - lastMotion = *motionevent; - lastButtons = buttons; - lastModifiers = modifiers; - XFreeEventData(X11->display, &ev.xcookie); - continue; - } else { - // filtered - XFreeEventData(X11->display, &ev.xcookie); - break; - } - } - - // different state or different window, put this event back and stop compression - XPutBackEvent(X11->display, &ev); - XFreeEventData(X11->display, &ev.xcookie); - break; - } else if (X11->xiMaxContacts != 0 // if touch event - && ev.type == GenericEvent - && ev.xcookie.extension == X11->xinput_opcode - && ev.xcookie.evtype == XI_Motion - && XGetEventData(X11->display, &ev.xcookie)) { - // this is an XI_Motion event... - motionevent = (XIDeviceEvent *) ev.xcookie.data; modifiers = X11->translateModifiers(motionevent->mods.effective); - + int index = xiFindActiveDevice(motionevent->deviceid); + if (index == -1) { + // Can not find device in our Active list; likely from multiple master pointers... + XPutBackEvent(X11->display, &ev); + XFreeEventData(X11->display, &ev.xcookie); + break; + } uint active = 0; - for (int i = 0; i < X11->xideviceinfo->num_classes; ++i) { - XIAnyClassInfo *classinfo = X11->xideviceinfo->classes[i]; - if (classinfo->type == XIValuatorClass) { - XIValuatorClassInfo *valuatorclassinfo = reinterpret_cast<XIValuatorClassInfo *>(classinfo); - int n = valuatorclassinfo->number; - - if (!XIMaskIsSet(motionevent->valuators.mask, n)) - continue; - - if (valuatorclassinfo->label == ATOM(AbsMTTrackingID)) { - int id = motionevent->valuators.values[n]; - active |= 1 << id; + bool isTouch = X11->xiIsTouch[index]; + if (isTouch) + { + for (int i = 0; i < X11->xiDeviceInfo[index].num_classes; ++i) { + XIAnyClassInfo *classinfo = X11->xiDeviceInfo[index].classes[i]; + if (classinfo->type == XIValuatorClass) { + XIValuatorClassInfo *valuatorclassinfo = reinterpret_cast<XIValuatorClassInfo *>(classinfo); + int n = valuatorclassinfo->number; + + if (!XIMaskIsSet(motionevent->valuators.mask, n)) + continue; + + if (valuatorclassinfo->label == ATOM(AbsMTTrackingID)) { + int id = motionevent->valuators.values[n]; + active |= 1 << id; + } } } } + else + { + buttons = translateXI2MouseButtons(&motionevent->buttons); + } // .. can we compress it? if (motionevent->event == lastMotion.event - && modifiers == lastModifiers - && activeTouchPoints == active) { + && modifiers == lastModifiers + && (isTouch || buttons == lastButtons) + && (!isTouch || activeTouchPoints == active)) { // send event through filters if (!qt_x11EventFilter(&ev) && !x11Event(&ev)) { // compress this motion event lastMotion = *motionevent; + if (isTouch) + lastButtons = buttons; + lastModifiers = modifiers; XFreeEventData(X11->display, &ev.xcookie); continue; } else { @@ -5215,98 +5216,99 @@ bool QETWidget::translateXI2Event(const XIEvent *xievent) XPutBackEvent(X11->display, &ev); break; } - - if (X11->xideviceinfo->deviceid != lastMotion.deviceid) - qFatal("Qt: Internal error, don't know how to handle events from a different master pointer"); } - if (X11->xiMaxContacts != 0 - && (xievent->evtype == XI_ButtonPress - || xievent->evtype == XI_ButtonRelease - || xievent->evtype == XI_Motion)) { + bool isTouch = false; + if (xievent->evtype == XI_ButtonPress + || xievent->evtype == XI_ButtonRelease + || xievent->evtype == XI_Motion) { const XIDeviceEvent *xideviceevent = reinterpret_cast<const XIDeviceEvent *>(xievent); - QList<QTouchEvent::TouchPoint> touchPoints = qApp->d_func()->appAllTouchPoints; - if (touchPoints.count() != X11->xiMaxContacts) { - // initial event, allocate space for all (potential) touch points - touchPoints.reserve(X11->xiMaxContacts); - for (int i = 0; i < X11->xiMaxContacts; ++i) - touchPoints << QTouchEvent::TouchPoint(i); - } - qreal x, y, nx, ny, w = 0.0, h = 0.0, p = -1.0; - x = y = nx = ny = 0.0; - int id; - uint active = 0; - for (int i = 0; i < X11->xideviceinfo->num_classes; ++i) { - XIAnyClassInfo *classinfo = X11->xideviceinfo->classes[i]; - if (classinfo->type == XIValuatorClass) { - XIValuatorClassInfo *valuatorclassinfo = reinterpret_cast<XIValuatorClassInfo *>(classinfo); - int n = valuatorclassinfo->number; - - if (!XIMaskIsSet(xideviceevent->valuators.mask, n)) - continue; + int index = xiFindActiveDevice(xideviceevent->deviceid); + isTouch = (index == -1) ? false : X11->xiIsTouch[index]; + if (isTouch) { + QList<QTouchEvent::TouchPoint> touchPoints = qApp->d_func()->appAllTouchPoints; + if (touchPoints.count() != 10) { //X11->xiMaxContacts) { + // initial event, allocate space for all (potential) touch points + touchPoints.reserve(10); + for (int i = 0; i < 10; ++i) + touchPoints << QTouchEvent::TouchPoint(i); + } + qreal x, y, nx, ny, w = 0.0, h = 0.0, p = -1.0; + x = y = nx = ny = 0.0; + int id; + uint active = 0; + for (int i = 0; i < X11->xiDeviceInfo[index].num_classes; ++i) { + XIAnyClassInfo *classinfo = X11->xiDeviceInfo[index].classes[i]; + if (classinfo->type == XIValuatorClass) { + XIValuatorClassInfo *valuatorclassinfo = reinterpret_cast<XIValuatorClassInfo *>(classinfo); + int n = valuatorclassinfo->number; + + if (!XIMaskIsSet(xideviceevent->valuators.mask, n)) + continue; - if (valuatorclassinfo->label == ATOM(AbsMTPositionX)) { - x = xideviceevent->valuators.values[n]; - nx = (x - valuatorclassinfo->min) / (valuatorclassinfo->max - valuatorclassinfo->min); - } else if (valuatorclassinfo->label == ATOM(AbsMTPositionY)) { - y = xideviceevent->valuators.values[n]; - ny = (y - valuatorclassinfo->min) / (valuatorclassinfo->max - valuatorclassinfo->min); - } else if (valuatorclassinfo->label == ATOM(AbsMTTouchMajor)) { - w = xideviceevent->valuators.values[n]; - } else if (valuatorclassinfo->label == ATOM(AbsMTTouchMinor)) { - h = xideviceevent->valuators.values[n]; - } else if (valuatorclassinfo->label == ATOM(AbsMTPressure)) { - p = (xideviceevent->valuators.values[n] - valuatorclassinfo->min) / (valuatorclassinfo->max - valuatorclassinfo->min); - } else if (valuatorclassinfo->label == ATOM(AbsMTTrackingID)) { - id = xideviceevent->valuators.values[n]; - active |= 1 << id; - QTouchEvent::TouchPoint &touchPoint = touchPoints[id]; - - Qt::TouchPointStates newstate; - if (touchPoint.state() == Qt::TouchPointReleased) { - newstate |= Qt::TouchPointPressed; - } else { - if (touchPoint.screenPos() != QPoint(x, y)) - newstate |= Qt::TouchPointMoved; + if (valuatorclassinfo->label == ATOM(AbsMTPositionX)) { + x = xideviceevent->valuators.values[n]; + nx = (x - valuatorclassinfo->min) / (valuatorclassinfo->max - valuatorclassinfo->min); + } else if (valuatorclassinfo->label == ATOM(AbsMTPositionY)) { + y = xideviceevent->valuators.values[n]; + ny = (y - valuatorclassinfo->min) / (valuatorclassinfo->max - valuatorclassinfo->min); + } else if (valuatorclassinfo->label == ATOM(AbsMTTouchMajor)) { + w = xideviceevent->valuators.values[n]; + } else if (valuatorclassinfo->label == ATOM(AbsMTTouchMinor)) { + h = xideviceevent->valuators.values[n]; + } else if (valuatorclassinfo->label == ATOM(AbsMTPressure)) { + p = (xideviceevent->valuators.values[n] - valuatorclassinfo->min) / (valuatorclassinfo->max - valuatorclassinfo->min); + } else if (valuatorclassinfo->label == ATOM(AbsMTTrackingID)) { + id = xideviceevent->valuators.values[n]; + active |= 1 << id; + QTouchEvent::TouchPoint &touchPoint = touchPoints[id]; + + Qt::TouchPointStates newstate; + if (touchPoint.state() == Qt::TouchPointReleased) { + newstate |= Qt::TouchPointPressed; + } else { + if (touchPoint.screenPos() != QPoint(x, y)) + newstate |= Qt::TouchPointMoved; + else + newstate |= Qt::TouchPointStationary; + } + + if (id == 0) + newstate |= Qt::TouchPointPrimary; + + touchPoint.setState(newstate); + if (w != 0.0 && h != 0.0) + touchPoint.setScreenRect(QRectF((nx * width) - w/2, (ny * height) - h/2, w, h)); else - newstate |= Qt::TouchPointStationary; + touchPoint.setScreenPos(QPoint(nx * width, ny * height)); + touchPoint.setNormalizedPos(QPointF(nx, ny)); + touchPoint.setPressure(p); } + } + } - if (id == 0) + // mark previously-active-but-now-inactive touch points as released + for (int i = 0; i < touchPoints.count(); ++i) { + if (!(active & (1 << i)) && touchPoints.at(i).state() != Qt::TouchPointReleased) { + Qt::TouchPointStates newstate = Qt::TouchPointReleased; + + if (touchPoints.at(i).id() == 0) newstate |= Qt::TouchPointPrimary; - touchPoint.setState(newstate); - if (w != 0.0 && h != 0.0) - touchPoint.setScreenRect(QRectF((nx * width) - w/2, (ny * height) - h/2, w, h)); - else - touchPoint.setScreenPos(QPoint(nx * width, ny * height)); - touchPoint.setNormalizedPos(QPointF(nx, ny)); - touchPoint.setPressure(p); + touchPoints[i].setState(newstate); } } - } - - // mark previously-active-but-now-inactive touch points as released - for (int i = 0; i < touchPoints.count(); ++i) { - if (!(active & (1 << i)) && touchPoints.at(i).state() != Qt::TouchPointReleased) { - Qt::TouchPointStates newstate = Qt::TouchPointReleased; - if (touchPoints.at(i).id() == 0) - newstate |= Qt::TouchPointPrimary; - - touchPoints[i].setState(newstate); + if (xideviceevent->evtype == XI_ButtonRelease) { + // final event, forget touch state + qApp->d_func()->appAllTouchPoints.clear(); + } else { + // save current state so that we have something to reuse later + qApp->d_func()->appAllTouchPoints = touchPoints; } - } - if (xideviceevent->evtype == XI_ButtonRelease) { - // final event, forget touch state - qApp->d_func()->appAllTouchPoints.clear(); - } else { - // save current state so that we have something to reuse later - qApp->d_func()->appAllTouchPoints = touchPoints; + QApplicationPrivate::translateRawTouchEvent(this, QTouchEvent::TouchScreen, touchPoints); } - - QApplicationPrivate::translateRawTouchEvent(this, QTouchEvent::TouchScreen, touchPoints); } // event parameters @@ -5322,13 +5324,13 @@ bool QETWidget::translateXI2Event(const XIEvent *xievent) if (xievent->evtype == XI_Motion) { XIDeviceEvent *motionevent = (XIDeviceEvent *) xievent; + if (X11->xiMasterIndex == -1 || motionevent->deviceid != X11->xiMasterDeviceId) + return sendMouseEvent(xtype, window, type, pos, globalPos, button, buttons, modifiers); + XIDeviceEvent lastMotion = *motionevent; Qt::MouseButtons lastButtons = translateXI2MouseButtons(&lastMotion.buttons); Qt::KeyboardModifiers lastModifiers = X11->translateModifiers(lastMotion.mods.effective); - if (X11->xideviceinfo->deviceid != lastMotion.deviceid) - qFatal("Qt: Internal error, don't know how to handle events from a different master pointer"); - xtype = MotionNotify; window = lastMotion.event; type = QEvent::MouseMove; @@ -5344,8 +5346,8 @@ bool QETWidget::translateXI2Event(const XIEvent *xievent) } else if (xievent->evtype == XI_Enter || xievent->evtype == XI_Leave) { XIEnterEvent *enterevent = (XIEnterEvent *) xievent; - if (X11->xideviceinfo->deviceid != enterevent->deviceid) - qFatal("Qt: Internal error, don't know how to handle events from a different master pointer"); + if (X11->xiMasterIndex == -1 || enterevent->deviceid != X11->xiMasterDeviceId) + return sendMouseEvent(xtype, window, type, pos, globalPos, button, buttons, modifiers); xtype = enterevent->evtype == XI_Enter ? EnterNotify : LeaveNotify; window = enterevent->event; @@ -5365,8 +5367,8 @@ bool QETWidget::translateXI2Event(const XIEvent *xievent) // XI_ButtonPress or XI_ButtonRelease XIDeviceEvent *deviceevent = (XIDeviceEvent *) xievent; - if (X11->xideviceinfo->deviceid != deviceevent->deviceid) - qFatal("Qt: Internal error, don't know how to handle events from a different master pointer"); + if (X11->xiMasterIndex == -1 || deviceevent->deviceid != X11->xiMasterDeviceId) + return sendMouseEvent(xtype, window, type, pos, globalPos, button, buttons, modifiers); xtype = deviceevent->evtype == XI_ButtonPress ? ButtonPress : ButtonRelease; window = deviceevent->event; diff --git a/src/gui/kernel/qcursor_x11.cpp b/src/gui/kernel/qcursor_x11.cpp index 7faf930..c0d6ee8 100644 --- a/src/gui/kernel/qcursor_x11.cpp +++ b/src/gui/kernel/qcursor_x11.cpp @@ -162,7 +162,7 @@ QPoint QCursor::pos() XIGroupState groups; for (int i = 0; i < ScreenCount(X11->display); ++i) { if (XIQueryPointer(X11->display, - X11->xideviceinfo->deviceid, + X11->xiMasterDeviceId, QX11Info::appRootWindow(i), &root, &child, @@ -207,7 +207,7 @@ int QCursor::x11Screen() XIGroupState groups; for (int i = 0; i < ScreenCount(X11->display); ++i) { if (XIQueryPointer(X11->display, - X11->xideviceinfo->deviceid, + X11->xiMasterDeviceId, QX11Info::appRootWindow(i), &root, &child, @@ -254,7 +254,7 @@ void QCursor::setPos(int x, int y) XIGroupState groups; for (screen = 0; screen < ScreenCount(X11->display); ++screen) { if (XIQueryPointer(X11->display, - X11->xideviceinfo->deviceid, + X11->xiMasterDeviceId, QX11Info::appRootWindow(screen), &root, &child, @@ -295,7 +295,7 @@ void QCursor::setPos(int x, int y) #if !defined(QT_NO_XINPUT2) if (X11->use_xinput) - XIWarpPointer(X11->display, X11->xideviceinfo->deviceid, XNone, QX11Info::appRootWindow(screen), 0, 0, 0, 0, x, y); + XIWarpPointer(X11->display, X11->xiMasterDeviceId, XNone, QX11Info::appRootWindow(screen), 0, 0, 0, 0, x, y); else #endif XWarpPointer(X11->display, XNone, QX11Info::appRootWindow(screen), 0, 0, 0, 0, x, y); diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h index c1056cd..26a9ab5 100644 --- a/src/gui/kernel/qt_x11_p.h +++ b/src/gui/kernel/qt_x11_p.h @@ -423,10 +423,16 @@ struct QX11Data #endif #if !defined(QT_NO_XINPUT2) - // device info for the master pointer Qt is using - XIDeviceInfo *xideviceinfo; - XIButtonClassInfo *xibuttonclassinfo; - int xiMaxContacts; + XIDeviceInfo *xiDeviceInfo; // device info for all connected devices + int xiDeviceCount; + int xiMasterIndex; // Index in xiDeviceInfo of the Master core pointer device + int xiMasterDeviceId; // Device Id of the Master core pointer + XIButtonClassInfo *xibuttonclassinfo; // button class information for the Master pointer + // Touch devices can be slaves or floating; they are not necessarily bound to a core pointer + // So we create a list of all of the 'active' devices to listen to and grab. This list + // will contain any device that supports the TrackingID and the Master Core Pointer + QList<int> xiActiveDevices; + QList<bool> xiIsTouch; #elif !defined(QT_NO_XINPUT) PtrXCloseDevice ptrXCloseDevice; PtrXListInputDevices ptrXListInputDevices; diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index 859ccee..8754a62 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -330,13 +330,13 @@ void qt_x11_enforce_cursor(QWidget * w, bool force) if (X11->use_xinput) { // duplicated below (more or less) if (oc) { - XIDefineCursor(X11->display, X11->xideviceinfo->deviceid, winid, oc->handle()); + XIDefineCursor(X11->display, X11->xiMasterDeviceId, winid, oc->handle()); } else if (w->isEnabled()) { - XIDefineCursor(X11->display, X11->xideviceinfo->deviceid, winid, w->cursor().handle()); + XIDefineCursor(X11->display, X11->xiMasterDeviceId, winid, w->cursor().handle()); } else { // enforce the windows behavior of clearing the cursor on // disabled widgets - XIDefineCursor(X11->display, X11->xideviceinfo->deviceid, winid, XNone); + XIDefineCursor(X11->display, X11->xiMasterDeviceId, winid, XNone); } } else # endif @@ -356,7 +356,7 @@ void qt_x11_enforce_cursor(QWidget * w, bool force) } else { #if !defined(QT_NO_XINPUT2) if (X11->use_xinput) { - XIDefineCursor(X11->display, X11->xideviceinfo->deviceid, winid, XNone); + XIDefineCursor(X11->display, X11->xiMasterDeviceId, winid, XNone); } else #endif { @@ -892,20 +892,24 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO #if !defined(QT_NO_XINPUT2) if (X11->use_xinput) { - XIEventMask xieventmask; - uchar bitmask[2] = { 0, 0 }; - - xieventmask.deviceid = XIAllMasterDevices; - xieventmask.mask = bitmask; - xieventmask.mask_len = sizeof(bitmask); - - XISetMask(bitmask, XI_ButtonPress); - XISetMask(bitmask, XI_ButtonRelease); - XISetMask(bitmask, XI_Motion); - XISetMask(bitmask, XI_Enter); - XISetMask(bitmask, XI_Leave); + foreach (int deviceId, X11->xiActiveDevices) { + XIEventMask xieventmask; + uchar bitmask[2] = { 0, 0 }; + + xieventmask.deviceid = deviceId; + xieventmask.mask = bitmask; + xieventmask.mask_len = sizeof(bitmask); + + XISetMask(bitmask, XI_ButtonPress); + XISetMask(bitmask, XI_ButtonRelease); + XISetMask(bitmask, XI_Motion); + if (deviceId == X11->xiMasterDeviceId) { + XISetMask(bitmask, XI_Enter); + XISetMask(bitmask, XI_Leave); + } - XISelectEvents(dpy, id, &xieventmask, 1); + XISelectEvents(dpy, id, &xieventmask, 1); + } // remove the corresponding core events from the standard event mask eventmask &= ~(ButtonPressMask @@ -1635,7 +1639,7 @@ void QWidgetPrivate::grabMouse_sys(Qt::HANDLE xcursorid) XIEventMask xieventmask; uchar bitmask[2] = { 0, 0 }; - xieventmask.deviceid = X11->xideviceinfo->deviceid; + xieventmask.deviceid = X11->xiMasterDeviceId; xieventmask.mask = bitmask; xieventmask.mask_len = sizeof(bitmask); @@ -1646,7 +1650,7 @@ void QWidgetPrivate::grabMouse_sys(Qt::HANDLE xcursorid) XISetMask(bitmask, XI_Leave); status = XIGrabDevice(X11->display, - X11->xideviceinfo->deviceid, + X11->xiMasterDeviceId, q->effectiveWinId(), X11->time, xcursorid, @@ -1700,7 +1704,7 @@ void QWidget::releaseMouse() if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) { #if !defined(QT_NO_XINPUT2) if (X11->use_xinput) - XIUngrabDevice(X11->display, X11->xideviceinfo->deviceid, X11->time); + XIUngrabDevice(X11->display, X11->xiMasterDeviceId, X11->time); else #endif XUngrabPointer(X11->display, X11->time); diff --git a/src/gui/kernel/qx11embed_x11.cpp b/src/gui/kernel/qx11embed_x11.cpp index 1c88fb5..41ce245 100644 --- a/src/gui/kernel/qx11embed_x11.cpp +++ b/src/gui/kernel/qx11embed_x11.cpp @@ -1541,7 +1541,7 @@ bool QX11EmbedContainer::x11Event(XEvent *event) setFocus(Qt::MouseFocusReason); #if !defined(QT_NO_XINPUT2) if (X11->use_xinput) - XIAllowEvents(x11Info().display(), X11->xideviceinfo->deviceid, ReplayPointer, CurrentTime); + XIAllowEvents(x11Info().display(), X11->xiMasterDeviceId, ReplayPointer, CurrentTime); else #endif XAllowEvents(x11Info().display(), ReplayPointer, CurrentTime); @@ -1552,7 +1552,7 @@ bool QX11EmbedContainer::x11Event(XEvent *event) if (!d->clientIsXEmbed) { #if !defined(QT_NO_XINPUT2) if (X11->use_xinput) - XIAllowEvents(x11Info().display(), X11->xideviceinfo->deviceid, SyncPointer, CurrentTime); + XIAllowEvents(x11Info().display(), X11->xiMasterDeviceId, SyncPointer, CurrentTime); else #endif XAllowEvents(x11Info().display(), SyncPointer, CurrentTime); @@ -1793,7 +1793,7 @@ void QX11EmbedContainerPrivate::checkGrab() if (X11->use_xinput) { XIEventMask xieventmask; uchar bitmask[1] = { 0 }; - xieventmask.deviceid = X11->xideviceinfo->deviceid; + xieventmask.deviceid = X11->xiMasterDeviceId; xieventmask.mask = bitmask; xieventmask.mask_len = sizeof(bitmask); XISetMask(bitmask, XI_ButtonPress); @@ -1801,7 +1801,7 @@ void QX11EmbedContainerPrivate::checkGrab() XIGrabModifiers anymods; anymods.modifiers = XIAnyModifier; - XIGrabButton(q->x11Info().display(), X11->xideviceinfo->deviceid, XIAnyButton, q->internalWinId(), XNone, GrabModeSync, GrabModeAsync, true, &xieventmask, 1, &anymods); + XIGrabButton(q->x11Info().display(), X11->xiMasterDeviceId, XIAnyButton, q->internalWinId(), XNone, GrabModeSync, GrabModeAsync, true, &xieventmask, 1, &anymods); } else #endif { @@ -1817,7 +1817,7 @@ void QX11EmbedContainerPrivate::checkGrab() if (X11->use_xinput) { XIGrabModifiers anymods; anymods.modifiers = XIAnyModifier; - XIUngrabButton(q->x11Info().display(), X11->xideviceinfo->deviceid, AnyButton, q->internalWinId(), 1, &anymods); + XIUngrabButton(q->x11Info().display(), X11->xiMasterDeviceId, AnyButton, q->internalWinId(), 1, &anymods); } else #endif { -- 1.7.7.4