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
qvxmousemanager.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 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
22QVxMouseManager::QVxMouseManager(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 = QString::fromLocal8Bit(qgetenv("QT_QPA_VXEVDEV_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(qLcVxMouse, "vxmouse: 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, &QVxMouseManager::addMouse);
57 connect(deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
58 this, &QVxMouseManager::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 QVxMouseManager::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 QVxMouseManager::handleMouseEvent(int x, int y, Qt::MouseButtons buttons,
91 Qt::MouseButton button, QEvent::Type type)
92{
93 m_x += x;
94 m_y += y;
95
96 clampPosition();
97
98 QPoint pos(m_x + m_xoffset, m_y + m_yoffset);
99 // Cannot track the keyboard modifiers ourselves here. Instead, report the
100 // modifiers from the last key event that has been seen by QGuiApplication.
101 QWindowSystemInterface::handleMouseEvent(0, pos, pos, buttons, button, type, QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers());
102}
103
104void QVxMouseManager::addMouse(const QString &deviceNode)
105{
106 qCDebug(qLcVxMouse, "Adding mouse at %ls", qUtf16Printable(deviceNode));
107 auto handler = QVxMouseHandler::create(deviceNode, m_spec);
108 if (handler) {
109 connect(handler.get(), &QVxMouseHandler::handleMouseEvent,
110 this, &QVxMouseManager::handleMouseEvent);
111 m_mice.add(deviceNode, std::move(handler));
112 updateDeviceCount();
113 } else {
114 qWarning("vxmouse: Failed to open mouse device %ls", qUtf16Printable(deviceNode));
115 }
116}
117
118void QVxMouseManager::removeMouse(const QString &deviceNode)
119{
120 if (m_mice.remove(deviceNode)) {
121 qCDebug(qLcVxMouse, "Removing mouse at %ls", qUtf16Printable(deviceNode));
122 updateDeviceCount();
123 }
124}
125
126void QVxMouseManager::updateDeviceCount()
127{
128 QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
129 QInputDeviceManager::DeviceTypePointer, m_mice.count());
130}
131
132QT_END_NAMESPACE
QVxMouseManager(const QString &key, const QString &specification, QObject *parent=nullptr)
void handleMouseEvent(int x, int y, Qt::MouseButtons buttons, Qt::MouseButton button, QEvent::Type type)
void addMouse(const QString &deviceNode=QString())
void removeMouse(const QString &deviceNode)