@@ -0,0 +1,182 @@
2+ * Copyright (C) 2015 Canonical Ltd.
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.
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.
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/>.
26+UInput::UInput(QObject *parent) :
29+ m_devName = QByteArrayLiteral("unity8-simulated-mouse");
30+ m_uinput.setFileName(QStringLiteral("/dev/uinput"));
32+ memset(&m_uinput_mouse_dev, 0, sizeof(m_uinput_mouse_dev));
33+ m_uinput_mouse_dev.id.bustype = BUS_USB;
34+ m_uinput_mouse_dev.id.version = 1;
35+ strncpy(m_uinput_mouse_dev.name, m_devName.constData(), m_devName.length());
40+ if (m_mouseCreated) {
45+void UInput::createMouse()
47+ if (m_mouseCreated) {
48+ qDebug() << "Already have a virtual device. Not creating another one.";
52+ if (!m_uinput.isOpen() && !m_uinput.open(QFile::WriteOnly)) {
56+ ioctl(m_uinput.handle(), UI_SET_EVBIT, EV_REL);
57+ ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_X);
58+ ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_Y);
59+ ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_HWHEEL);
60+ ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_WHEEL);
62+ ioctl(m_uinput.handle(), UI_SET_EVBIT, EV_KEY);
63+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_MOUSE);
64+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_LEFT);
65+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_MIDDLE);
66+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_RIGHT);
67+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_FORWARD);
68+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_BACK);
70+ ioctl(m_uinput.handle(), UI_SET_EVBIT, EV_SYN);
72+ int len = write(m_uinput.handle(), &m_uinput_mouse_dev, sizeof(m_uinput_mouse_dev));
74+ qWarning() << "Failed to write to uinput. Cannot create virtual uinput mouse.";
78+ int err = ioctl(m_uinput.handle(), UI_DEV_CREATE);
80+ qWarning() << "Cannot create virtual uinput device. Create ioctl failed:" << err;
83+ m_mouseCreated = true;
84+ qDebug() << "Virtual uinput mouse device created.";
87+void UInput::removeMouse()
89+ if (!m_mouseCreated) {
93+ if (!m_uinput.isOpen() && !m_uinput.open(QFile::WriteOnly)) {
94+ qWarning() << "cannot open uinput... ";
98+ int err = ioctl(m_uinput.handle(), UI_DEV_DESTROY);
100+ qWarning() << "Failed to destroy virtual uinput device. Destroy ioctl failed:" << err;
102+ qDebug() << "Virtual uinput mouse device removed.";
105+ m_mouseCreated = false;
108+void UInput::moveMouse(int dx, int dy)
110+ struct input_event event;
111+ memset(&event, 0, sizeof(event));
112+ clock_gettime(CLOCK_MONOTONIC, (timespec*)&event.time);
113+ event.type = EV_REL;
116+ write(m_uinput.handle(), &event, sizeof(event));
120+ write(m_uinput.handle(), &event, sizeof(event));
122+ event.type = EV_SYN;
123+ event.code = SYN_REPORT;
125+ write(m_uinput.handle(), &event, sizeof(event));
128+void UInput::pressMouse(Button button)
130+ injectMouse(button, 1);
133+void UInput::releaseMouse(Button button)
135+ injectMouse(button, 0);
138+void UInput::scrollMouse(int dh, int dv)
140+ struct input_event event;
141+ memset(&event, 0, sizeof(event));
142+ clock_gettime(CLOCK_MONOTONIC, (timespec*)&event.time);
143+ event.type = EV_REL;
144+ event.code = REL_HWHEEL;
146+ write(m_uinput.handle(), &event, sizeof(event));
148+ event.code = REL_WHEEL;
150+ write(m_uinput.handle(), &event, sizeof(event));
152+ event.type = EV_SYN;
153+ event.code = SYN_REPORT;
155+ write(m_uinput.handle(), &event, sizeof(event));
158+void UInput::injectMouse(Button button, int down)
160+ struct input_event event;
161+ memset(&event, 0, sizeof(event));
162+ clock_gettime(CLOCK_MONOTONIC, (timespec*)&event.time);
163+ event.type = EV_KEY;
166+ event.code = BTN_LEFT;
169+ event.code = BTN_RIGHT;
172+ event.code = BTN_MIDDLE;
176+ write(m_uinput.handle(), &event, sizeof(event));
178+ event.type = EV_SYN;
179+ event.code = SYN_REPORT;
181+ write(m_uinput.handle(), &event, sizeof(event));