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