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
qevdevmousemanager.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
5
6#include <QtInputSupport/private/qevdevutil_p.h>
7
8#include <QStringList>
9#include <QGuiApplication>
10#include <QScreen>
11#include <QLoggingCategory>
12#include <qpa/qwindowsysteminterface.h>
13#include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h>
14#include <private/qguiapplication_p.h>
15#include <private/qinputdevicemanager_p_p.h>
16#include <private/qhighdpiscaling_p.h>
17
19
20using namespace Qt::StringLiterals;
21
22QEvdevMouseManager::QEvdevMouseManager(const QString &key, const QString &specification, QObject *parent)
23 : QObject(parent), m_x(0), m_y(0), m_xoffset(0), m_yoffset(0)
24{
25 Q_UNUSED(key);
26
27 QString spec = qEnvironmentVariable("QT_QPA_EVDEV_MOUSE_PARAMETERS");
28
29 if (spec.isEmpty())
30 spec = specification;
31
32 auto parsed = QEvdevUtil::parseSpecification(spec);
33 m_spec = std::move(parsed.spec);
34
35 for (const auto &arg : std::as_const(parsed.args)) {
36 if (arg.startsWith("xoffset="_L1)) {
37 m_xoffset = arg.mid(8).toInt();
38 } else if (arg.startsWith("yoffset="_L1)) {
39 m_yoffset = arg.mid(8).toInt();
40 }
41 }
42
43 // add all mice for devices specified in the argument list
44 for (const QString &device : std::as_const(parsed.devices))
45 addMouse(device);
46
47 if (parsed.devices.isEmpty()) {
48 qCDebug(qLcEvdevMouse, "evdevmouse: Using device discovery");
49 if (auto deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Mouse | QDeviceDiscovery::Device_Touchpad, this)) {
50 // scan and add already connected keyboards
51 const QStringList devices = deviceDiscovery->scanConnectedDevices();
52 for (const QString &device : devices)
53 addMouse(device);
54
55 connect(deviceDiscovery, &QDeviceDiscovery::deviceDetected,
56 this, &QEvdevMouseManager::addMouse);
57 connect(deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
58 this, &QEvdevMouseManager::removeMouse);
59 }
60 }
61
62 QInputDeviceManager *manager = QGuiApplicationPrivate::inputDeviceManager();
63 connect(manager, &QInputDeviceManager::cursorPositionChangeRequested, this, [this](const QPoint &pos) {
64 m_x = pos.x();
65 m_y = pos.y();
66 clampPosition();
67 });
68}
69
73
74void QEvdevMouseManager::clampPosition()
75{
76 // clamp to screen geometry
77 QScreen *primaryScreen = QGuiApplication::primaryScreen();
78 QRect g = QHighDpi::toNativePixels(primaryScreen->virtualGeometry(), primaryScreen);
79 if (m_x + m_xoffset < g.left())
80 m_x = g.left() - m_xoffset;
81 else if (m_x + m_xoffset > g.right())
82 m_x = g.right() - m_xoffset;
83
84 if (m_y + m_yoffset < g.top())
85 m_y = g.top() - m_yoffset;
86 else if (m_y + m_yoffset > g.bottom())
87 m_y = g.bottom() - m_yoffset;
88}
89
90void QEvdevMouseManager::handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons,
91 Qt::MouseButton button, QEvent::Type type)
92{
93 // update current absolute coordinates
94 if (!abs) {
95 m_x += x;
96 m_y += y;
97 } else {
98 m_x = x;
99 m_y = y;
100 }
101
102 clampPosition();
103
104 QPoint pos(m_x + m_xoffset, m_y + m_yoffset);
105 // Cannot track the keyboard modifiers ourselves here. Instead, report the
106 // modifiers from the last key event that has been seen by QGuiApplication.
107 QWindowSystemInterface::handleMouseEvent(0, pos, pos, buttons, button, type, QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers());
108}
109
111{
112 QPoint pos(m_x + m_xoffset, m_y + m_yoffset);
113 QWindowSystemInterface::handleWheelEvent(0, pos, pos, QPoint(), delta, QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers());
114}
115
116void QEvdevMouseManager::addMouse(const QString &deviceNode)
117{
118 qCDebug(qLcEvdevMouse, "Adding mouse at %ls", qUtf16Printable(deviceNode));
119 auto handler = QEvdevMouseHandler::create(deviceNode, m_spec);
120 if (handler) {
121 connect(handler.get(), &QEvdevMouseHandler::handleMouseEvent,
122 this, &QEvdevMouseManager::handleMouseEvent);
123 connect(handler.get(), &QEvdevMouseHandler::handleWheelEvent,
124 this, &QEvdevMouseManager::handleWheelEvent);
125 m_mice.add(deviceNode, std::move(handler));
126 updateDeviceCount();
127 } else {
128 qWarning("evdevmouse: Failed to open mouse device %ls", qUtf16Printable(deviceNode));
129 }
130}
131
132void QEvdevMouseManager::removeMouse(const QString &deviceNode)
133{
134 if (m_mice.remove(deviceNode)) {
135 qCDebug(qLcEvdevMouse, "Removing mouse at %ls", qUtf16Printable(deviceNode));
136 updateDeviceCount();
137 }
138}
139
140void QEvdevMouseManager::updateDeviceCount()
141{
142 QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
143 QInputDeviceManager::DeviceTypePointer, m_mice.count());
144}
145
146QT_END_NAMESPACE
void addMouse(const QString &deviceNode=QString())
void removeMouse(const QString &deviceNode)
void handleWheelEvent(QPoint delta)
QEvdevMouseManager(const QString &key, const QString &specification, QObject *parent=nullptr)
void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons, Qt::MouseButton button, QEvent::Type type)