2
* Copyright (C) 2014 Canonical, Ltd.
4
* This program is free software: you can redistribute it and/or modify it under
5
* the terms of the GNU Lesser General Public License version 3, as published by
6
* the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful, but WITHOUT
9
* ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10
* SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
* Lesser General Public License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18
#include <gmock/gmock.h>
19
#include <gtest/gtest.h>
21
#include <qteventfeeder.h>
22
#include <debughelpers.h>
24
#include <QGuiApplication>
27
#include "mock_qtwindowsystem.h"
30
using ::testing::AllOf;
31
using ::testing::AnyNumber;
32
using ::testing::Contains;
33
using ::testing::AtLeast;
34
using ::testing::InSequence;
35
using ::testing::Mock;
36
using ::testing::SizeIs;
37
using ::testing::Return;
39
// own gmock extensions
40
using ::testing::IsPressed;
41
using ::testing::IsReleased;
42
using ::testing::HasId;
43
using ::testing::StateIsMoved;
45
void PrintTo(const struct QWindowSystemInterface::TouchPoint& touchPoint, ::std::ostream* os) {
47
<< "id=" << touchPoint.id
48
<< "," << touchPointStateToString(touchPoint.state)
52
class QtEventFeederTest : public ::testing::Test {
54
void SetUp() override;
55
void TearDown() override;
57
void setIrrelevantMockWindowSystemExpectations();
59
MockQtWindowSystem *mockWindowSystem;
60
QtEventFeeder *qtEventFeeder;
63
void QtEventFeederTest::SetUp()
65
mockWindowSystem = new MockQtWindowSystem;
67
EXPECT_CALL(*mockWindowSystem, registerTouchDevice(_));
69
qtEventFeeder = new QtEventFeeder(mockWindowSystem);
71
ASSERT_TRUE(Mock::VerifyAndClearExpectations(mockWindowSystem));
74
void QtEventFeederTest::TearDown()
76
// mockWindowSystem will be deleted by QtEventFeeder
80
void QtEventFeederTest::setIrrelevantMockWindowSystemExpectations()
82
EXPECT_CALL(*mockWindowSystem, hasTargetWindow())
84
.WillRepeatedly(Return(true));
85
EXPECT_CALL(*mockWindowSystem, targetWindowGeometry())
87
.WillRepeatedly(Return(QRect(0,0,100,100)));
92
Mir sends a MirEvent([touch(id=0,state=pressed)]. QtEventFeeder happily forwards that to Qt.
94
Then, Mir sends a MirEvent([touch(id=1,state=pressed)]). In MirEvents, every single active touch
95
point must be listed in the event even if it didn't change at all in the meantime. So that's a bug.
96
But instead of crashing or forwarding the bogus event stream down to Qt, QtEventFeeder should attempt
97
to fix the situation by synthesizing a touch[id=1,state=released] to be send along with the
98
touch(id=1,state=pressed) it got. So that Qt receives a correct touch event stream.
100
TEST_F(QtEventFeederTest, GenerateMissingTouchEnd)
103
setIrrelevantMockWindowSystemExpectations();
105
EXPECT_CALL(*mockWindowSystem, handleTouchEvent(_,_,AllOf(SizeIs(1),
106
Contains(AllOf(HasId(0),
107
IsPressed()))),_)).Times(1);
110
mirEvent.type = mir_event_type_motion;
111
mirEvent.motion.pointer_count = 1;
112
mirEvent.motion.pointer_coordinates[0].id = 0;
113
mirEvent.motion.pointer_coordinates[0].x = 10;
114
mirEvent.motion.pointer_coordinates[0].y = 10;
115
mirEvent.motion.pointer_coordinates[0].touch_major = 1;
116
mirEvent.motion.pointer_coordinates[0].touch_minor = 1;
117
mirEvent.motion.pointer_coordinates[0].pressure = 10;
118
mirEvent.motion.action = mir_motion_action_down;
119
mirEvent.motion.event_time = 123 * 1000000;
121
qtEventFeeder->dispatch(mirEvent);
123
ASSERT_TRUE(Mock::VerifyAndClearExpectations(mockWindowSystem));
125
setIrrelevantMockWindowSystemExpectations();
127
EXPECT_CALL(*mockWindowSystem, handleTouchEvent(_,_,AllOf(SizeIs(2),
128
Contains(AllOf(HasId(0),IsReleased())),
129
Contains(AllOf(HasId(1),IsPressed()))
132
mirEvent.type = mir_event_type_motion;
133
mirEvent.motion.pointer_count = 1;
134
mirEvent.motion.pointer_coordinates[0].id = 1;
135
mirEvent.motion.pointer_coordinates[0].x = 20;
136
mirEvent.motion.pointer_coordinates[0].y = 20;
137
mirEvent.motion.pointer_coordinates[0].touch_major = 1;
138
mirEvent.motion.pointer_coordinates[0].touch_minor = 1;
139
mirEvent.motion.pointer_coordinates[0].pressure = 10;
140
mirEvent.motion.action = mir_motion_action_down;
141
mirEvent.motion.event_time = 125 * 1000000;
143
qtEventFeeder->dispatch(mirEvent);
145
ASSERT_TRUE(Mock::VerifyAndClearExpectations(mockWindowSystem));
148
TEST_F(QtEventFeederTest, PressSameTouchTwice)
150
setIrrelevantMockWindowSystemExpectations();
152
EXPECT_CALL(*mockWindowSystem, handleTouchEvent(_,_,AllOf(SizeIs(1),
153
Contains(AllOf(HasId(0),
154
IsPressed()))),_)).Times(1);
157
mirEvent.type = mir_event_type_motion;
158
mirEvent.motion.pointer_count = 1;
159
mirEvent.motion.pointer_coordinates[0].id = 0;
160
mirEvent.motion.pointer_coordinates[0].x = 10;
161
mirEvent.motion.pointer_coordinates[0].y = 10;
162
mirEvent.motion.pointer_coordinates[0].touch_major = 1;
163
mirEvent.motion.pointer_coordinates[0].touch_minor = 1;
164
mirEvent.motion.pointer_coordinates[0].pressure = 10;
165
mirEvent.motion.action = mir_motion_action_down;
166
mirEvent.motion.event_time = 123 * 1000000;
168
qtEventFeeder->dispatch(mirEvent);
170
ASSERT_TRUE(Mock::VerifyAndClearExpectations(mockWindowSystem));
172
setIrrelevantMockWindowSystemExpectations();
174
EXPECT_CALL(*mockWindowSystem, handleTouchEvent(_,_,AllOf(SizeIs(1),
175
Contains(AllOf(HasId(0), StateIsMoved()))
178
mirEvent.type = mir_event_type_motion;
179
mirEvent.motion.pointer_count = 1;
180
mirEvent.motion.pointer_coordinates[0].id = 0;
181
mirEvent.motion.pointer_coordinates[0].x = 20;
182
mirEvent.motion.pointer_coordinates[0].y = 20;
183
mirEvent.motion.pointer_coordinates[0].touch_major = 1;
184
mirEvent.motion.pointer_coordinates[0].touch_minor = 1;
185
mirEvent.motion.pointer_coordinates[0].pressure = 10;
186
mirEvent.motion.action = mir_motion_action_down;
187
mirEvent.motion.event_time = 125 * 1000000;
189
qtEventFeeder->dispatch(mirEvent);
191
ASSERT_TRUE(Mock::VerifyAndClearExpectations(mockWindowSystem));
194
TEST_F(QtEventFeederTest, IgnoreHovering)
196
setIrrelevantMockWindowSystemExpectations();
197
EXPECT_CALL(*mockWindowSystem, handleTouchEvent(_,_,_,_)).Times(0);
200
mirEvent.type = mir_event_type_motion;
201
mirEvent.motion.pointer_count = 1;
202
mirEvent.motion.pointer_coordinates[0].id = 0;
203
mirEvent.motion.pointer_coordinates[0].x = 10;
204
mirEvent.motion.pointer_coordinates[0].y = 10;
205
mirEvent.motion.pointer_coordinates[0].touch_major = 1;
206
mirEvent.motion.pointer_coordinates[0].touch_minor = 1;
207
mirEvent.motion.pointer_coordinates[0].pressure = 10;
208
mirEvent.motion.action = mir_motion_action_hover_enter;
209
mirEvent.motion.event_time = 123 * 1000000;
211
qtEventFeeder->dispatch(mirEvent);
213
mirEvent.motion.pointer_coordinates[0].x = 20;
214
mirEvent.motion.pointer_coordinates[0].y = 20;
215
mirEvent.motion.action = mir_motion_action_hover_move;
216
mirEvent.motion.event_time = 125 * 1000000;
218
qtEventFeeder->dispatch(mirEvent);
220
mirEvent.motion.action = mir_motion_action_hover_exit;
221
mirEvent.motion.event_time = 127 * 1000000;
223
qtEventFeeder->dispatch(mirEvent);