xref: /aosp_15_r20/external/libchrome-gestures/src/mouse_interpreter_unittest.cc (revision aed3e5085e770be5b69ce25295ecf6ddf906af95)
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