Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qlibinputtouch.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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 "qlibinputtouch_p.h"
5#include "qoutputmapping_p.h"
6#include <libinput.h>
7#include <QtGui/QGuiApplication>
8#include <QtGui/QPointingDevice>
9#include <QtGui/QScreen>
10#include <QtGui/QPointingDevice>
11#include <QtGui/private/qhighdpiscaling_p.h>
12#include <QtGui/private/qpointingdevice_p.h>
13
15
17Q_LOGGING_CATEGORY(qLcLibInputEvents, "qt.qpa.input.events")
18
19QWindowSystemInterface::TouchPoint *QLibInputTouch::DeviceState::point(int32_t slot)
20{
21 const int id = qMax(0, slot);
22
23 for (int i = 0; i < m_points.size(); ++i)
24 if (m_points.at(i).id == id)
25 return &m_points[i];
26
27 return nullptr;
28}
29
30QLibInputTouch::DeviceState *QLibInputTouch::deviceState(libinput_event_touch *e)
31{
32 libinput_device *dev = libinput_event_get_device(libinput_event_touch_get_base_event(e));
33 return &m_devState[dev];
34}
35
36QRect QLibInputTouch::screenGeometry(DeviceState *state)
37{
39 if (!state->m_screenName.isEmpty()) {
40 if (!m_screen) {
41 const QList<QScreen *> screens = QGuiApplication::screens();
42 for (QScreen *s : screens) {
43 if (s->name() == state->m_screenName) {
44 m_screen = s;
45 break;
46 }
47 }
48 }
49 if (m_screen)
50 screen = m_screen;
51 }
53}
54
55QPointF QLibInputTouch::getPos(libinput_event_touch *e)
56{
57 DeviceState *state = deviceState(e);
58 QRect geom = screenGeometry(state);
59 const double x = libinput_event_touch_get_x_transformed(e, geom.width());
60 const double y = libinput_event_touch_get_y_transformed(e, geom.height());
61 return geom.topLeft() + QPointF(x, y);
62}
63
64static void setMatrix(libinput_device *dev)
65{
66 if (libinput_device_config_calibration_has_matrix(dev)) {
67 QByteArray env = qgetenv("QT_QPA_LIBINPUT_TOUCH_MATRIX");
68 env = env.simplified();
69 if (env.size()) {
70 float matrix[6];
71 QList<QByteArray> list = env.split(' ');
72 if (list.length() != 6) {
73 qCWarning(qLcLibInput, "matrix length %lld wrong, should be 6", list.length());
74 return;
75 }
76 for (int i = 0; i < 6; i++) {
77 bool ok = true;
78 matrix[i] = list[i].toFloat(&ok);
79 if (!ok) {
80 qCWarning(qLcLibInput, "Invalid matrix entry %d %s ", i, list[i].constData());
81 return;
82 }
83 }
84 if (libinput_device_config_calibration_set_matrix(dev, matrix) != LIBINPUT_CONFIG_STATUS_SUCCESS)
85 qCWarning(qLcLibInput, "Failed to set libinput calibration matrix ");
86 }
87 } else {
88 qCWarning(qLcLibInput, "Touch device doesn't support matrix");
89 }
90}
91void QLibInputTouch::registerDevice(libinput_device *dev)
92{
93 struct udev_device *udev_device;
94 udev_device = libinput_device_get_udev_device(dev);
95 QString devNode = QString::fromUtf8(udev_device_get_devnode(udev_device));
96 QString devName = QString::fromUtf8(libinput_device_get_name(dev));
97
98 qCDebug(qLcLibInput, "libinput: registerDevice %s - %s",
99 qPrintable(devNode), qPrintable(devName));
100
102 QRect geom;
103 if (mapping->load()) {
104 m_devState[dev].m_screenName = mapping->screenNameForDeviceNode(devNode);
105 if (!m_devState[dev].m_screenName.isEmpty()) {
106 geom = screenGeometry(&m_devState[dev]);
107 qCDebug(qLcLibInput) << "libinput: Mapping device" << devNode
108 << "to screen" << m_devState[dev].m_screenName
109 << "with geometry" << geom;
110 }
111 }
112
113 QPointingDevice *&td = m_devState[dev].m_touchDevice;
114 td = new QPointingDevice(devName, udev_device_get_devnum(udev_device),
117 auto devPriv = QPointingDevicePrivate::get(td);
118 devPriv->busId = QString::fromLocal8Bit(udev_device_get_syspath(udev_device)); // TODO is that the best to choose?
119 if (!geom.isNull())
120 devPriv->setAvailableVirtualGeometry(geom);
122 setMatrix(dev);
123}
124
125void QLibInputTouch::unregisterDevice(libinput_device *dev)
126{
127 Q_UNUSED(dev);
128 // There is no way to remove a QPointingDevice.
129}
130
131void QLibInputTouch::processTouchDown(libinput_event_touch *e)
132{
133 int slot = libinput_event_touch_get_slot(e);
134 DeviceState *state = deviceState(e);
135 QWindowSystemInterface::TouchPoint *tp = state->point(slot);
136 if (tp) {
137 qWarning("Incorrect touch state");
138 } else {
140 newTp.id = qMax(0, slot);
141 newTp.state = QEventPoint::State::Pressed;
142 newTp.area = QRect(0, 0, 8, 8);
143 newTp.area.moveCenter(getPos(e));
144 state->m_points.append(newTp);
145 qCDebug(qLcLibInputEvents) << "touch down" << newTp;
146 }
147}
148
149void QLibInputTouch::processTouchMotion(libinput_event_touch *e)
150{
151 int slot = libinput_event_touch_get_slot(e);
152 DeviceState *state = deviceState(e);
153 QWindowSystemInterface::TouchPoint *tp = state->point(slot);
154 if (tp) {
156 const QPointF p = getPos(e);
157 if (tp->area.center() == p)
159 else
160 tp->area.moveCenter(p);
161 // 'down' may be followed by 'motion' within the same "frame".
162 // Handle this by compressing and keeping the Pressed state until the 'frame'.
164 tp->state = tmpState;
165 qCDebug(qLcLibInputEvents) << "touch move" << tp;
166 } else {
167 qWarning("Inconsistent touch state (got 'motion' without 'down')");
168 }
169}
170
171void QLibInputTouch::processTouchUp(libinput_event_touch *e)
172{
173 int slot = libinput_event_touch_get_slot(e);
174 DeviceState *state = deviceState(e);
175 QWindowSystemInterface::TouchPoint *tp = state->point(slot);
176 if (tp) {
178 // There may not be a Frame event after the last Up. Work this around.
179 QEventPoint::States s;
180 for (int i = 0; i < state->m_points.size(); ++i)
181 s |= state->m_points.at(i).state;
182 qCDebug(qLcLibInputEvents) << "touch up" << s << tp;
185 else
186 qCDebug(qLcLibInputEvents, "waiting for all points to be released");
187 } else {
188 qWarning("Inconsistent touch state (got 'up' without 'down')");
189 }
190}
191
192void QLibInputTouch::processTouchCancel(libinput_event_touch *e)
193{
194 DeviceState *state = deviceState(e);
195 qCDebug(qLcLibInputEvents) << "touch cancel" << state->m_points;
196 if (state->m_touchDevice)
198 else
199 qWarning("TouchCancel without registered device");
200}
201
202void QLibInputTouch::processTouchFrame(libinput_event_touch *e)
203{
204 DeviceState *state = deviceState(e);
205 if (!state->m_touchDevice) {
206 qWarning("TouchFrame without registered device");
207 return;
208 }
209 qCDebug(qLcLibInputEvents) << "touch frame" << state->m_points;
210 if (state->m_points.isEmpty())
211 return;
212
213 QWindowSystemInterface::handleTouchEvent(nullptr, state->m_touchDevice, state->m_points,
215
216 for (int i = 0; i < state->m_points.size(); ++i) {
219 state->m_points.removeAt(i--);
220 else if (tp.state == QEventPoint::State::Pressed)
222 }
223}
224
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:494
QByteArray simplified() const &
Definition qbytearray.h:266
QList< QByteArray > split(char sep) const
Splits the byte array into subarrays wherever sep occurs, and returns the list of those arrays.
State
Specifies the state of this event point.
Definition qeventpoint.h:48
QScreen * primaryScreen
the primary (or default) screen of the application.
static Qt::KeyboardModifiers keyboardModifiers()
Returns the current state of the modifier keys on the keyboard.
static QList< QScreen * > screens()
Returns a list of all the screens associated with the windowing system the application is connected t...
bool isEmpty() const noexcept
Returns true if the hash contains no items; otherwise returns false.
Definition qhash.h:928
void processTouchDown(libinput_event_touch *e)
void unregisterDevice(libinput_device *dev)
void processTouchMotion(libinput_event_touch *e)
void processTouchCancel(libinput_event_touch *e)
void registerDevice(libinput_device *dev)
void processTouchFrame(libinput_event_touch *e)
void processTouchUp(libinput_event_touch *e)
qsizetype length() const noexcept
Definition qlist.h:399
static QOutputMapping * get()
\inmodule QtCore\reentrant
Definition qpoint.h:217
static QPointingDevicePrivate * get(QPointingDevice *q)
The QPointingDevice class describes a device from which mouse, touch or tablet events originate.
constexpr void moveCenter(const QPointF &p) noexcept
Moves the rectangle, leaving the center point at the given position.
Definition qrect.h:726
constexpr QPointF center() const noexcept
Returns the center point of the rectangle.
Definition qrect.h:699
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition qrect.h:164
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:221
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
The QScreen class is used to query screen properties. \inmodule QtGui.
Definition qscreen.h:32
QRect geometry
the screen's geometry in pixels
Definition qscreen.h:45
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5949
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
The QWindowSystemInterface provides an event queue for the QPA platform.
static bool handleTouchEvent(QWindow *window, const QPointingDevice *device, const QList< struct TouchPoint > &points, Qt::KeyboardModifiers mods=Qt::NoModifier)
static bool handleTouchCancelEvent(QWindow *window, const QPointingDevice *device, Qt::KeyboardModifiers mods=Qt::NoModifier)
static void registerInputDevice(const QInputDevice *device)
else opt state
[0]
T toNativePixels(const T &value, const C *context)
DeviceState
Definition qprint_p.h:56
Combined button and popup list for selecting options.
static void setMatrix(libinput_device *dev)
#define qWarning
Definition qlogging.h:166
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLint GLint GLint GLint GLint x
[0]
GLint y
GLdouble s
[6]
Definition qopenglext.h:235
GLuint GLenum matrix
GLenum GLenum GLenum GLenum mapping
GLfloat GLfloat p
[1]
#define qPrintable(string)
Definition qstring.h:1531
QScreen * screen
[1]
Definition main.cpp:29
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
#define Q_UNUSED(x)
QList< int > list
[14]