1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
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 "ui/events/event.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <memory>
11
12 #include "base/stl_util.h"
13 #include "base/test/metrics/histogram_tester.h"
14 #include "build/build_config.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "ui/base/ui_base_features.h"
17 #include "ui/events/event_constants.h"
18 #include "ui/events/event_utils.h"
19 #include "ui/events/keycodes/dom/dom_code.h"
20 #include "ui/events/keycodes/dom/keycode_converter.h"
21 #include "ui/events/keycodes/keyboard_code_conversion.h"
22 #include "ui/events/test/events_test_utils.h"
23 #include "ui/events/test/keyboard_layout.h"
24 #include "ui/events/test/test_event_target.h"
25 #include "ui/gfx/transform.h"
26
27 namespace ui {
28
TEST(EventTest,NoNativeEvent)29 TEST(EventTest, NoNativeEvent) {
30 KeyEvent keyev(ET_KEY_PRESSED, VKEY_SPACE, EF_NONE);
31 EXPECT_FALSE(keyev.HasNativeEvent());
32 }
33
TEST(EventTest,NativeEvent)34 TEST(EventTest, NativeEvent) {
35 #if defined(OS_WIN)
36 MSG native_event = {nullptr, WM_KEYUP, VKEY_A, 0};
37 KeyEvent keyev(native_event);
38 EXPECT_TRUE(keyev.HasNativeEvent());
39 #endif
40 }
41
TEST(EventTest,GetCharacter)42 TEST(EventTest, GetCharacter) {
43 ui::ScopedKeyboardLayout keyboard_layout(ui::KEYBOARD_LAYOUT_ENGLISH_US);
44
45 // Check if Control+Enter returns 10.
46 KeyEvent keyev1(ET_KEY_PRESSED, VKEY_RETURN, EF_CONTROL_DOWN);
47 EXPECT_EQ(10, keyev1.GetCharacter());
48 // Check if Enter returns 13.
49 KeyEvent keyev2(ET_KEY_PRESSED, VKEY_RETURN, EF_NONE);
50 EXPECT_EQ(13, keyev2.GetCharacter());
51
52 // Check if expected Unicode character was returned for a key combination
53 // contains Control.
54 // e.g. Control+Shift+2 produces U+200C on "Persian" keyboard.
55 // http://crbug.com/582453
56 KeyEvent keyev5(0x200C, VKEY_UNKNOWN, ui::DomCode::NONE,
57 EF_CONTROL_DOWN | EF_SHIFT_DOWN);
58 EXPECT_EQ(0x200C, keyev5.GetCharacter());
59 }
60
TEST(EventTest,ClickCount)61 TEST(EventTest, ClickCount) {
62 const gfx::Point origin(0, 0);
63 MouseEvent mouseev(ET_MOUSE_PRESSED, origin, origin, EventTimeForNow(), 0, 0);
64 for (int i = 1; i <= 3; ++i) {
65 mouseev.SetClickCount(i);
66 EXPECT_EQ(i, mouseev.GetClickCount());
67 }
68 }
69
TEST(EventTest,RepeatedClick)70 TEST(EventTest, RepeatedClick) {
71 const gfx::Point origin(0, 0);
72 MouseEvent event1(ET_MOUSE_PRESSED, origin, origin, EventTimeForNow(), 0, 0);
73 MouseEvent event2(ET_MOUSE_PRESSED, origin, origin, EventTimeForNow(), 0, 0);
74 LocatedEventTestApi test_event1(&event1);
75 LocatedEventTestApi test_event2(&event2);
76
77 base::TimeTicks start = base::TimeTicks::Now();
78 base::TimeTicks soon = start + base::TimeDelta::FromMilliseconds(1);
79 base::TimeTicks later = start + base::TimeDelta::FromMilliseconds(1000);
80
81 // Same time stamp (likely the same native event).
82 test_event1.set_location(gfx::Point(0, 0));
83 test_event2.set_location(gfx::Point(1, 0));
84 test_event1.set_time_stamp(start);
85 test_event2.set_time_stamp(start);
86 EXPECT_FALSE(MouseEvent::IsRepeatedClickEvent(event1, event2));
87 MouseEvent mouse_ev3(event1);
88 EXPECT_FALSE(MouseEvent::IsRepeatedClickEvent(event1, mouse_ev3));
89
90 // Close point.
91 test_event1.set_location(gfx::Point(0, 0));
92 test_event2.set_location(gfx::Point(1, 0));
93 test_event1.set_time_stamp(start);
94 test_event2.set_time_stamp(soon);
95 EXPECT_TRUE(MouseEvent::IsRepeatedClickEvent(event1, event2));
96
97 // Too far.
98 test_event1.set_location(gfx::Point(0, 0));
99 test_event2.set_location(gfx::Point(10, 0));
100 test_event1.set_time_stamp(start);
101 test_event2.set_time_stamp(soon);
102 EXPECT_FALSE(MouseEvent::IsRepeatedClickEvent(event1, event2));
103
104 // Too long a time between clicks.
105 test_event1.set_location(gfx::Point(0, 0));
106 test_event2.set_location(gfx::Point(0, 0));
107 test_event1.set_time_stamp(start);
108 test_event2.set_time_stamp(later);
109 EXPECT_FALSE(MouseEvent::IsRepeatedClickEvent(event1, event2));
110 }
111
TEST(EventTest,RepeatedKeyEvent)112 TEST(EventTest, RepeatedKeyEvent) {
113 base::TimeTicks start = base::TimeTicks::Now();
114 base::TimeTicks time1 = start + base::TimeDelta::FromMilliseconds(1);
115 base::TimeTicks time2 = start + base::TimeDelta::FromMilliseconds(2);
116 base::TimeTicks time3 = start + base::TimeDelta::FromMilliseconds(3);
117
118 KeyEvent event1(ET_KEY_PRESSED, VKEY_A, 0, start);
119 KeyEvent event2(ET_KEY_PRESSED, VKEY_A, 0, time1);
120 KeyEvent event3(ET_KEY_PRESSED, VKEY_A, EF_LEFT_MOUSE_BUTTON, time2);
121 KeyEvent event4(ET_KEY_PRESSED, VKEY_A, 0, time3);
122
123 event1.InitializeNative();
124 EXPECT_TRUE((event1.flags() & EF_IS_REPEAT) == 0);
125 event2.InitializeNative();
126 EXPECT_TRUE((event2.flags() & EF_IS_REPEAT) != 0);
127
128 event3.InitializeNative();
129 EXPECT_TRUE((event3.flags() & EF_IS_REPEAT) != 0);
130
131 event4.InitializeNative();
132 EXPECT_TRUE((event4.flags() & EF_IS_REPEAT) != 0);
133 }
134
135 // Tests that re-processing the same mouse press event (detected by timestamp)
136 // does not yield a double click event: http://crbug.com/389162
TEST(EventTest,DoubleClickRequiresUniqueTimestamp)137 TEST(EventTest, DoubleClickRequiresUniqueTimestamp) {
138 const gfx::Point point(0, 0);
139 base::TimeTicks time1 = base::TimeTicks::Now();
140 base::TimeTicks time2 = time1 + base::TimeDelta::FromMilliseconds(1);
141
142 // Re-processing the same press doesn't yield a double-click.
143 MouseEvent event(ET_MOUSE_PRESSED, point, point, time1, 0, 0);
144 EXPECT_EQ(1, MouseEvent::GetRepeatCount(event));
145 EXPECT_EQ(1, MouseEvent::GetRepeatCount(event));
146 // Processing a press with the same timestamp doesn't yield a double-click.
147 event = MouseEvent(ET_MOUSE_PRESSED, point, point, time1, 0, 0);
148 EXPECT_EQ(1, MouseEvent::GetRepeatCount(event));
149 // Processing a press with a later timestamp does yield a double-click.
150 event = MouseEvent(ET_MOUSE_PRESSED, point, point, time2, 0, 0);
151 EXPECT_EQ(2, MouseEvent::GetRepeatCount(event));
152 MouseEvent::ResetLastClickForTest();
153
154 // Test processing a double press and release sequence with one timestamp.
155 event = MouseEvent(ET_MOUSE_PRESSED, point, point, time1, 0, 0);
156 EXPECT_EQ(1, MouseEvent::GetRepeatCount(event));
157 event = MouseEvent(ET_MOUSE_RELEASED, point, point, time1, 0, 0);
158 EXPECT_EQ(1, MouseEvent::GetRepeatCount(event));
159 event = MouseEvent(ET_MOUSE_PRESSED, point, point, time1, 0, 0);
160 EXPECT_EQ(1, MouseEvent::GetRepeatCount(event));
161 event = MouseEvent(ET_MOUSE_RELEASED, point, point, time1, 0, 0);
162 EXPECT_EQ(1, MouseEvent::GetRepeatCount(event));
163 MouseEvent::ResetLastClickForTest();
164
165 // Test processing a double press and release sequence with two timestamps.
166 event = MouseEvent(ET_MOUSE_PRESSED, point, point, time1, 0, 0);
167 EXPECT_EQ(1, MouseEvent::GetRepeatCount(event));
168 event = MouseEvent(ET_MOUSE_RELEASED, point, point, time1, 0, 0);
169 EXPECT_EQ(1, MouseEvent::GetRepeatCount(event));
170 event = MouseEvent(ET_MOUSE_PRESSED, point, point, time2, 0, 0);
171 EXPECT_EQ(2, MouseEvent::GetRepeatCount(event));
172 event = MouseEvent(ET_MOUSE_RELEASED, point, point, time2, 0, 0);
173 EXPECT_EQ(2, MouseEvent::GetRepeatCount(event));
174 MouseEvent::ResetLastClickForTest();
175 }
176
177 // Tests that right clicking, then left clicking does not yield double clicks.
TEST(EventTest,SingleClickRightLeft)178 TEST(EventTest, SingleClickRightLeft) {
179 const gfx::Point point(0, 0);
180 base::TimeTicks time1 = base::TimeTicks::Now();
181 base::TimeTicks time2 = time1 + base::TimeDelta::FromMilliseconds(1);
182 base::TimeTicks time3 = time1 + base::TimeDelta::FromMilliseconds(2);
183
184 MouseEvent event(ET_MOUSE_PRESSED, point, point, time1,
185 ui::EF_RIGHT_MOUSE_BUTTON, ui::EF_RIGHT_MOUSE_BUTTON);
186 EXPECT_EQ(1, MouseEvent::GetRepeatCount(event));
187 event = MouseEvent(ET_MOUSE_PRESSED, point, point, time2,
188 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
189 EXPECT_EQ(1, MouseEvent::GetRepeatCount(event));
190 event = MouseEvent(ET_MOUSE_RELEASED, point, point, time2,
191 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
192 EXPECT_EQ(1, MouseEvent::GetRepeatCount(event));
193 event = MouseEvent(ET_MOUSE_PRESSED, point, point, time3,
194 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
195 EXPECT_EQ(2, MouseEvent::GetRepeatCount(event));
196 MouseEvent::ResetLastClickForTest();
197 }
198
TEST(EventTest,KeyEvent)199 TEST(EventTest, KeyEvent) {
200 ui::ScopedKeyboardLayout keyboard_layout(ui::KEYBOARD_LAYOUT_ENGLISH_US);
201
202 static const struct {
203 KeyboardCode key_code;
204 int flags;
205 uint16_t character;
206 } kTestData[] = {
207 {VKEY_A, 0, 'a'},
208 {VKEY_A, EF_SHIFT_DOWN, 'A'},
209 {VKEY_A, EF_CAPS_LOCK_ON, 'A'},
210 {VKEY_A, EF_SHIFT_DOWN | EF_CAPS_LOCK_ON, 'a'},
211 {VKEY_A, EF_CONTROL_DOWN, 0x01},
212 {VKEY_A, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x01'},
213 {VKEY_Z, 0, 'z'},
214 {VKEY_Z, EF_SHIFT_DOWN, 'Z'},
215 {VKEY_Z, EF_CAPS_LOCK_ON, 'Z'},
216 {VKEY_Z, EF_SHIFT_DOWN | EF_CAPS_LOCK_ON, 'z'},
217 {VKEY_Z, EF_CONTROL_DOWN, '\x1A'},
218 {VKEY_Z, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x1A'},
219
220 {VKEY_2, EF_CONTROL_DOWN, '\x12'},
221 {VKEY_2, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\0'},
222 {VKEY_6, EF_CONTROL_DOWN, '\x16'},
223 {VKEY_6, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x1E'},
224 {VKEY_OEM_MINUS, EF_CONTROL_DOWN, '\x0D'},
225 {VKEY_OEM_MINUS, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x1F'},
226 {VKEY_OEM_4, EF_CONTROL_DOWN, '\x1B'},
227 {VKEY_OEM_4, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x1B'},
228 {VKEY_OEM_5, EF_CONTROL_DOWN, '\x1C'},
229 {VKEY_OEM_5, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x1C'},
230 {VKEY_OEM_6, EF_CONTROL_DOWN, '\x1D'},
231 {VKEY_OEM_6, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x1D'},
232 {VKEY_RETURN, EF_CONTROL_DOWN, '\x0A'},
233
234 {VKEY_0, 0, '0'},
235 {VKEY_0, EF_SHIFT_DOWN, ')'},
236 {VKEY_0, EF_SHIFT_DOWN | EF_CAPS_LOCK_ON, ')'},
237 {VKEY_0, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x09'},
238
239 {VKEY_9, 0, '9'},
240 {VKEY_9, EF_SHIFT_DOWN, '('},
241 {VKEY_9, EF_SHIFT_DOWN | EF_CAPS_LOCK_ON, '('},
242 {VKEY_9, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x08'},
243
244 {VKEY_NUMPAD0, EF_CONTROL_DOWN, '\x10'},
245 {VKEY_NUMPAD0, EF_SHIFT_DOWN, '0'},
246
247 {VKEY_NUMPAD9, EF_CONTROL_DOWN, '\x19'},
248 {VKEY_NUMPAD9, EF_SHIFT_DOWN, '9'},
249
250 {VKEY_TAB, EF_NONE, '\t'},
251 {VKEY_TAB, EF_CONTROL_DOWN, '\t'},
252 {VKEY_TAB, EF_SHIFT_DOWN, '\t'},
253
254 {VKEY_MULTIPLY, EF_CONTROL_DOWN, '\x0A'},
255 {VKEY_MULTIPLY, EF_SHIFT_DOWN, '*'},
256 {VKEY_ADD, EF_CONTROL_DOWN, '\x0B'},
257 {VKEY_ADD, EF_SHIFT_DOWN, '+'},
258 {VKEY_SUBTRACT, EF_CONTROL_DOWN, '\x0D'},
259 {VKEY_SUBTRACT, EF_SHIFT_DOWN, '-'},
260 {VKEY_DECIMAL, EF_CONTROL_DOWN, '\x0E'},
261 {VKEY_DECIMAL, EF_SHIFT_DOWN, '.'},
262 {VKEY_DIVIDE, EF_CONTROL_DOWN, '\x0F'},
263 {VKEY_DIVIDE, EF_SHIFT_DOWN, '/'},
264
265 {VKEY_OEM_1, EF_CONTROL_DOWN, '\x1B'},
266 {VKEY_OEM_1, EF_SHIFT_DOWN, ':'},
267 {VKEY_OEM_PLUS, EF_CONTROL_DOWN, '\x1D'},
268 {VKEY_OEM_PLUS, EF_SHIFT_DOWN, '+'},
269 {VKEY_OEM_COMMA, EF_CONTROL_DOWN, '\x0C'},
270 {VKEY_OEM_COMMA, EF_SHIFT_DOWN, '<'},
271 {VKEY_OEM_PERIOD, EF_CONTROL_DOWN, '\x0E'},
272 {VKEY_OEM_PERIOD, EF_SHIFT_DOWN, '>'},
273 {VKEY_OEM_3, EF_CONTROL_DOWN, '\x0'},
274 {VKEY_OEM_3, EF_SHIFT_DOWN, '~'},
275 };
276
277 for (size_t i = 0; i < base::size(kTestData); ++i) {
278 KeyEvent key(ET_KEY_PRESSED, kTestData[i].key_code, kTestData[i].flags);
279 EXPECT_EQ(kTestData[i].character, key.GetCharacter())
280 << " Index:" << i << " key_code:" << kTestData[i].key_code;
281 }
282 }
283
TEST(EventTest,KeyEventDirectUnicode)284 TEST(EventTest, KeyEventDirectUnicode) {
285 KeyEvent key(0x1234U, ui::VKEY_UNKNOWN, ui::DomCode::NONE, ui::EF_NONE);
286 EXPECT_EQ(0x1234U, key.GetCharacter());
287 EXPECT_EQ(ET_KEY_PRESSED, key.type());
288 EXPECT_TRUE(key.is_char());
289 }
290
TEST(EventTest,NormalizeKeyEventFlags)291 TEST(EventTest, NormalizeKeyEventFlags) {
292 // Do not normalize flags for synthesized events without
293 // KeyEvent::NormalizeFlags called explicitly.
294 {
295 KeyEvent keyev(ET_KEY_PRESSED, VKEY_SHIFT, EF_SHIFT_DOWN);
296 EXPECT_EQ(EF_SHIFT_DOWN, keyev.flags());
297 }
298 {
299 KeyEvent keyev(ET_KEY_RELEASED, VKEY_SHIFT, EF_SHIFT_DOWN);
300 EXPECT_EQ(EF_SHIFT_DOWN, keyev.flags());
301 keyev.NormalizeFlags();
302 EXPECT_EQ(EF_NONE, keyev.flags());
303 }
304 {
305 KeyEvent keyev(ET_KEY_PRESSED, VKEY_CONTROL, EF_CONTROL_DOWN);
306 EXPECT_EQ(EF_CONTROL_DOWN, keyev.flags());
307 }
308 {
309 KeyEvent keyev(ET_KEY_RELEASED, VKEY_CONTROL, EF_CONTROL_DOWN);
310 EXPECT_EQ(EF_CONTROL_DOWN, keyev.flags());
311 keyev.NormalizeFlags();
312 EXPECT_EQ(EF_NONE, keyev.flags());
313 }
314 {
315 KeyEvent keyev(ET_KEY_PRESSED, VKEY_MENU, EF_ALT_DOWN);
316 EXPECT_EQ(EF_ALT_DOWN, keyev.flags());
317 }
318 {
319 KeyEvent keyev(ET_KEY_RELEASED, VKEY_MENU, EF_ALT_DOWN);
320 EXPECT_EQ(EF_ALT_DOWN, keyev.flags());
321 keyev.NormalizeFlags();
322 EXPECT_EQ(EF_NONE, keyev.flags());
323 }
324 }
325
TEST(EventTest,KeyEventCopy)326 TEST(EventTest, KeyEventCopy) {
327 KeyEvent key(ET_KEY_PRESSED, VKEY_A, EF_NONE);
328 std::unique_ptr<KeyEvent> copied_key(new KeyEvent(key));
329 EXPECT_EQ(copied_key->type(), key.type());
330 EXPECT_EQ(copied_key->key_code(), key.key_code());
331 }
332
TEST(EventTest,KeyEventCode)333 TEST(EventTest, KeyEventCode) {
334 const DomCode kDomCodeForSpace = DomCode::SPACE;
335 const char kCodeForSpace[] = "Space";
336 ASSERT_EQ(kDomCodeForSpace,
337 ui::KeycodeConverter::CodeStringToDomCode(kCodeForSpace));
338 const uint16_t kNativeCodeSpace =
339 ui::KeycodeConverter::DomCodeToNativeKeycode(kDomCodeForSpace);
340 ASSERT_NE(ui::KeycodeConverter::InvalidNativeKeycode(), kNativeCodeSpace);
341 ASSERT_EQ(kNativeCodeSpace,
342 ui::KeycodeConverter::DomCodeToNativeKeycode(kDomCodeForSpace));
343
344 {
345 KeyEvent key(ET_KEY_PRESSED, VKEY_SPACE, kDomCodeForSpace, EF_NONE);
346 EXPECT_EQ(kCodeForSpace, key.GetCodeString());
347 }
348 {
349 // Regardless the KeyEvent.key_code (VKEY_RETURN), code should be
350 // the specified value.
351 KeyEvent key(ET_KEY_PRESSED, VKEY_RETURN, kDomCodeForSpace, EF_NONE);
352 EXPECT_EQ(kCodeForSpace, key.GetCodeString());
353 }
354 {
355 // If the synthetic event is initialized without code, the code is
356 // determined from the KeyboardCode assuming a US keyboard layout.
357 KeyEvent key(ET_KEY_PRESSED, VKEY_SPACE, EF_NONE);
358 EXPECT_EQ(kCodeForSpace, key.GetCodeString());
359 }
360 #if defined(OS_WIN)
361 {
362 // Test a non extended key.
363 ASSERT_EQ((kNativeCodeSpace & 0xFF), kNativeCodeSpace);
364
365 const LPARAM lParam = GetLParamFromScanCode(kNativeCodeSpace);
366 MSG native_event = {nullptr, WM_KEYUP, VKEY_SPACE, lParam};
367 KeyEvent key(native_event);
368
369 // KeyEvent converts from the native keycode (scan code) to the code.
370 EXPECT_EQ(kCodeForSpace, key.GetCodeString());
371 }
372 {
373 const char kCodeForHome[] = "Home";
374 const uint16_t kNativeCodeHome = 0xe047;
375
376 // 'Home' is an extended key with 0xe000 bits.
377 ASSERT_NE((kNativeCodeHome & 0xFF), kNativeCodeHome);
378 const LPARAM lParam = GetLParamFromScanCode(kNativeCodeHome);
379
380 MSG native_event = {nullptr, WM_KEYUP, VKEY_HOME, lParam};
381 KeyEvent key(native_event);
382
383 // KeyEvent converts from the native keycode (scan code) to the code.
384 EXPECT_EQ(kCodeForHome, key.GetCodeString());
385 }
386 #endif // OS_WIN
387 }
388
TEST(EventTest,TouchEventRadiusDefaultsToOtherAxis)389 TEST(EventTest, TouchEventRadiusDefaultsToOtherAxis) {
390 const base::TimeTicks time = base::TimeTicks::Now();
391 const float non_zero_length1 = 30;
392 const float non_zero_length2 = 46;
393
394 TouchEvent event1(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), time,
395 PointerDetails(ui::EventPointerType::kTouch,
396 /* pointer_id*/ 0,
397 /* radius_x */ non_zero_length1,
398 /* radius_y */ 0.0f,
399 /* force */ 0));
400 EXPECT_EQ(non_zero_length1, event1.pointer_details().radius_x);
401 EXPECT_EQ(non_zero_length1, event1.pointer_details().radius_y);
402
403 TouchEvent event2(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), time,
404 PointerDetails(ui::EventPointerType::kTouch,
405 /* pointer_id*/ 0,
406 /* radius_x */ 0.0f,
407 /* radius_y */ non_zero_length2,
408 /* force */ 0));
409 EXPECT_EQ(non_zero_length2, event2.pointer_details().radius_x);
410 EXPECT_EQ(non_zero_length2, event2.pointer_details().radius_y);
411 }
412
TEST(EventTest,TouchEventRotationAngleFixing)413 TEST(EventTest, TouchEventRotationAngleFixing) {
414 const base::TimeTicks time = base::TimeTicks::Now();
415 const float radius_x = 20;
416 const float radius_y = 10;
417
418 {
419 const float angle_in_range = 0;
420 TouchEvent event(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), time,
421 PointerDetails(ui::EventPointerType::kTouch,
422 /* pointer_id*/ 0, radius_x, radius_y,
423 /* force */ 0, angle_in_range),
424 0);
425 EXPECT_FLOAT_EQ(angle_in_range, event.ComputeRotationAngle());
426 }
427
428 {
429 const float angle_in_range = 179.9f;
430 TouchEvent event(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), time,
431 PointerDetails(ui::EventPointerType::kTouch,
432 /* pointer_id*/ 0, radius_x, radius_y,
433 /* force */ 0, angle_in_range),
434 0);
435 EXPECT_FLOAT_EQ(angle_in_range, event.ComputeRotationAngle());
436 }
437
438 {
439 const float angle_negative = -0.1f;
440 TouchEvent event(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), time,
441 PointerDetails(ui::EventPointerType::kTouch,
442 /* pointer_id*/ 0, radius_x, radius_y,
443 /* force */ 0, angle_negative),
444 0);
445 EXPECT_FLOAT_EQ(180 - 0.1f, event.ComputeRotationAngle());
446 }
447
448 {
449 const float angle_negative = -200;
450 TouchEvent event(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), time,
451 PointerDetails(ui::EventPointerType::kTouch,
452 /* pointer_id*/ 0, radius_x, radius_y,
453 /* force */ 0, angle_negative),
454 0);
455 EXPECT_FLOAT_EQ(360 - 200, event.ComputeRotationAngle());
456 }
457
458 {
459 const float angle_too_big = 180;
460 TouchEvent event(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), time,
461 PointerDetails(ui::EventPointerType::kTouch,
462 /* pointer_id*/ 0, radius_x, radius_y,
463 /* force */ 0, angle_too_big),
464 0);
465 EXPECT_FLOAT_EQ(0, event.ComputeRotationAngle());
466 }
467
468 {
469 const float angle_too_big = 400;
470 TouchEvent event(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), time,
471 PointerDetails(ui::EventPointerType::kTouch,
472 /* pointer_id*/ 0, radius_x, radius_y,
473 /* force */ 0, angle_too_big),
474 0);
475 EXPECT_FLOAT_EQ(400 - 360, event.ComputeRotationAngle());
476 }
477 }
478
TEST(EventTest,PointerDetailsTouch)479 TEST(EventTest, PointerDetailsTouch) {
480 ui::TouchEvent touch_event_plain(
481 ET_TOUCH_PRESSED, gfx::Point(0, 0), ui::EventTimeForNow(),
482 PointerDetails(ui::EventPointerType::kTouch, 0));
483
484 EXPECT_EQ(EventPointerType::kTouch,
485 touch_event_plain.pointer_details().pointer_type);
486 EXPECT_EQ(0.0f, touch_event_plain.pointer_details().radius_x);
487 EXPECT_EQ(0.0f, touch_event_plain.pointer_details().radius_y);
488 EXPECT_TRUE(std::isnan(touch_event_plain.pointer_details().force));
489 EXPECT_EQ(0.0f, touch_event_plain.pointer_details().tilt_x);
490 EXPECT_EQ(0.0f, touch_event_plain.pointer_details().tilt_y);
491
492 ui::TouchEvent touch_event_with_details(
493 ET_TOUCH_PRESSED, gfx::Point(0, 0), ui::EventTimeForNow(),
494 PointerDetails(ui::EventPointerType::kTouch,
495 /* pointer_id*/ 0,
496 /* radius_x */ 10.0f,
497 /* radius_y */ 5.0f,
498 /* force */ 15.0f));
499
500 EXPECT_EQ(EventPointerType::kTouch,
501 touch_event_with_details.pointer_details().pointer_type);
502 EXPECT_EQ(10.0f, touch_event_with_details.pointer_details().radius_x);
503 EXPECT_EQ(5.0f, touch_event_with_details.pointer_details().radius_y);
504 EXPECT_EQ(15.0f, touch_event_with_details.pointer_details().force);
505 EXPECT_EQ(0.0f, touch_event_with_details.pointer_details().tilt_x);
506 EXPECT_EQ(0.0f, touch_event_with_details.pointer_details().tilt_y);
507
508 ui::TouchEvent touch_event_copy(touch_event_with_details);
509 EXPECT_EQ(touch_event_with_details.pointer_details(),
510 touch_event_copy.pointer_details());
511 }
512
TEST(EventTest,PointerDetailsMouse)513 TEST(EventTest, PointerDetailsMouse) {
514 ui::MouseEvent mouse_event(ET_MOUSE_PRESSED, gfx::Point(0, 0),
515 gfx::Point(0, 0), ui::EventTimeForNow(), 0, 0);
516
517 EXPECT_EQ(EventPointerType::kMouse,
518 mouse_event.pointer_details().pointer_type);
519 EXPECT_EQ(0.0f, mouse_event.pointer_details().radius_x);
520 EXPECT_EQ(0.0f, mouse_event.pointer_details().radius_y);
521 EXPECT_TRUE(std::isnan(mouse_event.pointer_details().force));
522 EXPECT_EQ(0.0f, mouse_event.pointer_details().tilt_x);
523 EXPECT_EQ(0.0f, mouse_event.pointer_details().tilt_y);
524
525 ui::MouseEvent mouse_event_copy(mouse_event);
526 EXPECT_EQ(mouse_event.pointer_details(), mouse_event_copy.pointer_details());
527 }
528
TEST(EventTest,PointerDetailsStylus)529 TEST(EventTest, PointerDetailsStylus) {
530 ui::PointerDetails pointer_details(EventPointerType::kPen,
531 /* pointer_id*/ 0,
532 /* radius_x */ 0.0f,
533 /* radius_y */ 0.0f,
534 /* force */ 21.0f,
535 /* twist */ 196,
536 /* tilt_x */ 45.0f,
537 /* tilt_y */ -45.0f,
538 /* tangential_pressure */ 0.7f);
539
540 ui::MouseEvent stylus_event(ET_MOUSE_PRESSED, gfx::Point(0, 0),
541 gfx::Point(0, 0), ui::EventTimeForNow(), 0, 0,
542 pointer_details);
543 EXPECT_EQ(EventPointerType::kPen,
544 stylus_event.pointer_details().pointer_type);
545 EXPECT_EQ(21.0f, stylus_event.pointer_details().force);
546 EXPECT_EQ(45.0f, stylus_event.pointer_details().tilt_x);
547 EXPECT_EQ(-45.0f, stylus_event.pointer_details().tilt_y);
548 EXPECT_EQ(0.0f, stylus_event.pointer_details().radius_x);
549 EXPECT_EQ(0.0f, stylus_event.pointer_details().radius_y);
550 EXPECT_EQ(0.7f, stylus_event.pointer_details().tangential_pressure);
551 EXPECT_EQ(196, stylus_event.pointer_details().twist);
552
553 ui::MouseEvent stylus_event_copy(stylus_event);
554 EXPECT_EQ(stylus_event.pointer_details(),
555 stylus_event_copy.pointer_details());
556 }
557
TEST(EventTest,PointerDetailsCustomTouch)558 TEST(EventTest, PointerDetailsCustomTouch) {
559 ui::TouchEvent touch_event(ET_TOUCH_PRESSED, gfx::Point(0, 0),
560 ui::EventTimeForNow(),
561 PointerDetails(ui::EventPointerType::kTouch, 0));
562
563 EXPECT_EQ(EventPointerType::kTouch,
564 touch_event.pointer_details().pointer_type);
565 EXPECT_EQ(0.0f, touch_event.pointer_details().radius_x);
566 EXPECT_EQ(0.0f, touch_event.pointer_details().radius_y);
567 EXPECT_TRUE(std::isnan(touch_event.pointer_details().force));
568 EXPECT_EQ(0.0f, touch_event.pointer_details().tilt_x);
569 EXPECT_EQ(0.0f, touch_event.pointer_details().tilt_y);
570
571 ui::PointerDetails pointer_details(EventPointerType::kPen,
572 /* pointer_id*/ 0,
573 /* radius_x */ 5.0f,
574 /* radius_y */ 6.0f,
575 /* force */ 21.0f,
576 /* twist */ 196,
577 /* tilt_x */ 45.0f,
578 /* tilt_y */ -45.0f,
579 /* tangential_pressure */ 0.7f);
580 touch_event.SetPointerDetailsForTest(pointer_details);
581
582 EXPECT_EQ(EventPointerType::kPen, touch_event.pointer_details().pointer_type);
583 EXPECT_EQ(21.0f, touch_event.pointer_details().force);
584 EXPECT_EQ(45.0f, touch_event.pointer_details().tilt_x);
585 EXPECT_EQ(-45.0f, touch_event.pointer_details().tilt_y);
586 EXPECT_EQ(5.0f, touch_event.pointer_details().radius_x);
587 EXPECT_EQ(6.0f, touch_event.pointer_details().radius_y);
588 EXPECT_EQ(0.7f, touch_event.pointer_details().tangential_pressure);
589 EXPECT_EQ(196, touch_event.pointer_details().twist);
590
591 ui::TouchEvent touch_event_copy(touch_event);
592 EXPECT_EQ(touch_event.pointer_details(), touch_event_copy.pointer_details());
593 }
594
TEST(EventTest,MouseEventLatencyUIComponentExists)595 TEST(EventTest, MouseEventLatencyUIComponentExists) {
596 const gfx::Point origin(0, 0);
597 MouseEvent mouseev(ET_MOUSE_PRESSED, origin, origin, EventTimeForNow(), 0, 0);
598 EXPECT_TRUE(mouseev.latency()->FindLatency(
599 ui::INPUT_EVENT_LATENCY_UI_COMPONENT, nullptr));
600 }
601
TEST(EventTest,MouseWheelEventLatencyUIComponentExists)602 TEST(EventTest, MouseWheelEventLatencyUIComponentExists) {
603 const gfx::Point origin(0, 0);
604 MouseWheelEvent mouseWheelev(gfx::Vector2d(), origin, origin,
605 EventTimeForNow(), 0, 0);
606 EXPECT_TRUE(mouseWheelev.latency()->FindLatency(
607 ui::INPUT_EVENT_LATENCY_UI_COMPONENT, nullptr));
608 }
609
TEST(EventTest,MouseWheelEventLinearTickCalculation)610 TEST(EventTest, MouseWheelEventLinearTickCalculation) {
611 const gfx::Point origin;
612 MouseWheelEvent mouse_wheel_ev(
613 gfx::Vector2d(-2 * MouseWheelEvent::kWheelDelta,
614 MouseWheelEvent::kWheelDelta),
615 origin, origin, EventTimeForNow(), 0, 0);
616 EXPECT_EQ(mouse_wheel_ev.tick_120ths().x(), -240);
617 EXPECT_EQ(mouse_wheel_ev.tick_120ths().y(), 120);
618 }
619
TEST(EventTest,OrdinalMotionConversion)620 TEST(EventTest, OrdinalMotionConversion) {
621 const gfx::Point origin(0, 0);
622 const gfx::Vector2dF movement(2.67, 3.14);
623
624 // Model conversion depends on the class having a specific static method.
625 struct OrdinalMotionConversionModel {
626 static void ConvertPointToTarget(const OrdinalMotionConversionModel*,
627 const OrdinalMotionConversionModel*,
628 gfx::Point*) {
629 // Do nothing.
630 }
631 } src, dst;
632
633 MouseEvent mouseev1(ET_MOUSE_PRESSED, origin, origin, EventTimeForNow(), 0,
634 0);
635 MouseEvent::DispatcherApi(&mouseev1).set_movement(movement);
636 EXPECT_EQ(mouseev1.movement(), movement);
637 EXPECT_TRUE(mouseev1.flags() & EF_UNADJUSTED_MOUSE);
638
639 MouseEvent mouseev2(mouseev1, &src, &dst);
640 EXPECT_EQ(mouseev2.movement(), movement);
641 EXPECT_TRUE(mouseev2.flags() & EF_UNADJUSTED_MOUSE);
642
643 // Setting the flags in construction should override the model's.
644 MouseEvent mouseev3(mouseev1, &src, &dst, EventType::ET_MOUSE_MOVED,
645 /* flags */ 0);
646 EXPECT_EQ(mouseev3.movement(), movement);
647 EXPECT_FALSE(mouseev3.flags() & EF_UNADJUSTED_MOUSE);
648 }
649
650 // Checks that Event.Latency.OS.MOUSE_WHEEL histogram is computed properly.
TEST(EventTest,EventLatencyOSMouseWheelHistogram)651 TEST(EventTest, EventLatencyOSMouseWheelHistogram) {
652 #if defined(OS_WIN)
653 base::HistogramTester histogram_tester;
654 MSG event = {nullptr, WM_MOUSEWHEEL, 0, 0};
655 MouseWheelEvent mouseWheelEvent(event);
656 histogram_tester.ExpectTotalCount("Event.Latency.OS.MOUSE_WHEEL", 1);
657 #endif
658 }
659
TEST(EventTest,UpdateForRootTransformation)660 TEST(EventTest, UpdateForRootTransformation) {
661 gfx::Transform identity_transform;
662 const gfx::Point location(10, 10);
663 const gfx::Point root_location(20, 20);
664
665 // A mouse event that is untargeted should reset the root location when
666 // transformed. Though the events start out with different locations and
667 // root_locations, they should be equal afterwards.
668 ui::MouseEvent untargeted(ET_MOUSE_PRESSED, location, root_location,
669 EventTimeForNow(), 0, 0);
670 untargeted.UpdateForRootTransform(identity_transform, identity_transform);
671 EXPECT_EQ(location, untargeted.location());
672 EXPECT_EQ(location, untargeted.root_location());
673
674 ui::test::TestEventTarget target;
675
676 // A mouse event that is targeted should not set the root location to the
677 // local location. They start with different locations and should stay
678 // unequal after a transform is applied.
679 {
680 ui::MouseEvent targeted(ET_MOUSE_PRESSED, location, root_location,
681 EventTimeForNow(), 0, 0);
682 Event::DispatcherApi(&targeted).set_target(&target);
683 targeted.UpdateForRootTransform(identity_transform, identity_transform);
684 EXPECT_EQ(location, targeted.location());
685 EXPECT_EQ(root_location, targeted.root_location());
686 }
687
688 {
689 // Targeted event with 2x and 3x scales.
690 gfx::Transform transform2x;
691 transform2x.Scale(2, 2);
692 gfx::Transform transform3x;
693 transform3x.Scale(3, 3);
694 ui::MouseEvent targeted(ET_MOUSE_PRESSED, location, root_location,
695 EventTimeForNow(), 0, 0);
696 Event::DispatcherApi(&targeted).set_target(&target);
697 targeted.UpdateForRootTransform(transform2x, transform3x);
698 EXPECT_EQ(gfx::Point(30, 30), targeted.location());
699 EXPECT_EQ(gfx::Point(40, 40), targeted.root_location());
700 }
701 }
702
TEST(EventTest,OperatorEqual)703 TEST(EventTest, OperatorEqual) {
704 MouseEvent m1(ET_MOUSE_PRESSED, gfx::Point(1, 2), gfx::Point(2, 3),
705 EventTimeForNow(), EF_LEFT_MOUSE_BUTTON, EF_RIGHT_MOUSE_BUTTON);
706 base::flat_map<std::string, std::vector<uint8_t>> properties;
707 properties["a"] = {1u};
708 m1.SetProperties(properties);
709 EXPECT_EQ(properties, *(m1.properties()));
710 MouseEvent m2(ET_MOUSE_RELEASED, gfx::Point(11, 21), gfx::Point(2, 2),
711 EventTimeForNow(), EF_RIGHT_MOUSE_BUTTON, EF_LEFT_MOUSE_BUTTON);
712 m2 = m1;
713 ASSERT_TRUE(m2.properties());
714 EXPECT_EQ(properties, *(m2.properties()));
715 }
716
717 // Verifies that ToString() generates something and doesn't crash. The specific
718 // format isn't important.
TEST(EventTest,ToStringNotEmpty)719 TEST(EventTest, ToStringNotEmpty) {
720 MouseEvent mouse_event(ET_MOUSE_PRESSED, gfx::Point(1, 2), gfx::Point(2, 3),
721 EventTimeForNow(), EF_LEFT_MOUSE_BUTTON,
722 EF_RIGHT_MOUSE_BUTTON);
723 EXPECT_FALSE(mouse_event.ToString().empty());
724
725 ScrollEvent scroll_event(ET_SCROLL, gfx::Point(1, 2), EventTimeForNow(),
726 EF_NONE, 1.f, 2.f, 3.f, 4.f, 1);
727 EXPECT_FALSE(scroll_event.ToString().empty());
728 }
729
730 #if defined(OS_WIN)
731 namespace {
732
733 const struct AltGraphEventTestCase {
734 KeyboardCode key_code;
735 KeyboardLayout layout;
736 std::vector<KeyboardCode> modifier_key_codes;
737 int expected_flags;
738 } kAltGraphEventTestCases[] = {
739 // US English -> AltRight never behaves as AltGraph.
740 {VKEY_C,
741 KEYBOARD_LAYOUT_ENGLISH_US,
742 {VKEY_RMENU, VKEY_LCONTROL, VKEY_MENU, VKEY_CONTROL},
743 EF_ALT_DOWN | EF_CONTROL_DOWN},
744 {VKEY_E,
745 KEYBOARD_LAYOUT_ENGLISH_US,
746 {VKEY_RMENU, VKEY_LCONTROL, VKEY_MENU, VKEY_CONTROL},
747 EF_ALT_DOWN | EF_CONTROL_DOWN},
748
749 // French -> Always expect AltGraph if VKEY_RMENU is pressed.
750 {VKEY_C,
751 KEYBOARD_LAYOUT_FRENCH,
752 {VKEY_RMENU, VKEY_LCONTROL, VKEY_MENU, VKEY_CONTROL},
753 EF_ALTGR_DOWN},
754 {VKEY_E,
755 KEYBOARD_LAYOUT_FRENCH,
756 {VKEY_RMENU, VKEY_LCONTROL, VKEY_MENU, VKEY_CONTROL},
757 EF_ALTGR_DOWN},
758
759 // French -> Expect Control+Alt is AltGraph on AltGraph-shifted keys.
760 {VKEY_C,
761 KEYBOARD_LAYOUT_FRENCH,
762 {VKEY_LMENU, VKEY_LCONTROL, VKEY_MENU, VKEY_CONTROL},
763 EF_ALT_DOWN | EF_CONTROL_DOWN},
764 {VKEY_E,
765 KEYBOARD_LAYOUT_FRENCH,
766 {VKEY_LMENU, VKEY_LCONTROL, VKEY_MENU, VKEY_CONTROL},
767 EF_ALTGR_DOWN},
768 };
769
770 class AltGraphEventTest
771 : public testing::TestWithParam<std::tuple<UINT, AltGraphEventTestCase>> {
772 public:
AltGraphEventTest()773 AltGraphEventTest()
774 : msg_({nullptr, message_type(),
775 static_cast<WPARAM>(test_case().key_code)}) {
776 // Save the current keyboard layout and state, to restore later.
777 CHECK(GetKeyboardState(original_keyboard_state_));
778 original_keyboard_layout_ = GetKeyboardLayout(0);
779
780 // Configure specified layout, and update keyboard state for specified
781 // modifier keys.
782 CHECK(ActivateKeyboardLayout(GetPlatformKeyboardLayout(test_case().layout),
783 0));
784 BYTE test_keyboard_state[256] = {};
785 for (const auto& key_code : test_case().modifier_key_codes)
786 test_keyboard_state[key_code] = 0x80;
787 CHECK(SetKeyboardState(test_keyboard_state));
788 }
789
~AltGraphEventTest()790 ~AltGraphEventTest() {
791 // Restore the original keyboard layout & key states.
792 CHECK(ActivateKeyboardLayout(original_keyboard_layout_, 0));
793 CHECK(SetKeyboardState(original_keyboard_state_));
794 }
795
796 protected:
message_type() const797 UINT message_type() const { return std::get<0>(GetParam()); }
test_case() const798 const AltGraphEventTestCase& test_case() const {
799 return std::get<1>(GetParam());
800 }
801
802 const MSG msg_;
803 BYTE original_keyboard_state_[256] = {};
804 HKL original_keyboard_layout_ = nullptr;
805 };
806
807 } // namespace
808
TEST_P(AltGraphEventTest,KeyEventAltGraphModifer)809 TEST_P(AltGraphEventTest, KeyEventAltGraphModifer) {
810 KeyEvent event(msg_);
811 if (message_type() == WM_CHAR) {
812 // By definition, if we receive a WM_CHAR message when Control and Alt are
813 // pressed, it indicates AltGraph.
814 EXPECT_EQ(event.flags() & (EF_CONTROL_DOWN | EF_ALT_DOWN | EF_ALTGR_DOWN),
815 EF_ALTGR_DOWN);
816 } else {
817 EXPECT_EQ(event.flags() & (EF_CONTROL_DOWN | EF_ALT_DOWN | EF_ALTGR_DOWN),
818 test_case().expected_flags);
819 }
820 }
821
822 INSTANTIATE_TEST_SUITE_P(
823 WM_KEY,
824 AltGraphEventTest,
825 ::testing::Combine(::testing::Values(WM_KEYDOWN, WM_KEYUP),
826 ::testing::ValuesIn(kAltGraphEventTestCases)));
827 INSTANTIATE_TEST_SUITE_P(
828 WM_CHAR,
829 AltGraphEventTest,
830 ::testing::Combine(::testing::Values(WM_CHAR),
831 ::testing::ValuesIn(kAltGraphEventTestCases)));
832
833 #endif // defined(OS_WIN)
834
835 } // namespace ui
836