Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qinputdevice.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qinputdevice.h"
9#include <QCoreApplication>
10#include <QDebug>
11#include <QMutex>
12#include <QScreen>
13
15
16using namespace Qt::StringLiterals;
17
18/*!
19 \class QInputDevice
20 \brief The QInputDevice class describes a device from which a QInputEvent originates.
21 \since 6.0
22 \inmodule QtGui
23
24 Each QInputEvent contains a QInputDevice pointer to allow accessing
25 device-specific properties like type, capabilities and seat. It is the
26 responsibility of the platform or generic plug-ins to discover, create and
27 register an instance of this class corresponding to each available input
28 device, via QWindowSystemInterface::registerInputDevice(), before
29 generating any input event referring to that device.
30
31 Applications do not need to instantiate this class, but can read the
32 instances pointed to by QInputEvent::device() and QInputDevice::devices().
33*/
34
35/*!
36 \enum QInputDevice::Capability
37
38 Indicates what kind of information the input device or its driver can
39 provide.
40
41 \value None
42 No information about input device capabilities available.
43
44 \value Position
45 Indicates that position information is available, meaning that the
46 position() family of functions in the touch points return valid points.
47
48 \value Area
49 Indicates that touch area information is available, meaning that
50 QEventPoint::ellipseDiameters() in the touch points return valid
51 values.
52
53 \value Pressure
54 Indicates that pressure information is available, meaning that
55 QEventPoint::pressure() returns a valid value.
56
57 \value Velocity
58 Indicates that velocity information is available, meaning that
59 QEventPoint::velocity() returns a valid vector.
60
61 \value NormalizedPosition
62 Indicates that the normalized position is available, meaning that
63 QEventPoint::globalPosition() returns a valid value.
64
65 \value MouseEmulation
66 Indicates that the device synthesizes mouse events.
67
68 \value Scroll
69 Indicates that the device has a scroll capability.
70
71 \value [since 6.2] PixelScroll
72 Indicates that the device (usually a
73 \l {QInputDevice::DeviceType::TouchPad}{touchpad})
74 scrolls with \l {QWheelEvent::pixelDelta()}{pixel precision}.
75
76 \value Hover
77 Indicates that the device has a hover capability.
78
79 \value Rotation
80 Indicates that \l {QEventPoint::}{rotation} information is available.
81
82 \value XTilt
83 Indicates that \l {QTabletEvent::xTilt()}{tilt} information is
84 available for the X-axis.
85
86 \value YTilt
87 Indicates that \l {QTabletEvent::yTilt()}{tilt} information is
88 available for the Y-axis.
89
90 \value TangentialPressure
91 Indicates that \l {QTabletEvent::tangentialPressure()}
92 {tangential pressure} information is available.
93
94 \value ZPosition
95 Indicates that position information for the \l {QTabletEvent::z()}
96 {Z-axis} is available.
97
98 \value All
99*/
100
101/*!
102 Creates a new invalid input device instance as a child of \a parent.
103*/
104QInputDevice::QInputDevice(QObject *parent)
105 : QObject(*(new QInputDevicePrivate(QString(), -1, QInputDevice::DeviceType::Unknown)), parent)
106{
107}
108
109QInputDevice::~QInputDevice()
110{
111 QInputDevicePrivate::unregisterDevice(this);
112}
113
114/*!
115 Creates a new input device instance. The given \a name is normally a
116 manufacturer-assigned model name if available, or something else
117 identifiable; \a id is a platform-specific number that will be unique per
118 device (for example the xinput ID on X11); \a type identifies what kind of
119 device. On window systems that are capable of handling input from multiple
120 users or sets of input devices at the same time (such as Wayland or X11),
121 \a seatName identifies the name of the set of devices that will be used
122 together. If the device is a child or slave device (for example one of
123 several mice that can take turns moving the "core pointer"), the master
124 device should be given as the \a parent.
125
126 The platform plugin creates, registers and continues to own each device
127 instance; usually \a parent should be given for memory management purposes
128 even if there is no master for a particular device.
129
130 By default, capabilities() are \c None.
131*/
132QInputDevice::QInputDevice(const QString &name, qint64 id, QInputDevice::DeviceType type,
133 const QString &seatName, QObject *parent)
134 : QObject(*new QInputDevicePrivate(name, id, type, QInputDevice::Capability::None, seatName), parent)
135{
136}
137
138/*!
139 \internal
140*/
141QInputDevice::QInputDevice(QInputDevicePrivate &d, QObject *parent)
142 : QObject(d, parent)
143{
144}
145
146/*!
147 \property QInputDevice::availableVirtualGeometry
148 \brief the region within the virtual desktop that this device can access.
149
150 For example, a \l {QInputDevice::DeviceType}{TouchScreen} input
151 device is fixed in place upon a single physical screen and usually
152 calibrated so that this area is the same as QScreen::geometry(), whereas
153 a \l {QInputDevice::DeviceType}{Mouse} is typically able to access all
154 screens on the virtual desktop.
155
156 Alternatively, a Wacom graphics tablet may be configured so that it is
157 mapped to all screens, or only to the screen where the user prefers to
158 create drawings, or only to the window in which drawing occurs.
159
160 A \l {QInputDevice::DeviceType}{Stylus} device that is integrated
161 with a touchscreen may be physically limited to that screen.
162
163 If the returned rectangle is \l {QRect::isNull()}{null}, it means this device
164 can access the entire virtual desktop.
165*/
166QRect QInputDevice::availableVirtualGeometry() const
167{
168 Q_D(const QInputDevice);
169 return d->availableVirtualGeometry;
170}
171
172/*!
173 \property QInputDevice::name
174 \brief the device name.
175*/
176
177/*!
178 Returns the device name.
179
180 This string may be empty. It is however useful on systems that have
181 multiple input devices: it can be used to differentiate from which device a
182 QPointerEvent originates.
183*/
184QString QInputDevice::name() const
185{
186 Q_D(const QInputDevice);
187 return d->name;
188}
189
190/*!
191 \property QInputDevice::type
192 \brief the device type
193*/
194
195/*!
196 Returns the device type.
197*/
198QInputDevice::DeviceType QInputDevice::type() const
199{
200 Q_D(const QInputDevice);
201 return d->deviceType;
202}
203
204/*!
205 \property QInputDevice::capabilities
206 \brief the device capabilities.
207*/
208
209/*!
210 Returns the device capabilities.
211*/
212QInputDevice::Capabilities QInputDevice::capabilities() const
213{
214 Q_D(const QInputDevice);
215 return QInputDevice::Capabilities(d->capabilities);
216}
217
218/*!
219 Returns whether the device capabilities include the given \a capability.
220*/
221bool QInputDevice::hasCapability(QInputDevice::Capability capability) const
222{
223 return capabilities().testFlag(capability);
224}
225
226/*!
227 \property QInputDevice::systemId
228 \brief the platform-specific system ID.
229*/
230
231/*!
232 Returns the platform specific system ID (for example xinput ID on the X11 platform).
233
234 All platforms are expected to provide a unique system ID for each device.
235*/
236qint64 QInputDevice::systemId() const
237{
238 Q_D(const QInputDevice);
239 return d->systemId;
240}
241
242/*!
243 \property QInputDevice::seatName
244 \brief the seat associated with the device.
245*/
246
247/*!
248 Returns the seat with which the device is associated, if known; otherwise empty.
249
250 Devices that are intended to be used together by one user may be configured
251 to have the same seat name. That is only possible on Wayland and X11
252 platforms so far.
253*/
254QString QInputDevice::seatName() const
255{
256 Q_D(const QInputDevice);
257 return d->seatName;
258}
259
260using InputDevicesList = QList<const QInputDevice *>;
261Q_GLOBAL_STATIC(InputDevicesList, deviceList)
262Q_CONSTINIT static QBasicMutex devicesMutex;
263
264/*!
265 Returns a list of all registered input devices (keyboards and pointing devices).
266
267 \note The list of devices is not always complete on all platforms. So far,
268 the most-complete information is available on the \l {Qt for Linux}{Linux}
269 platform, at startup and in response to hot-plugging. Most other platforms
270 are only able to provide generic devices of various types, only after receiving
271 events from them; and most platforms do not tell Qt when a device is plugged in,
272 or when it is unplugged at runtime.
273
274 \note The returned list cannot be used to add new devices. To add a simulated
275 touch screen for an autotest, QTest::createTouchDevice() can be used.
276 Platform plugins should call QWindowSystemInterface::registerInputDevice()
277 to add devices as they are discovered.
278*/
279QList<const QInputDevice *> QInputDevice::devices()
280{
281 QMutexLocker lock(&devicesMutex);
282 return *deviceList();
283}
284
285/*!
286 \since 6.3
287
288 Returns a list of seat names for all registered input devices (keyboards and pointing devices).
289*/
290QStringList QInputDevice::seatNames()
291{
292 QMutexLocker locker(&devicesMutex);
293 const InputDevicesList devices = *deviceList();
294 locker.unlock();
295 QStringList result;
296 for (const QInputDevice *d : devices) {
297 if (!result.contains(d->seatName()))
298 result.append(d->seatName());
299 }
300
301 return result;
302}
303
304/*!
305 Returns the core or master keyboard on the given seat \a seatName.
306*/
307const QInputDevice *QInputDevice::primaryKeyboard(const QString& seatName)
308{
309 QMutexLocker locker(&devicesMutex);
310 const InputDevicesList devices = *deviceList();
311 locker.unlock();
312 const QInputDevice *ret = nullptr;
313 for (const QInputDevice *d : devices) {
314 if (d->type() != DeviceType::Keyboard)
315 continue;
316 if (seatName.isNull() || d->seatName() == seatName) {
317 // the master keyboard's parent is not another input device
318 if (!d->parent() || !qobject_cast<const QInputDevice *>(d->parent()))
319 return d;
320 if (!ret)
321 ret = d;
322 }
323 }
324 if (!ret) {
325 qCDebug(lcQpaInputDevices) << "no keyboards registered for seat" << seatName
326 << "The platform plugin should have provided one via "
327 "QWindowSystemInterface::registerInputDevice(). Creating a default one for now.";
328 ret = new QInputDevice("core keyboard"_L1, 0, DeviceType::Keyboard, seatName, QCoreApplication::instance());
329 QInputDevicePrivate::registerDevice(ret);
330 return ret;
331 }
332 qWarning() << "core keyboard ambiguous for seat" << seatName;
333 return ret;
334}
335
336QInputDevicePrivate::~QInputDevicePrivate()
337 = default;
338
339/*!
340 \internal
341 Checks whether a matching device is already registered
342 (via operator==, not pointer equality).
343*/
344bool QInputDevicePrivate::isRegistered(const QInputDevice *dev)
345{
346 if (!dev)
347 return false;
348 QMutexLocker locker(&devicesMutex);
349 InputDevicesList v = *deviceList();
350 for (const QInputDevice *d : v)
351 if (d && *d == *dev)
352 return true;
353 return false;
354}
355
356/*!
357 \internal
358 Find the device with the given \a systemId (for example the xinput
359 device ID on X11), which is expected to be unique if nonzero.
360
361 If the \a systemId is not unique, this function returns the first one found.
362
363 \note Use QInputDevicePrivate::queryTabletDevice() if the device is a
364 tablet or a tablet stylus; in that case, \a id is not unique.
365*/
366const QInputDevice *QInputDevicePrivate::fromId(qint64 systemId)
367{
368 QMutexLocker locker(&devicesMutex);
369 for (const QInputDevice *dev : *deviceList()) {
370 if (dev->systemId() == systemId)
371 return dev;
372 }
373 return nullptr;
374}
375
376void QInputDevicePrivate::registerDevice(const QInputDevice *dev)
377{
378 QMutexLocker lock(&devicesMutex);
379 deviceList()->append(dev);
380 qCInfo(lcQpaInputDevices) << "Registered" << dev;
381}
382
383/*!
384 \internal
385*/
386void QInputDevicePrivate::unregisterDevice(const QInputDevice *dev)
387{
388 if (deviceList.isDestroyed())
389 return; // nothing to remove!
390
391 QMutexLocker lock(&devicesMutex);
392 deviceList()->removeOne(dev);
393 qCInfo(lcQpaInputDevices) << "Unregistered" << dev;
394}
395
396bool QInputDevice::operator==(const QInputDevice &other) const
397{
398 return systemId() == other.systemId();
399}
400
401#ifndef QT_NO_DEBUG_STREAM
402QDebug operator<<(QDebug debug, const QInputDevice *device)
403{
404 QDebugStateSaver saver(debug);
405 debug.nospace();
406 debug.noquote();
407
408 debug << "QInputDevice(";
409 if (!device)
410 return debug << "0x0)";
411
412 const QInputDevicePrivate *d = QInputDevicePrivate::get(device);
413
414 if (d->pointingDeviceType)
415 return operator<<(debug, static_cast<const QPointingDevice *>(device));
416
417 debug << "QInputDevice(";
418 debug << '"' << device->name() << "\", type=" << device->type()
419 << ", ID=" << device->systemId() << ", seat='" << device->seatName() << "'";
420 debug << ')';
421 return debug;
422}
423#endif // !QT_NO_DEBUG_STREAM
424
425QT_END_NAMESPACE
426
427#include "moc_qinputdevice.cpp"
Combined button and popup list for selecting options.