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