2
* Copyright (C) 2013,2015 Canonical, Ltd.
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; version 3.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
19
#include "ucmousetouchadaptor.h"
20
#include "uctestextras.h"
22
#include <qpa/qwindowsysteminterface.h>
24
#include <QCoreApplication>
25
#include <QMouseEvent>
28
using QTest::QTouchEventSequence;
32
Qt::MouseButton translateMouseButton(xcb_button_t detail)
35
case 1: return Qt::LeftButton;
36
case 2: return Qt::MidButton;
37
case 3: return Qt::RightButton;
38
// Button values 4-7 are Wheel events
39
default: return Qt::NoButton;
42
} // end of anonymous namespace
45
* \qmltype MouseTouchAdaptor
46
* \instantiates UCMouseTouchAdaptor
47
* \inqmlmodule Ubuntu.Test 1.0
48
* \ingroup ubuntu-test
49
* \brief Singleton type turning mouse events into single finger touch events.
51
* When enabled, mouse events will be translated into single finger touch events.
52
* Being a singleton, the feature must be enabled explicitly either on component
53
* completion or through a binding.
56
* target: MouseTouchAdaptor
63
UCMouseTouchAdaptor::UCMouseTouchAdaptor()
65
, m_leftButtonIsPressed(false)
68
QCoreApplication::instance()->installNativeEventFilter(this);
70
UCTestExtras::registerTouchDevice();
71
m_touchDevice = UCTestExtras::m_touchDevice;
74
bool UCMouseTouchAdaptor::nativeEventFilter(const QByteArray & eventType,
75
void * message, long * /*result*/)
81
if (eventType != "xcb_generic_event_t") {
83
qWarning("MouseTouchAdaptor: XCB backend not in use. Adaptor inoperative!");
87
xcb_generic_event_t *xcbEvent = static_cast<xcb_generic_event_t *>(message);
89
switch (xcbEvent->response_type & ~0x80) {
90
case XCB_BUTTON_PRESS:
91
return handleButtonPress(reinterpret_cast<xcb_button_press_event_t *>(xcbEvent));
93
case XCB_BUTTON_RELEASE:
94
return handleButtonRelease(reinterpret_cast<xcb_button_release_event_t *>(xcbEvent));
96
case XCB_MOTION_NOTIFY:
97
return handleMotionNotify(reinterpret_cast<xcb_motion_notify_event_t *>(xcbEvent));
105
bool UCMouseTouchAdaptor::handleButtonPress(xcb_button_press_event_t *pressEvent)
107
Qt::MouseButton button = translateMouseButton(pressEvent->detail);
109
// Just eat the event if it wasn't a left mouse press
110
if (button != Qt::LeftButton)
113
QWindow *targetWindow = findQWindowWithXWindowID(static_cast<WId>(pressEvent->event));
115
QPoint windowPos(pressEvent->event_x / targetWindow->devicePixelRatio(), pressEvent->event_y / targetWindow->devicePixelRatio());
117
QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
118
false /* autoCommit */);
119
touchEvent.press(0 /* touchId */, windowPos);
120
touchEvent.commit(false /* processEvents */);
122
m_leftButtonIsPressed = true;
126
bool UCMouseTouchAdaptor::handleButtonRelease(xcb_button_release_event_t *releaseEvent)
128
Qt::MouseButton button = translateMouseButton(releaseEvent->detail);
130
// Just eat the event if it wasn't a left mouse release
131
if (button != Qt::LeftButton)
134
QWindow *targetWindow = findQWindowWithXWindowID(static_cast<WId>(releaseEvent->event));
136
QPoint windowPos(releaseEvent->event_x / targetWindow->devicePixelRatio(), releaseEvent->event_y / targetWindow->devicePixelRatio());
138
QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
139
false /* autoCommit */);
140
touchEvent.release(0 /* touchId */, windowPos);
141
touchEvent.commit(false /* processEvents */);
143
m_leftButtonIsPressed = false;
147
bool UCMouseTouchAdaptor::handleMotionNotify(xcb_motion_notify_event_t *event)
149
if (!m_leftButtonIsPressed) {
153
QWindow *targetWindow = findQWindowWithXWindowID(static_cast<WId>(event->event));
155
QPoint windowPos(event->event_x / targetWindow->devicePixelRatio(), event->event_y / targetWindow->devicePixelRatio());
157
QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
158
false /* autoCommit */);
159
touchEvent.move(0 /* touchId */, windowPos);
160
touchEvent.commit(false /* processEvents */);
165
QWindow *UCMouseTouchAdaptor::findQWindowWithXWindowID(WId windowId)
167
QWindowList windowList = QGuiApplication::topLevelWindows();
168
QWindow *foundWindow = nullptr;
171
while (!foundWindow && i < windowList.count()) {
172
QWindow *window = windowList[i];
173
if (window->winId() == windowId) {
174
foundWindow = window;
180
Q_ASSERT(foundWindow);
185
* \qmlproperty bool MouseTouchAdaptor::enabled
186
* Enables the mouse to touch conversion functionality. Defaults to true.
188
bool UCMouseTouchAdaptor::enabled() const
192
void UCMouseTouchAdaptor::setEnabled(bool value)
194
if (value != m_enabled) {
196
Q_EMIT enabledChanged(value);