1 // Copyright 2012 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <gtest/gtest.h>
6
7 #include "include/gestures.h"
8 #include "include/mouse_interpreter.h"
9 #include "include/unittest_util.h"
10 #include "include/util.h"
11
12 namespace gestures {
13
make_hwprops_for_mouse(unsigned has_wheel,unsigned wheel_is_hi_res)14 HardwareProperties make_hwprops_for_mouse(
15 unsigned has_wheel, unsigned wheel_is_hi_res) {
16 return {
17 .right = 0,
18 .bottom = 0,
19 .res_x = 0,
20 .res_y = 0,
21 .orientation_minimum = 0,
22 .orientation_maximum = 0,
23 .max_finger_cnt = 0,
24 .max_touch_cnt = 0,
25 .supports_t5r2 = 0,
26 .support_semi_mt = 0,
27 .is_button_pad = 0,
28 .has_wheel = has_wheel,
29 .wheel_is_hi_res = wheel_is_hi_res,
30 .is_haptic_pad = 0,
31 };
32 }
33
34 class MouseInterpreterTest : public ::testing::Test {};
35
TEST(MouseInterpreterTest,SimpleTest)36 TEST(MouseInterpreterTest, SimpleTest) {
37 HardwareProperties hwprops = make_hwprops_for_mouse(1, 0);
38 MouseInterpreter mi(nullptr, nullptr);
39 TestInterpreterWrapper wrapper(&mi, &hwprops);
40 Gesture* gs;
41
42 HardwareState hwstates[] = {
43 { 200000, 0, 0, 0, nullptr, 0, 0, 0, 0, 0, 0.0 },
44 { 210000, 0, 0, 0, nullptr, 9, -7, 0, 0, 0, 0.0 },
45 { 220000, 1, 0, 0, nullptr, 0, 0, 0, 0, 0, 0.0 },
46 { 230000, 0, 0, 0, nullptr, 0, 0, 0, 0, 0, 0.0 },
47 { 240000, 0, 0, 0, nullptr, 0, 0, -3, -360, 4, 0.0 },
48 };
49
50 mi.output_mouse_wheel_gestures_.val_ = true;
51
52 gs = wrapper.SyncInterpret(hwstates[0], nullptr);
53 EXPECT_EQ(nullptr, gs);
54
55 gs = wrapper.SyncInterpret(hwstates[1], nullptr);
56 ASSERT_NE(nullptr, gs);
57 EXPECT_EQ(kGestureTypeMove, gs->type);
58 EXPECT_EQ(9, gs->details.move.dx);
59 EXPECT_EQ(-7, gs->details.move.dy);
60 EXPECT_EQ(200000, gs->start_time);
61 EXPECT_EQ(210000, gs->end_time);
62
63 gs = wrapper.SyncInterpret(hwstates[2], nullptr);
64 ASSERT_NE(nullptr, gs);
65 EXPECT_EQ(kGestureTypeButtonsChange, gs->type);
66 EXPECT_EQ(1, gs->details.buttons.down);
67 EXPECT_EQ(0, gs->details.buttons.up);
68 EXPECT_EQ(210000, gs->start_time);
69 EXPECT_EQ(220000, gs->end_time);
70
71 gs = wrapper.SyncInterpret(hwstates[3], nullptr);
72 ASSERT_NE(nullptr, gs);
73 EXPECT_EQ(kGestureTypeButtonsChange, gs->type);
74 EXPECT_EQ(0, gs->details.buttons.down);
75 EXPECT_EQ(1, gs->details.buttons.up);
76 EXPECT_EQ(220000, gs->start_time);
77 EXPECT_EQ(230000, gs->end_time);
78
79 gs = wrapper.SyncInterpret(hwstates[4], nullptr);
80 ASSERT_NE(nullptr, gs);
81 EXPECT_EQ(kGestureTypeMouseWheel, gs->type);
82 EXPECT_LT(-1, gs->details.wheel.dx);
83 EXPECT_GT(1, gs->details.wheel.dy);
84 EXPECT_EQ(240000, gs->start_time);
85 EXPECT_EQ(240000, gs->end_time);
86 }
87
TEST(MouseInterpreterTest,HighResolutionVerticalScrollTest)88 TEST(MouseInterpreterTest, HighResolutionVerticalScrollTest) {
89 HardwareProperties hwprops = make_hwprops_for_mouse(1, 1);
90 MouseInterpreter mi(nullptr, nullptr);
91 TestInterpreterWrapper wrapper(&mi, &hwprops);
92 Gesture* gs;
93
94 HardwareState hwstates[] = {
95 { 200000, 0, 0, 0, nullptr, 0, 0, 0, 0, 0, 0.0 },
96 { 210000, 0, 0, 0, nullptr, 0, 0, 0, -15, 0, 0.0 },
97 { 220000, 0, 0, 0, nullptr, 0, 0, -1, -15, 0, 0.0 },
98 { 230000, 0, 0, 0, nullptr, 0, 0, 0,-120, 0, 0.0 },
99 { 240000, 0, 0, 0, nullptr, 0, 0, -1, 0, 0, 0.0 },
100 };
101
102 mi.output_mouse_wheel_gestures_.val_ = true;
103 mi.hi_res_scrolling_.val_ = 1;
104 mi.scroll_velocity_buffer_size_.val_ = 1;
105
106 gs = wrapper.SyncInterpret(hwstates[0], nullptr);
107 EXPECT_EQ(nullptr, gs);
108
109 gs = wrapper.SyncInterpret(hwstates[1], nullptr);
110 ASSERT_NE(nullptr, gs);
111 EXPECT_EQ(kGestureTypeMouseWheel, gs->type);
112 EXPECT_EQ(0, gs->details.wheel.dx);
113 float offset_of_8th_notch_scroll = gs->details.wheel.dy;
114 EXPECT_LT(1, offset_of_8th_notch_scroll);
115
116 gs = wrapper.SyncInterpret(hwstates[2], nullptr);
117 ASSERT_NE(nullptr, gs);
118 EXPECT_EQ(kGestureTypeMouseWheel, gs->type);
119 EXPECT_EQ(0, gs->details.wheel.dx);
120 // Having a low-res scroll event as well as the high-resolution one shouldn't
121 // change the output value.
122 EXPECT_NEAR(offset_of_8th_notch_scroll, gs->details.wheel.dy, 0.1);
123
124 gs = wrapper.SyncInterpret(hwstates[3], nullptr);
125 ASSERT_NE(nullptr, gs);
126 EXPECT_EQ(kGestureTypeMouseWheel, gs->type);
127 EXPECT_EQ(0, gs->details.wheel.dx);
128 float offset_of_high_res_scroll = gs->details.wheel.dy;
129
130 mi.hi_res_scrolling_.val_ = 0;
131
132 gs = wrapper.SyncInterpret(hwstates[4], nullptr);
133 ASSERT_NE(nullptr, gs);
134 EXPECT_EQ(kGestureTypeMouseWheel, gs->type);
135 EXPECT_EQ(0, gs->details.wheel.dx);
136 // A high-res scroll should yield the same offset as a low-res one with
137 // proper unit conversion.
138 EXPECT_NEAR(offset_of_high_res_scroll, gs->details.wheel.dy, 0.1);
139 }
140
TEST(MouseInterpreterTest,ScrollAccelerationOnAndOffTest)141 TEST(MouseInterpreterTest, ScrollAccelerationOnAndOffTest) {
142 HardwareProperties hwprops = make_hwprops_for_mouse(1, 1);
143 MouseInterpreter mi(nullptr, nullptr);
144 TestInterpreterWrapper wrapper(&mi, &hwprops);
145 Gesture* gs;
146
147 HardwareState hwstates[] = {
148 { 200000, 0, 0, 0, nullptr, 0, 0, 0, 0, 0, 0.0 },
149 { 210000, 0, 0, 0, nullptr, 0, 0, 5, 0, 0, 0.0 },
150 { 220000, 0, 0, 0, nullptr, 0, 0, 5, 0, 0, 0.0 },
151 { 230000, 0, 0, 0, nullptr, 0, 0, 10, 0, 0, 0.0 },
152 { 240000, 0, 0, 0, nullptr, 0, 0, 10, 0, 0, 0.0 },
153 };
154
155 // Scroll acceleration is on.
156 mi.scroll_acceleration_.val_ = true;
157 mi.output_mouse_wheel_gestures_.val_ = true;
158 mi.hi_res_scrolling_.val_ = false;
159 mi.scroll_velocity_buffer_size_.val_ = 1;
160
161 gs = wrapper.SyncInterpret(hwstates[0], nullptr);
162 EXPECT_EQ(nullptr, gs);
163
164 gs = wrapper.SyncInterpret(hwstates[1], nullptr);
165 ASSERT_NE(nullptr, gs);
166 EXPECT_EQ(kGestureTypeMouseWheel, gs->type);
167 EXPECT_NE(0, gs->details.scroll.dy);
168
169 float offset_when_acceleration_on = gs->details.scroll.dy;
170
171 gs = wrapper.SyncInterpret(hwstates[2], nullptr);
172 ASSERT_NE(nullptr, gs);
173 EXPECT_EQ(kGestureTypeMouseWheel, gs->type);
174 EXPECT_NE(0, gs->details.scroll.dy);
175 // When acceleration is on, the offset is related to scroll speed. Though
176 // the wheel displacement are both 5, since the scroll speeds are different,
177 // the offset are different.
178 EXPECT_NE(offset_when_acceleration_on, gs->details.scroll.dy);
179
180 // Turn scroll acceleration off.
181 mi.scroll_acceleration_.val_ = false;
182
183 gs = wrapper.SyncInterpret(hwstates[3], nullptr);
184 ASSERT_NE(nullptr, gs);
185 EXPECT_EQ(kGestureTypeMouseWheel, gs->type);
186 EXPECT_NE(0, gs->details.scroll.dy);
187
188 float offset_when_acceleration_off = gs->details.scroll.dy;
189
190 gs = wrapper.SyncInterpret(hwstates[4], nullptr);
191 ASSERT_NE(nullptr, gs);
192 EXPECT_EQ(kGestureTypeMouseWheel, gs->type);
193 EXPECT_NE(0, gs->details.scroll.dy);
194 // When acceleration is off, the offset is not related to scroll speed.
195 // Same wheel displacement yields to same offset.
196 EXPECT_EQ(offset_when_acceleration_off, gs->details.scroll.dy);
197 }
198
TEST(MouseInterpreterTest,JankyScrollTest)199 TEST(MouseInterpreterTest, JankyScrollTest) {
200 HardwareProperties hwprops = make_hwprops_for_mouse(1, 0);
201 MouseInterpreter mi(nullptr, nullptr);
202 TestInterpreterWrapper wrapper(&mi, &hwprops);
203 Gesture* gs;
204
205 // Because we do not allow time deltas less than 8ms when calculating scroll
206 // acceleration, the last two scroll events should give the same dy
207 // (timestamp is in units of seconds)
208 HardwareState hwstates[] = {
209 { 200000, 0, 0, 0, nullptr, 0, 0, -1, 0, 0, 0.0 },
210 { 200000.008, 0, 0, 0, nullptr, 0, 0, -1, 0, 0, 0.0 },
211 { 200000.0085, 0, 0, 0, nullptr, 0, 0, -1, 0, 0, 0.0 },
212 };
213
214 mi.output_mouse_wheel_gestures_.val_ = true;
215 mi.scroll_velocity_buffer_size_.val_ = 1;
216
217 gs = wrapper.SyncInterpret(hwstates[0], nullptr);
218 ASSERT_NE(nullptr, gs);
219 EXPECT_EQ(kGestureTypeMouseWheel, gs->type);
220 EXPECT_EQ(0, gs->details.wheel.dx);
221 // Ignore the dy from the first scroll event, as the gesture interpreter
222 // hardcodes that time delta to 1 second, making it invalid for this test.
223
224 gs = wrapper.SyncInterpret(hwstates[1], nullptr);
225 ASSERT_NE(nullptr, gs);
226 EXPECT_EQ(kGestureTypeMouseWheel, gs->type);
227 EXPECT_EQ(0, gs->details.wheel.dx);
228 float scroll_offset = gs->details.wheel.dy;
229
230 gs = wrapper.SyncInterpret(hwstates[2], nullptr);
231 ASSERT_NE(nullptr, gs);
232 EXPECT_EQ(kGestureTypeMouseWheel, gs->type);
233 EXPECT_EQ(0, gs->details.wheel.dx);
234
235 EXPECT_NEAR(scroll_offset, gs->details.wheel.dy, 0.1);
236 }
237
TEST(MouseInterpreterTest,WheelTickReportingHighResTest)238 TEST(MouseInterpreterTest, WheelTickReportingHighResTest) {
239 HardwareProperties hwprops = make_hwprops_for_mouse(1, 1);
240 MouseInterpreter mi(nullptr, nullptr);
241 TestInterpreterWrapper wrapper(&mi, &hwprops);
242 Gesture* gs;
243
244 HardwareState hwstates[] = {
245 { 200000, 0, 0, 0, nullptr, 0, 0, 0, 0, 0, 0.0 },
246 { 210000, 0, 0, 0, nullptr, 0, 0, 0, -30, 0, 0.0 },
247 };
248
249 mi.output_mouse_wheel_gestures_.val_ = true;
250 mi.hi_res_scrolling_.val_ = true;
251
252 gs = wrapper.SyncInterpret(hwstates[0], nullptr);
253 EXPECT_EQ(nullptr, gs);
254
255 gs = wrapper.SyncInterpret(hwstates[1], nullptr);
256 ASSERT_NE(nullptr, gs);
257 EXPECT_EQ(kGestureTypeMouseWheel, gs->type);
258 EXPECT_EQ( 0, gs->details.wheel.tick_120ths_dx);
259 EXPECT_EQ(30, gs->details.wheel.tick_120ths_dy);
260 }
261
TEST(MouseInterpreterTest,WheelTickReportingLowResTest)262 TEST(MouseInterpreterTest, WheelTickReportingLowResTest) {
263 HardwareProperties hwprops = make_hwprops_for_mouse(1, 0);
264 MouseInterpreter mi(nullptr, nullptr);
265 TestInterpreterWrapper wrapper(&mi, &hwprops);
266 Gesture* gs;
267
268 HardwareState hwstates[] = {
269 { 200000, 0, 0, 0, nullptr, 0, 0, 0, 0, 0, 0.0 },
270 { 210000, 0, 0, 0, nullptr, 0, 0, 1, 0, 0, 0.0 },
271 { 210000, 0, 0, 0, nullptr, 0, 0, 0, 0, 1, 0.0 },
272 };
273
274 mi.output_mouse_wheel_gestures_.val_ = true;
275 mi.hi_res_scrolling_.val_ = false;
276
277 gs = wrapper.SyncInterpret(hwstates[0], nullptr);
278 EXPECT_EQ(nullptr, gs);
279
280 gs = wrapper.SyncInterpret(hwstates[1], nullptr);
281 ASSERT_NE(nullptr, gs);
282 EXPECT_EQ(kGestureTypeMouseWheel, gs->type);
283 EXPECT_EQ( 0, gs->details.wheel.tick_120ths_dx);
284 EXPECT_EQ(-120, gs->details.wheel.tick_120ths_dy);
285
286 gs = wrapper.SyncInterpret(hwstates[2], nullptr);
287 ASSERT_NE(nullptr, gs);
288 EXPECT_EQ(kGestureTypeMouseWheel, gs->type);
289 EXPECT_EQ(120, gs->details.wheel.tick_120ths_dx);
290 EXPECT_EQ( 0, gs->details.wheel.tick_120ths_dy);
291 }
292
TEST(MouseInterpreterTest,EmulateScrollWheelTest)293 TEST(MouseInterpreterTest, EmulateScrollWheelTest) {
294 HardwareProperties hwprops = make_hwprops_for_mouse(0, 0);
295 MouseInterpreter mi(nullptr, nullptr);
296 TestInterpreterWrapper wrapper(&mi, &hwprops);
297 Gesture* gs;
298
299 HardwareState hwstates[] = {
300 { 200000, GESTURES_BUTTON_NONE, 0, 0, nullptr, 0, 0, 0, 0, 0, 0.0 },
301 { 210000, GESTURES_BUTTON_NONE, 0, 0, nullptr, 9, -7, 0, 0, 0, 0.0 },
302 { 220000, GESTURES_BUTTON_LEFT, 0, 0, nullptr, 0, 0, 0, 0, 0, 0.0 },
303 { 230000, GESTURES_BUTTON_LEFT + GESTURES_BUTTON_RIGHT, 0, 0, nullptr,
304 0, 0, 0, 0, 0, 0.0 },
305 { 240000, GESTURES_BUTTON_LEFT + GESTURES_BUTTON_RIGHT, 0, 0, nullptr,
306 2, 2, 0, 0, 0, 0.0 },
307 { 250000, GESTURES_BUTTON_NONE, 0, 0, nullptr, 0, 0, 0, 0, 0, 0.0 },
308 { 260000, GESTURES_BUTTON_NONE, 0, 0, nullptr, 9, -7, 0, 0, 0, 0.0 },
309 { 270000, GESTURES_BUTTON_MIDDLE, 0, 0, nullptr, 0, 0, 0, 0, 0, 0.0 },
310 { 280000, GESTURES_BUTTON_MIDDLE, 0, 0, nullptr, 0, 0, 0, 0, 0, 0.0 },
311 { 290000, GESTURES_BUTTON_NONE, 0, 0, nullptr, 0, 0, -3, -360, 4, 0.0 },
312 };
313
314 mi.output_mouse_wheel_gestures_.val_ = true;
315
316 gs = wrapper.SyncInterpret(hwstates[0], nullptr);
317 EXPECT_EQ(nullptr, gs);
318
319 gs = wrapper.SyncInterpret(hwstates[1], nullptr);
320 ASSERT_NE(nullptr, gs);
321 EXPECT_EQ(kGestureTypeMove, gs->type);
322 EXPECT_EQ(9, gs->details.move.dx);
323 EXPECT_EQ(-7, gs->details.move.dy);
324 EXPECT_EQ(200000, gs->start_time);
325 EXPECT_EQ(210000, gs->end_time);
326
327 gs = wrapper.SyncInterpret(hwstates[2], nullptr);
328 ASSERT_NE(nullptr, gs);
329 EXPECT_EQ(kGestureTypeButtonsChange, gs->type);
330 EXPECT_EQ(1, gs->details.buttons.down);
331 EXPECT_EQ(0, gs->details.buttons.up);
332 EXPECT_EQ(210000, gs->start_time);
333 EXPECT_EQ(220000, gs->end_time);
334
335 gs = wrapper.SyncInterpret(hwstates[3], nullptr);
336 ASSERT_EQ(nullptr, gs);
337
338 // Temporarily adjust the threshold to force wheel_emulation_active_
339 auto thresh = mi.scroll_wheel_emulation_thresh_.val_;
340 mi.scroll_wheel_emulation_thresh_.val_ = 0.1;
341 EXPECT_FALSE(mi.wheel_emulation_active_);
342 gs = wrapper.SyncInterpret(hwstates[4], nullptr);
343 EXPECT_TRUE(mi.wheel_emulation_active_);
344 ASSERT_NE(nullptr, gs);
345 EXPECT_EQ(kGestureTypeScroll, gs->type);
346 EXPECT_EQ(200, gs->details.scroll.dx);
347 EXPECT_EQ(200, gs->details.scroll.dy);
348 EXPECT_EQ(240000, gs->start_time);
349 EXPECT_EQ(240000, gs->end_time);
350 mi.scroll_wheel_emulation_thresh_.val_ = thresh;
351
352 gs = wrapper.SyncInterpret(hwstates[5], nullptr);
353 ASSERT_NE(nullptr, gs);
354 EXPECT_EQ(kGestureTypeButtonsChange, gs->type);
355 EXPECT_EQ(0, gs->details.buttons.down);
356 EXPECT_EQ(5, gs->details.buttons.up);
357 EXPECT_EQ(240000, gs->start_time);
358 EXPECT_EQ(250000, gs->end_time);
359
360 gs = wrapper.SyncInterpret(hwstates[6], nullptr);
361 ASSERT_NE(nullptr, gs);
362 EXPECT_EQ(kGestureTypeMove, gs->type);
363 EXPECT_EQ(9, gs->details.move.dx);
364 EXPECT_EQ(-7, gs->details.move.dy);
365 EXPECT_EQ(250000, gs->start_time);
366 EXPECT_EQ(260000, gs->end_time);
367
368 gs = wrapper.SyncInterpret(hwstates[7], nullptr);
369 ASSERT_EQ(nullptr, gs);
370
371 gs = wrapper.SyncInterpret(hwstates[8], nullptr);
372 ASSERT_EQ(nullptr, gs);
373
374 gs = wrapper.SyncInterpret(hwstates[9], nullptr);
375 ASSERT_NE(nullptr, gs);
376 EXPECT_EQ(kGestureTypeButtonsChange, gs->type);
377 EXPECT_EQ(0, gs->details.buttons.down);
378 EXPECT_EQ(2, gs->details.buttons.up);
379 EXPECT_EQ(280000, gs->start_time);
380 EXPECT_EQ(290000, gs->end_time);
381 }
382
383 } // namespace gestures
384