on 940eb14 help sign in
unity8/plugins/UInput/uinput.cpp
181 lines 5.0 kB history raw
1/*
2 * Copyright (C) 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17#include "uinput.h"
19#include <QFile>
20#include <QDebug>
21#include <QDateTime>
23#include <unistd.h>
25UInput::UInput(QObject *parent) :
26 QObject(parent)
28 m_devName = QStringLiteral("unity8-simulated-mouse");
29 m_uinput.setFileName("/dev/uinput");
31 memset(&m_uinput_mouse_dev, 0, sizeof(m_uinput_mouse_dev));
32 m_uinput_mouse_dev.id.bustype = BUS_USB;
33 m_uinput_mouse_dev.id.version = 1;
34 strncpy(m_uinput_mouse_dev.name, m_devName.toLocal8Bit().data(), m_devName.length());
37UInput::~UInput()
39 if (m_mouseCreated) {
40 removeMouse();
41 }
44void UInput::createMouse()
46 if (m_mouseCreated) {
47 qDebug() << "Already have a virtual device. Not creating another one.";
48 return;
49 }
51 if (!m_uinput.isOpen() && !m_uinput.open(QFile::WriteOnly)) {
52 return;
53 }
55 ioctl(m_uinput.handle(), UI_SET_EVBIT, EV_REL);
56 ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_X);
57 ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_Y);
58 ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_HWHEEL);
59 ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_WHEEL);
61 ioctl(m_uinput.handle(), UI_SET_EVBIT, EV_KEY);
62 ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_MOUSE);
63 ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_LEFT);
64 ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_MIDDLE);
65 ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_RIGHT);
66 ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_FORWARD);
67 ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_BACK);
69 ioctl(m_uinput.handle(), UI_SET_EVBIT, EV_SYN);
71 int len = write(m_uinput.handle(), &m_uinput_mouse_dev, sizeof(m_uinput_mouse_dev));
72 if (len <= 0) {
73 qWarning() << "Failed to write to uinput. Cannot create virtual uinput mouse.";
74 return;
75 }
77 int err = ioctl(m_uinput.handle(), UI_DEV_CREATE);
78 if (err != 0) {
79 qWarning() << "Cannot create virtual uinput device. Create ioctl failed:" << err;
80 return;
81 }
82 m_mouseCreated = true;
83 qDebug() << "Virtual uinput mouse device created.";
86void UInput::removeMouse()
88 if (!m_mouseCreated) {
89 return;
90 }
92 if (!m_uinput.isOpen() && !m_uinput.open(QFile::WriteOnly)) {
93 qWarning() << "cannot open uinput... ";
94 return;
95 }
97 int err = ioctl(m_uinput.handle(), UI_DEV_DESTROY);
98 if (err != 0) {
99 qWarning() << "Failed to destroy virtual uinput device. Destroy ioctl failed:" << err;
100 } else {
101 qDebug() << "Virtual uinput mouse device removed.";
102 }
103 m_uinput.close();
104 m_mouseCreated = false;
107void UInput::moveMouse(int dx, int dy)
109 struct input_event event;
110 memset(&event, 0, sizeof(event));
111 gettimeofday(&event.time, 0);
112 event.type = EV_REL;
113 event.code = REL_X;
114 event.value = dx;
115 write(m_uinput.handle(), &event, sizeof(event));
117 event.code = REL_Y;
118 event.value = dy;
119 write(m_uinput.handle(), &event, sizeof(event));
121 event.type = EV_SYN;
122 event.code = SYN_REPORT;
123 event.value = 0;
124 write(m_uinput.handle(), &event, sizeof(event));
127void UInput::pressMouse(Button button)
129 injectMouse(button, 1);
132void UInput::releaseMouse(Button button)
134 injectMouse(button, 0);
137void UInput::scrollMouse(int dh, int dv)
139 struct input_event event;
140 memset(&event, 0, sizeof(event));
141 gettimeofday(&event.time, 0);
142 event.type = EV_REL;
143 event.code = REL_HWHEEL;
144 event.value = dh;
145 write(m_uinput.handle(), &event, sizeof(event));
147 event.code = REL_WHEEL;
148 event.value = dv;
149 write(m_uinput.handle(), &event, sizeof(event));
151 event.type = EV_SYN;
152 event.code = SYN_REPORT;
153 event.value = 0;
154 write(m_uinput.handle(), &event, sizeof(event));
157void UInput::injectMouse(Button button, int down)
159 struct input_event event;
160 memset(&event, 0, sizeof(event));
161 gettimeofday(&event.time, 0);
162 event.type = EV_KEY;
163 switch (button) {
164 case ButtonLeft:
165 event.code = BTN_LEFT;
166 break;
167 case ButtonRight:
168 event.code = BTN_RIGHT;
169 break;
170 case ButtonMiddle:
171 event.code = BTN_MIDDLE;
172 break;
173 }
174 event.value = down;
175 write(m_uinput.handle(), &event, sizeof(event));
177 event.type = EV_SYN;
178 event.code = SYN_REPORT;
179 event.value = 0;
180 write(m_uinput.handle(), &event, sizeof(event));