@@ -0,0 +1,142 @@
1+#include "uinput.h"
2+
3+#include <QFile>
4+#include <QDebug>
5+#include <QDateTime>
6+
7+#include <unistd.h>
8+
9+UInput::UInput(QObject *parent) :
10+ QObject(parent)
11+{
12+ m_devName = QStringLiteral("unity8-simulated-mouse");
13+ m_uinput.setFileName("/dev/uinput");
14+
15+ memset(&m_uinput_mouse_dev, 0, sizeof(m_uinput_mouse_dev));
16+ m_uinput_mouse_dev.id.bustype = BUS_USB;
17+ m_uinput_mouse_dev.id.version = 1;
18+ strncpy(m_uinput_mouse_dev.name, m_devName.toLocal8Bit().data(), m_devName.length());
19+
20+}
21+
22+UInput::~UInput()
23+{
24+ if (m_mouseCreated) {
25+ removeMouse();
26+ }
27+}
28+
29+void UInput::createMouse()
30+{
31+ if (m_mouseCreated) {
32+ qDebug() << "Already have a virtual device. Not creating another one.";
33+ return;
34+ }
35+
36+ if (!m_uinput.isOpen() && !m_uinput.open(QFile::WriteOnly)) {
37+ return;
38+ }
39+
40+ ioctl(m_uinput.handle(), UI_SET_EVBIT, EV_REL);
41+ ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_X);
42+ ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_Y);
43+
44+ ioctl(m_uinput.handle(), UI_SET_EVBIT, EV_KEY);
45+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_MOUSE);
46+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_LEFT);
47+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_MIDDLE);
48+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_RIGHT);
49+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_FORWARD);
50+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_BACK);
51+
52+ ioctl(m_uinput.handle(), UI_SET_EVBIT, EV_SYN);
53+
54+ int len = write(m_uinput.handle(), &m_uinput_mouse_dev, sizeof(m_uinput_mouse_dev));
55+ if (len <= 0) {
56+ qWarning() << "Failed to write to uinput. Cannot create virtual uinput mouse.";
57+ return;
58+ }
59+
60+ int err = ioctl(m_uinput.handle(), UI_DEV_CREATE);
61+ if (err != 0) {
62+ qWarning() << "Cannot create virtual uinput device. Create ioctl failed:" << err;
63+ return;
64+ }
65+ m_mouseCreated = true;
66+ qDebug() << "Virtual uinput mouse device created.";
67+}
68+
69+void UInput::removeMouse()
70+{
71+ if (!m_mouseCreated) {
72+ return;
73+ }
74+
75+ if (!m_uinput.isOpen() && !m_uinput.open(QFile::WriteOnly)) {
76+ qDebug() << "cannot open uinput... ";
77+ return;
78+ }
79+
80+ int err = ioctl(m_uinput.handle(), UI_DEV_DESTROY);
81+ if (err != 0) {
82+ qWarning() << "Failed to destroy virtual uinput device. Destroy ioctl failed:" << err;
83+ } else {
84+ qDebug() << "Virtual uinput mouse device removed.";
85+ }
86+ m_uinput.close();
87+ m_mouseCreated = false;
88+}
89+
90+void UInput::moveMouse(int dx, int dy)
91+{
92+ struct input_event event;
93+ memset(&event, 0, sizeof(event));
94+ gettimeofday(&event.time, 0);
95+ event.type = EV_REL;
96+ event.code = REL_X;
97+ event.value = dx;
98+ write(m_uinput.handle(), &event, sizeof(event));
99+
100+ event.code = REL_Y;
101+ event.value = dy;
102+ write(m_uinput.handle(), &event, sizeof(event));
103+
104+ event.type = EV_SYN;
105+ event.code = SYN_REPORT;
106+ event.value = 0;
107+ write(m_uinput.handle(), &event, sizeof(event));
108+}
109+
110+void UInput::pressMouse(Qt::MouseButton button)
111+{
112+ injectMouse(button, 1);
113+}
114+
115+void UInput::releaseMouse(Qt::MouseButton button)
116+{
117+ injectMouse(button, 0);
118+}
119+
120+void UInput::injectMouse(Qt::MouseButton button, int down)
121+{
122+ struct input_event event;
123+ memset(&event, 0, sizeof(event));
124+ gettimeofday(&event.time, 0);
125+ event.type = EV_KEY;
126+ switch (button) {
127+ case Qt::LeftButton:
128+ event.code = BTN_LEFT;
129+ break;
130+ case Qt::RightButton:
131+ event.code = BTN_RIGHT;
132+ break;
133+ case Qt::MiddleButton:
134+ event.code = BTN_MIDDLE;
135+ break;
136+ default:
137+ qWarning() << "Unsupported mouse button.";
138+ return;
139+ }
140+ event.value = down;
141+ write(m_uinput.handle(), &event, sizeof(event));
142+}