~unity-2d-team/unity-2d/trunk

« back to all changes in this revision

Viewing changes to libunity-2d-private/tests/pointerbarriertest.cpp

  • Committer: Tarmac
  • Author(s): Albert Astals, Gerry Boland, gerry.boland at canonical, Albert Astals Cid
  • Date: 2012-03-06 18:06:03 UTC
  • mfrom: (935.1.39 unity-2d_pointer_barrier)
  • Revision ID: tarmac-20120306180603-usgyjt9ji6dln1ru
Implementation of Pointer barriers and use in the launcher autohide behaviour. Fixes: https://bugs.launchpad.net/bugs/947976. Approved by Gerry Boland.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of unity-2d
 
3
 *
 
4
 * Copyright 2010 Canonical Ltd.
 
5
 *
 
6
 * Authors:
 
7
 * - Aurélien Gâteau <aurelien.gateau@canonical.com>
 
8
 *
 
9
 * This program is free software; you can redistribute it and/or modify
 
10
 * it under the terms of the GNU General Public License as published by
 
11
 * the Free Software Foundation; version 3.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
 */
 
21
 
 
22
// Local
 
23
#include <unitytestmacro.h>
 
24
#include <pointerbarrier.h>
 
25
 
 
26
// Qt
 
27
#include <QApplication>
 
28
#include <QSignalSpy>
 
29
#include <QX11Info>
 
30
#include <QtTestGui>
 
31
 
 
32
#include <X11/extensions/XTest.h>
 
33
 
 
34
class DisableTriggerZoneOnTriggerHelper : public QObject
 
35
{
 
36
    Q_OBJECT
 
37
public:
 
38
    DisableTriggerZoneOnTriggerHelper(PointerBarrierWrapper *barrier)
 
39
    {
 
40
        m_barrier = barrier;
 
41
        connect(barrier, SIGNAL(triggered()), this, SLOT(disable()));
 
42
    }
 
43
 
 
44
public Q_SLOTS:
 
45
    void disable()
 
46
    {
 
47
        m_barrier->setTriggerZoneEnabled(false);
 
48
    }
 
49
 
 
50
private:
 
51
    PointerBarrierWrapper *m_barrier;
 
52
};
 
53
 
 
54
class PointerBarrierTest : public QObject
 
55
{
 
56
    Q_OBJECT
 
57
private Q_SLOTS:
 
58
    void testBreak()
 
59
    {
 
60
        Display *display = QX11Info::display();
 
61
        PointerBarrierWrapper barrier;
 
62
 
 
63
        QSignalSpy brokenSpy(&barrier, SIGNAL(broken()));
 
64
        QSignalSpy triggeredSpy(&barrier, SIGNAL(triggered()));
 
65
 
 
66
        XTestFakeMotionEvent(display, -1, 50, 50, 0);
 
67
        QCOMPARE(QCursor::pos(), QPoint(50, 50));
 
68
 
 
69
        barrier.setP1(QPointF(100, 0));
 
70
        barrier.setP2(QPointF(100, 100));
 
71
        barrier.setThreshold(6500);
 
72
        barrier.setMaxVelocityMultiplier(2);
 
73
        barrier.setDecayRate(1500);
 
74
        barrier.setBreakPressure(2000);
 
75
 
 
76
        XTestFakeRelativeMotionEvent(display, 300, 0, 0);
 
77
        // We are stopped by the barrier and instead in 350, 50 we are in 99, 50
 
78
        QCOMPARE(QCursor::pos(), QPoint(99, 50));
 
79
 
 
80
        QCOMPARE(brokenSpy.count(), 0);
 
81
        QCOMPARE(triggeredSpy.count(), 0);
 
82
 
 
83
        for (int i = 0; i < 10; ++i) {
 
84
            XTestFakeRelativeMotionEvent(display, 100, 0, 0);
 
85
            QTest::qWait(100);
 
86
        }
 
87
        // We have broken the barrier and are somewhere else 
 
88
        QVERIFY(QCursor::pos() != QPoint(99, 50));
 
89
        QCOMPARE(brokenSpy.count(), 1);
 
90
        QCOMPARE(triggeredSpy.count(), 0);
 
91
    }
 
92
 
 
93
    void testStopArea()
 
94
    {
 
95
        Display *display = QX11Info::display();
 
96
        PointerBarrierWrapper barrier;
 
97
 
 
98
        QSignalSpy brokenSpy(&barrier, SIGNAL(broken()));
 
99
        QSignalSpy triggeredSpy(&barrier, SIGNAL(triggered()));
 
100
 
 
101
        XTestFakeMotionEvent(display, -1, 50, 150, 0);
 
102
        QCOMPARE(QCursor::pos(), QPoint(50, 150));
 
103
 
 
104
        barrier.setP1(QPointF(100, 0));
 
105
        barrier.setP2(QPointF(100, 100));
 
106
        barrier.setThreshold(6500);
 
107
        barrier.setMaxVelocityMultiplier(2);
 
108
        barrier.setDecayRate(1500);
 
109
        barrier.setBreakPressure(2000);
 
110
 
 
111
        XTestFakeRelativeMotionEvent(display, 300, 0, 0);
 
112
        // We are not stopped by the barrier because it's above us
 
113
        // and are in 350, 150
 
114
        QCOMPARE(QCursor::pos(), QPoint(350, 150));
 
115
 
 
116
        QCOMPARE(brokenSpy.count(), 0);
 
117
        QCOMPARE(triggeredSpy.count(), 0);
 
118
    }
 
119
 
 
120
    void testTrigger()
 
121
    {
 
122
        Display *display = QX11Info::display();
 
123
        PointerBarrierWrapper barrier;
 
124
 
 
125
        QSignalSpy brokenSpy(&barrier, SIGNAL(broken()));
 
126
        QSignalSpy triggeredSpy(&barrier, SIGNAL(triggered()));
 
127
 
 
128
        XTestFakeMotionEvent(display, -1, 50, 50, 0);
 
129
        QCOMPARE(QCursor::pos(), QPoint(50, 50));
 
130
 
 
131
        barrier.setP1(QPointF(100, 0));
 
132
        barrier.setP2(QPointF(100, 100));
 
133
        barrier.setTriggerZoneP1(QPointF(100, 0));
 
134
        barrier.setTriggerZoneP2(QPointF(100, 100));
 
135
        barrier.setTriggerZoneEnabled(true);
 
136
        barrier.setThreshold(6500);
 
137
        barrier.setMaxVelocityMultiplier(2);
 
138
        barrier.setDecayRate(1500);
 
139
        barrier.setTriggerPressure(2000);
 
140
        barrier.setBreakPressure(2000);
 
141
 
 
142
        XTestFakeRelativeMotionEvent(display, 300, 0, 0);
 
143
        // We are stopped by the barrier and instead in 350, 50 we are in 99, 50
 
144
        QCOMPARE(QCursor::pos(), QPoint(99, 50));
 
145
 
 
146
        QCOMPARE(brokenSpy.count(), 0);
 
147
        QCOMPARE(triggeredSpy.count(), 0);
 
148
 
 
149
        for (int i = 0; i < 10; ++i) {
 
150
            XTestFakeRelativeMotionEvent(display, 100, 0, 0);
 
151
            QTest::qWait(100);
 
152
        }
 
153
        // We have triggered the barrier and are still there
 
154
        QCOMPARE(QCursor::pos(), QPoint(99, 50));
 
155
        QCOMPARE(brokenSpy.count(), 0);
 
156
        QVERIFY(triggeredSpy.count() >= 1);
 
157
    }
 
158
 
 
159
    void testTriggerAndBreak()
 
160
    {
 
161
        Display *display = QX11Info::display();
 
162
        PointerBarrierWrapper barrier;
 
163
 
 
164
        QSignalSpy brokenSpy(&barrier, SIGNAL(broken()));
 
165
        QSignalSpy triggeredSpy(&barrier, SIGNAL(triggered()));
 
166
 
 
167
        XTestFakeMotionEvent(display, -1, 50, 50, 0);
 
168
        QCOMPARE(QCursor::pos(), QPoint(50, 50));
 
169
 
 
170
        barrier.setP1(QPointF(100, 0));
 
171
        barrier.setP2(QPointF(100, 100));
 
172
        barrier.setTriggerZoneP1(QPointF(100, 0));
 
173
        barrier.setTriggerZoneP2(QPointF(100, 100));
 
174
        barrier.setTriggerZoneEnabled(true);
 
175
        barrier.setThreshold(6500);
 
176
        barrier.setMaxVelocityMultiplier(2);
 
177
        barrier.setDecayRate(1500);
 
178
        barrier.setTriggerPressure(2000);
 
179
        barrier.setBreakPressure(2000);
 
180
 
 
181
        DisableTriggerZoneOnTriggerHelper helper(&barrier);
 
182
 
 
183
        XTestFakeRelativeMotionEvent(display, 300, 0, 0);
 
184
        // We are stopped by the barrier and instead in 350, 50 we are in 99, 50
 
185
        QCOMPARE(QCursor::pos(), QPoint(99, 50));
 
186
 
 
187
        QCOMPARE(brokenSpy.count(), 0);
 
188
        QCOMPARE(triggeredSpy.count(), 0);
 
189
 
 
190
        for (int i = 0; i < 10; ++i) {
 
191
            XTestFakeRelativeMotionEvent(display, 100, 0, 0);
 
192
            QTest::qWait(100);
 
193
        }
 
194
        // We have triggered and broken the barrier and somewhere else
 
195
        QVERIFY(QCursor::pos() != QPoint(99, 50));
 
196
        QCOMPARE(brokenSpy.count(), 1);
 
197
        QCOMPARE(triggeredSpy.count(), 1);
 
198
    }
 
199
 
 
200
    void testTriggerWithoutAndBreak()
 
201
    {
 
202
        Display *display = QX11Info::display();
 
203
        PointerBarrierWrapper barrier;
 
204
 
 
205
        QSignalSpy brokenSpy(&barrier, SIGNAL(broken()));
 
206
        QSignalSpy triggeredSpy(&barrier, SIGNAL(triggered()));
 
207
 
 
208
        XTestFakeMotionEvent(display, -1, 50, 50, 0);
 
209
        QCOMPARE(QCursor::pos(), QPoint(50, 50));
 
210
 
 
211
        barrier.setP1(QPointF(100, 0));
 
212
        barrier.setP2(QPointF(100, 100));
 
213
        barrier.setTriggerZoneP1(QPointF(100, 0));
 
214
        barrier.setTriggerZoneP2(QPointF(100, 100));
 
215
        barrier.setTriggerZoneEnabled(true);
 
216
        barrier.setThreshold(6500);
 
217
        barrier.setMaxVelocityMultiplier(2);
 
218
        barrier.setDecayRate(1500);
 
219
        barrier.setTriggerPressure(2000);
 
220
        barrier.setBreakPressure(2000);
 
221
 
 
222
        DisableTriggerZoneOnTriggerHelper helper(&barrier);
 
223
 
 
224
        XTestFakeRelativeMotionEvent(display, 300, 0, 0);
 
225
        // We are stopped by the barrier and instead in 350, 50 we are in 99, 50
 
226
        QCOMPARE(QCursor::pos(), QPoint(99, 50));
 
227
 
 
228
        QCOMPARE(brokenSpy.count(), 0);
 
229
        QCOMPARE(triggeredSpy.count(), 0);
 
230
 
 
231
        for (int i = 0; i < 10 && barrier.triggerZoneEnabled(); ++i) {
 
232
            XTestFakeRelativeMotionEvent(display, 100, 0, 0);
 
233
            QTest::qWait(100);
 
234
        }
 
235
        // We have triggered the barrier
 
236
        QCOMPARE(QCursor::pos(), QPoint(99, 50));
 
237
        QCOMPARE(brokenSpy.count(), 0);
 
238
        QCOMPARE(triggeredSpy.count(), 1);
 
239
 
 
240
        // We can push a bit more without breaking the barrier
 
241
        for (int i = 0; i < 2; ++i) {
 
242
            XTestFakeRelativeMotionEvent(display, 100, 0, 0);
 
243
            QTest::qWait(100);
 
244
        }
 
245
        QCOMPARE(QCursor::pos(), QPoint(99, 50));
 
246
        QCOMPARE(brokenSpy.count(), 0);
 
247
        QCOMPARE(triggeredSpy.count(), 1);
 
248
    }
 
249
 
 
250
    void testTriggerAndBreakZones()
 
251
    {
 
252
        Display *display = QX11Info::display();
 
253
        PointerBarrierWrapper barrier;
 
254
 
 
255
        QSignalSpy brokenSpy(&barrier, SIGNAL(broken()));
 
256
        QSignalSpy triggeredSpy(&barrier, SIGNAL(triggered()));
 
257
 
 
258
        XTestFakeMotionEvent(display, -1, 50, 25, 0);
 
259
        QCOMPARE(QCursor::pos(), QPoint(50, 25));
 
260
 
 
261
        barrier.setP1(QPointF(100, 0));
 
262
        barrier.setP2(QPointF(100, 200));
 
263
        barrier.setTriggerZoneP1(QPointF(100, 50));
 
264
        barrier.setTriggerZoneP2(QPointF(100, 150));
 
265
        barrier.setTriggerZoneEnabled(true);
 
266
        barrier.setThreshold(6500);
 
267
        barrier.setMaxVelocityMultiplier(2);
 
268
        barrier.setDecayRate(1500);
 
269
        barrier.setTriggerPressure(2000);
 
270
        barrier.setBreakPressure(2000);
 
271
 
 
272
        DisableTriggerZoneOnTriggerHelper helper(&barrier);
 
273
 
 
274
        XTestFakeRelativeMotionEvent(display, 300, 0, 0);
 
275
        // We are stopped by the barrier and instead in 350, 25 we are in 99, 25
 
276
        QCOMPARE(QCursor::pos(), QPoint(99, 25));
 
277
 
 
278
        QCOMPARE(brokenSpy.count(), 0);
 
279
        QCOMPARE(triggeredSpy.count(), 0);
 
280
 
 
281
        for (int i = 0; i < 10; ++i) {
 
282
            XTestFakeRelativeMotionEvent(display, 100, 0, 0);
 
283
            QTest::qWait(100);
 
284
        }
 
285
 
 
286
        // We are above the trigger zone so we have only broke the barrier
 
287
        QVERIFY(QCursor::pos() != QPoint(99, 25));
 
288
        QCOMPARE(brokenSpy.count(), 1);
 
289
        QCOMPARE(triggeredSpy.count(), 0);
 
290
 
 
291
        // Go back
 
292
        XTestFakeMotionEvent(display, -1, 50, 100, 0);
 
293
 
 
294
        XTestFakeRelativeMotionEvent(display, 300, 0, 0);
 
295
        // We are stopped by the barrier and instead in 350, 100 we are in 99, 100
 
296
        QCOMPARE(QCursor::pos(), QPoint(99, 100));
 
297
 
 
298
        for (int i = 0; i < 10; ++i) {
 
299
            XTestFakeRelativeMotionEvent(display, 100, 0, 0);
 
300
            QTest::qWait(100);
 
301
        }
 
302
 
 
303
        // We are in the trigger zone so we have triggered and broken the barrier
 
304
        QVERIFY(QCursor::pos() != QPoint(99, 100));
 
305
        QCOMPARE(brokenSpy.count(), 2);
 
306
        QCOMPARE(triggeredSpy.count(), 1);
 
307
    }
 
308
};
 
309
 
 
310
UAPP_TEST_MAIN(PointerBarrierTest)
 
311
 
 
312
#include "pointerbarriertest.moc"