| Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp |
| Source code | Switch to Preprocessed file |
| Line | Source | Count | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | /**************************************************************************** | - | ||||||||||||||||||||||||
| 2 | ** | - | ||||||||||||||||||||||||
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | - | ||||||||||||||||||||||||
| 4 | ** Contact: https://www.qt.io/licensing/ | - | ||||||||||||||||||||||||
| 5 | ** | - | ||||||||||||||||||||||||
| 6 | ** This file is part of the plugins of the Qt Toolkit. | - | ||||||||||||||||||||||||
| 7 | ** | - | ||||||||||||||||||||||||
| 8 | ** $QT_BEGIN_LICENSE:LGPL$ | - | ||||||||||||||||||||||||
| 9 | ** Commercial License Usage | - | ||||||||||||||||||||||||
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||||||||||||||||||||
| 11 | ** accordance with the commercial license agreement provided with the | - | ||||||||||||||||||||||||
| 12 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||||||||||||||||||||
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||||||||||||||||||||
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | - | ||||||||||||||||||||||||
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | - | ||||||||||||||||||||||||
| 16 | ** | - | ||||||||||||||||||||||||
| 17 | ** GNU Lesser General Public License Usage | - | ||||||||||||||||||||||||
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||||||||||||||||||||
| 19 | ** General Public License version 3 as published by the Free Software | - | ||||||||||||||||||||||||
| 20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | - | ||||||||||||||||||||||||
| 21 | ** packaging of this file. Please review the following information to | - | ||||||||||||||||||||||||
| 22 | ** ensure the GNU Lesser General Public License version 3 requirements | - | ||||||||||||||||||||||||
| 23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | - | ||||||||||||||||||||||||
| 24 | ** | - | ||||||||||||||||||||||||
| 25 | ** GNU General Public License Usage | - | ||||||||||||||||||||||||
| 26 | ** Alternatively, this file may be used under the terms of the GNU | - | ||||||||||||||||||||||||
| 27 | ** General Public License version 2.0 or (at your option) the GNU General | - | ||||||||||||||||||||||||
| 28 | ** Public license version 3 or any later version approved by the KDE Free | - | ||||||||||||||||||||||||
| 29 | ** Qt Foundation. The licenses are as published by the Free Software | - | ||||||||||||||||||||||||
| 30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | - | ||||||||||||||||||||||||
| 31 | ** included in the packaging of this file. Please review the following | - | ||||||||||||||||||||||||
| 32 | ** information to ensure the GNU General Public License requirements will | - | ||||||||||||||||||||||||
| 33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | - | ||||||||||||||||||||||||
| 34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | - | ||||||||||||||||||||||||
| 35 | ** | - | ||||||||||||||||||||||||
| 36 | ** $QT_END_LICENSE$ | - | ||||||||||||||||||||||||
| 37 | ** | - | ||||||||||||||||||||||||
| 38 | ****************************************************************************/ | - | ||||||||||||||||||||||||
| 39 | - | |||||||||||||||||||||||||
| 40 | #include "qxcbconnection.h" | - | ||||||||||||||||||||||||
| 41 | #include "qxcbkeyboard.h" | - | ||||||||||||||||||||||||
| 42 | #include "qxcbscreen.h" | - | ||||||||||||||||||||||||
| 43 | #include "qxcbwindow.h" | - | ||||||||||||||||||||||||
| 44 | #include "qtouchdevice.h" | - | ||||||||||||||||||||||||
| 45 | #include <qpa/qwindowsysteminterface_p.h> | - | ||||||||||||||||||||||||
| 46 | #include <QDebug> | - | ||||||||||||||||||||||||
| 47 | #include <cmath> | - | ||||||||||||||||||||||||
| 48 | - | |||||||||||||||||||||||||
| 49 | #ifdef XCB_USE_XINPUT2 | - | ||||||||||||||||||||||||
| 50 | - | |||||||||||||||||||||||||
| 51 | #include <X11/extensions/XInput2.h> | - | ||||||||||||||||||||||||
| 52 | #include <X11/extensions/XI2proto.h> | - | ||||||||||||||||||||||||
| 53 | - | |||||||||||||||||||||||||
| 54 | struct XInput2TouchDeviceData { | - | ||||||||||||||||||||||||
| 55 | XInput2TouchDeviceData() | - | ||||||||||||||||||||||||
| 56 | : xiDeviceInfo(0) | - | ||||||||||||||||||||||||
| 57 | , qtTouchDevice(0) | - | ||||||||||||||||||||||||
| 58 | , providesTouchOrientation(false) | - | ||||||||||||||||||||||||
| 59 | { | - | ||||||||||||||||||||||||
| 60 | } executed 540 times by 5 tests: end of blockExecuted by:
| 540 | ||||||||||||||||||||||||
| 61 | XIDeviceInfo *xiDeviceInfo; | - | ||||||||||||||||||||||||
| 62 | QTouchDevice *qtTouchDevice; | - | ||||||||||||||||||||||||
| 63 | QHash<int, QWindowSystemInterface::TouchPoint> touchPoints; | - | ||||||||||||||||||||||||
| 64 | - | |||||||||||||||||||||||||
| 65 | // Stuff that is relevant only for touchpads | - | ||||||||||||||||||||||||
| 66 | QHash<int, QPointF> pointPressedPosition; // in screen coordinates where each point was pressed | - | ||||||||||||||||||||||||
| 67 | QPointF firstPressedPosition; // in screen coordinates where the first point was pressed | - | ||||||||||||||||||||||||
| 68 | QPointF firstPressedNormalPosition; // device coordinates (0 to 1, 0 to 1) where the first point was pressed | - | ||||||||||||||||||||||||
| 69 | QSizeF size; // device size in mm | - | ||||||||||||||||||||||||
| 70 | bool providesTouchOrientation; | - | ||||||||||||||||||||||||
| 71 | }; | - | ||||||||||||||||||||||||
| 72 | - | |||||||||||||||||||||||||
| 73 | void QXcbConnection::initializeXInput2() | - | ||||||||||||||||||||||||
| 74 | { | - | ||||||||||||||||||||||||
| 75 | // TODO Qt 6 (or perhaps earlier): remove these redundant env variables | - | ||||||||||||||||||||||||
| 76 | if (qEnvironmentVariableIsSet("QT_XCB_DEBUG_XINPUT"))
| 0-135 | ||||||||||||||||||||||||
| 77 | const_cast<QLoggingCategory&>(lcQpaXInput()).setEnabled(QtDebugMsg, true); never executed: const_cast<QLoggingCategory&>(lcQpaXInput()).setEnabled(QtDebugMsg, true); | 0 | ||||||||||||||||||||||||
| 78 | if (qEnvironmentVariableIsSet("QT_XCB_DEBUG_XINPUT_DEVICES"))
| 0-135 | ||||||||||||||||||||||||
| 79 | const_cast<QLoggingCategory&>(lcQpaXInputDevices()).setEnabled(QtDebugMsg, true); never executed: const_cast<QLoggingCategory&>(lcQpaXInputDevices()).setEnabled(QtDebugMsg, true); | 0 | ||||||||||||||||||||||||
| 80 | Display *xDisplay = static_cast<Display *>(m_xlib_display); | - | ||||||||||||||||||||||||
| 81 | if (XQueryExtension(xDisplay, "XInputExtension", &m_xiOpCode, &m_xiEventBase, &m_xiErrorBase)) {
| 0-135 | ||||||||||||||||||||||||
| 82 | int xiMajor = 2; | - | ||||||||||||||||||||||||
| 83 | m_xi2Minor = 2; // try 2.2 first, needed for TouchBegin/Update/End | - | ||||||||||||||||||||||||
| 84 | if (XIQueryVersion(xDisplay, &xiMajor, &m_xi2Minor) == BadRequest) {
| 0-135 | ||||||||||||||||||||||||
| 85 | m_xi2Minor = 1; // for smooth scrolling 2.1 is enough | - | ||||||||||||||||||||||||
| 86 | if (XIQueryVersion(xDisplay, &xiMajor, &m_xi2Minor) == BadRequest) {
| 0 | ||||||||||||||||||||||||
| 87 | m_xi2Minor = 0; // for tablet support 2.0 is enough | - | ||||||||||||||||||||||||
| 88 | m_xi2Enabled = XIQueryVersion(xDisplay, &xiMajor, &m_xi2Minor) != BadRequest; | - | ||||||||||||||||||||||||
| 89 | } else never executed: end of block | 0 | ||||||||||||||||||||||||
| 90 | m_xi2Enabled = true; never executed: m_xi2Enabled = true; | 0 | ||||||||||||||||||||||||
| 91 | } else | - | ||||||||||||||||||||||||
| 92 | m_xi2Enabled = true; executed 135 times by 5 tests: m_xi2Enabled = true;Executed by:
| 135 | ||||||||||||||||||||||||
| 93 | if (m_xi2Enabled) {
| 0-135 | ||||||||||||||||||||||||
| 94 | #ifdef XCB_USE_XINPUT22 | - | ||||||||||||||||||||||||
| 95 | qCDebug(lcQpaXInputDevices, "XInput version %d.%d is available and Qt supports 2.2 or greater", xiMajor, m_xi2Minor); never executed: QMessageLogger(__FILE__, 95, __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug("XInput version %d.%d is available and Qt supports 2.2 or greater", xiMajor, m_xi2Minor);
| 0-135 | ||||||||||||||||||||||||
| 96 | #else | - | ||||||||||||||||||||||||
| 97 | qCDebug(lcQpaXInputDevices, "XInput version %d.%d is available and Qt supports 2.0", xiMajor, m_xi2Minor); | - | ||||||||||||||||||||||||
| 98 | #endif | - | ||||||||||||||||||||||||
| 99 | } executed 135 times by 5 tests: end of blockExecuted by:
| 135 | ||||||||||||||||||||||||
| 100 | - | |||||||||||||||||||||||||
| 101 | xi2SetupDevices(); | - | ||||||||||||||||||||||||
| 102 | } executed 135 times by 5 tests: end of blockExecuted by:
| 135 | ||||||||||||||||||||||||
| 103 | } executed 135 times by 5 tests: end of blockExecuted by:
| 135 | ||||||||||||||||||||||||
| 104 | - | |||||||||||||||||||||||||
| 105 | void QXcbConnection::xi2SetupDevices() | - | ||||||||||||||||||||||||
| 106 | { | - | ||||||||||||||||||||||||
| 107 | #ifndef QT_NO_TABLETEVENT | - | ||||||||||||||||||||||||
| 108 | m_tabletData.clear(); | - | ||||||||||||||||||||||||
| 109 | #endif | - | ||||||||||||||||||||||||
| 110 | m_scrollingDevices.clear(); | - | ||||||||||||||||||||||||
| 111 | - | |||||||||||||||||||||||||
| 112 | if (!m_xi2Enabled)
| 0-135 | ||||||||||||||||||||||||
| 113 | return; never executed: return; | 0 | ||||||||||||||||||||||||
| 114 | - | |||||||||||||||||||||||||
| 115 | Display *xDisplay = static_cast<Display *>(m_xlib_display); | - | ||||||||||||||||||||||||
| 116 | int deviceCount = 0; | - | ||||||||||||||||||||||||
| 117 | XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount); | - | ||||||||||||||||||||||||
| 118 | for (int i = 0; i < deviceCount; ++i) {
| 135-1215 | ||||||||||||||||||||||||
| 119 | // Only non-master pointing devices are relevant here. | - | ||||||||||||||||||||||||
| 120 | if (devices[i].use != XISlavePointer)
| 540-675 | ||||||||||||||||||||||||
| 121 | continue; executed 675 times by 5 tests: continue;Executed by:
| 675 | ||||||||||||||||||||||||
| 122 | qCDebug(lcQpaXInputDevices) << "input device " << devices[i].name << "ID" << devices[i].deviceid; never executed: QMessageLogger(__FILE__, 122, __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug() << "input device " << devices[i].name << "ID" << devices[i].deviceid;
| 0-540 | ||||||||||||||||||||||||
| 123 | #ifndef QT_NO_TABLETEVENT | - | ||||||||||||||||||||||||
| 124 | TabletData tabletData; | - | ||||||||||||||||||||||||
| 125 | #endif | - | ||||||||||||||||||||||||
| 126 | ScrollingDevice scrollingDevice; | - | ||||||||||||||||||||||||
| 127 | for (int c = 0; c < devices[i].num_classes; ++c) {
| 540-2700 | ||||||||||||||||||||||||
| 128 | switch (devices[i].classes[c]->type) { | - | ||||||||||||||||||||||||
| 129 | case XIValuatorClass: { executed 1620 times by 5 tests: case 2:Executed by:
| 1620 | ||||||||||||||||||||||||
| 130 | XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(devices[i].classes[c]); | - | ||||||||||||||||||||||||
| 131 | const int valuatorAtom = qatom(vci->label); | - | ||||||||||||||||||||||||
| 132 | qCDebug(lcQpaXInputDevices) << " has valuator" << atomName(vci->label) << "recognized?" << (valuatorAtom < QXcbAtom::NAtoms); never executed: QMessageLogger(__FILE__, 132, __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug() << " has valuator" << atomName(vci->label) << "recognized?" << (valuatorAtom < QXcbAtom::NAtoms);
| 0-1620 | ||||||||||||||||||||||||
| 133 | #ifndef QT_NO_TABLETEVENT | - | ||||||||||||||||||||||||
| 134 | if (valuatorAtom < QXcbAtom::NAtoms) {
| 0-1620 | ||||||||||||||||||||||||
| 135 | TabletData::ValuatorClassInfo info; | - | ||||||||||||||||||||||||
| 136 | info.minVal = vci->min; | - | ||||||||||||||||||||||||
| 137 | info.maxVal = vci->max; | - | ||||||||||||||||||||||||
| 138 | info.number = vci->number; | - | ||||||||||||||||||||||||
| 139 | tabletData.valuatorInfo[valuatorAtom] = info; | - | ||||||||||||||||||||||||
| 140 | } executed 1620 times by 5 tests: end of blockExecuted by:
| 1620 | ||||||||||||||||||||||||
| 141 | #endif // QT_NO_TABLETEVENT | - | ||||||||||||||||||||||||
| 142 | if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
| 0-1620 | ||||||||||||||||||||||||
| 143 | scrollingDevice.lastScrollPosition.setX(vci->value); executed 270 times by 5 tests: scrollingDevice.lastScrollPosition.setX(vci->value);Executed by:
| 270 | ||||||||||||||||||||||||
| 144 | else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
| 0-1350 | ||||||||||||||||||||||||
| 145 | scrollingDevice.lastScrollPosition.setY(vci->value); executed 270 times by 5 tests: scrollingDevice.lastScrollPosition.setY(vci->value);Executed by:
| 270 | ||||||||||||||||||||||||
| 146 | break; executed 1620 times by 5 tests: break;Executed by:
| 1620 | ||||||||||||||||||||||||
| 147 | } | - | ||||||||||||||||||||||||
| 148 | #ifdef XCB_USE_XINPUT21 | - | ||||||||||||||||||||||||
| 149 | case XIScrollClass: { executed 540 times by 5 tests: case 3:Executed by:
| 540 | ||||||||||||||||||||||||
| 150 | XIScrollClassInfo *sci = reinterpret_cast<XIScrollClassInfo *>(devices[i].classes[c]); | - | ||||||||||||||||||||||||
| 151 | if (sci->scroll_type == XIScrollTypeVertical) {
| 270 | ||||||||||||||||||||||||
| 152 | scrollingDevice.orientations |= Qt::Vertical; | - | ||||||||||||||||||||||||
| 153 | scrollingDevice.verticalIndex = sci->number; | - | ||||||||||||||||||||||||
| 154 | scrollingDevice.verticalIncrement = sci->increment; | - | ||||||||||||||||||||||||
| 155 | } executed 270 times by 5 tests: end of blockExecuted by:
| 270 | ||||||||||||||||||||||||
| 156 | else if (sci->scroll_type == XIScrollTypeHorizontal) {
| 0-270 | ||||||||||||||||||||||||
| 157 | scrollingDevice.orientations |= Qt::Horizontal; | - | ||||||||||||||||||||||||
| 158 | scrollingDevice.horizontalIndex = sci->number; | - | ||||||||||||||||||||||||
| 159 | scrollingDevice.horizontalIncrement = sci->increment; | - | ||||||||||||||||||||||||
| 160 | } executed 270 times by 5 tests: end of blockExecuted by:
| 270 | ||||||||||||||||||||||||
| 161 | break; executed 540 times by 5 tests: break;Executed by:
| 540 | ||||||||||||||||||||||||
| 162 | } | - | ||||||||||||||||||||||||
| 163 | case XIButtonClass: { executed 540 times by 5 tests: case 1:Executed by:
| 540 | ||||||||||||||||||||||||
| 164 | XIButtonClassInfo *bci = reinterpret_cast<XIButtonClassInfo *>(devices[i].classes[c]); | - | ||||||||||||||||||||||||
| 165 | if (bci->num_buttons >= 5) {
| 0-540 | ||||||||||||||||||||||||
| 166 | Atom label4 = bci->labels[3]; | - | ||||||||||||||||||||||||
| 167 | Atom label5 = bci->labels[4]; | - | ||||||||||||||||||||||||
| 168 | // Some drivers have no labels on the wheel buttons, some have no label on just one and some have no label on | - | ||||||||||||||||||||||||
| 169 | // button 4 and the wrong one on button 5. So we just check that they are not labelled with unrelated buttons. | - | ||||||||||||||||||||||||
| 170 | if ((!label4 || qatom(label4) == QXcbAtom::ButtonWheelUp || qatom(label4) == QXcbAtom::ButtonWheelDown) &&
| 0-405 | ||||||||||||||||||||||||
| 171 | (!label5 || qatom(label5) == QXcbAtom::ButtonWheelUp || qatom(label5) == QXcbAtom::ButtonWheelDown))
| 0-540 | ||||||||||||||||||||||||
| 172 | scrollingDevice.legacyOrientations |= Qt::Vertical; executed 540 times by 5 tests: scrollingDevice.legacyOrientations |= Qt::Vertical;Executed by:
| 540 | ||||||||||||||||||||||||
| 173 | } executed 540 times by 5 tests: end of blockExecuted by:
| 540 | ||||||||||||||||||||||||
| 174 | if (bci->num_buttons >= 7) {
| 135-405 | ||||||||||||||||||||||||
| 175 | Atom label6 = bci->labels[5]; | - | ||||||||||||||||||||||||
| 176 | Atom label7 = bci->labels[6]; | - | ||||||||||||||||||||||||
| 177 | if ((!label6 || qatom(label6) == QXcbAtom::ButtonHorizWheelLeft) && (!label7 || qatom(label7) == QXcbAtom::ButtonHorizWheelRight))
| 0-405 | ||||||||||||||||||||||||
| 178 | scrollingDevice.legacyOrientations |= Qt::Horizontal; executed 405 times by 5 tests: scrollingDevice.legacyOrientations |= Qt::Horizontal;Executed by:
| 405 | ||||||||||||||||||||||||
| 179 | } executed 405 times by 5 tests: end of blockExecuted by:
| 405 | ||||||||||||||||||||||||
| 180 | qCDebug(lcQpaXInputDevices, " has %d buttons", bci->num_buttons); never executed: QMessageLogger(__FILE__, 180, __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug(" has %d buttons", bci->num_buttons);
| 0-540 | ||||||||||||||||||||||||
| 181 | break; executed 540 times by 5 tests: break;Executed by:
| 540 | ||||||||||||||||||||||||
| 182 | } | - | ||||||||||||||||||||||||
| 183 | #endif | - | ||||||||||||||||||||||||
| 184 | case XIKeyClass: never executed: case 0: | 0 | ||||||||||||||||||||||||
| 185 | qCDebug(lcQpaXInputDevices) << " it's a keyboard"; never executed: QMessageLogger(__FILE__, 185, __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug() << " it's a keyboard";
| 0 | ||||||||||||||||||||||||
| 186 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 187 | #ifdef XCB_USE_XINPUT22 | - | ||||||||||||||||||||||||
| 188 | case XITouchClass: never executed: case 8: | 0 | ||||||||||||||||||||||||
| 189 | // will be handled in deviceForId() | - | ||||||||||||||||||||||||
| 190 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 191 | #endif | - | ||||||||||||||||||||||||
| 192 | default: never executed: default: | 0 | ||||||||||||||||||||||||
| 193 | qCDebug(lcQpaXInputDevices) << " has class" << devices[i].classes[c]->type; never executed: QMessageLogger(__FILE__, 193, __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug() << " has class" << devices[i].classes[c]->type;
| 0 | ||||||||||||||||||||||||
| 194 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 195 | } | - | ||||||||||||||||||||||||
| 196 | } | - | ||||||||||||||||||||||||
| 197 | bool isTablet = false; | - | ||||||||||||||||||||||||
| 198 | #ifndef QT_NO_TABLETEVENT | - | ||||||||||||||||||||||||
| 199 | // If we have found the valuators which we expect a tablet to have, it might be a tablet. | - | ||||||||||||||||||||||||
| 200 | if (tabletData.valuatorInfo.contains(QXcbAtom::AbsX) &&
| 270 | ||||||||||||||||||||||||
| 201 | tabletData.valuatorInfo.contains(QXcbAtom::AbsY) &&
| 0-270 | ||||||||||||||||||||||||
| 202 | tabletData.valuatorInfo.contains(QXcbAtom::AbsPressure))
| 0-270 | ||||||||||||||||||||||||
| 203 | isTablet = true; never executed: isTablet = true; | 0 | ||||||||||||||||||||||||
| 204 | - | |||||||||||||||||||||||||
| 205 | // But we need to be careful not to take the touch and tablet-button devices as tablets. | - | ||||||||||||||||||||||||
| 206 | QByteArray name = QByteArray(devices[i].name).toLower(); | - | ||||||||||||||||||||||||
| 207 | QString dbgType = QLatin1String("UNKNOWN"); | - | ||||||||||||||||||||||||
| 208 | if (name.contains("eraser")) {
| 0-540 | ||||||||||||||||||||||||
| 209 | isTablet = true; | - | ||||||||||||||||||||||||
| 210 | tabletData.pointerType = QTabletEvent::Eraser; | - | ||||||||||||||||||||||||
| 211 | dbgType = QLatin1String("eraser"); | - | ||||||||||||||||||||||||
| 212 | } else if (name.contains("cursor")) { never executed: end of block
| 0-540 | ||||||||||||||||||||||||
| 213 | isTablet = true; | - | ||||||||||||||||||||||||
| 214 | tabletData.pointerType = QTabletEvent::Cursor; | - | ||||||||||||||||||||||||
| 215 | dbgType = QLatin1String("cursor"); | - | ||||||||||||||||||||||||
| 216 | } else if ((name.contains("pen") || name.contains("stylus")) && isTablet) { never executed: end of block
| 0-540 | ||||||||||||||||||||||||
| 217 | tabletData.pointerType = QTabletEvent::Pen; | - | ||||||||||||||||||||||||
| 218 | dbgType = QLatin1String("pen"); | - | ||||||||||||||||||||||||
| 219 | } else if (name.contains("wacom") && isTablet && !name.contains("touch")) { never executed: end of block
| 0-540 | ||||||||||||||||||||||||
| 220 | // combined device (evdev) rather than separate pen/eraser (wacom driver) | - | ||||||||||||||||||||||||
| 221 | tabletData.pointerType = QTabletEvent::Pen; | - | ||||||||||||||||||||||||
| 222 | dbgType = QLatin1String("pen"); | - | ||||||||||||||||||||||||
| 223 | } else if (name.contains("aiptek") /* && device == QXcbAtom::KEYBOARD */) { never executed: end of block
| 0-540 | ||||||||||||||||||||||||
| 224 | // some "Genius" tablets | - | ||||||||||||||||||||||||
| 225 | isTablet = true; | - | ||||||||||||||||||||||||
| 226 | tabletData.pointerType = QTabletEvent::Pen; | - | ||||||||||||||||||||||||
| 227 | dbgType = QLatin1String("pen"); | - | ||||||||||||||||||||||||
| 228 | } else if (name.contains("waltop") && name.contains("tablet")) { never executed: end of block
| 0-540 | ||||||||||||||||||||||||
| 229 | // other "Genius" tablets | - | ||||||||||||||||||||||||
| 230 | // WALTOP International Corp. Slim Tablet | - | ||||||||||||||||||||||||
| 231 | isTablet = true; | - | ||||||||||||||||||||||||
| 232 | tabletData.pointerType = QTabletEvent::Pen; | - | ||||||||||||||||||||||||
| 233 | dbgType = QLatin1String("pen"); | - | ||||||||||||||||||||||||
| 234 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
| 235 | isTablet = false; | - | ||||||||||||||||||||||||
| 236 | } executed 540 times by 5 tests: end of blockExecuted by:
| 540 | ||||||||||||||||||||||||
| 237 | - | |||||||||||||||||||||||||
| 238 | if (isTablet) {
| 0-540 | ||||||||||||||||||||||||
| 239 | tabletData.deviceId = devices[i].deviceid; | - | ||||||||||||||||||||||||
| 240 | m_tabletData.append(tabletData); | - | ||||||||||||||||||||||||
| 241 | qCDebug(lcQpaXInputDevices) << " it's a tablet with pointer type" << dbgType; never executed: QMessageLogger(__FILE__, 241, __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug() << " it's a tablet with pointer type" << dbgType;
| 0 | ||||||||||||||||||||||||
| 242 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 243 | #endif // QT_NO_TABLETEVENT | - | ||||||||||||||||||||||||
| 244 | - | |||||||||||||||||||||||||
| 245 | #ifdef XCB_USE_XINPUT21 | - | ||||||||||||||||||||||||
| 246 | if (scrollingDevice.orientations || scrollingDevice.legacyOrientations) { | - | ||||||||||||||||||||||||
| 247 | scrollingDevice.deviceId = devices[i].deviceid; | - | ||||||||||||||||||||||||
| 248 | // Only use legacy wheel button events when we don't have real scroll valuators. | - | ||||||||||||||||||||||||
| 249 | scrollingDevice.legacyOrientations &= ~scrollingDevice.orientations; | - | ||||||||||||||||||||||||
| 250 | m_scrollingDevices.insert(scrollingDevice.deviceId, scrollingDevice); | - | ||||||||||||||||||||||||
| 251 | qCDebug(lcQpaXInputDevices) << " it's a scrolling device"; never executed: QMessageLogger(__FILE__, 251, __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug() << " it's a scrolling device";
| 0-540 | ||||||||||||||||||||||||
| 252 | } executed 540 times by 5 tests: end of blockExecuted by:
| 540 | ||||||||||||||||||||||||
| 253 | #endif | - | ||||||||||||||||||||||||
| 254 | - | |||||||||||||||||||||||||
| 255 | if (!isTablet) {
| 0-540 | ||||||||||||||||||||||||
| 256 | // touchDeviceForId populates XInput2DeviceData the first time it is called | - | ||||||||||||||||||||||||
| 257 | // with a new deviceId. On subsequent calls it will return the cached object. | - | ||||||||||||||||||||||||
| 258 | XInput2TouchDeviceData *dev = touchDeviceForId(devices[i].deviceid); | - | ||||||||||||||||||||||||
| 259 | if (dev && lcQpaXInputDevices().isDebugEnabled()) {
| 0-540 | ||||||||||||||||||||||||
| 260 | if (dev->qtTouchDevice->type() == QTouchDevice::TouchScreen)
| 0 | ||||||||||||||||||||||||
| 261 | qCDebug(lcQpaXInputDevices, " it's a touchscreen with type %d capabilities 0x%X max touch points %d", never executed: QMessageLogger( __FILE__ , 263 , __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug(" it's a touchscreen with type %d capabilities 0x%X max touch points %d", dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), dev->qtTouchDevice->maximumTouchPoints()) ;
| 0 | ||||||||||||||||||||||||
| 262 | dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), never executed: QMessageLogger( __FILE__ , 263 , __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug(" it's a touchscreen with type %d capabilities 0x%X max touch points %d", dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), dev->qtTouchDevice->maximumTouchPoints()) ; | 0 | ||||||||||||||||||||||||
| 263 | dev->qtTouchDevice->maximumTouchPoints()); never executed: QMessageLogger( __FILE__ , 263 , __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug(" it's a touchscreen with type %d capabilities 0x%X max touch points %d", dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), dev->qtTouchDevice->maximumTouchPoints()) ; | 0 | ||||||||||||||||||||||||
| 264 | else if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad)
| 0 | ||||||||||||||||||||||||
| 265 | qCDebug(lcQpaXInputDevices, " it's a touchpad with type %d capabilities 0x%X max touch points %d size %f x %f", never executed: QMessageLogger( __FILE__ , 268 , __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug(" it's a touchpad with type %d capabilities 0x%X max touch points %d size %f x %f", dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), dev->qtTouchDevice->maximumTouchPoints(), dev->size.width(), dev->size.height()) ;
| 0 | ||||||||||||||||||||||||
| 266 | dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), never executed: QMessageLogger( __FILE__ , 268 , __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug(" it's a touchpad with type %d capabilities 0x%X max touch points %d size %f x %f", dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), dev->qtTouchDevice->maximumTouchPoints(), dev->size.width(), dev->size.height()) ; | 0 | ||||||||||||||||||||||||
| 267 | dev->qtTouchDevice->maximumTouchPoints(), never executed: QMessageLogger( __FILE__ , 268 , __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug(" it's a touchpad with type %d capabilities 0x%X max touch points %d size %f x %f", dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), dev->qtTouchDevice->maximumTouchPoints(), dev->size.width(), dev->size.height()) ; | 0 | ||||||||||||||||||||||||
| 268 | dev->size.width(), dev->size.height()); never executed: QMessageLogger( __FILE__ , 268 , __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug(" it's a touchpad with type %d capabilities 0x%X max touch points %d size %f x %f", dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), dev->qtTouchDevice->maximumTouchPoints(), dev->size.width(), dev->size.height()) ; | 0 | ||||||||||||||||||||||||
| 269 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 270 | } executed 540 times by 5 tests: end of blockExecuted by:
| 540 | ||||||||||||||||||||||||
| 271 | } executed 540 times by 5 tests: end of blockExecuted by:
| 540 | ||||||||||||||||||||||||
| 272 | XIFreeDeviceInfo(devices); | - | ||||||||||||||||||||||||
| 273 | } executed 135 times by 5 tests: end of blockExecuted by:
| 135 | ||||||||||||||||||||||||
| 274 | - | |||||||||||||||||||||||||
| 275 | void QXcbConnection::finalizeXInput2() | - | ||||||||||||||||||||||||
| 276 | { | - | ||||||||||||||||||||||||
| 277 | for (XInput2TouchDeviceData *dev : qAsConst(m_touchDevices)) { | - | ||||||||||||||||||||||||
| 278 | if (dev->xiDeviceInfo)
| 0 | ||||||||||||||||||||||||
| 279 | XIFreeDeviceInfo(dev->xiDeviceInfo); never executed: XIFreeDeviceInfo(dev->xiDeviceInfo); | 0 | ||||||||||||||||||||||||
| 280 | delete dev; | - | ||||||||||||||||||||||||
| 281 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 282 | } executed 347 times by 219 tests: end of blockExecuted by:
| 347 | ||||||||||||||||||||||||
| 283 | - | |||||||||||||||||||||||||
| 284 | void QXcbConnection::xi2Select(xcb_window_t window) | - | ||||||||||||||||||||||||
| 285 | { | - | ||||||||||||||||||||||||
| 286 | if (!m_xi2Enabled || window == rootWindow())
| 0-4107 | ||||||||||||||||||||||||
| 287 | return; never executed: return; | 0 | ||||||||||||||||||||||||
| 288 | - | |||||||||||||||||||||||||
| 289 | Display *xDisplay = static_cast<Display *>(m_xlib_display); | - | ||||||||||||||||||||||||
| 290 | unsigned int bitMask = 0; | - | ||||||||||||||||||||||||
| 291 | unsigned char *xiBitMask = reinterpret_cast<unsigned char *>(&bitMask); | - | ||||||||||||||||||||||||
| 292 | - | |||||||||||||||||||||||||
| 293 | #ifdef XCB_USE_XINPUT22 | - | ||||||||||||||||||||||||
| 294 | if (isAtLeastXI22()) {
| 0-4107 | ||||||||||||||||||||||||
| 295 | bitMask |= XI_TouchBeginMask; | - | ||||||||||||||||||||||||
| 296 | bitMask |= XI_TouchUpdateMask; | - | ||||||||||||||||||||||||
| 297 | bitMask |= XI_TouchEndMask; | - | ||||||||||||||||||||||||
| 298 | bitMask |= XI_PropertyEventMask; // for tablets | - | ||||||||||||||||||||||||
| 299 | if (xi2MouseEvents()) {
| 0-4107 | ||||||||||||||||||||||||
| 300 | // We want both mouse and touch through XI2 if touch is supported (>= 2.2). | - | ||||||||||||||||||||||||
| 301 | // The plain xcb press and motion events will not be delivered after this. | - | ||||||||||||||||||||||||
| 302 | bitMask |= XI_ButtonPressMask; | - | ||||||||||||||||||||||||
| 303 | bitMask |= XI_ButtonReleaseMask; | - | ||||||||||||||||||||||||
| 304 | bitMask |= XI_MotionMask; | - | ||||||||||||||||||||||||
| 305 | - | |||||||||||||||||||||||||
| 306 | // There is a check for enter/leave events in plain xcb enter/leave event handler | - | ||||||||||||||||||||||||
| 307 | bitMask |= XI_EnterMask; | - | ||||||||||||||||||||||||
| 308 | bitMask |= XI_LeaveMask; | - | ||||||||||||||||||||||||
| 309 | - | |||||||||||||||||||||||||
| 310 | qCDebug(lcQpaXInput, "XInput 2.2: Selecting press/release/motion events in addition to touch"); never executed: QMessageLogger(__FILE__, 310, __PRETTY_FUNCTION__, lcQpaXInput().categoryName()).debug("XInput 2.2: Selecting press/release/motion events in addition to touch");
| 0-4107 | ||||||||||||||||||||||||
| 311 | } executed 4107 times by 125 tests: end of blockExecuted by:
| 4107 | ||||||||||||||||||||||||
| 312 | XIEventMask mask; | - | ||||||||||||||||||||||||
| 313 | mask.mask_len = sizeof(bitMask); | - | ||||||||||||||||||||||||
| 314 | mask.mask = xiBitMask; | - | ||||||||||||||||||||||||
| 315 | // When xi2MouseEvents() is true (the default), pointer emulation for touch and tablet | - | ||||||||||||||||||||||||
| 316 | // events will get disabled. This is preferable, as Qt Quick handles touch events | - | ||||||||||||||||||||||||
| 317 | // directly, while for other applications QtGui synthesizes mouse events. | - | ||||||||||||||||||||||||
| 318 | mask.deviceid = XIAllMasterDevices; | - | ||||||||||||||||||||||||
| 319 | Status result = XISelectEvents(xDisplay, window, &mask, 1); | - | ||||||||||||||||||||||||
| 320 | if (result == Success)
| 0-4107 | ||||||||||||||||||||||||
| 321 | QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false); executed 4107 times by 125 tests: QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);Executed by:
| 4107 | ||||||||||||||||||||||||
| 322 | else | - | ||||||||||||||||||||||||
| 323 | qCDebug(lcQpaXInput, "XInput 2.2: failed to select pointer/touch events, window %x, result %d", window, result); never executed: QMessageLogger(__FILE__, 323, __PRETTY_FUNCTION__, lcQpaXInput().categoryName()).debug("XInput 2.2: failed to select pointer/touch events, window %x, result %d", window, result);
| 0 | ||||||||||||||||||||||||
| 324 | } executed 4107 times by 125 tests: end of blockExecuted by:
| 4107 | ||||||||||||||||||||||||
| 325 | - | |||||||||||||||||||||||||
| 326 | const bool pointerSelected = isAtLeastXI22() && xi2MouseEvents();
| 0-4107 | ||||||||||||||||||||||||
| 327 | #else | - | ||||||||||||||||||||||||
| 328 | const bool pointerSelected = false; | - | ||||||||||||||||||||||||
| 329 | #endif // XCB_USE_XINPUT22 | - | ||||||||||||||||||||||||
| 330 | - | |||||||||||||||||||||||||
| 331 | QSet<int> tabletDevices; | - | ||||||||||||||||||||||||
| 332 | #ifndef QT_NO_TABLETEVENT | - | ||||||||||||||||||||||||
| 333 | if (!m_tabletData.isEmpty()) {
| 0-4107 | ||||||||||||||||||||||||
| 334 | unsigned int tabletBitMask; | - | ||||||||||||||||||||||||
| 335 | unsigned char *xiTabletBitMask = reinterpret_cast<unsigned char *>(&tabletBitMask); | - | ||||||||||||||||||||||||
| 336 | QVector<XIEventMask> xiEventMask(m_tabletData.count()); | - | ||||||||||||||||||||||||
| 337 | tabletBitMask = XI_PropertyEventMask; | - | ||||||||||||||||||||||||
| 338 | if (!pointerSelected)
| 0 | ||||||||||||||||||||||||
| 339 | tabletBitMask |= XI_ButtonPressMask | XI_ButtonReleaseMask | XI_MotionMask; never executed: tabletBitMask |= (1 << 4) | (1 << 5) | (1 << 6); | 0 | ||||||||||||||||||||||||
| 340 | for (int i = 0; i < m_tabletData.count(); ++i) {
| 0 | ||||||||||||||||||||||||
| 341 | int deviceId = m_tabletData.at(i).deviceId; | - | ||||||||||||||||||||||||
| 342 | tabletDevices.insert(deviceId); | - | ||||||||||||||||||||||||
| 343 | xiEventMask[i].deviceid = deviceId; | - | ||||||||||||||||||||||||
| 344 | xiEventMask[i].mask_len = sizeof(tabletBitMask); | - | ||||||||||||||||||||||||
| 345 | xiEventMask[i].mask = xiTabletBitMask; | - | ||||||||||||||||||||||||
| 346 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 347 | XISelectEvents(xDisplay, window, xiEventMask.data(), m_tabletData.count()); | - | ||||||||||||||||||||||||
| 348 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 349 | #endif // QT_NO_TABLETEVENT | - | ||||||||||||||||||||||||
| 350 | - | |||||||||||||||||||||||||
| 351 | #ifdef XCB_USE_XINPUT21 | - | ||||||||||||||||||||||||
| 352 | // Enable each scroll device | - | ||||||||||||||||||||||||
| 353 | if (!m_scrollingDevices.isEmpty() && !pointerSelected) {
| 0-4107 | ||||||||||||||||||||||||
| 354 | // Only when XI2 mouse events are not enabled, otherwise motion and release are selected already. | - | ||||||||||||||||||||||||
| 355 | QVector<XIEventMask> xiEventMask(m_scrollingDevices.size()); | - | ||||||||||||||||||||||||
| 356 | unsigned int scrollBitMask; | - | ||||||||||||||||||||||||
| 357 | unsigned char *xiScrollBitMask = reinterpret_cast<unsigned char *>(&scrollBitMask); | - | ||||||||||||||||||||||||
| 358 | - | |||||||||||||||||||||||||
| 359 | scrollBitMask = XI_MotionMask; | - | ||||||||||||||||||||||||
| 360 | scrollBitMask |= XI_ButtonReleaseMask; | - | ||||||||||||||||||||||||
| 361 | int i=0; | - | ||||||||||||||||||||||||
| 362 | for (const ScrollingDevice& scrollingDevice : qAsConst(m_scrollingDevices)) { | - | ||||||||||||||||||||||||
| 363 | if (tabletDevices.contains(scrollingDevice.deviceId))
| 0 | ||||||||||||||||||||||||
| 364 | continue; // All necessary events are already captured. never executed: continue; | 0 | ||||||||||||||||||||||||
| 365 | xiEventMask[i].deviceid = scrollingDevice.deviceId; | - | ||||||||||||||||||||||||
| 366 | xiEventMask[i].mask_len = sizeof(scrollBitMask); | - | ||||||||||||||||||||||||
| 367 | xiEventMask[i].mask = xiScrollBitMask; | - | ||||||||||||||||||||||||
| 368 | i++; | - | ||||||||||||||||||||||||
| 369 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 370 | XISelectEvents(xDisplay, window, xiEventMask.data(), i); | - | ||||||||||||||||||||||||
| 371 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 372 | #else | - | ||||||||||||||||||||||||
| 373 | Q_UNUSED(xiBitMask); | - | ||||||||||||||||||||||||
| 374 | #endif | - | ||||||||||||||||||||||||
| 375 | - | |||||||||||||||||||||||||
| 376 | { | - | ||||||||||||||||||||||||
| 377 | // Listen for hotplug events | - | ||||||||||||||||||||||||
| 378 | XIEventMask xiEventMask; | - | ||||||||||||||||||||||||
| 379 | bitMask = XI_HierarchyChangedMask; | - | ||||||||||||||||||||||||
| 380 | bitMask |= XI_DeviceChangedMask; | - | ||||||||||||||||||||||||
| 381 | xiEventMask.deviceid = XIAllDevices; | - | ||||||||||||||||||||||||
| 382 | xiEventMask.mask_len = sizeof(bitMask); | - | ||||||||||||||||||||||||
| 383 | xiEventMask.mask = xiBitMask; | - | ||||||||||||||||||||||||
| 384 | XISelectEvents(xDisplay, window, &xiEventMask, 1); | - | ||||||||||||||||||||||||
| 385 | } | - | ||||||||||||||||||||||||
| 386 | } executed 4107 times by 125 tests: end of blockExecuted by:
| 4107 | ||||||||||||||||||||||||
| 387 | - | |||||||||||||||||||||||||
| 388 | XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id) | - | ||||||||||||||||||||||||
| 389 | { | - | ||||||||||||||||||||||||
| 390 | XInput2TouchDeviceData *dev = Q_NULLPTR; | - | ||||||||||||||||||||||||
| 391 | QHash<int, XInput2TouchDeviceData*>::const_iterator devIt = m_touchDevices.constFind(id); | - | ||||||||||||||||||||||||
| 392 | if (devIt != m_touchDevices.cend()) {
| 0-540 | ||||||||||||||||||||||||
| 393 | dev = devIt.value(); | - | ||||||||||||||||||||||||
| 394 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
| 395 | int nrDevices = 0; | - | ||||||||||||||||||||||||
| 396 | QTouchDevice::Capabilities caps = 0; | - | ||||||||||||||||||||||||
| 397 | dev = new XInput2TouchDeviceData; | - | ||||||||||||||||||||||||
| 398 | dev->xiDeviceInfo = XIQueryDevice(static_cast<Display *>(m_xlib_display), id, &nrDevices); | - | ||||||||||||||||||||||||
| 399 | if (nrDevices <= 0) {
| 0-540 | ||||||||||||||||||||||||
| 400 | delete dev; | - | ||||||||||||||||||||||||
| 401 | return 0; never executed: return 0; | 0 | ||||||||||||||||||||||||
| 402 | } | - | ||||||||||||||||||||||||
| 403 | int type = -1; | - | ||||||||||||||||||||||||
| 404 | int maxTouchPoints = 1; | - | ||||||||||||||||||||||||
| 405 | bool hasRelativeCoords = false; | - | ||||||||||||||||||||||||
| 406 | for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) {
| 540-2700 | ||||||||||||||||||||||||
| 407 | XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i]; | - | ||||||||||||||||||||||||
| 408 | switch (classinfo->type) { | - | ||||||||||||||||||||||||
| 409 | #ifdef XCB_USE_XINPUT22 | - | ||||||||||||||||||||||||
| 410 | case XITouchClass: { never executed: case 8: | 0 | ||||||||||||||||||||||||
| 411 | XITouchClassInfo *tci = reinterpret_cast<XITouchClassInfo *>(classinfo); | - | ||||||||||||||||||||||||
| 412 | maxTouchPoints = tci->num_touches; | - | ||||||||||||||||||||||||
| 413 | qCDebug(lcQpaXInputDevices, " has touch class with mode %d", tci->mode); never executed: QMessageLogger(__FILE__, 413, __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug(" has touch class with mode %d", tci->mode);
| 0 | ||||||||||||||||||||||||
| 414 | switch (tci->mode) { | - | ||||||||||||||||||||||||
| 415 | case XIDependentTouch: never executed: case 2: | 0 | ||||||||||||||||||||||||
| 416 | type = QTouchDevice::TouchPad; | - | ||||||||||||||||||||||||
| 417 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 418 | case XIDirectTouch: never executed: case 1: | 0 | ||||||||||||||||||||||||
| 419 | type = QTouchDevice::TouchScreen; | - | ||||||||||||||||||||||||
| 420 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 421 | } | - | ||||||||||||||||||||||||
| 422 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 423 | } | - | ||||||||||||||||||||||||
| 424 | #endif // XCB_USE_XINPUT22 | - | ||||||||||||||||||||||||
| 425 | case XIValuatorClass: { executed 1620 times by 5 tests: case 2:Executed by:
| 1620 | ||||||||||||||||||||||||
| 426 | XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo); | - | ||||||||||||||||||||||||
| 427 | // Some devices (mice) report a resolution of 0; they will be excluded later, | - | ||||||||||||||||||||||||
| 428 | // for now just prevent a division by zero | - | ||||||||||||||||||||||||
| 429 | const int vciResolution = vci->resolution ? vci->resolution : 1;
| 810 | ||||||||||||||||||||||||
| 430 | if (vci->label == atom(QXcbAtom::AbsMTPositionX))
| 0-1620 | ||||||||||||||||||||||||
| 431 | caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition; never executed: caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition; | 0 | ||||||||||||||||||||||||
| 432 | else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor))
| 0-1620 | ||||||||||||||||||||||||
| 433 | caps |= QTouchDevice::Area; never executed: caps |= QTouchDevice::Area; | 0 | ||||||||||||||||||||||||
| 434 | else if (vci->label == atom(QXcbAtom::AbsMTOrientation))
| 0-1620 | ||||||||||||||||||||||||
| 435 | dev->providesTouchOrientation = true; never executed: dev->providesTouchOrientation = true; | 0 | ||||||||||||||||||||||||
| 436 | else if (vci->label == atom(QXcbAtom::AbsMTPressure) || vci->label == atom(QXcbAtom::AbsPressure))
| 0-1620 | ||||||||||||||||||||||||
| 437 | caps |= QTouchDevice::Pressure; never executed: caps |= QTouchDevice::Pressure; | 0 | ||||||||||||||||||||||||
| 438 | else if (vci->label == atom(QXcbAtom::RelX)) {
| 270-1350 | ||||||||||||||||||||||||
| 439 | hasRelativeCoords = true; | - | ||||||||||||||||||||||||
| 440 | dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution); | - | ||||||||||||||||||||||||
| 441 | } else if (vci->label == atom(QXcbAtom::RelY)) { executed 270 times by 5 tests: end of blockExecuted by:
| 270-1080 | ||||||||||||||||||||||||
| 442 | hasRelativeCoords = true; | - | ||||||||||||||||||||||||
| 443 | dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution); | - | ||||||||||||||||||||||||
| 444 | } else if (vci->label == atom(QXcbAtom::AbsX)) { executed 270 times by 5 tests: end of blockExecuted by:
| 270-810 | ||||||||||||||||||||||||
| 445 | caps |= QTouchDevice::Position; | - | ||||||||||||||||||||||||
| 446 | dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution); | - | ||||||||||||||||||||||||
| 447 | } else if (vci->label == atom(QXcbAtom::AbsY)) { executed 270 times by 5 tests: end of blockExecuted by:
| 270-540 | ||||||||||||||||||||||||
| 448 | caps |= QTouchDevice::Position; | - | ||||||||||||||||||||||||
| 449 | dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution); | - | ||||||||||||||||||||||||
| 450 | } executed 270 times by 5 tests: end of blockExecuted by:
| 270 | ||||||||||||||||||||||||
| 451 | break; executed 1620 times by 5 tests: break;Executed by:
| 1620 | ||||||||||||||||||||||||
| 452 | } | - | ||||||||||||||||||||||||
| 453 | default: executed 1080 times by 5 tests: default:Executed by:
| 1080 | ||||||||||||||||||||||||
| 454 | break; executed 1080 times by 5 tests: break;Executed by:
| 1080 | ||||||||||||||||||||||||
| 455 | } | - | ||||||||||||||||||||||||
| 456 | } | - | ||||||||||||||||||||||||
| 457 | if (type < 0 && caps && hasRelativeCoords) {
| 0-540 | ||||||||||||||||||||||||
| 458 | type = QTouchDevice::TouchPad; | - | ||||||||||||||||||||||||
| 459 | if (dev->size.width() < 10 || dev->size.height() < 10 ||
| 0 | ||||||||||||||||||||||||
| 460 | dev->size.width() > 10000 || dev->size.height() > 10000)
| 0 | ||||||||||||||||||||||||
| 461 | dev->size = QSizeF(130, 110); never executed: dev->size = QSizeF(130, 110); | 0 | ||||||||||||||||||||||||
| 462 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 463 | if (!isAtLeastXI22() || type == QTouchDevice::TouchPad)
| 0-540 | ||||||||||||||||||||||||
| 464 | caps |= QTouchDevice::MouseEmulation; never executed: caps |= QTouchDevice::MouseEmulation; | 0 | ||||||||||||||||||||||||
| 465 | - | |||||||||||||||||||||||||
| 466 | if (type >= QTouchDevice::TouchScreen && type <= QTouchDevice::TouchPad) {
| 0-540 | ||||||||||||||||||||||||
| 467 | dev->qtTouchDevice = new QTouchDevice; | - | ||||||||||||||||||||||||
| 468 | dev->qtTouchDevice->setName(QString::fromUtf8(dev->xiDeviceInfo->name)); | - | ||||||||||||||||||||||||
| 469 | dev->qtTouchDevice->setType((QTouchDevice::DeviceType)type); | - | ||||||||||||||||||||||||
| 470 | dev->qtTouchDevice->setCapabilities(caps); | - | ||||||||||||||||||||||||
| 471 | dev->qtTouchDevice->setMaximumTouchPoints(maxTouchPoints); | - | ||||||||||||||||||||||||
| 472 | if (caps != 0)
| 0 | ||||||||||||||||||||||||
| 473 | QWindowSystemInterface::registerTouchDevice(dev->qtTouchDevice); never executed: QWindowSystemInterface::registerTouchDevice(dev->qtTouchDevice); | 0 | ||||||||||||||||||||||||
| 474 | m_touchDevices[id] = dev; | - | ||||||||||||||||||||||||
| 475 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
| 476 | XIFreeDeviceInfo(dev->xiDeviceInfo); | - | ||||||||||||||||||||||||
| 477 | delete dev; | - | ||||||||||||||||||||||||
| 478 | dev = 0; | - | ||||||||||||||||||||||||
| 479 | } executed 540 times by 5 tests: end of blockExecuted by:
| 540 | ||||||||||||||||||||||||
| 480 | } | - | ||||||||||||||||||||||||
| 481 | return dev; executed 540 times by 5 tests: return dev;Executed by:
| 540 | ||||||||||||||||||||||||
| 482 | } | - | ||||||||||||||||||||||||
| 483 | - | |||||||||||||||||||||||||
| 484 | #if defined(XCB_USE_XINPUT21) || !defined(QT_NO_TABLETEVENT) | - | ||||||||||||||||||||||||
| 485 | static inline qreal fixed1616ToReal(FP1616 val) | - | ||||||||||||||||||||||||
| 486 | { | - | ||||||||||||||||||||||||
| 487 | return qreal(val) / 0x10000; never executed: return qreal(val) / 0x10000; | 0 | ||||||||||||||||||||||||
| 488 | } | - | ||||||||||||||||||||||||
| 489 | #endif // defined(XCB_USE_XINPUT21) || !defined(QT_NO_TABLETEVENT) | - | ||||||||||||||||||||||||
| 490 | - | |||||||||||||||||||||||||
| 491 | void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) | - | ||||||||||||||||||||||||
| 492 | { | - | ||||||||||||||||||||||||
| 493 | xi2PrepareXIGenericDeviceEvent(event); | - | ||||||||||||||||||||||||
| 494 | xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event); | - | ||||||||||||||||||||||||
| 495 | int sourceDeviceId = xiEvent->deviceid; // may be the master id | - | ||||||||||||||||||||||||
| 496 | xXIDeviceEvent *xiDeviceEvent = 0; | - | ||||||||||||||||||||||||
| 497 | xXIEnterEvent *xiEnterEvent = 0; | - | ||||||||||||||||||||||||
| 498 | QXcbWindowEventListener *eventListener = 0; | - | ||||||||||||||||||||||||
| 499 | - | |||||||||||||||||||||||||
| 500 | switch (xiEvent->evtype) { | - | ||||||||||||||||||||||||
| 501 | case XI_ButtonPress: never executed: case 4: | 0 | ||||||||||||||||||||||||
| 502 | case XI_ButtonRelease: never executed: case 5: | 0 | ||||||||||||||||||||||||
| 503 | case XI_Motion: executed 464 times by 18 tests: case 6:Executed by:
| 464 | ||||||||||||||||||||||||
| 504 | #ifdef XCB_USE_XINPUT22 | - | ||||||||||||||||||||||||
| 505 | case XI_TouchBegin: never executed: case 18: | 0 | ||||||||||||||||||||||||
| 506 | case XI_TouchUpdate: never executed: case 19: | 0 | ||||||||||||||||||||||||
| 507 | case XI_TouchEnd: never executed: case 20: | 0 | ||||||||||||||||||||||||
| 508 | #endif | - | ||||||||||||||||||||||||
| 509 | { | - | ||||||||||||||||||||||||
| 510 | xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event); | - | ||||||||||||||||||||||||
| 511 | eventListener = windowEventListenerFromId(xiDeviceEvent->event); | - | ||||||||||||||||||||||||
| 512 | sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master | - | ||||||||||||||||||||||||
| 513 | break; executed 464 times by 18 tests: break;Executed by:
| 464 | ||||||||||||||||||||||||
| 514 | } | - | ||||||||||||||||||||||||
| 515 | case XI_Enter: executed 889 times by 70 tests: case 7:Executed by:
| 889 | ||||||||||||||||||||||||
| 516 | case XI_Leave: { executed 832 times by 58 tests: case 8:Executed by:
| 832 | ||||||||||||||||||||||||
| 517 | xiEnterEvent = reinterpret_cast<xXIEnterEvent *>(event); | - | ||||||||||||||||||||||||
| 518 | eventListener = windowEventListenerFromId(xiEnterEvent->event); | - | ||||||||||||||||||||||||
| 519 | sourceDeviceId = xiEnterEvent->sourceid; // use the actual device id instead of the master | - | ||||||||||||||||||||||||
| 520 | break; executed 1721 times by 70 tests: break;Executed by:
| 1721 | ||||||||||||||||||||||||
| 521 | } | - | ||||||||||||||||||||||||
| 522 | case XI_HierarchyChanged: never executed: case 11: | 0 | ||||||||||||||||||||||||
| 523 | xi2HandleHierachyEvent(xiEvent); | - | ||||||||||||||||||||||||
| 524 | return; never executed: return; | 0 | ||||||||||||||||||||||||
| 525 | case XI_DeviceChanged: never executed: case 1: | 0 | ||||||||||||||||||||||||
| 526 | xi2HandleDeviceChangedEvent(xiEvent); | - | ||||||||||||||||||||||||
| 527 | return; never executed: return; | 0 | ||||||||||||||||||||||||
| 528 | default: never executed: default: | 0 | ||||||||||||||||||||||||
| 529 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 530 | } | - | ||||||||||||||||||||||||
| 531 | - | |||||||||||||||||||||||||
| 532 | if (eventListener) {
| 866-1319 | ||||||||||||||||||||||||
| 533 | long result = 0; | - | ||||||||||||||||||||||||
| 534 | if (eventListener->handleGenericEvent(reinterpret_cast<xcb_generic_event_t *>(event), &result))
| 0-1319 | ||||||||||||||||||||||||
| 535 | return; never executed: return; | 0 | ||||||||||||||||||||||||
| 536 | } executed 1319 times by 70 tests: end of blockExecuted by:
| 1319 | ||||||||||||||||||||||||
| 537 | - | |||||||||||||||||||||||||
| 538 | #ifndef QT_NO_TABLETEVENT | - | ||||||||||||||||||||||||
| 539 | if (!xiEnterEvent) {
| 464-1721 | ||||||||||||||||||||||||
| 540 | QXcbConnection::TabletData *tablet = tabletDataForDevice(sourceDeviceId); | - | ||||||||||||||||||||||||
| 541 | if (tablet && xi2HandleTabletEvent(xiEvent, tablet))
| 0-464 | ||||||||||||||||||||||||
| 542 | return; never executed: return; | 0 | ||||||||||||||||||||||||
| 543 | } executed 464 times by 18 tests: end of blockExecuted by:
| 464 | ||||||||||||||||||||||||
| 544 | #endif // QT_NO_TABLETEVENT | - | ||||||||||||||||||||||||
| 545 | - | |||||||||||||||||||||||||
| 546 | #ifdef XCB_USE_XINPUT21 | - | ||||||||||||||||||||||||
| 547 | QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(sourceDeviceId); | - | ||||||||||||||||||||||||
| 548 | if (device != m_scrollingDevices.end())
| 0-2185 | ||||||||||||||||||||||||
| 549 | xi2HandleScrollEvent(xiEvent, device.value()); never executed: xi2HandleScrollEvent(xiEvent, device.value()); | 0 | ||||||||||||||||||||||||
| 550 | #endif // XCB_USE_XINPUT21 | - | ||||||||||||||||||||||||
| 551 | - | |||||||||||||||||||||||||
| 552 | #ifdef XCB_USE_XINPUT22 | - | ||||||||||||||||||||||||
| 553 | if (xiDeviceEvent) {
| 464-1721 | ||||||||||||||||||||||||
| 554 | switch (xiDeviceEvent->evtype) { | - | ||||||||||||||||||||||||
| 555 | case XI_ButtonPress: never executed: case 4: | 0 | ||||||||||||||||||||||||
| 556 | case XI_ButtonRelease: never executed: case 5: | 0 | ||||||||||||||||||||||||
| 557 | case XI_Motion: executed 464 times by 18 tests: case 6:Executed by:
| 464 | ||||||||||||||||||||||||
| 558 | if (xi2MouseEvents() && eventListener && !(xiDeviceEvent->flags & XIPointerEmulated))
| 0-464 | ||||||||||||||||||||||||
| 559 | eventListener->handleXIMouseEvent(event); executed 453 times by 17 tests: eventListener->handleXIMouseEvent(event);Executed by:
| 453 | ||||||||||||||||||||||||
| 560 | break; executed 464 times by 18 tests: break;Executed by:
| 464 | ||||||||||||||||||||||||
| 561 | - | |||||||||||||||||||||||||
| 562 | case XI_TouchBegin: never executed: case 18: | 0 | ||||||||||||||||||||||||
| 563 | case XI_TouchUpdate: never executed: case 19: | 0 | ||||||||||||||||||||||||
| 564 | case XI_TouchEnd: never executed: case 20: | 0 | ||||||||||||||||||||||||
| 565 | if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
| 0 | ||||||||||||||||||||||||
| 566 | qCDebug(lcQpaXInputEvents, "XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x", never executed: QMessageLogger( __FILE__ , 569 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x", event->event_type, xiDeviceEvent->sequenceNumber, xiDeviceEvent->detail, fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y), fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event) ;
| 0 | ||||||||||||||||||||||||
| 567 | event->event_type, xiDeviceEvent->sequenceNumber, xiDeviceEvent->detail, never executed: QMessageLogger( __FILE__ , 569 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x", event->event_type, xiDeviceEvent->sequenceNumber, xiDeviceEvent->detail, fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y), fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event) ; | 0 | ||||||||||||||||||||||||
| 568 | fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y), never executed: QMessageLogger( __FILE__ , 569 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x", event->event_type, xiDeviceEvent->sequenceNumber, xiDeviceEvent->detail, fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y), fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event) ; | 0 | ||||||||||||||||||||||||
| 569 | fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event); never executed: QMessageLogger( __FILE__ , 569 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x", event->event_type, xiDeviceEvent->sequenceNumber, xiDeviceEvent->detail, fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y), fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event) ; | 0 | ||||||||||||||||||||||||
| 570 | if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event))
| 0 | ||||||||||||||||||||||||
| 571 | xi2ProcessTouch(xiDeviceEvent, platformWindow); never executed: xi2ProcessTouch(xiDeviceEvent, platformWindow); | 0 | ||||||||||||||||||||||||
| 572 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 573 | } | - | ||||||||||||||||||||||||
| 574 | } else if (xiEnterEvent && xi2MouseEvents() && eventListener) { executed 464 times by 18 tests: end of blockExecuted by:
| 0-1721 | ||||||||||||||||||||||||
| 575 | switch (xiEnterEvent->evtype) { | - | ||||||||||||||||||||||||
| 576 | case XI_Enter: executed 719 times by 70 tests: case 7:Executed by:
| 719 | ||||||||||||||||||||||||
| 577 | case XI_Leave: executed 147 times by 27 tests: case 8:Executed by:
| 147 | ||||||||||||||||||||||||
| 578 | eventListener->handleXIEnterLeave(event); | - | ||||||||||||||||||||||||
| 579 | break; executed 866 times by 70 tests: break;Executed by:
| 866 | ||||||||||||||||||||||||
| 580 | } | - | ||||||||||||||||||||||||
| 581 | } executed 866 times by 70 tests: end of blockExecuted by:
| 866 | ||||||||||||||||||||||||
| 582 | #endif // XCB_USE_XINPUT22 | - | ||||||||||||||||||||||||
| 583 | } executed 2185 times by 70 tests: end of blockExecuted by:
| 2185 | ||||||||||||||||||||||||
| 584 | - | |||||||||||||||||||||||||
| 585 | #ifdef XCB_USE_XINPUT22 | - | ||||||||||||||||||||||||
| 586 | static qreal valuatorNormalized(double value, XIValuatorClassInfo *vci) | - | ||||||||||||||||||||||||
| 587 | { | - | ||||||||||||||||||||||||
| 588 | if (value > vci->max)
| 0 | ||||||||||||||||||||||||
| 589 | value = vci->max; never executed: value = vci->max; | 0 | ||||||||||||||||||||||||
| 590 | if (value < vci->min)
| 0 | ||||||||||||||||||||||||
| 591 | value = vci->min; never executed: value = vci->min; | 0 | ||||||||||||||||||||||||
| 592 | return (value - vci->min) / (vci->max - vci->min); never executed: return (value - vci->min) / (vci->max - vci->min); | 0 | ||||||||||||||||||||||||
| 593 | } | - | ||||||||||||||||||||||||
| 594 | - | |||||||||||||||||||||||||
| 595 | void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow) | - | ||||||||||||||||||||||||
| 596 | { | - | ||||||||||||||||||||||||
| 597 | xXIDeviceEvent *xiDeviceEvent = static_cast<xXIDeviceEvent *>(xiDevEvent); | - | ||||||||||||||||||||||||
| 598 | XInput2TouchDeviceData *dev = touchDeviceForId(xiDeviceEvent->sourceid); | - | ||||||||||||||||||||||||
| 599 | Q_ASSERT(dev); | - | ||||||||||||||||||||||||
| 600 | const bool firstTouch = dev->touchPoints.isEmpty(); | - | ||||||||||||||||||||||||
| 601 | if (xiDeviceEvent->evtype == XI_TouchBegin) {
| 0 | ||||||||||||||||||||||||
| 602 | QWindowSystemInterface::TouchPoint tp; | - | ||||||||||||||||||||||||
| 603 | tp.id = xiDeviceEvent->detail % INT_MAX; | - | ||||||||||||||||||||||||
| 604 | tp.state = Qt::TouchPointPressed; | - | ||||||||||||||||||||||||
| 605 | tp.pressure = -1.0; | - | ||||||||||||||||||||||||
| 606 | dev->touchPoints[tp.id] = tp; | - | ||||||||||||||||||||||||
| 607 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 608 | QWindowSystemInterface::TouchPoint &touchPoint = dev->touchPoints[xiDeviceEvent->detail]; | - | ||||||||||||||||||||||||
| 609 | QXcbScreen* screen = platformWindow->xcbScreen(); | - | ||||||||||||||||||||||||
| 610 | qreal x = fixed1616ToReal(xiDeviceEvent->root_x); | - | ||||||||||||||||||||||||
| 611 | qreal y = fixed1616ToReal(xiDeviceEvent->root_y); | - | ||||||||||||||||||||||||
| 612 | qreal nx = -1.0, ny = -1.0; | - | ||||||||||||||||||||||||
| 613 | qreal w = 0.0, h = 0.0; | - | ||||||||||||||||||||||||
| 614 | bool majorAxisIsY = touchPoint.area.height() > touchPoint.area.width(); | - | ||||||||||||||||||||||||
| 615 | for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) {
| 0 | ||||||||||||||||||||||||
| 616 | XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i]; | - | ||||||||||||||||||||||||
| 617 | if (classinfo->type == XIValuatorClass) {
| 0 | ||||||||||||||||||||||||
| 618 | XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo); | - | ||||||||||||||||||||||||
| 619 | int n = vci->number; | - | ||||||||||||||||||||||||
| 620 | double value; | - | ||||||||||||||||||||||||
| 621 | if (!xi2GetValuatorValueIfSet(xiDeviceEvent, n, &value))
| 0 | ||||||||||||||||||||||||
| 622 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||
| 623 | if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
| 0 | ||||||||||||||||||||||||
| 624 | qCDebug(lcQpaXInputEvents, " valuator %20s value %lf from range %lf -> %lf", never executed: QMessageLogger( __FILE__ , 625 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug(" valuator %20s value %lf from range %lf -> %lf", atomName(vci->label).constData(), value, vci->min, vci->max) ;
| 0 | ||||||||||||||||||||||||
| 625 | atomName(vci->label).constData(), value, vci->min, vci->max ); never executed: QMessageLogger( __FILE__ , 625 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug(" valuator %20s value %lf from range %lf -> %lf", atomName(vci->label).constData(), value, vci->min, vci->max) ; | 0 | ||||||||||||||||||||||||
| 626 | if (vci->label == atom(QXcbAtom::RelX)) {
| 0 | ||||||||||||||||||||||||
| 627 | nx = valuatorNormalized(value, vci); | - | ||||||||||||||||||||||||
| 628 | } else if (vci->label == atom(QXcbAtom::RelY)) { never executed: end of block
| 0 | ||||||||||||||||||||||||
| 629 | ny = valuatorNormalized(value, vci); | - | ||||||||||||||||||||||||
| 630 | } else if (vci->label == atom(QXcbAtom::AbsX)) { never executed: end of block
| 0 | ||||||||||||||||||||||||
| 631 | nx = valuatorNormalized(value, vci); | - | ||||||||||||||||||||||||
| 632 | } else if (vci->label == atom(QXcbAtom::AbsY)) { never executed: end of block
| 0 | ||||||||||||||||||||||||
| 633 | ny = valuatorNormalized(value, vci); | - | ||||||||||||||||||||||||
| 634 | } else if (vci->label == atom(QXcbAtom::AbsMTPositionX)) { never executed: end of block
| 0 | ||||||||||||||||||||||||
| 635 | nx = valuatorNormalized(value, vci); | - | ||||||||||||||||||||||||
| 636 | } else if (vci->label == atom(QXcbAtom::AbsMTPositionY)) { never executed: end of block
| 0 | ||||||||||||||||||||||||
| 637 | ny = valuatorNormalized(value, vci); | - | ||||||||||||||||||||||||
| 638 | } else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor)) { never executed: end of block
| 0 | ||||||||||||||||||||||||
| 639 | const qreal sw = screen->geometry().width(); | - | ||||||||||||||||||||||||
| 640 | const qreal sh = screen->geometry().height(); | - | ||||||||||||||||||||||||
| 641 | w = valuatorNormalized(value, vci) * std::sqrt(sw * sw + sh * sh); | - | ||||||||||||||||||||||||
| 642 | } else if (vci->label == atom(QXcbAtom::AbsMTTouchMinor)) { never executed: end of block
| 0 | ||||||||||||||||||||||||
| 643 | const qreal sw = screen->geometry().width(); | - | ||||||||||||||||||||||||
| 644 | const qreal sh = screen->geometry().height(); | - | ||||||||||||||||||||||||
| 645 | h = valuatorNormalized(value, vci) * std::sqrt(sw * sw + sh * sh); | - | ||||||||||||||||||||||||
| 646 | } else if (vci->label == atom(QXcbAtom::AbsMTOrientation)) { never executed: end of block
| 0 | ||||||||||||||||||||||||
| 647 | // Find the closest axis. | - | ||||||||||||||||||||||||
| 648 | // 0 corresponds to the Y axis, vci->max to the X axis. | - | ||||||||||||||||||||||||
| 649 | // Flipping over the Y axis and rotating by 180 degrees | - | ||||||||||||||||||||||||
| 650 | // don't change the result, so normalize value to range | - | ||||||||||||||||||||||||
| 651 | // [0, vci->max] first. | - | ||||||||||||||||||||||||
| 652 | value = qAbs(value); | - | ||||||||||||||||||||||||
| 653 | while (value > vci->max)
| 0 | ||||||||||||||||||||||||
| 654 | value -= 2 * vci->max; never executed: value -= 2 * vci->max; | 0 | ||||||||||||||||||||||||
| 655 | value = qAbs(value); | - | ||||||||||||||||||||||||
| 656 | majorAxisIsY = value < vci->max - value; | - | ||||||||||||||||||||||||
| 657 | } else if (vci->label == atom(QXcbAtom::AbsMTPressure) || never executed: end of block
| 0 | ||||||||||||||||||||||||
| 658 | vci->label == atom(QXcbAtom::AbsPressure)) {
| 0 | ||||||||||||||||||||||||
| 659 | touchPoint.pressure = valuatorNormalized(value, vci); | - | ||||||||||||||||||||||||
| 660 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 661 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 662 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 663 | // If any value was not updated, use the last-known value. | - | ||||||||||||||||||||||||
| 664 | if (nx == -1.0) {
| 0 | ||||||||||||||||||||||||
| 665 | x = touchPoint.area.center().x(); | - | ||||||||||||||||||||||||
| 666 | nx = x / screen->geometry().width(); | - | ||||||||||||||||||||||||
| 667 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 668 | if (ny == -1.0) {
| 0 | ||||||||||||||||||||||||
| 669 | y = touchPoint.area.center().y(); | - | ||||||||||||||||||||||||
| 670 | ny = y / screen->geometry().height(); | - | ||||||||||||||||||||||||
| 671 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 672 | if (xiDeviceEvent->evtype != XI_TouchEnd) {
| 0 | ||||||||||||||||||||||||
| 673 | if (!dev->providesTouchOrientation) {
| 0 | ||||||||||||||||||||||||
| 674 | if (w == 0.0)
| 0 | ||||||||||||||||||||||||
| 675 | w = touchPoint.area.width(); never executed: w = touchPoint.area.width(); | 0 | ||||||||||||||||||||||||
| 676 | h = w; | - | ||||||||||||||||||||||||
| 677 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
| 678 | if (w == 0.0)
| 0 | ||||||||||||||||||||||||
| 679 | w = qMax(touchPoint.area.width(), touchPoint.area.height()); never executed: w = qMax(touchPoint.area.width(), touchPoint.area.height()); | 0 | ||||||||||||||||||||||||
| 680 | if (h == 0.0)
| 0 | ||||||||||||||||||||||||
| 681 | h = qMin(touchPoint.area.width(), touchPoint.area.height()); never executed: h = qMin(touchPoint.area.width(), touchPoint.area.height()); | 0 | ||||||||||||||||||||||||
| 682 | if (majorAxisIsY)
| 0 | ||||||||||||||||||||||||
| 683 | qSwap(w, h); never executed: qSwap(w, h); | 0 | ||||||||||||||||||||||||
| 684 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 685 | } | - | ||||||||||||||||||||||||
| 686 | - | |||||||||||||||||||||||||
| 687 | switch (xiDeviceEvent->evtype) { | - | ||||||||||||||||||||||||
| 688 | case XI_TouchBegin: never executed: case 18: | 0 | ||||||||||||||||||||||||
| 689 | if (firstTouch) {
| 0 | ||||||||||||||||||||||||
| 690 | dev->firstPressedPosition = QPointF(x, y); | - | ||||||||||||||||||||||||
| 691 | dev->firstPressedNormalPosition = QPointF(nx, ny); | - | ||||||||||||||||||||||||
| 692 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 693 | dev->pointPressedPosition.insert(touchPoint.id, QPointF(x, y)); | - | ||||||||||||||||||||||||
| 694 | - | |||||||||||||||||||||||||
| 695 | // Touches must be accepted when we are grabbing touch events. Otherwise the entire sequence | - | ||||||||||||||||||||||||
| 696 | // will get replayed when the grab ends. | - | ||||||||||||||||||||||||
| 697 | if (m_xiGrab) {
| 0 | ||||||||||||||||||||||||
| 698 | // XIAllowTouchEvents deadlocks with libXi < 1.7.4 (this has nothing to do with the XI2 versions like 2.2) | - | ||||||||||||||||||||||||
| 699 | // http://lists.x.org/archives/xorg-devel/2014-July/043059.html | - | ||||||||||||||||||||||||
| 700 | #ifndef LIBXI_MAJOR | - | ||||||||||||||||||||||||
| 701 | static bool allowTouchWarningShown = false; | - | ||||||||||||||||||||||||
| 702 | if (!allowTouchWarningShown) { | - | ||||||||||||||||||||||||
| 703 | allowTouchWarningShown = true; | - | ||||||||||||||||||||||||
| 704 | qWarning("Skipping XIAllowTouchEvents() because it was not possible to detect libXi version at build time." | - | ||||||||||||||||||||||||
| 705 | " Minimum libXi version required is 1.7.4." | - | ||||||||||||||||||||||||
| 706 | " Expect issues with touch behavior."); | - | ||||||||||||||||||||||||
| 707 | } | - | ||||||||||||||||||||||||
| 708 | #elif LIBXI_MAJOR == 1 && (LIBXI_MINOR < 7 || (LIBXI_MINOR == 7 && LIBXI_PATCH < 4)) | - | ||||||||||||||||||||||||
| 709 | static bool allowTouchWarningShown = false; | - | ||||||||||||||||||||||||
| 710 | if (!allowTouchWarningShown) { | - | ||||||||||||||||||||||||
| 711 | allowTouchWarningShown = true; | - | ||||||||||||||||||||||||
| 712 | qWarning("Skipping XIAllowTouchEvents() due to not having libXi >= 1.7.4." | - | ||||||||||||||||||||||||
| 713 | " libXi version at build time was %d.%d.%d." | - | ||||||||||||||||||||||||
| 714 | " Expect issues with touch behavior.", LIBXI_MAJOR, LIBXI_MINOR, LIBXI_PATCH); | - | ||||||||||||||||||||||||
| 715 | } | - | ||||||||||||||||||||||||
| 716 | #else | - | ||||||||||||||||||||||||
| 717 | XIAllowTouchEvents(static_cast<Display *>(m_xlib_display), xiDeviceEvent->deviceid, | - | ||||||||||||||||||||||||
| 718 | xiDeviceEvent->detail, xiDeviceEvent->event, XIAcceptTouch); | - | ||||||||||||||||||||||||
| 719 | #endif | - | ||||||||||||||||||||||||
| 720 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 721 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 722 | case XI_TouchUpdate: never executed: case 19: | 0 | ||||||||||||||||||||||||
| 723 | if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) {
| 0 | ||||||||||||||||||||||||
| 724 | qreal dx = (nx - dev->firstPressedNormalPosition.x()) * | - | ||||||||||||||||||||||||
| 725 | dev->size.width() * screen->geometry().width() / screen->physicalSize().width(); | - | ||||||||||||||||||||||||
| 726 | qreal dy = (ny - dev->firstPressedNormalPosition.y()) * | - | ||||||||||||||||||||||||
| 727 | dev->size.height() * screen->geometry().height() / screen->physicalSize().height(); | - | ||||||||||||||||||||||||
| 728 | x = dev->firstPressedPosition.x() + dx; | - | ||||||||||||||||||||||||
| 729 | y = dev->firstPressedPosition.y() + dy; | - | ||||||||||||||||||||||||
| 730 | touchPoint.state = Qt::TouchPointMoved; | - | ||||||||||||||||||||||||
| 731 | } else if (touchPoint.area.center() != QPoint(x, y)) { never executed: end of block
| 0 | ||||||||||||||||||||||||
| 732 | touchPoint.state = Qt::TouchPointMoved; | - | ||||||||||||||||||||||||
| 733 | dev->pointPressedPosition[touchPoint.id] = QPointF(x, y); | - | ||||||||||||||||||||||||
| 734 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 735 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 736 | case XI_TouchEnd: never executed: case 20: | 0 | ||||||||||||||||||||||||
| 737 | touchPoint.state = Qt::TouchPointReleased; | - | ||||||||||||||||||||||||
| 738 | if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) {
| 0 | ||||||||||||||||||||||||
| 739 | qreal dx = (nx - dev->firstPressedNormalPosition.x()) * | - | ||||||||||||||||||||||||
| 740 | dev->size.width() * screen->geometry().width() / screen->physicalSize().width(); | - | ||||||||||||||||||||||||
| 741 | qreal dy = (ny - dev->firstPressedNormalPosition.y()) * | - | ||||||||||||||||||||||||
| 742 | dev->size.width() * screen->geometry().width() / screen->physicalSize().width(); | - | ||||||||||||||||||||||||
| 743 | x = dev->firstPressedPosition.x() + dx; | - | ||||||||||||||||||||||||
| 744 | y = dev->firstPressedPosition.y() + dy; | - | ||||||||||||||||||||||||
| 745 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 746 | dev->pointPressedPosition.remove(touchPoint.id); | - | ||||||||||||||||||||||||
| 747 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 748 | touchPoint.area = QRectF(x - w/2, y - h/2, w, h); | - | ||||||||||||||||||||||||
| 749 | touchPoint.normalPosition = QPointF(nx, ny); | - | ||||||||||||||||||||||||
| 750 | - | |||||||||||||||||||||||||
| 751 | if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
| 0 | ||||||||||||||||||||||||
| 752 | qCDebug(lcQpaXInputEvents) << " touchpoint " << touchPoint.id << " state " << touchPoint.state << " pos norm " << touchPoint.normalPosition << never executed: QMessageLogger(__FILE__, 752, __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug() << " touchpoint " << touchPoint.id << " state " << touchPoint.state << " pos norm " << touchPoint.normalPosition << " area " << touchPoint.area << " pressure " << touchPoint.pressure;
| 0 | ||||||||||||||||||||||||
| 753 | " area " << touchPoint.area << " pressure " << touchPoint.pressure; never executed: QMessageLogger(__FILE__, 752, __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug() << " touchpoint " << touchPoint.id << " state " << touchPoint.state << " pos norm " << touchPoint.normalPosition << " area " << touchPoint.area << " pressure " << touchPoint.pressure; | 0 | ||||||||||||||||||||||||
| 754 | QWindowSystemInterface::handleTouchEvent(platformWindow->window(), xiDeviceEvent->time, dev->qtTouchDevice, dev->touchPoints.values()); | - | ||||||||||||||||||||||||
| 755 | if (touchPoint.state == Qt::TouchPointReleased)
| 0 | ||||||||||||||||||||||||
| 756 | // If a touchpoint was released, we can forget it, because the ID won't be reused. | - | ||||||||||||||||||||||||
| 757 | dev->touchPoints.remove(touchPoint.id); never executed: dev->touchPoints.remove(touchPoint.id); | 0 | ||||||||||||||||||||||||
| 758 | else | - | ||||||||||||||||||||||||
| 759 | // Make sure that we don't send TouchPointPressed/Moved in more than one QTouchEvent | - | ||||||||||||||||||||||||
| 760 | // with this touch point if the next XI2 event is about a different touch point. | - | ||||||||||||||||||||||||
| 761 | touchPoint.state = Qt::TouchPointStationary; never executed: touchPoint.state = Qt::TouchPointStationary; | 0 | ||||||||||||||||||||||||
| 762 | } | - | ||||||||||||||||||||||||
| 763 | - | |||||||||||||||||||||||||
| 764 | bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab) | - | ||||||||||||||||||||||||
| 765 | { | - | ||||||||||||||||||||||||
| 766 | if (grab && !canGrab())
| 0-198 | ||||||||||||||||||||||||
| 767 | return false; never executed: return false; | 0 | ||||||||||||||||||||||||
| 768 | - | |||||||||||||||||||||||||
| 769 | int num_devices = 0; | - | ||||||||||||||||||||||||
| 770 | Display *xDisplay = static_cast<Display *>(xlib_display()); | - | ||||||||||||||||||||||||
| 771 | XIDeviceInfo *info = XIQueryDevice(xDisplay, XIAllMasterDevices, &num_devices); | - | ||||||||||||||||||||||||
| 772 | if (!info)
| 0-367 | ||||||||||||||||||||||||
| 773 | return false; never executed: return false; | 0 | ||||||||||||||||||||||||
| 774 | - | |||||||||||||||||||||||||
| 775 | XIEventMask evmask; | - | ||||||||||||||||||||||||
| 776 | unsigned char mask[XIMaskLen(XI_LASTEVENT)]; | - | ||||||||||||||||||||||||
| 777 | evmask.mask = mask; | - | ||||||||||||||||||||||||
| 778 | evmask.mask_len = sizeof(mask); | - | ||||||||||||||||||||||||
| 779 | memset(mask, 0, sizeof(mask)); | - | ||||||||||||||||||||||||
| 780 | evmask.deviceid = XIAllMasterDevices; | - | ||||||||||||||||||||||||
| 781 | - | |||||||||||||||||||||||||
| 782 | XISetMask(mask, XI_ButtonPress); | - | ||||||||||||||||||||||||
| 783 | XISetMask(mask, XI_ButtonRelease); | - | ||||||||||||||||||||||||
| 784 | XISetMask(mask, XI_Motion); | - | ||||||||||||||||||||||||
| 785 | XISetMask(mask, XI_Enter); | - | ||||||||||||||||||||||||
| 786 | XISetMask(mask, XI_Leave); | - | ||||||||||||||||||||||||
| 787 | XISetMask(mask, XI_TouchBegin); | - | ||||||||||||||||||||||||
| 788 | XISetMask(mask, XI_TouchUpdate); | - | ||||||||||||||||||||||||
| 789 | XISetMask(mask, XI_TouchEnd); | - | ||||||||||||||||||||||||
| 790 | - | |||||||||||||||||||||||||
| 791 | bool grabbed = true; | - | ||||||||||||||||||||||||
| 792 | for (int i = 0; i < num_devices; i++) {
| 367-734 | ||||||||||||||||||||||||
| 793 | int id = info[i].deviceid, n = 0; | - | ||||||||||||||||||||||||
| 794 | XIDeviceInfo *deviceInfo = XIQueryDevice(xDisplay, id, &n); | - | ||||||||||||||||||||||||
| 795 | if (deviceInfo) {
| 0-734 | ||||||||||||||||||||||||
| 796 | const bool grabbable = deviceInfo->use != XIMasterKeyboard; | - | ||||||||||||||||||||||||
| 797 | XIFreeDeviceInfo(deviceInfo); | - | ||||||||||||||||||||||||
| 798 | if (!grabbable)
| 367 | ||||||||||||||||||||||||
| 799 | continue; executed 367 times by 21 tests: continue;Executed by:
| 367 | ||||||||||||||||||||||||
| 800 | } executed 367 times by 21 tests: end of blockExecuted by:
| 367 | ||||||||||||||||||||||||
| 801 | if (!grab) {
| 169-198 | ||||||||||||||||||||||||
| 802 | Status result = XIUngrabDevice(xDisplay, id, CurrentTime); | - | ||||||||||||||||||||||||
| 803 | if (result != Success) {
| 0-169 | ||||||||||||||||||||||||
| 804 | grabbed = false; | - | ||||||||||||||||||||||||
| 805 | qCDebug(lcQpaXInput, "XInput 2.2: failed to ungrab events for device %d (result %d)", id, result); never executed: QMessageLogger(__FILE__, 805, __PRETTY_FUNCTION__, lcQpaXInput().categoryName()).debug("XInput 2.2: failed to ungrab events for device %d (result %d)", id, result);
| 0 | ||||||||||||||||||||||||
| 806 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 807 | } else { executed 169 times by 21 tests: end of blockExecuted by:
| 169 | ||||||||||||||||||||||||
| 808 | Status result = XIGrabDevice(xDisplay, id, w, CurrentTime, None, XIGrabModeAsync, | - | ||||||||||||||||||||||||
| 809 | XIGrabModeAsync, False, &evmask); | - | ||||||||||||||||||||||||
| 810 | if (result != Success) {
| 0-198 | ||||||||||||||||||||||||
| 811 | grabbed = false; | - | ||||||||||||||||||||||||
| 812 | qCDebug(lcQpaXInput, "XInput 2.2: failed to grab events for device %d on window %x (result %d)", id, w, result); never executed: QMessageLogger(__FILE__, 812, __PRETTY_FUNCTION__, lcQpaXInput().categoryName()).debug("XInput 2.2: failed to grab events for device %d on window %x (result %d)", id, w, result);
| 0 | ||||||||||||||||||||||||
| 813 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 814 | } executed 198 times by 21 tests: end of blockExecuted by:
| 198 | ||||||||||||||||||||||||
| 815 | } | - | ||||||||||||||||||||||||
| 816 | - | |||||||||||||||||||||||||
| 817 | XIFreeDeviceInfo(info); | - | ||||||||||||||||||||||||
| 818 | - | |||||||||||||||||||||||||
| 819 | m_xiGrab = grabbed; | - | ||||||||||||||||||||||||
| 820 | - | |||||||||||||||||||||||||
| 821 | return grabbed; executed 367 times by 21 tests: return grabbed;Executed by:
| 367 | ||||||||||||||||||||||||
| 822 | } | - | ||||||||||||||||||||||||
| 823 | #endif // XCB_USE_XINPUT22 | - | ||||||||||||||||||||||||
| 824 | - | |||||||||||||||||||||||||
| 825 | void QXcbConnection::xi2HandleHierachyEvent(void *event) | - | ||||||||||||||||||||||||
| 826 | { | - | ||||||||||||||||||||||||
| 827 | xXIHierarchyEvent *xiEvent = reinterpret_cast<xXIHierarchyEvent *>(event); | - | ||||||||||||||||||||||||
| 828 | // We only care about hotplugged devices | - | ||||||||||||||||||||||||
| 829 | if (!(xiEvent->flags & (XISlaveRemoved | XISlaveAdded)))
| 0 | ||||||||||||||||||||||||
| 830 | return; never executed: return; | 0 | ||||||||||||||||||||||||
| 831 | xi2SetupDevices(); | - | ||||||||||||||||||||||||
| 832 | // Reselect events for all event-listening windows. | - | ||||||||||||||||||||||||
| 833 | for (auto it = m_mapper.cbegin(), end = m_mapper.cend(); it != end; ++it)
| 0 | ||||||||||||||||||||||||
| 834 | xi2Select(it.key()); never executed: xi2Select(it.key()); | 0 | ||||||||||||||||||||||||
| 835 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 836 | - | |||||||||||||||||||||||||
| 837 | void QXcbConnection::xi2HandleDeviceChangedEvent(void *event) | - | ||||||||||||||||||||||||
| 838 | { | - | ||||||||||||||||||||||||
| 839 | xXIDeviceChangedEvent *xiEvent = reinterpret_cast<xXIDeviceChangedEvent *>(event); | - | ||||||||||||||||||||||||
| 840 | - | |||||||||||||||||||||||||
| 841 | // ### If a slave device changes (XIDeviceChange), we should probably run setup on it again. | - | ||||||||||||||||||||||||
| 842 | if (xiEvent->reason != XISlaveSwitch)
| 0 | ||||||||||||||||||||||||
| 843 | return; never executed: return; | 0 | ||||||||||||||||||||||||
| 844 | - | |||||||||||||||||||||||||
| 845 | #ifdef XCB_USE_XINPUT21 | - | ||||||||||||||||||||||||
| 846 | // This code handles broken scrolling device drivers that reset absolute positions | - | ||||||||||||||||||||||||
| 847 | // when they are made active. Whenever a new slave device is made active the | - | ||||||||||||||||||||||||
| 848 | // primary pointer sends a DeviceChanged event with XISlaveSwitch, and the new | - | ||||||||||||||||||||||||
| 849 | // active slave in sourceid. | - | ||||||||||||||||||||||||
| 850 | - | |||||||||||||||||||||||||
| 851 | QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(xiEvent->sourceid); | - | ||||||||||||||||||||||||
| 852 | if (device == m_scrollingDevices.end())
| 0 | ||||||||||||||||||||||||
| 853 | return; never executed: return; | 0 | ||||||||||||||||||||||||
| 854 | - | |||||||||||||||||||||||||
| 855 | int nrDevices = 0; | - | ||||||||||||||||||||||||
| 856 | XIDeviceInfo* xiDeviceInfo = XIQueryDevice(static_cast<Display *>(m_xlib_display), xiEvent->sourceid, &nrDevices); | - | ||||||||||||||||||||||||
| 857 | if (nrDevices <= 0) {
| 0 | ||||||||||||||||||||||||
| 858 | qCDebug(lcQpaXInputDevices, "scrolling device %d no longer present", xiEvent->sourceid); never executed: QMessageLogger(__FILE__, 858, __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug("scrolling device %d no longer present", xiEvent->sourceid);
| 0 | ||||||||||||||||||||||||
| 859 | return; never executed: return; | 0 | ||||||||||||||||||||||||
| 860 | } | - | ||||||||||||||||||||||||
| 861 | updateScrollingDevice(*device, xiDeviceInfo->num_classes, xiDeviceInfo->classes); | - | ||||||||||||||||||||||||
| 862 | XIFreeDeviceInfo(xiDeviceInfo); | - | ||||||||||||||||||||||||
| 863 | #endif | - | ||||||||||||||||||||||||
| 864 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 865 | - | |||||||||||||||||||||||||
| 866 | void QXcbConnection::updateScrollingDevice(ScrollingDevice &scrollingDevice, int num_classes, void *classInfo) | - | ||||||||||||||||||||||||
| 867 | { | - | ||||||||||||||||||||||||
| 868 | #ifdef XCB_USE_XINPUT21 | - | ||||||||||||||||||||||||
| 869 | XIAnyClassInfo **classes = reinterpret_cast<XIAnyClassInfo**>(classInfo); | - | ||||||||||||||||||||||||
| 870 | QPointF lastScrollPosition; | - | ||||||||||||||||||||||||
| 871 | if (lcQpaXInput().isDebugEnabled())
| 0-2852 | ||||||||||||||||||||||||
| 872 | lastScrollPosition = scrollingDevice.lastScrollPosition; never executed: lastScrollPosition = scrollingDevice.lastScrollPosition; | 0 | ||||||||||||||||||||||||
| 873 | for (int c = 0; c < num_classes; ++c) {
| 2852-14260 | ||||||||||||||||||||||||
| 874 | if (classes[c]->type == XIValuatorClass) {
| 5704-8556 | ||||||||||||||||||||||||
| 875 | XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classes[c]); | - | ||||||||||||||||||||||||
| 876 | const int valuatorAtom = qatom(vci->label); | - | ||||||||||||||||||||||||
| 877 | if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
| 0-8556 | ||||||||||||||||||||||||
| 878 | scrollingDevice.lastScrollPosition.setX(vci->value); executed 1426 times by 70 tests: scrollingDevice.lastScrollPosition.setX(vci->value);Executed by:
| 1426 | ||||||||||||||||||||||||
| 879 | else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
| 0-7130 | ||||||||||||||||||||||||
| 880 | scrollingDevice.lastScrollPosition.setY(vci->value); executed 1426 times by 70 tests: scrollingDevice.lastScrollPosition.setY(vci->value);Executed by:
| 1426 | ||||||||||||||||||||||||
| 881 | } executed 8556 times by 70 tests: end of blockExecuted by:
| 8556 | ||||||||||||||||||||||||
| 882 | } executed 14260 times by 70 tests: end of blockExecuted by:
| 14260 | ||||||||||||||||||||||||
| 883 | if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled() && lastScrollPosition != scrollingDevice.lastScrollPosition))
| 0-2852 | ||||||||||||||||||||||||
| 884 | qCDebug(lcQpaXInputEvents, "scrolling device %d moved from (%f, %f) to (%f, %f)", scrollingDevice.deviceId, never executed: QMessageLogger( __FILE__ , 887 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("scrolling device %d moved from (%f, %f) to (%f, %f)", scrollingDevice.deviceId, lastScrollPosition.x(), lastScrollPosition.y(), scrollingDevice.lastScrollPosition.x(), scrollingDevice.lastScrollPosition.y()) ;
| 0 | ||||||||||||||||||||||||
| 885 | lastScrollPosition.x(), lastScrollPosition.y(), never executed: QMessageLogger( __FILE__ , 887 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("scrolling device %d moved from (%f, %f) to (%f, %f)", scrollingDevice.deviceId, lastScrollPosition.x(), lastScrollPosition.y(), scrollingDevice.lastScrollPosition.x(), scrollingDevice.lastScrollPosition.y()) ; | 0 | ||||||||||||||||||||||||
| 886 | scrollingDevice.lastScrollPosition.x(), never executed: QMessageLogger( __FILE__ , 887 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("scrolling device %d moved from (%f, %f) to (%f, %f)", scrollingDevice.deviceId, lastScrollPosition.x(), lastScrollPosition.y(), scrollingDevice.lastScrollPosition.x(), scrollingDevice.lastScrollPosition.y()) ; | 0 | ||||||||||||||||||||||||
| 887 | scrollingDevice.lastScrollPosition.y()); never executed: QMessageLogger( __FILE__ , 887 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("scrolling device %d moved from (%f, %f) to (%f, %f)", scrollingDevice.deviceId, lastScrollPosition.x(), lastScrollPosition.y(), scrollingDevice.lastScrollPosition.x(), scrollingDevice.lastScrollPosition.y()) ; | 0 | ||||||||||||||||||||||||
| 888 | #else | - | ||||||||||||||||||||||||
| 889 | Q_UNUSED(scrollingDevice); | - | ||||||||||||||||||||||||
| 890 | Q_UNUSED(num_classes); | - | ||||||||||||||||||||||||
| 891 | Q_UNUSED(classInfo); | - | ||||||||||||||||||||||||
| 892 | #endif | - | ||||||||||||||||||||||||
| 893 | } executed 2852 times by 70 tests: end of blockExecuted by:
| 2852 | ||||||||||||||||||||||||
| 894 | - | |||||||||||||||||||||||||
| 895 | #ifdef XCB_USE_XINPUT21 | - | ||||||||||||||||||||||||
| 896 | void QXcbConnection::handleEnterEvent() | - | ||||||||||||||||||||||||
| 897 | { | - | ||||||||||||||||||||||||
| 898 | QHash<int, ScrollingDevice>::iterator it = m_scrollingDevices.begin(); | - | ||||||||||||||||||||||||
| 899 | const QHash<int, ScrollingDevice>::iterator end = m_scrollingDevices.end(); | - | ||||||||||||||||||||||||
| 900 | while (it != end) {
| 713-2852 | ||||||||||||||||||||||||
| 901 | ScrollingDevice& scrollingDevice = it.value(); | - | ||||||||||||||||||||||||
| 902 | int nrDevices = 0; | - | ||||||||||||||||||||||||
| 903 | XIDeviceInfo* xiDeviceInfo = XIQueryDevice(static_cast<Display *>(m_xlib_display), scrollingDevice.deviceId, &nrDevices); | - | ||||||||||||||||||||||||
| 904 | if (nrDevices <= 0) {
| 0-2852 | ||||||||||||||||||||||||
| 905 | qCDebug(lcQpaXInputDevices, "scrolling device %d no longer present", scrollingDevice.deviceId); never executed: QMessageLogger(__FILE__, 905, __PRETTY_FUNCTION__, lcQpaXInputDevices().categoryName()).debug("scrolling device %d no longer present", scrollingDevice.deviceId);
| 0 | ||||||||||||||||||||||||
| 906 | it = m_scrollingDevices.erase(it); | - | ||||||||||||||||||||||||
| 907 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||
| 908 | } | - | ||||||||||||||||||||||||
| 909 | updateScrollingDevice(scrollingDevice, xiDeviceInfo->num_classes, xiDeviceInfo->classes); | - | ||||||||||||||||||||||||
| 910 | XIFreeDeviceInfo(xiDeviceInfo); | - | ||||||||||||||||||||||||
| 911 | ++it; | - | ||||||||||||||||||||||||
| 912 | } executed 2852 times by 70 tests: end of blockExecuted by:
| 2852 | ||||||||||||||||||||||||
| 913 | } executed 713 times by 70 tests: end of blockExecuted by:
| 713 | ||||||||||||||||||||||||
| 914 | #endif | - | ||||||||||||||||||||||||
| 915 | - | |||||||||||||||||||||||||
| 916 | void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice) | - | ||||||||||||||||||||||||
| 917 | { | - | ||||||||||||||||||||||||
| 918 | #ifdef XCB_USE_XINPUT21 | - | ||||||||||||||||||||||||
| 919 | xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event); | - | ||||||||||||||||||||||||
| 920 | - | |||||||||||||||||||||||||
| 921 | if (xiEvent->evtype == XI_Motion && scrollingDevice.orientations) {
| 0 | ||||||||||||||||||||||||
| 922 | xXIDeviceEvent* xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event); | - | ||||||||||||||||||||||||
| 923 | if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) {
| 0 | ||||||||||||||||||||||||
| 924 | QPoint rawDelta; | - | ||||||||||||||||||||||||
| 925 | QPoint angleDelta; | - | ||||||||||||||||||||||||
| 926 | double value; | - | ||||||||||||||||||||||||
| 927 | if (scrollingDevice.orientations & Qt::Vertical) {
| 0 | ||||||||||||||||||||||||
| 928 | if (xi2GetValuatorValueIfSet(xiDeviceEvent, scrollingDevice.verticalIndex, &value)) {
| 0 | ||||||||||||||||||||||||
| 929 | double delta = scrollingDevice.lastScrollPosition.y() - value; | - | ||||||||||||||||||||||||
| 930 | scrollingDevice.lastScrollPosition.setY(value); | - | ||||||||||||||||||||||||
| 931 | angleDelta.setY((delta / scrollingDevice.verticalIncrement) * 120); | - | ||||||||||||||||||||||||
| 932 | // We do not set "pixel" delta if it is only measured in ticks. | - | ||||||||||||||||||||||||
| 933 | if (scrollingDevice.verticalIncrement > 1)
| 0 | ||||||||||||||||||||||||
| 934 | rawDelta.setY(delta); never executed: rawDelta.setY(delta); | 0 | ||||||||||||||||||||||||
| 935 | else if (scrollingDevice.verticalIncrement < -1)
| 0 | ||||||||||||||||||||||||
| 936 | rawDelta.setY(-delta); never executed: rawDelta.setY(-delta); | 0 | ||||||||||||||||||||||||
| 937 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 938 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 939 | if (scrollingDevice.orientations & Qt::Horizontal) {
| 0 | ||||||||||||||||||||||||
| 940 | if (xi2GetValuatorValueIfSet(xiDeviceEvent, scrollingDevice.horizontalIndex, &value)) {
| 0 | ||||||||||||||||||||||||
| 941 | double delta = scrollingDevice.lastScrollPosition.x() - value; | - | ||||||||||||||||||||||||
| 942 | scrollingDevice.lastScrollPosition.setX(value); | - | ||||||||||||||||||||||||
| 943 | angleDelta.setX((delta / scrollingDevice.horizontalIncrement) * 120); | - | ||||||||||||||||||||||||
| 944 | // We do not set "pixel" delta if it is only measured in ticks. | - | ||||||||||||||||||||||||
| 945 | if (scrollingDevice.horizontalIncrement > 1)
| 0 | ||||||||||||||||||||||||
| 946 | rawDelta.setX(delta); never executed: rawDelta.setX(delta); | 0 | ||||||||||||||||||||||||
| 947 | else if (scrollingDevice.horizontalIncrement < -1)
| 0 | ||||||||||||||||||||||||
| 948 | rawDelta.setX(-delta); never executed: rawDelta.setX(-delta); | 0 | ||||||||||||||||||||||||
| 949 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 950 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 951 | if (!angleDelta.isNull()) {
| 0 | ||||||||||||||||||||||||
| 952 | QPoint local(fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y)); | - | ||||||||||||||||||||||||
| 953 | QPoint global(fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y)); | - | ||||||||||||||||||||||||
| 954 | Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(xiDeviceEvent->mods.effective_mods); | - | ||||||||||||||||||||||||
| 955 | if (modifiers & Qt::AltModifier) {
| 0 | ||||||||||||||||||||||||
| 956 | std::swap(angleDelta.rx(), angleDelta.ry()); | - | ||||||||||||||||||||||||
| 957 | std::swap(rawDelta.rx(), rawDelta.ry()); | - | ||||||||||||||||||||||||
| 958 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 959 | QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiEvent->time, local, global, rawDelta, angleDelta, modifiers); | - | ||||||||||||||||||||||||
| 960 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 961 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 962 | } else if (xiEvent->evtype == XI_ButtonRelease && scrollingDevice.legacyOrientations) { never executed: end of block
| 0 | ||||||||||||||||||||||||
| 963 | xXIDeviceEvent* xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event); | - | ||||||||||||||||||||||||
| 964 | if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) {
| 0 | ||||||||||||||||||||||||
| 965 | QPoint angleDelta; | - | ||||||||||||||||||||||||
| 966 | if (scrollingDevice.legacyOrientations & Qt::Vertical) {
| 0 | ||||||||||||||||||||||||
| 967 | if (xiDeviceEvent->detail == 4)
| 0 | ||||||||||||||||||||||||
| 968 | angleDelta.setY(120); never executed: angleDelta.setY(120); | 0 | ||||||||||||||||||||||||
| 969 | else if (xiDeviceEvent->detail == 5)
| 0 | ||||||||||||||||||||||||
| 970 | angleDelta.setY(-120); never executed: angleDelta.setY(-120); | 0 | ||||||||||||||||||||||||
| 971 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 972 | if (scrollingDevice.legacyOrientations & Qt::Horizontal) {
| 0 | ||||||||||||||||||||||||
| 973 | if (xiDeviceEvent->detail == 6)
| 0 | ||||||||||||||||||||||||
| 974 | angleDelta.setX(120); never executed: angleDelta.setX(120); | 0 | ||||||||||||||||||||||||
| 975 | else if (xiDeviceEvent->detail == 7)
| 0 | ||||||||||||||||||||||||
| 976 | angleDelta.setX(-120); never executed: angleDelta.setX(-120); | 0 | ||||||||||||||||||||||||
| 977 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 978 | if (!angleDelta.isNull()) {
| 0 | ||||||||||||||||||||||||
| 979 | QPoint local(fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y)); | - | ||||||||||||||||||||||||
| 980 | QPoint global(fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y)); | - | ||||||||||||||||||||||||
| 981 | Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(xiDeviceEvent->mods.effective_mods); | - | ||||||||||||||||||||||||
| 982 | if (modifiers & Qt::AltModifier)
| 0 | ||||||||||||||||||||||||
| 983 | std::swap(angleDelta.rx(), angleDelta.ry()); never executed: std::swap(angleDelta.rx(), angleDelta.ry()); | 0 | ||||||||||||||||||||||||
| 984 | QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiEvent->time, local, global, QPoint(), angleDelta, modifiers); | - | ||||||||||||||||||||||||
| 985 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 986 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 987 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 988 | #else | - | ||||||||||||||||||||||||
| 989 | Q_UNUSED(event); | - | ||||||||||||||||||||||||
| 990 | Q_UNUSED(scrollingDevice); | - | ||||||||||||||||||||||||
| 991 | #endif // XCB_USE_XINPUT21 | - | ||||||||||||||||||||||||
| 992 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 993 | - | |||||||||||||||||||||||||
| 994 | Qt::MouseButton QXcbConnection::xiToQtMouseButton(uint32_t b) | - | ||||||||||||||||||||||||
| 995 | { | - | ||||||||||||||||||||||||
| 996 | switch (b) { | - | ||||||||||||||||||||||||
| 997 | case 1: return Qt::LeftButton; never executed: return Qt::LeftButton;never executed: case 1: | 0 | ||||||||||||||||||||||||
| 998 | case 2: return Qt::MiddleButton; never executed: return Qt::MiddleButton;never executed: case 2: | 0 | ||||||||||||||||||||||||
| 999 | case 3: return Qt::RightButton; never executed: return Qt::RightButton;never executed: case 3: | 0 | ||||||||||||||||||||||||
| 1000 | // 4-7 are for scrolling | - | ||||||||||||||||||||||||
| 1001 | default: break; executed 453 times by 17 tests: break;Executed by:
executed 453 times by 17 tests: default:Executed by:
| 453 | ||||||||||||||||||||||||
| 1002 | } | - | ||||||||||||||||||||||||
| 1003 | if (b >= 8 && b <= Qt::MaxMouseButton)
| 0-453 | ||||||||||||||||||||||||
| 1004 | return static_cast<Qt::MouseButton>(Qt::BackButton << (b - 8)); never executed: return static_cast<Qt::MouseButton>(Qt::BackButton << (b - 8)); | 0 | ||||||||||||||||||||||||
| 1005 | return Qt::NoButton; executed 453 times by 17 tests: return Qt::NoButton;Executed by:
| 453 | ||||||||||||||||||||||||
| 1006 | } | - | ||||||||||||||||||||||||
| 1007 | - | |||||||||||||||||||||||||
| 1008 | static QTabletEvent::TabletDevice toolIdToTabletDevice(quint32 toolId) { | - | ||||||||||||||||||||||||
| 1009 | // keep in sync with wacom_intuos_inout() in Linux kernel driver wacom_wac.c | - | ||||||||||||||||||||||||
| 1010 | switch (toolId) { | - | ||||||||||||||||||||||||
| 1011 | case 0xd12: never executed: case 0xd12: | 0 | ||||||||||||||||||||||||
| 1012 | case 0x912: never executed: case 0x912: | 0 | ||||||||||||||||||||||||
| 1013 | case 0x112: never executed: case 0x112: | 0 | ||||||||||||||||||||||||
| 1014 | case 0x913: /* Intuos3 Airbrush */ never executed: case 0x913: | 0 | ||||||||||||||||||||||||
| 1015 | case 0x91b: /* Intuos3 Airbrush Eraser */ never executed: case 0x91b: | 0 | ||||||||||||||||||||||||
| 1016 | case 0x902: /* Intuos4/5 13HD/24HD Airbrush */ never executed: case 0x902: | 0 | ||||||||||||||||||||||||
| 1017 | case 0x90a: /* Intuos4/5 13HD/24HD Airbrush Eraser */ never executed: case 0x90a: | 0 | ||||||||||||||||||||||||
| 1018 | case 0x100902: /* Intuos4/5 13HD/24HD Airbrush */ never executed: case 0x100902: | 0 | ||||||||||||||||||||||||
| 1019 | case 0x10090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */ never executed: case 0x10090a: | 0 | ||||||||||||||||||||||||
| 1020 | return QTabletEvent::Airbrush; never executed: return QTabletEvent::Airbrush; | 0 | ||||||||||||||||||||||||
| 1021 | case 0x007: /* Mouse 4D and 2D */ never executed: case 0x007: | 0 | ||||||||||||||||||||||||
| 1022 | case 0x09c: never executed: case 0x09c: | 0 | ||||||||||||||||||||||||
| 1023 | case 0x094: never executed: case 0x094: | 0 | ||||||||||||||||||||||||
| 1024 | return QTabletEvent::FourDMouse; never executed: return QTabletEvent::FourDMouse; | 0 | ||||||||||||||||||||||||
| 1025 | case 0x017: /* Intuos3 2D Mouse */ never executed: case 0x017: | 0 | ||||||||||||||||||||||||
| 1026 | case 0x806: /* Intuos4 Mouse */ never executed: case 0x806: | 0 | ||||||||||||||||||||||||
| 1027 | case 0x096: /* Lens cursor */ never executed: case 0x096: | 0 | ||||||||||||||||||||||||
| 1028 | case 0x097: /* Intuos3 Lens cursor */ never executed: case 0x097: | 0 | ||||||||||||||||||||||||
| 1029 | case 0x006: /* Intuos4 Lens cursor */ never executed: case 0x006: | 0 | ||||||||||||||||||||||||
| 1030 | return QTabletEvent::Puck; never executed: return QTabletEvent::Puck; | 0 | ||||||||||||||||||||||||
| 1031 | case 0x885: /* Intuos3 Art Pen (Marker Pen) */ never executed: case 0x885: | 0 | ||||||||||||||||||||||||
| 1032 | case 0x100804: /* Intuos4/5 13HD/24HD Art Pen */ never executed: case 0x100804: | 0 | ||||||||||||||||||||||||
| 1033 | case 0x10080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */ never executed: case 0x10080c: | 0 | ||||||||||||||||||||||||
| 1034 | return QTabletEvent::RotationStylus; never executed: return QTabletEvent::RotationStylus; | 0 | ||||||||||||||||||||||||
| 1035 | case 0: never executed: case 0: | 0 | ||||||||||||||||||||||||
| 1036 | return QTabletEvent::NoDevice; never executed: return QTabletEvent::NoDevice; | 0 | ||||||||||||||||||||||||
| 1037 | } | - | ||||||||||||||||||||||||
| 1038 | return QTabletEvent::Stylus; // Safe default assumption if nonzero never executed: return QTabletEvent::Stylus; | 0 | ||||||||||||||||||||||||
| 1039 | } | - | ||||||||||||||||||||||||
| 1040 | - | |||||||||||||||||||||||||
| 1041 | #ifndef QT_NO_TABLETEVENT | - | ||||||||||||||||||||||||
| 1042 | bool QXcbConnection::xi2HandleTabletEvent(const void *event, TabletData *tabletData) | - | ||||||||||||||||||||||||
| 1043 | { | - | ||||||||||||||||||||||||
| 1044 | bool handled = true; | - | ||||||||||||||||||||||||
| 1045 | Display *xDisplay = static_cast<Display *>(m_xlib_display); | - | ||||||||||||||||||||||||
| 1046 | const xXIGenericDeviceEvent *xiEvent = static_cast<const xXIGenericDeviceEvent *>(event); | - | ||||||||||||||||||||||||
| 1047 | const xXIDeviceEvent *xiDeviceEvent = reinterpret_cast<const xXIDeviceEvent *>(xiEvent); | - | ||||||||||||||||||||||||
| 1048 | - | |||||||||||||||||||||||||
| 1049 | switch (xiEvent->evtype) { | - | ||||||||||||||||||||||||
| 1050 | case XI_ButtonPress: { never executed: case 4: | 0 | ||||||||||||||||||||||||
| 1051 | Qt::MouseButton b = xiToQtMouseButton(xiDeviceEvent->detail); | - | ||||||||||||||||||||||||
| 1052 | tabletData->buttons |= b; | - | ||||||||||||||||||||||||
| 1053 | xi2ReportTabletEvent(xiEvent, tabletData); | - | ||||||||||||||||||||||||
| 1054 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 1055 | } | - | ||||||||||||||||||||||||
| 1056 | case XI_ButtonRelease: { never executed: case 5: | 0 | ||||||||||||||||||||||||
| 1057 | Qt::MouseButton b = xiToQtMouseButton(xiDeviceEvent->detail); | - | ||||||||||||||||||||||||
| 1058 | tabletData->buttons ^= b; | - | ||||||||||||||||||||||||
| 1059 | xi2ReportTabletEvent(xiEvent, tabletData); | - | ||||||||||||||||||||||||
| 1060 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 1061 | } | - | ||||||||||||||||||||||||
| 1062 | case XI_Motion: never executed: case 6: | 0 | ||||||||||||||||||||||||
| 1063 | // Report TabletMove only when the stylus is touching the tablet or any button is pressed. | - | ||||||||||||||||||||||||
| 1064 | // TODO: report proximity (hover) motion (no suitable Qt event exists yet). | - | ||||||||||||||||||||||||
| 1065 | if (tabletData->buttons != Qt::NoButton)
| 0 | ||||||||||||||||||||||||
| 1066 | xi2ReportTabletEvent(xiEvent, tabletData); never executed: xi2ReportTabletEvent(xiEvent, tabletData); | 0 | ||||||||||||||||||||||||
| 1067 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 1068 | case XI_PropertyEvent: { never executed: case 12: | 0 | ||||||||||||||||||||||||
| 1069 | // This is the wacom driver's way of reporting tool proximity. | - | ||||||||||||||||||||||||
| 1070 | // The evdev driver doesn't do it this way. | - | ||||||||||||||||||||||||
| 1071 | const xXIPropertyEvent *ev = reinterpret_cast<const xXIPropertyEvent *>(event); | - | ||||||||||||||||||||||||
| 1072 | if (ev->what == XIPropertyModified) {
| 0 | ||||||||||||||||||||||||
| 1073 | if (ev->property == atom(QXcbAtom::WacomSerialIDs)) {
| 0 | ||||||||||||||||||||||||
| 1074 | enum WacomSerialIndex { | - | ||||||||||||||||||||||||
| 1075 | _WACSER_USB_ID = 0, | - | ||||||||||||||||||||||||
| 1076 | _WACSER_LAST_TOOL_SERIAL, | - | ||||||||||||||||||||||||
| 1077 | _WACSER_LAST_TOOL_ID, | - | ||||||||||||||||||||||||
| 1078 | _WACSER_TOOL_SERIAL, | - | ||||||||||||||||||||||||
| 1079 | _WACSER_TOOL_ID, | - | ||||||||||||||||||||||||
| 1080 | _WACSER_COUNT | - | ||||||||||||||||||||||||
| 1081 | }; | - | ||||||||||||||||||||||||
| 1082 | Atom propType; | - | ||||||||||||||||||||||||
| 1083 | int propFormat; | - | ||||||||||||||||||||||||
| 1084 | unsigned long numItems, bytesAfter; | - | ||||||||||||||||||||||||
| 1085 | unsigned char *data; | - | ||||||||||||||||||||||||
| 1086 | if (XIGetProperty(xDisplay, tabletData->deviceId, ev->property, 0, 100,
| 0 | ||||||||||||||||||||||||
| 1087 | 0, AnyPropertyType, &propType, &propFormat,
| 0 | ||||||||||||||||||||||||
| 1088 | &numItems, &bytesAfter, &data) == Success) {
| 0 | ||||||||||||||||||||||||
| 1089 | if (propType == atom(QXcbAtom::INTEGER) && propFormat == 32 && numItems == _WACSER_COUNT) {
| 0 | ||||||||||||||||||||||||
| 1090 | quint32 *ptr = reinterpret_cast<quint32 *>(data); | - | ||||||||||||||||||||||||
| 1091 | quint32 tool = ptr[_WACSER_TOOL_ID]; | - | ||||||||||||||||||||||||
| 1092 | // Workaround for http://sourceforge.net/p/linuxwacom/bugs/246/ | - | ||||||||||||||||||||||||
| 1093 | // e.g. on Thinkpad Helix, tool ID will be 0 and serial will be 1 | - | ||||||||||||||||||||||||
| 1094 | if (!tool && ptr[_WACSER_TOOL_SERIAL])
| 0 | ||||||||||||||||||||||||
| 1095 | tool = ptr[_WACSER_TOOL_SERIAL]; never executed: tool = ptr[_WACSER_TOOL_SERIAL]; | 0 | ||||||||||||||||||||||||
| 1096 | - | |||||||||||||||||||||||||
| 1097 | // The property change event informs us which tool is in proximity or which one left proximity. | - | ||||||||||||||||||||||||
| 1098 | if (tool) {
| 0 | ||||||||||||||||||||||||
| 1099 | tabletData->inProximity = true; | - | ||||||||||||||||||||||||
| 1100 | tabletData->tool = toolIdToTabletDevice(tool); | - | ||||||||||||||||||||||||
| 1101 | tabletData->serialId = qint64(ptr[_WACSER_USB_ID]) << 32 | qint64(ptr[_WACSER_TOOL_SERIAL]); | - | ||||||||||||||||||||||||
| 1102 | QWindowSystemInterface::handleTabletEnterProximityEvent(ev->time, | - | ||||||||||||||||||||||||
| 1103 | tabletData->tool, tabletData->pointerType, tabletData->serialId); | - | ||||||||||||||||||||||||
| 1104 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
| 1105 | tabletData->inProximity = false; | - | ||||||||||||||||||||||||
| 1106 | tabletData->tool = toolIdToTabletDevice(ptr[_WACSER_LAST_TOOL_ID]); | - | ||||||||||||||||||||||||
| 1107 | // Workaround for http://sourceforge.net/p/linuxwacom/bugs/246/ | - | ||||||||||||||||||||||||
| 1108 | // e.g. on Thinkpad Helix, tool ID will be 0 and serial will be 1 | - | ||||||||||||||||||||||||
| 1109 | if (!tabletData->tool)
| 0 | ||||||||||||||||||||||||
| 1110 | tabletData->tool = toolIdToTabletDevice(ptr[_WACSER_LAST_TOOL_SERIAL]); never executed: tabletData->tool = toolIdToTabletDevice(ptr[_WACSER_LAST_TOOL_SERIAL]); | 0 | ||||||||||||||||||||||||
| 1111 | tabletData->serialId = qint64(ptr[_WACSER_USB_ID]) << 32 | qint64(ptr[_WACSER_LAST_TOOL_SERIAL]); | - | ||||||||||||||||||||||||
| 1112 | QWindowSystemInterface::handleTabletLeaveProximityEvent(ev->time, | - | ||||||||||||||||||||||||
| 1113 | tabletData->tool, tabletData->pointerType, tabletData->serialId); | - | ||||||||||||||||||||||||
| 1114 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 1115 | // TODO maybe have a hash of tabletData->deviceId to device data so we can | - | ||||||||||||||||||||||||
| 1116 | // look up the tablet name here, and distinguish multiple tablets | - | ||||||||||||||||||||||||
| 1117 | if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
| 0 | ||||||||||||||||||||||||
| 1118 | qCDebug(lcQpaXInputEvents, "XI2 proximity change on tablet %d (USB %x): last tool: %x id %x current tool: %x id %x TabletDevice %d", never executed: QMessageLogger( __FILE__ , 1120 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("XI2 proximity change on tablet %d (USB %x): last tool: %x id %x current tool: %x id %x TabletDevice %d", tabletData->deviceId, ptr[_WACSER_USB_ID], ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID], ptr[_WACSER_TOOL_SERIAL], ptr[_WACSER_TOOL_ID], tabletData->tool) ;
| 0 | ||||||||||||||||||||||||
| 1119 | tabletData->deviceId, ptr[_WACSER_USB_ID], ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID], never executed: QMessageLogger( __FILE__ , 1120 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("XI2 proximity change on tablet %d (USB %x): last tool: %x id %x current tool: %x id %x TabletDevice %d", tabletData->deviceId, ptr[_WACSER_USB_ID], ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID], ptr[_WACSER_TOOL_SERIAL], ptr[_WACSER_TOOL_ID], tabletData->tool) ; | 0 | ||||||||||||||||||||||||
| 1120 | ptr[_WACSER_TOOL_SERIAL], ptr[_WACSER_TOOL_ID], tabletData->tool); never executed: QMessageLogger( __FILE__ , 1120 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("XI2 proximity change on tablet %d (USB %x): last tool: %x id %x current tool: %x id %x TabletDevice %d", tabletData->deviceId, ptr[_WACSER_USB_ID], ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID], ptr[_WACSER_TOOL_SERIAL], ptr[_WACSER_TOOL_ID], tabletData->tool) ; | 0 | ||||||||||||||||||||||||
| 1121 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 1122 | XFree(data); | - | ||||||||||||||||||||||||
| 1123 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 1124 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 1125 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 1126 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 1127 | } | - | ||||||||||||||||||||||||
| 1128 | default: never executed: default: | 0 | ||||||||||||||||||||||||
| 1129 | handled = false; | - | ||||||||||||||||||||||||
| 1130 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 1131 | } | - | ||||||||||||||||||||||||
| 1132 | - | |||||||||||||||||||||||||
| 1133 | return handled; never executed: return handled; | 0 | ||||||||||||||||||||||||
| 1134 | } | - | ||||||||||||||||||||||||
| 1135 | - | |||||||||||||||||||||||||
| 1136 | void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletData) | - | ||||||||||||||||||||||||
| 1137 | { | - | ||||||||||||||||||||||||
| 1138 | const xXIDeviceEvent *ev = reinterpret_cast<const xXIDeviceEvent *>(event); | - | ||||||||||||||||||||||||
| 1139 | QXcbWindow *xcbWindow = platformWindowFromId(ev->event); | - | ||||||||||||||||||||||||
| 1140 | if (!xcbWindow)
| 0 | ||||||||||||||||||||||||
| 1141 | return; never executed: return; | 0 | ||||||||||||||||||||||||
| 1142 | QWindow *window = xcbWindow->window(); | - | ||||||||||||||||||||||||
| 1143 | const double scale = 65536.0; | - | ||||||||||||||||||||||||
| 1144 | QPointF local(ev->event_x / scale, ev->event_y / scale); | - | ||||||||||||||||||||||||
| 1145 | QPointF global(ev->root_x / scale, ev->root_y / scale); | - | ||||||||||||||||||||||||
| 1146 | double pressure = 0, rotation = 0, tangentialPressure = 0; | - | ||||||||||||||||||||||||
| 1147 | int xTilt = 0, yTilt = 0; | - | ||||||||||||||||||||||||
| 1148 | - | |||||||||||||||||||||||||
| 1149 | for (QHash<int, TabletData::ValuatorClassInfo>::iterator it = tabletData->valuatorInfo.begin(), | - | ||||||||||||||||||||||||
| 1150 | ite = tabletData->valuatorInfo.end(); it != ite; ++it) {
| 0 | ||||||||||||||||||||||||
| 1151 | int valuator = it.key(); | - | ||||||||||||||||||||||||
| 1152 | TabletData::ValuatorClassInfo &classInfo(it.value()); | - | ||||||||||||||||||||||||
| 1153 | xi2GetValuatorValueIfSet(event, classInfo.number, &classInfo.curVal); | - | ||||||||||||||||||||||||
| 1154 | double normalizedValue = (classInfo.curVal - classInfo.minVal) / (classInfo.maxVal - classInfo.minVal); | - | ||||||||||||||||||||||||
| 1155 | switch (valuator) { | - | ||||||||||||||||||||||||
| 1156 | case QXcbAtom::AbsPressure: never executed: case QXcbAtom::AbsPressure: | 0 | ||||||||||||||||||||||||
| 1157 | pressure = normalizedValue; | - | ||||||||||||||||||||||||
| 1158 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 1159 | case QXcbAtom::AbsTiltX: never executed: case QXcbAtom::AbsTiltX: | 0 | ||||||||||||||||||||||||
| 1160 | xTilt = classInfo.curVal; | - | ||||||||||||||||||||||||
| 1161 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 1162 | case QXcbAtom::AbsTiltY: never executed: case QXcbAtom::AbsTiltY: | 0 | ||||||||||||||||||||||||
| 1163 | yTilt = classInfo.curVal; | - | ||||||||||||||||||||||||
| 1164 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 1165 | case QXcbAtom::AbsWheel: never executed: case QXcbAtom::AbsWheel: | 0 | ||||||||||||||||||||||||
| 1166 | switch (tabletData->tool) { | - | ||||||||||||||||||||||||
| 1167 | case QTabletEvent::Airbrush: never executed: case QTabletEvent::Airbrush: | 0 | ||||||||||||||||||||||||
| 1168 | tangentialPressure = normalizedValue * 2.0 - 1.0; // Convert 0..1 range to -1..+1 range | - | ||||||||||||||||||||||||
| 1169 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 1170 | case QTabletEvent::RotationStylus: never executed: case QTabletEvent::RotationStylus: | 0 | ||||||||||||||||||||||||
| 1171 | rotation = normalizedValue * 360.0 - 180.0; // Convert 0..1 range to -180..+180 degrees | - | ||||||||||||||||||||||||
| 1172 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 1173 | default: // Other types of styli do not use this valuator never executed: default: | 0 | ||||||||||||||||||||||||
| 1174 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 1175 | } | - | ||||||||||||||||||||||||
| 1176 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 1177 | default: never executed: default: | 0 | ||||||||||||||||||||||||
| 1178 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 1179 | } | - | ||||||||||||||||||||||||
| 1180 | } | - | ||||||||||||||||||||||||
| 1181 | - | |||||||||||||||||||||||||
| 1182 | if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
| 0 | ||||||||||||||||||||||||
| 1183 | qCDebug(lcQpaXInputEvents, "XI2 event on tablet %d with tool %d type %d seq %d detail %d time %d " never executed: QMessageLogger( __FILE__ , 1188 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("XI2 event on tablet %d with tool %d type %d seq %d detail %d time %d " "pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotat...Id, tabletData->tool, ev->evtype, ev->sequenceNumber, ev->detail, ev->time, fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y), fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y), (int)tabletData->buttons, pressure, xTilt, yTilt, rotation) ;
| 0 | ||||||||||||||||||||||||
| 1184 | "pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf", never executed: QMessageLogger( __FILE__ , 1188 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("XI2 event on tablet %d with tool %d type %d seq %d detail %d time %d " "pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotat...Id, tabletData->tool, ev->evtype, ev->sequenceNumber, ev->detail, ev->time, fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y), fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y), (int)tabletData->buttons, pressure, xTilt, yTilt, rotation) ; | 0 | ||||||||||||||||||||||||
| 1185 | tabletData->deviceId, tabletData->tool, ev->evtype, ev->sequenceNumber, ev->detail, ev->time, never executed: QMessageLogger( __FILE__ , 1188 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("XI2 event on tablet %d with tool %d type %d seq %d detail %d time %d " "pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotat...Id, tabletData->tool, ev->evtype, ev->sequenceNumber, ev->detail, ev->time, fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y), fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y), (int)tabletData->buttons, pressure, xTilt, yTilt, rotation) ; | 0 | ||||||||||||||||||||||||
| 1186 | fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y), never executed: QMessageLogger( __FILE__ , 1188 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("XI2 event on tablet %d with tool %d type %d seq %d detail %d time %d " "pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotat...Id, tabletData->tool, ev->evtype, ev->sequenceNumber, ev->detail, ev->time, fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y), fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y), (int)tabletData->buttons, pressure, xTilt, yTilt, rotation) ; | 0 | ||||||||||||||||||||||||
| 1187 | fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y), never executed: QMessageLogger( __FILE__ , 1188 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("XI2 event on tablet %d with tool %d type %d seq %d detail %d time %d " "pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotat...Id, tabletData->tool, ev->evtype, ev->sequenceNumber, ev->detail, ev->time, fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y), fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y), (int)tabletData->buttons, pressure, xTilt, yTilt, rotation) ; | 0 | ||||||||||||||||||||||||
| 1188 | (int)tabletData->buttons, pressure, xTilt, yTilt, rotation); never executed: QMessageLogger( __FILE__ , 1188 , __PRETTY_FUNCTION__, lcQpaXInputEvents().categoryName()).debug("XI2 event on tablet %d with tool %d type %d seq %d detail %d time %d " "pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotat...Id, tabletData->tool, ev->evtype, ev->sequenceNumber, ev->detail, ev->time, fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y), fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y), (int)tabletData->buttons, pressure, xTilt, yTilt, rotation) ; | 0 | ||||||||||||||||||||||||
| 1189 | - | |||||||||||||||||||||||||
| 1190 | QWindowSystemInterface::handleTabletEvent(window, ev->time, local, global, | - | ||||||||||||||||||||||||
| 1191 | tabletData->tool, tabletData->pointerType, | - | ||||||||||||||||||||||||
| 1192 | tabletData->buttons, pressure, | - | ||||||||||||||||||||||||
| 1193 | xTilt, yTilt, tangentialPressure, | - | ||||||||||||||||||||||||
| 1194 | rotation, 0, tabletData->serialId); | - | ||||||||||||||||||||||||
| 1195 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 1196 | - | |||||||||||||||||||||||||
| 1197 | QXcbConnection::TabletData *QXcbConnection::tabletDataForDevice(int id) | - | ||||||||||||||||||||||||
| 1198 | { | - | ||||||||||||||||||||||||
| 1199 | for (int i = 0; i < m_tabletData.count(); ++i) {
| 0-944 | ||||||||||||||||||||||||
| 1200 | if (m_tabletData.at(i).deviceId == id)
| 0 | ||||||||||||||||||||||||
| 1201 | return &m_tabletData[i]; never executed: return &m_tabletData[i]; | 0 | ||||||||||||||||||||||||
| 1202 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 1203 | return Q_NULLPTR; executed 944 times by 18 tests: return nullptr;Executed by:
| 944 | ||||||||||||||||||||||||
| 1204 | } | - | ||||||||||||||||||||||||
| 1205 | - | |||||||||||||||||||||||||
| 1206 | #endif // QT_NO_TABLETEVENT | - | ||||||||||||||||||||||||
| 1207 | - | |||||||||||||||||||||||||
| 1208 | #endif // XCB_USE_XINPUT2 | - | ||||||||||||||||||||||||
| Source code | Switch to Preprocessed file |