~loic.molinari/ubuntu-ui-toolkit/ubuntu-ui-toolkit-ubuntushape-new-button-style-support

« back to all changes in this revision

Viewing changes to src/Ubuntu/Test/plugin/ucmousetouchadaptor.cpp

  • Committer: Tarmac
  • Author(s): Zsombor Egri, Zoltán Balogh, Benjamin Zeller
  • Date: 2015-11-17 14:44:49 UTC
  • mfrom: (1693.4.43 migrate_unity8_gestures)
  • Revision ID: tarmac-20151117144449-p0s2lj04nx4fuq80
Migrate DirectionalDragArea from Unity8, named as SwipeArea. Original code (from lp:unity8) by: Daniel d'Andrada <daniel.dandrada@canonical.com>.

Approved by PS Jenkins bot, Christian Dywan, Benjamin Zeller, Zsombor Egri, Daniel d'Andrada.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2013,2015 Canonical, Ltd.
 
3
 *
 
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.
 
7
 *
 
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.
 
12
 *
 
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/>.
 
15
 *
 
16
 * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
 
17
 */
 
18
 
 
19
#include "ucmousetouchadaptor.h"
 
20
#include "uctestextras.h"
 
21
 
 
22
#include <qpa/qwindowsysteminterface.h>
 
23
 
 
24
#include <QCoreApplication>
 
25
#include <QMouseEvent>
 
26
#include <QTest>
 
27
 
 
28
using QTest::QTouchEventSequence;
 
29
 
 
30
namespace {
 
31
 
 
32
Qt::MouseButton translateMouseButton(xcb_button_t detail)
 
33
{
 
34
    switch (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;
 
40
    }
 
41
}
 
42
} // end of anonymous namespace
 
43
 
 
44
/*!
 
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.
 
50
 *
 
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.
 
54
 * \qml
 
55
 * Binding {
 
56
 *     target: MouseTouchAdaptor
 
57
 *     property: "enabled"
 
58
 *     value: true
 
59
 * }
 
60
 * \endqml
 
61
 *
 
62
 */
 
63
UCMouseTouchAdaptor::UCMouseTouchAdaptor()
 
64
    : QObject(nullptr)
 
65
    , m_leftButtonIsPressed(false)
 
66
    , m_enabled(true)
 
67
{
 
68
    QCoreApplication::instance()->installNativeEventFilter(this);
 
69
 
 
70
    UCTestExtras::registerTouchDevice();
 
71
    m_touchDevice = UCTestExtras::m_touchDevice;
 
72
}
 
73
 
 
74
bool UCMouseTouchAdaptor::nativeEventFilter(const QByteArray & eventType,
 
75
                                          void * message, long * /*result*/)
 
76
{
 
77
    if (!m_enabled) {
 
78
        return false;
 
79
    }
 
80
 
 
81
    if (eventType != "xcb_generic_event_t") {
 
82
        // wrong backend.
 
83
        qWarning("MouseTouchAdaptor: XCB backend not in use. Adaptor inoperative!");
 
84
        return false;
 
85
    }
 
86
 
 
87
    xcb_generic_event_t *xcbEvent = static_cast<xcb_generic_event_t *>(message);
 
88
 
 
89
    switch (xcbEvent->response_type & ~0x80) {
 
90
        case XCB_BUTTON_PRESS:
 
91
            return handleButtonPress(reinterpret_cast<xcb_button_press_event_t *>(xcbEvent));
 
92
            break;
 
93
        case XCB_BUTTON_RELEASE:
 
94
            return handleButtonRelease(reinterpret_cast<xcb_button_release_event_t *>(xcbEvent));
 
95
            break;
 
96
        case XCB_MOTION_NOTIFY:
 
97
            return handleMotionNotify(reinterpret_cast<xcb_motion_notify_event_t *>(xcbEvent));
 
98
            break;
 
99
        default:
 
100
            return false;
 
101
            break;
 
102
    };
 
103
}
 
104
 
 
105
bool UCMouseTouchAdaptor::handleButtonPress(xcb_button_press_event_t *pressEvent)
 
106
{
 
107
    Qt::MouseButton button = translateMouseButton(pressEvent->detail);
 
108
 
 
109
    // Just eat the event if it wasn't a left mouse press
 
110
    if (button != Qt::LeftButton)
 
111
        return true;
 
112
 
 
113
    QWindow *targetWindow = findQWindowWithXWindowID(static_cast<WId>(pressEvent->event));
 
114
 
 
115
    QPoint windowPos(pressEvent->event_x / targetWindow->devicePixelRatio(), pressEvent->event_y / targetWindow->devicePixelRatio());
 
116
 
 
117
    QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
 
118
                                                       false /* autoCommit */);
 
119
    touchEvent.press(0 /* touchId */, windowPos);
 
120
    touchEvent.commit(false /* processEvents */);
 
121
 
 
122
    m_leftButtonIsPressed = true;
 
123
    return true;
 
124
}
 
125
 
 
126
bool UCMouseTouchAdaptor::handleButtonRelease(xcb_button_release_event_t *releaseEvent)
 
127
{
 
128
    Qt::MouseButton button = translateMouseButton(releaseEvent->detail);
 
129
 
 
130
    // Just eat the event if it wasn't a left mouse release
 
131
    if (button != Qt::LeftButton)
 
132
        return true;
 
133
 
 
134
    QWindow *targetWindow = findQWindowWithXWindowID(static_cast<WId>(releaseEvent->event));
 
135
 
 
136
    QPoint windowPos(releaseEvent->event_x / targetWindow->devicePixelRatio(), releaseEvent->event_y / targetWindow->devicePixelRatio());
 
137
 
 
138
    QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
 
139
                                                       false /* autoCommit */);
 
140
    touchEvent.release(0 /* touchId */, windowPos);
 
141
    touchEvent.commit(false /* processEvents */);
 
142
 
 
143
    m_leftButtonIsPressed = false;
 
144
    return true;
 
145
}
 
146
 
 
147
bool UCMouseTouchAdaptor::handleMotionNotify(xcb_motion_notify_event_t *event)
 
148
{
 
149
    if (!m_leftButtonIsPressed) {
 
150
        return true;
 
151
    }
 
152
 
 
153
    QWindow *targetWindow = findQWindowWithXWindowID(static_cast<WId>(event->event));
 
154
 
 
155
    QPoint windowPos(event->event_x / targetWindow->devicePixelRatio(), event->event_y / targetWindow->devicePixelRatio());
 
156
 
 
157
    QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
 
158
                                                       false /* autoCommit */);
 
159
    touchEvent.move(0 /* touchId */, windowPos);
 
160
    touchEvent.commit(false /* processEvents */);
 
161
 
 
162
    return true;
 
163
}
 
164
 
 
165
QWindow *UCMouseTouchAdaptor::findQWindowWithXWindowID(WId windowId)
 
166
{
 
167
    QWindowList windowList = QGuiApplication::topLevelWindows();
 
168
    QWindow *foundWindow = nullptr;
 
169
 
 
170
    int i = 0;
 
171
    while (!foundWindow && i < windowList.count()) {
 
172
        QWindow *window = windowList[i];
 
173
        if (window->winId() == windowId) {
 
174
            foundWindow = window;
 
175
        } else {
 
176
            ++i;
 
177
        }
 
178
    }
 
179
 
 
180
    Q_ASSERT(foundWindow);
 
181
    return foundWindow;
 
182
}
 
183
 
 
184
/*!
 
185
 * \qmlproperty bool MouseTouchAdaptor::enabled
 
186
 * Enables the mouse to touch conversion functionality. Defaults to true.
 
187
 */
 
188
bool UCMouseTouchAdaptor::enabled() const
 
189
{
 
190
    return m_enabled;
 
191
}
 
192
void UCMouseTouchAdaptor::setEnabled(bool value)
 
193
{
 
194
    if (value != m_enabled) {
 
195
        m_enabled = value;
 
196
        Q_EMIT enabledChanged(value);
 
197
    }
 
198
}