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