Qt 6.x
The Qt SDK
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) {
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
64void QLibInputTouch::registerDevice(libinput_device *dev)
65{
66 struct udev_device *udev_device;
67 udev_device = libinput_device_get_udev_device(dev);
68 QString devNode = QString::fromUtf8(udev_device_get_devnode(udev_device));
69 QString devName = QString::fromUtf8(libinput_device_get_name(dev));
70
71 qCDebug(qLcLibInput, "libinput: registerDevice %s - %s",
72 qPrintable(devNode), qPrintable(devName));
73
75 QRect geom;
76 if (mapping->load()) {
77 m_devState[dev].m_screenName = mapping->screenNameForDeviceNode(devNode);
78 if (!m_devState[dev].m_screenName.isEmpty()) {
79 geom = screenGeometry(&m_devState[dev]);
80 qCDebug(qLcLibInput) << "libinput: Mapping device" << devNode
81 << "to screen" << m_devState[dev].m_screenName
82 << "with geometry" << geom;
83 }
84 }
85
86 QPointingDevice *&td = m_devState[dev].m_touchDevice;
87 td = new QPointingDevice(devName, udev_device_get_devnum(udev_device),
90 auto devPriv = QPointingDevicePrivate::get(td);
91 devPriv->busId = QString::fromLocal8Bit(udev_device_get_syspath(udev_device)); // TODO is that the best to choose?
92 if (!geom.isNull())
93 devPriv->setAvailableVirtualGeometry(geom);
95}
96
97void QLibInputTouch::unregisterDevice(libinput_device *dev)
98{
99 Q_UNUSED(dev);
100 // There is no way to remove a QPointingDevice.
101}
102
103void QLibInputTouch::processTouchDown(libinput_event_touch *e)
104{
105 int slot = libinput_event_touch_get_slot(e);
106 DeviceState *state = deviceState(e);
107 QWindowSystemInterface::TouchPoint *tp = state->point(slot);
108 if (tp) {
109 qWarning("Incorrect touch state");
110 } else {
112 newTp.id = qMax(0, slot);
114 newTp.area = QRect(0, 0, 8, 8);
115 newTp.area.moveCenter(getPos(e));
116 state->m_points.append(newTp);
117 qCDebug(qLcLibInputEvents) << "touch down" << newTp;
118 }
119}
120
121void QLibInputTouch::processTouchMotion(libinput_event_touch *e)
122{
123 int slot = libinput_event_touch_get_slot(e);
124 DeviceState *state = deviceState(e);
125 QWindowSystemInterface::TouchPoint *tp = state->point(slot);
126 if (tp) {
128 const QPointF p = getPos(e);
129 if (tp->area.center() == p)
131 else
132 tp->area.moveCenter(p);
133 // 'down' may be followed by 'motion' within the same "frame".
134 // Handle this by compressing and keeping the Pressed state until the 'frame'.
136 tp->state = tmpState;
137 qCDebug(qLcLibInputEvents) << "touch move" << tp;
138 } else {
139 qWarning("Inconsistent touch state (got 'motion' without 'down')");
140 }
141}
142
143void QLibInputTouch::processTouchUp(libinput_event_touch *e)
144{
145 int slot = libinput_event_touch_get_slot(e);
146 DeviceState *state = deviceState(e);
147 QWindowSystemInterface::TouchPoint *tp = state->point(slot);
148 if (tp) {
150 // There may not be a Frame event after the last Up. Work this around.
151 QEventPoint::States s;
152 for (int i = 0; i < state->m_points.size(); ++i)
153 s |= state->m_points.at(i).state;
154 qCDebug(qLcLibInputEvents) << "touch up" << s << tp;
157 else
158 qCDebug(qLcLibInputEvents, "waiting for all points to be released");
159 } else {
160 qWarning("Inconsistent touch state (got 'up' without 'down')");
161 }
162}
163
164void QLibInputTouch::processTouchCancel(libinput_event_touch *e)
165{
166 DeviceState *state = deviceState(e);
167 qCDebug(qLcLibInputEvents) << "touch cancel" << state->m_points;
168 if (state->m_touchDevice)
170 else
171 qWarning("TouchCancel without registered device");
172}
173
174void QLibInputTouch::processTouchFrame(libinput_event_touch *e)
175{
176 DeviceState *state = deviceState(e);
177 if (!state->m_touchDevice) {
178 qWarning("TouchFrame without registered device");
179 return;
180 }
181 qCDebug(qLcLibInputEvents) << "touch frame" << state->m_points;
182 if (state->m_points.isEmpty())
183 return;
184
185 QWindowSystemInterface::handleTouchEvent(nullptr, state->m_touchDevice, state->m_points,
187
188 for (int i = 0; i < state->m_points.size(); ++i) {
191 state->m_points.removeAt(i--);
192 else if (tp.state == QEventPoint::State::Pressed)
194 }
195}
196
State
Specifies the state of this event point.
Definition qeventpoint.h:49
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:926
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)
Definition qlist.h:74
static QOutputMapping * get()
\inmodule QtCore\reentrant
Definition qpoint.h:214
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:712
constexpr QPointF center() const noexcept
Returns the center point of the rectangle.
Definition qrect.h:685
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:238
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition qrect.h:163
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:220
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:235
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:127
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5788
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
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)
double e
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.
#define qWarning
Definition qlogging.h:162
#define Q_LOGGING_CATEGORY(name,...)
#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
GLenum GLenum GLenum GLenum mapping
GLfloat GLfloat p
[1]
#define qPrintable(string)
Definition qstring.h:1391
QScreen * screen
[1]
Definition main.cpp:29
#define Q_UNUSED(x)