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