qevdevtablet.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/platformsupport/input/evdevtablet/qevdevtablet.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
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 module 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 "qevdevtablet_p.h"-
35#include <qpa/qwindowsysteminterface.h>-
36#include <QStringList>-
37#include <QSocketNotifier>-
38#include <QGuiApplication>-
39#include <QLoggingCategory>-
40#include <QtCore/private/qcore_unix_p.h>-
41#include <QtPlatformSupport/private/qdevicediscovery_p.h>-
42#include <linux/input.h>-
43-
44QT_BEGIN_NAMESPACE-
45-
46Q_LOGGING_CATEGORY(qLcEvdevTablet, "qt.qpa.input")
never executed: return category;
0
47-
48class QEvdevTabletData-
49{-
50public:-
51 QEvdevTabletData(QEvdevTabletHandler *q_ptr);-
52 bool queryLimits();-
53 void testGrab();-
54 void processInputEvent(input_event *ev);-
55 void reportProximityEnter();-
56 void reportProximityLeave();-
57 void report();-
58-
59 QEvdevTabletHandler *q;-
60 QSocketNotifier *notifier;-
61 int fd;-
62 int lastEventType;-
63 QString devName;-
64 struct {-
65 int x, y, p, d;-
66 } minValues, maxValues;-
67 struct {-
68 int x, y, p, d;-
69 bool down, lastReportDown;-
70 int tool, lastReportTool;-
71 QPointF lastReportPos;-
72 } state;-
73};-
74-
75QEvdevTabletData::QEvdevTabletData(QEvdevTabletHandler *q_ptr)-
76 : q(q_ptr), notifier(0), fd(-1), lastEventType(0)-
77{-
78 memset(&minValues, 0, sizeof(minValues));-
79 memset(&maxValues, 0, sizeof(maxValues));-
80 memset(&state, 0, sizeof(state));-
81}
never executed: end of block
0
82-
83bool QEvdevTabletData::queryLimits()-
84{-
85 bool ok = true;-
86 input_absinfo absInfo;-
87 memset(&absInfo, 0, sizeof(input_absinfo));-
88 ok &= ioctl(fd, EVIOCGABS(ABS_X), &absInfo) >= 0;-
89 if (ok) {
okDescription
TRUEnever evaluated
FALSEnever evaluated
0
90 minValues.x = absInfo.minimum;-
91 maxValues.x = absInfo.maximum;-
92 qCDebug(qLcEvdevTablet, "evdevtablet: min X: %d max X: %d", minValues.x, maxValues.x);
never executed: QMessageLogger(__FILE__, 92, __PRETTY_FUNCTION__, qLcEvdevTablet().categoryName()).debug("evdevtablet: min X: %d max X: %d", minValues.x, maxValues.x);
qt_category_enabledDescription
TRUEnever evaluated
FALSEnever evaluated
0
93 }
never executed: end of block
0
94 ok &= ioctl(fd, EVIOCGABS(ABS_Y), &absInfo) >= 0;-
95 if (ok) {
okDescription
TRUEnever evaluated
FALSEnever evaluated
0
96 minValues.y = absInfo.minimum;-
97 maxValues.y = absInfo.maximum;-
98 qCDebug(qLcEvdevTablet, "evdevtablet: min Y: %d max Y: %d", minValues.y, maxValues.y);
never executed: QMessageLogger(__FILE__, 98, __PRETTY_FUNCTION__, qLcEvdevTablet().categoryName()).debug("evdevtablet: min Y: %d max Y: %d", minValues.y, maxValues.y);
qt_category_enabledDescription
TRUEnever evaluated
FALSEnever evaluated
0
99 }
never executed: end of block
0
100 if (ioctl(fd, EVIOCGABS(ABS_PRESSURE), &absInfo) >= 0) {
ioctl(fd, (((2...&absInfo) >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
101 minValues.p = absInfo.minimum;-
102 maxValues.p = absInfo.maximum;-
103 qCDebug(qLcEvdevTablet, "evdevtablet: min pressure: %d max pressure: %d", minValues.p, maxValues.p);
never executed: QMessageLogger(__FILE__, 103, __PRETTY_FUNCTION__, qLcEvdevTablet().categoryName()).debug("evdevtablet: min pressure: %d max pressure: %d", minValues.p, maxValues.p);
qt_category_enabledDescription
TRUEnever evaluated
FALSEnever evaluated
0
104 }
never executed: end of block
0
105 if (ioctl(fd, EVIOCGABS(ABS_DISTANCE), &absInfo) >= 0) {
ioctl(fd, (((2...&absInfo) >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
106 minValues.d = absInfo.minimum;-
107 maxValues.d = absInfo.maximum;-
108 qCDebug(qLcEvdevTablet, "evdevtablet: min distance: %d max distance: %d", minValues.d, maxValues.d);
never executed: QMessageLogger(__FILE__, 108, __PRETTY_FUNCTION__, qLcEvdevTablet().categoryName()).debug("evdevtablet: min distance: %d max distance: %d", minValues.d, maxValues.d);
qt_category_enabledDescription
TRUEnever evaluated
FALSEnever evaluated
0
109 }
never executed: end of block
0
110 char name[128];-
111 if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), name) >= 0) {
ioctl(fd, (((2...)), name) >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
112 devName = QString::fromLocal8Bit(name);-
113 qCDebug(qLcEvdevTablet, "evdevtablet: device name: %s", name);
never executed: QMessageLogger(__FILE__, 113, __PRETTY_FUNCTION__, qLcEvdevTablet().categoryName()).debug("evdevtablet: device name: %s", name);
qt_category_enabledDescription
TRUEnever evaluated
FALSEnever evaluated
0
114 }
never executed: end of block
0
115 return ok;
never executed: return ok;
0
116}-
117-
118void QEvdevTabletData::testGrab()-
119{-
120 bool grabSuccess = !ioctl(fd, EVIOCGRAB, (void *) 1);-
121 if (grabSuccess)
grabSuccessDescription
TRUEnever evaluated
FALSEnever evaluated
0
122 ioctl(fd, EVIOCGRAB, (void *) 0);
never executed: ioctl(fd, (((1U) << (((0 +8)+8)+14)) | ((('E')) << (0 +8)) | (((0x90)) << 0) | ((((sizeof(int)))) << ((0 +8)+8))), (void *) 0);
0
123 else-
124 qWarning("evdevtablet: ERROR: The device is grabbed by another process. No events will be read.");
never executed: QMessageLogger(__FILE__, 124, __PRETTY_FUNCTION__).warning("evdevtablet: ERROR: The device is grabbed by another process. No events will be read.");
0
125}-
126-
127void QEvdevTabletData::processInputEvent(input_event *ev)-
128{-
129 if (ev->type == EV_ABS) {
ev->type == 0x03Description
TRUEnever evaluated
FALSEnever evaluated
0
130 switch (ev->code) {-
131 case ABS_X:
never executed: case 0x00:
0
132 state.x = ev->value;-
133 break;
never executed: break;
0
134 case ABS_Y:
never executed: case 0x01:
0
135 state.y = ev->value;-
136 break;
never executed: break;
0
137 case ABS_PRESSURE:
never executed: case 0x18:
0
138 state.p = ev->value;-
139 break;
never executed: break;
0
140 case ABS_DISTANCE:
never executed: case 0x19:
0
141 state.d = ev->value;-
142 break;
never executed: break;
0
143 default:
never executed: default:
0
144 break;
never executed: break;
0
145 }-
146 } else if (ev->type == EV_KEY) {
ev->type == 0x01Description
TRUEnever evaluated
FALSEnever evaluated
0
147 // code BTN_TOOL_* value 1 -> proximity enter-
148 // code BTN_TOOL_* value 0 -> proximity leave-
149 // code BTN_TOUCH value 1 -> contact with screen-
150 // code BTN_TOUCH value 0 -> no contact-
151 switch (ev->code) {-
152 case BTN_TOUCH:
never executed: case 0x14a:
0
153 state.down = ev->value != 0;-
154 break;
never executed: break;
0
155 case BTN_TOOL_PEN:
never executed: case 0x140:
0
156 state.tool = ev->value ? QTabletEvent::Pen : 0;
ev->valueDescription
TRUEnever evaluated
FALSEnever evaluated
0
157 break;
never executed: break;
0
158 case BTN_TOOL_RUBBER:
never executed: case 0x141:
0
159 state.tool = ev->value ? QTabletEvent::Eraser : 0;
ev->valueDescription
TRUEnever evaluated
FALSEnever evaluated
0
160 break;
never executed: break;
0
161 default:
never executed: default:
0
162 break;
never executed: break;
0
163 }-
164 } else if (ev->type == EV_SYN && ev->code == SYN_REPORT && lastEventType != ev->type) {
ev->type == 0x00Description
TRUEnever evaluated
FALSEnever evaluated
ev->code == 0Description
TRUEnever evaluated
FALSEnever evaluated
lastEventType != ev->typeDescription
TRUEnever evaluated
FALSEnever evaluated
0
165 report();-
166 }
never executed: end of block
0
167 lastEventType = ev->type;-
168}
never executed: end of block
0
169-
170void QEvdevTabletData::reportProximityEnter()-
171{-
172 QWindowSystemInterface::handleTabletEnterProximityEvent(QTabletEvent::Stylus, state.tool, 1);-
173}
never executed: end of block
0
174-
175void QEvdevTabletData::reportProximityLeave()-
176{-
177 QWindowSystemInterface::handleTabletLeaveProximityEvent(QTabletEvent::Stylus, state.tool, 1);-
178}
never executed: end of block
0
179-
180void QEvdevTabletData::report()-
181{-
182 if (!state.lastReportTool && state.tool)
!state.lastReportToolDescription
TRUEnever evaluated
FALSEnever evaluated
state.toolDescription
TRUEnever evaluated
FALSEnever evaluated
0
183 reportProximityEnter();
never executed: reportProximityEnter();
0
184-
185 qreal nx = (state.x - minValues.x) / qreal(maxValues.x - minValues.x);-
186 qreal ny = (state.y - minValues.y) / qreal(maxValues.y - minValues.y);-
187-
188 QRect winRect = QGuiApplication::primaryScreen()->geometry();-
189 QPointF globalPos(nx * winRect.width(), ny * winRect.height());-
190 int pointer = state.tool;-
191 // Prevent sending confusing values of 0 when moving the pen outside the active area.-
192 if (!state.down && state.lastReportDown) {
!state.downDescription
TRUEnever evaluated
FALSEnever evaluated
state.lastReportDownDescription
TRUEnever evaluated
FALSEnever evaluated
0
193 globalPos = state.lastReportPos;-
194 pointer = state.lastReportTool;-
195 }
never executed: end of block
0
196-
197 qreal pressure = (state.p - minValues.p) / qreal(maxValues.p - minValues.p);-
198-
199 if (state.down || state.lastReportDown) {
state.downDescription
TRUEnever evaluated
FALSEnever evaluated
state.lastReportDownDescription
TRUEnever evaluated
FALSEnever evaluated
0
200 QWindowSystemInterface::handleTabletEvent(0, state.down, QPointF(), globalPos,-
201 QTabletEvent::Stylus, pointer,-
202 pressure, 0, 0, 0, 0, 0, 1, qGuiApp->keyboardModifiers());-
203 }
never executed: end of block
0
204-
205 if (state.lastReportTool && !state.tool)
state.lastReportToolDescription
TRUEnever evaluated
FALSEnever evaluated
!state.toolDescription
TRUEnever evaluated
FALSEnever evaluated
0
206 reportProximityLeave();
never executed: reportProximityLeave();
0
207-
208 state.lastReportDown = state.down;-
209 state.lastReportTool = state.tool;-
210 state.lastReportPos = globalPos;-
211}
never executed: end of block
0
212-
213-
214QEvdevTabletHandler::QEvdevTabletHandler(const QString &spec, QObject *parent)-
215 : QObject(parent), d(0)-
216{-
217 setObjectName(QLatin1String("Evdev Tablet Handler"));-
218 d = new QEvdevTabletData(this);-
219 QString dev;-
220 QStringList args = spec.split(QLatin1Char(':'));-
221 for (int i = 0; i < args.count(); ++i) {
i < args.count()Description
TRUEnever evaluated
FALSEnever evaluated
0
222 if (args.at(i).startsWith(QLatin1String("/dev/"))) {
args.at(i).sta...ring("/dev/"))Description
TRUEnever evaluated
FALSEnever evaluated
0
223 dev = args.at(i);-
224 break;
never executed: break;
0
225 }-
226 }
never executed: end of block
0
227 if (dev.isEmpty()) {
dev.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
228 QScopedPointer<QDeviceDiscovery> deviceDiscovery(-
229 QDeviceDiscovery::create(QDeviceDiscovery::Device_Tablet, this));-
230 if (deviceDiscovery) {
deviceDiscoveryDescription
TRUEnever evaluated
FALSEnever evaluated
0
231 QStringList devices = deviceDiscovery->scanConnectedDevices();-
232 if (!devices.isEmpty())
!devices.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
233 dev = devices.at(0);
never executed: dev = devices.at(0);
0
234 }
never executed: end of block
0
235 }
never executed: end of block
0
236 if (!dev.isEmpty()) {
!dev.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
237 qCDebug(qLcEvdevTablet, "evdevtablet: using %s", qPrintable(dev));
never executed: QMessageLogger(__FILE__, 237, __PRETTY_FUNCTION__, qLcEvdevTablet().categoryName()).debug("evdevtablet: using %s", QString(dev).toLocal8Bit().constData());
qt_category_enabledDescription
TRUEnever evaluated
FALSEnever evaluated
0
238 d->fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);-
239 if (d->fd >= 0) {
d->fd >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
240 d->testGrab();-
241 if (d->queryLimits()) {
d->queryLimits()Description
TRUEnever evaluated
FALSEnever evaluated
0
242 d->notifier = new QSocketNotifier(d->fd, QSocketNotifier::Read, this);-
243 connect(d->notifier, SIGNAL(activated(int)), this, SLOT(readData()));-
244 }
never executed: end of block
0
245 } else {
never executed: end of block
0
246 qErrnoWarning(errno, "evdevtablet: Cannot open input device");-
247 }
never executed: end of block
0
248 }-
249}
never executed: end of block
0
250-
251QEvdevTabletHandler::~QEvdevTabletHandler()-
252{-
253 delete d->notifier;-
254 if (d->fd >= 0)
d->fd >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
255 QT_CLOSE(d->fd);
never executed: qt_safe_close(d->fd);
0
256-
257 delete d;-
258}
never executed: end of block
0
259-
260void QEvdevTabletHandler::readData()-
261{-
262 static input_event buffer[32];-
263 int n = 0;-
264 for (; ;) {-
265 int result = QT_READ(d->fd, reinterpret_cast<char*>(buffer) + n, sizeof(buffer) - n);-
266 if (!result) {
!resultDescription
TRUEnever evaluated
FALSEnever evaluated
0
267 qWarning("evdevtablet: Got EOF from input device");-
268 return;
never executed: return;
0
269 } else if (result < 0) {
result < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
270 if (errno != EINTR && errno != EAGAIN) {
(*__errno_location ()) != 4Description
TRUEnever evaluated
FALSEnever evaluated
(*__errno_location ()) != 11Description
TRUEnever evaluated
FALSEnever evaluated
0
271 qErrnoWarning(errno, "evdevtablet: Could not read from input device");-
272 if (errno == ENODEV) { // device got disconnected -> stop reading
(*__errno_location ()) == 19Description
TRUEnever evaluated
FALSEnever evaluated
0
273 delete d->notifier;-
274 d->notifier = 0;-
275 QT_CLOSE(d->fd);-
276 d->fd = -1;-
277 }
never executed: end of block
0
278 return;
never executed: return;
0
279 }-
280 } else {
never executed: end of block
0
281 n += result;-
282 if (n % sizeof(input_event) == 0)
n % sizeof(input_event) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
283 break;
never executed: break;
0
284 }
never executed: end of block
0
285 }-
286-
287 n /= sizeof(input_event);-
288-
289 for (int i = 0; i < n; ++i)
i < nDescription
TRUEnever evaluated
FALSEnever evaluated
0
290 d->processInputEvent(&buffer[i]);
never executed: d->processInputEvent(&buffer[i]);
0
291}
never executed: end of block
0
292-
293-
294QEvdevTabletHandlerThread::QEvdevTabletHandlerThread(const QString &spec, QObject *parent)-
295 : QDaemonThread(parent), m_spec(spec), m_handler(0)-
296{-
297 start();-
298}
never executed: end of block
0
299-
300QEvdevTabletHandlerThread::~QEvdevTabletHandlerThread()-
301{-
302 quit();-
303 wait();-
304}
never executed: end of block
0
305-
306void QEvdevTabletHandlerThread::run()-
307{-
308 m_handler = new QEvdevTabletHandler(m_spec);-
309 exec();-
310 delete m_handler;-
311 m_handler = 0;-
312}
never executed: end of block
0
313-
314-
315QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9