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 <stddef.h>
6 #include <stdint.h>
7
8 #include <cstring>
9 #include <memory>
10 #include <set>
11 #include <utility>
12
13 #include "base/stl_util.h"
14 #include "base/test/metrics/histogram_tester.h"
15 #include "base/test/simple_test_tick_clock.h"
16 #include "build/build_config.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "ui/events/devices/x11/device_data_manager_x11.h"
19 #include "ui/events/devices/x11/touch_factory_x11.h"
20 #include "ui/events/event.h"
21 #include "ui/events/event_constants.h"
22 #include "ui/events/event_utils.h"
23 #include "ui/events/keycodes/dom/dom_code.h"
24 #include "ui/events/keycodes/dom/keycode_converter.h"
25 #include "ui/events/test/events_test_utils.h"
26 #include "ui/events/test/events_test_utils_x11.h"
27 #include "ui/events/test/keyboard_layout.h"
28 #include "ui/events/test/scoped_event_test_tick_clock.h"
29 #include "ui/events/types/event_type.h"
30 #include "ui/events/x/events_x_utils.h"
31 #include "ui/events/x/x11_event_translation.h"
32 #include "ui/gfx/geometry/point.h"
33 #include "ui/gfx/x/connection.h"
34 #include "ui/gfx/x/event.h"
35 #include "ui/gfx/x/xproto.h"
36
37 namespace ui {
38
39 namespace {
40
41 // Initializes the passed-in event.
InitButtonEvent(x11::Event * event,bool is_press,const gfx::Point & location,int button,x11::KeyButMask state)42 void InitButtonEvent(x11::Event* event,
43 bool is_press,
44 const gfx::Point& location,
45 int button,
46 x11::KeyButMask state) {
47 *event = x11::Event(x11::ButtonEvent{
48 .opcode = is_press ? x11::ButtonEvent::Press : x11::ButtonEvent::Release,
49 .detail = static_cast<x11::Button>(button),
50 .event_x = location.x(),
51 .event_y = location.y(),
52 .state = state,
53 });
54 }
55
56 #if !defined(OS_CHROMEOS)
57 // Initializes the passed-in x11::Event.
InitKeyEvent(x11::Event * event,bool is_press,int keycode,x11::KeyButMask state)58 void InitKeyEvent(x11::Event* event,
59 bool is_press,
60 int keycode,
61 x11::KeyButMask state) {
62 // We don't bother setting fields that the event code doesn't use, such as
63 // x_root/y_root and window/root/subwindow.
64 *event = x11::Event(x11::KeyEvent{
65 .opcode = is_press ? x11::KeyEvent::Press : x11::KeyEvent::Release,
66 .detail = static_cast<x11::KeyCode>(keycode),
67 .state = state,
68 });
69 }
70 #endif
71
ComputeRotationAngle(float twist)72 float ComputeRotationAngle(float twist) {
73 float rotation_angle = twist;
74 while (rotation_angle < 0)
75 rotation_angle += 180.f;
76 while (rotation_angle >= 180)
77 rotation_angle -= 180.f;
78 return rotation_angle;
79 }
80
FlooredEventLocationString(const x11::Event & xev)81 std::string FlooredEventLocationString(const x11::Event& xev) {
82 return gfx::ToFlooredPoint(gfx::PointF(ui::EventLocationFromXEvent(xev)))
83 .ToString();
84 }
85
86 } // namespace
87
88 class EventsXTest : public testing::Test {
89 public:
90 EventsXTest() = default;
91 ~EventsXTest() override = default;
92
SetUp()93 void SetUp() override {
94 DeviceDataManagerX11::CreateInstance();
95 ui::TouchFactory::GetInstance()->ResetForTest();
96 ResetTimestampRolloverCountersForTesting();
97 }
TearDown()98 void TearDown() override { ResetTimestampRolloverCountersForTesting(); }
99
100 private:
101 DISALLOW_COPY_AND_ASSIGN(EventsXTest);
102 };
103
TEST_F(EventsXTest,ButtonEvents)104 TEST_F(EventsXTest, ButtonEvents) {
105 x11::Event event;
106 gfx::Point location(5, 10);
107 gfx::Vector2d offset;
108
109 InitButtonEvent(&event, true, location, 1, {});
110 EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromXEvent(event));
111 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, ui::EventFlagsFromXEvent(event));
112 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON,
113 ui::GetChangedMouseButtonFlagsFromXEvent(event));
114 EXPECT_EQ(location, ui::EventLocationFromXEvent(event));
115
116 InitButtonEvent(&event, true, location, 2,
117 x11::KeyButMask::Button1 | x11::KeyButMask::Shift);
118 EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromXEvent(event));
119 EXPECT_EQ(
120 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON | ui::EF_SHIFT_DOWN,
121 ui::EventFlagsFromXEvent(event));
122 EXPECT_EQ(ui::EF_MIDDLE_MOUSE_BUTTON,
123 ui::GetChangedMouseButtonFlagsFromXEvent(event));
124 EXPECT_EQ(location, ui::EventLocationFromXEvent(event));
125
126 InitButtonEvent(&event, false, location, 3, {});
127 EXPECT_EQ(ui::ET_MOUSE_RELEASED, ui::EventTypeFromXEvent(event));
128 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, ui::EventFlagsFromXEvent(event));
129 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON,
130 ui::GetChangedMouseButtonFlagsFromXEvent(event));
131 EXPECT_EQ(location, ui::EventLocationFromXEvent(event));
132
133 // Scroll up.
134 InitButtonEvent(&event, true, location, 4, {});
135 EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromXEvent(event));
136 EXPECT_EQ(0, ui::EventFlagsFromXEvent(event));
137 EXPECT_EQ(ui::EF_NONE, ui::GetChangedMouseButtonFlagsFromXEvent(event));
138 EXPECT_EQ(location, ui::EventLocationFromXEvent(event));
139 offset = ui::GetMouseWheelOffsetFromXEvent(event);
140 EXPECT_GT(offset.y(), 0);
141 EXPECT_EQ(0, offset.x());
142
143 // Scroll down.
144 InitButtonEvent(&event, true, location, 5, {});
145 EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromXEvent(event));
146 EXPECT_EQ(0, ui::EventFlagsFromXEvent(event));
147 EXPECT_EQ(ui::EF_NONE, ui::GetChangedMouseButtonFlagsFromXEvent(event));
148 EXPECT_EQ(location, ui::EventLocationFromXEvent(event));
149 offset = ui::GetMouseWheelOffsetFromXEvent(event);
150 EXPECT_LT(offset.y(), 0);
151 EXPECT_EQ(0, offset.x());
152
153 // Scroll left.
154 InitButtonEvent(&event, true, location, 6, {});
155 EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromXEvent(event));
156 EXPECT_EQ(0, ui::EventFlagsFromXEvent(event));
157 EXPECT_EQ(ui::EF_NONE, ui::GetChangedMouseButtonFlagsFromXEvent(event));
158 EXPECT_EQ(location, ui::EventLocationFromXEvent(event));
159 offset = ui::GetMouseWheelOffsetFromXEvent(event);
160 EXPECT_EQ(0, offset.y());
161 EXPECT_GT(offset.x(), 0);
162
163 // Scroll right.
164 InitButtonEvent(&event, true, location, 7, {});
165 EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromXEvent(event));
166 EXPECT_EQ(0, ui::EventFlagsFromXEvent(event));
167 EXPECT_EQ(ui::EF_NONE, ui::GetChangedMouseButtonFlagsFromXEvent(event));
168 EXPECT_EQ(location, ui::EventLocationFromXEvent(event));
169 offset = ui::GetMouseWheelOffsetFromXEvent(event);
170 EXPECT_EQ(0, offset.y());
171 EXPECT_LT(offset.x(), 0);
172
173 // TODO(derat): Test XInput code.
174 }
175
TEST_F(EventsXTest,AvoidExtraEventsOnWheelRelease)176 TEST_F(EventsXTest, AvoidExtraEventsOnWheelRelease) {
177 x11::Event event;
178 gfx::Point location(5, 10);
179
180 InitButtonEvent(&event, true, location, 4, {});
181 EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromXEvent(event));
182
183 // We should return ET_UNKNOWN for the release event instead of returning
184 // ET_MOUSEWHEEL; otherwise we'll scroll twice for each scrollwheel step.
185 InitButtonEvent(&event, false, location, 4, {});
186 EXPECT_EQ(ui::ET_UNKNOWN, ui::EventTypeFromXEvent(event));
187
188 // TODO(derat): Test XInput code.
189 }
190
TEST_F(EventsXTest,EnterLeaveEvent)191 TEST_F(EventsXTest, EnterLeaveEvent) {
192 x11::Event event(x11::CrossingEvent{
193 .opcode = x11::CrossingEvent::EnterNotify,
194 .root_x = 110,
195 .root_y = 120,
196 .event_x = 10,
197 .event_y = 20,
198 });
199
200 // Mouse enter events are converted to mouse move events to be consistent with
201 // the way views handle mouse enter. See comments for EnterNotify case in
202 // ui::EventTypeFromXEvent for more details.
203 EXPECT_EQ(ui::ET_MOUSE_MOVED, ui::EventTypeFromXEvent(event));
204 EXPECT_TRUE(ui::EventFlagsFromXEvent(event) & ui::EF_IS_SYNTHESIZED);
205 EXPECT_EQ("10,20", ui::EventLocationFromXEvent(event).ToString());
206 EXPECT_EQ("110,120", ui::EventSystemLocationFromXEvent(event).ToString());
207
208 event = x11::Event(x11::CrossingEvent{
209 .opcode = x11::CrossingEvent::LeaveNotify,
210 .root_x = 230,
211 .root_y = 240,
212 .event_x = 30,
213 .event_y = 40,
214 });
215 EXPECT_EQ(ui::ET_MOUSE_EXITED, ui::EventTypeFromXEvent(event));
216 EXPECT_EQ("30,40", ui::EventLocationFromXEvent(event).ToString());
217 EXPECT_EQ("230,240", ui::EventSystemLocationFromXEvent(event).ToString());
218 }
219
TEST_F(EventsXTest,ClickCount)220 TEST_F(EventsXTest, ClickCount) {
221 x11::Event event;
222 gfx::Point location(5, 10);
223
224 base::TimeDelta time_stamp = base::TimeTicks::Now().since_origin() -
225 base::TimeDelta::FromMilliseconds(10);
226 for (int i = 1; i <= 3; ++i) {
227 InitButtonEvent(&event, true, location, 1, {});
228 {
229 uint32_t time = time_stamp.InMilliseconds() & UINT32_MAX;
230 event.As<x11::ButtonEvent>()->time = static_cast<x11::Time>(time);
231 auto mouseev = ui::BuildMouseEventFromXEvent(event);
232 EXPECT_EQ(ui::ET_MOUSE_PRESSED, mouseev->type());
233 EXPECT_EQ(i, mouseev->GetClickCount());
234 }
235
236 InitButtonEvent(&event, false, location, 1, {});
237 {
238 uint32_t time = time_stamp.InMilliseconds() & UINT32_MAX;
239 event.As<x11::ButtonEvent>()->time = static_cast<x11::Time>(time);
240 auto mouseev = ui::BuildMouseEventFromXEvent(event);
241 EXPECT_EQ(ui::ET_MOUSE_RELEASED, mouseev->type());
242 EXPECT_EQ(i, mouseev->GetClickCount());
243 }
244 time_stamp += base::TimeDelta::FromMilliseconds(1);
245 }
246 }
247
TEST_F(EventsXTest,TouchEventBasic)248 TEST_F(EventsXTest, TouchEventBasic) {
249 std::vector<int> devices;
250 devices.push_back(0);
251 ui::SetUpTouchDevicesForTest(devices);
252 std::vector<Valuator> valuators;
253
254 // Init touch begin with tracking id 5, touch id 0.
255 valuators.emplace_back(DeviceDataManagerX11::DT_TOUCH_MAJOR, 20);
256 valuators.emplace_back(DeviceDataManagerX11::DT_TOUCH_ORIENTATION, 0.3f);
257 valuators.emplace_back(DeviceDataManagerX11::DT_TOUCH_PRESSURE, 100);
258 ui::ScopedXI2Event scoped_xevent;
259 scoped_xevent.InitTouchEvent(0, x11::Input::DeviceEvent::TouchBegin, 5,
260 gfx::Point(10, 10), valuators);
261 EXPECT_EQ(ui::ET_TOUCH_PRESSED, ui::EventTypeFromXEvent(*scoped_xevent));
262 EXPECT_EQ("10,10", FlooredEventLocationString(*scoped_xevent));
263 EXPECT_EQ(GetTouchIdFromXEvent(*scoped_xevent), 0);
264 PointerDetails pointer_details =
265 GetTouchPointerDetailsFromXEvent(*scoped_xevent);
266 EXPECT_FLOAT_EQ(ComputeRotationAngle(pointer_details.twist), 0.15f);
267 EXPECT_FLOAT_EQ(pointer_details.radius_x, 10.0f);
268 EXPECT_FLOAT_EQ(pointer_details.force, 0.1f);
269
270 // Touch update, with new orientation info.
271 valuators.clear();
272 valuators.emplace_back(DeviceDataManagerX11::DT_TOUCH_ORIENTATION, 0.5f);
273 scoped_xevent.InitTouchEvent(0, x11::Input::DeviceEvent::TouchUpdate, 5,
274 gfx::Point(20, 20), valuators);
275 EXPECT_EQ(ui::ET_TOUCH_MOVED, ui::EventTypeFromXEvent(*scoped_xevent));
276 EXPECT_EQ("20,20", FlooredEventLocationString(*scoped_xevent));
277 EXPECT_EQ(GetTouchIdFromXEvent(*scoped_xevent), 0);
278 pointer_details = GetTouchPointerDetailsFromXEvent(*scoped_xevent);
279 EXPECT_FLOAT_EQ(ComputeRotationAngle(pointer_details.twist), 0.25f);
280 EXPECT_FLOAT_EQ(pointer_details.radius_x, 10.0f);
281 EXPECT_FLOAT_EQ(pointer_details.force, 0.1f);
282
283 // Another touch with tracking id 6, touch id 1.
284 valuators.clear();
285 valuators.emplace_back(DeviceDataManagerX11::DT_TOUCH_MAJOR, 100);
286 valuators.emplace_back(DeviceDataManagerX11::DT_TOUCH_ORIENTATION, 0.9f);
287 valuators.emplace_back(DeviceDataManagerX11::DT_TOUCH_PRESSURE, 500);
288 scoped_xevent.InitTouchEvent(0, x11::Input::DeviceEvent::TouchBegin, 6,
289 gfx::Point(200, 200), valuators);
290 EXPECT_EQ(ui::ET_TOUCH_PRESSED, ui::EventTypeFromXEvent(*scoped_xevent));
291 EXPECT_EQ("200,200", FlooredEventLocationString(*scoped_xevent));
292 EXPECT_EQ(GetTouchIdFromXEvent(*scoped_xevent), 1);
293 pointer_details = GetTouchPointerDetailsFromXEvent(*scoped_xevent);
294 EXPECT_FLOAT_EQ(ComputeRotationAngle(pointer_details.twist), 0.45f);
295 EXPECT_FLOAT_EQ(pointer_details.radius_x, 50.0f);
296 EXPECT_FLOAT_EQ(pointer_details.force, 0.5f);
297
298 // Touch with tracking id 5 should have old radius/angle value and new pressue
299 // value.
300 valuators.clear();
301 valuators.emplace_back(DeviceDataManagerX11::DT_TOUCH_PRESSURE, 50);
302 scoped_xevent.InitTouchEvent(0, x11::Input::DeviceEvent::TouchEnd, 5,
303 gfx::Point(30, 30), valuators);
304 EXPECT_EQ(ui::ET_TOUCH_RELEASED, ui::EventTypeFromXEvent(*scoped_xevent));
305 EXPECT_EQ("30,30", FlooredEventLocationString(*scoped_xevent));
306 EXPECT_EQ(GetTouchIdFromXEvent(*scoped_xevent), 0);
307 pointer_details = GetTouchPointerDetailsFromXEvent(*scoped_xevent);
308 EXPECT_FLOAT_EQ(ComputeRotationAngle(pointer_details.twist), 0.25f);
309 EXPECT_FLOAT_EQ(pointer_details.radius_x, 10.0f);
310 EXPECT_FLOAT_EQ(pointer_details.force, 0.f);
311
312 // Touch with tracking id 6 should have old angle/pressure value and new
313 // radius value.
314 valuators.clear();
315 valuators.emplace_back(DeviceDataManagerX11::DT_TOUCH_MAJOR, 50);
316 scoped_xevent.InitTouchEvent(0, x11::Input::DeviceEvent::TouchEnd, 6,
317 gfx::Point(200, 200), valuators);
318 EXPECT_EQ(ui::ET_TOUCH_RELEASED, ui::EventTypeFromXEvent(*scoped_xevent));
319 EXPECT_EQ("200,200", FlooredEventLocationString(*scoped_xevent));
320 EXPECT_EQ(GetTouchIdFromXEvent(*scoped_xevent), 1);
321 pointer_details = GetTouchPointerDetailsFromXEvent(*scoped_xevent);
322 EXPECT_FLOAT_EQ(ComputeRotationAngle(pointer_details.twist), 0.45f);
323 EXPECT_FLOAT_EQ(pointer_details.radius_x, 25.0f);
324 EXPECT_FLOAT_EQ(pointer_details.force, 0.f);
325 }
326
GetTouchIdForTrackingId(uint32_t tracking_id)327 int GetTouchIdForTrackingId(uint32_t tracking_id) {
328 int slot = 0;
329 bool success =
330 TouchFactory::GetInstance()->QuerySlotForTrackingID(tracking_id, &slot);
331 if (success)
332 return slot;
333 return -1;
334 }
335
TEST_F(EventsXTest,TouchEventNotRemovingFromNativeMapping)336 TEST_F(EventsXTest, TouchEventNotRemovingFromNativeMapping) {
337 const int kTrackingId = 5;
338 const int kDeviceId = 0;
339
340 std::vector<int> devices{kDeviceId};
341 ui::SetUpTouchDevicesForTest(devices);
342 std::vector<Valuator> valuators;
343
344 // Two touch presses with the same tracking id.
345 ui::ScopedXI2Event xpress0;
346 xpress0.InitTouchEvent(kDeviceId, x11::Input::DeviceEvent::TouchBegin,
347 kTrackingId, gfx::Point(10, 10), valuators);
348 auto upress0 = ui::BuildTouchEventFromXEvent(*xpress0);
349 EXPECT_EQ(kDeviceId, GetTouchIdForTrackingId(kTrackingId));
350
351 ui::ScopedXI2Event xpress1;
352 xpress1.InitTouchEvent(kDeviceId, x11::Input::DeviceEvent::TouchBegin,
353 kTrackingId, gfx::Point(20, 20), valuators);
354 auto upress1 = ui::BuildTouchEventFromXEvent(*xpress1);
355 EXPECT_EQ(kDeviceId, GetTouchIdForTrackingId(kTrackingId));
356
357 // The second touch release should clear the mapping from the
358 // tracking id.
359 ui::ScopedXI2Event xrelease1;
360 xrelease1.InitTouchEvent(kDeviceId, x11::Input::DeviceEvent::TouchEnd,
361 kTrackingId, gfx::Point(10, 10), valuators);
362 { auto urelease1 = ui::BuildTouchEventFromXEvent(*xrelease1); }
363 EXPECT_EQ(-1, GetTouchIdForTrackingId(kTrackingId));
364 }
365
366 // Copied events should not remove native touch id mappings, as this causes a
367 // crash (crbug.com/467102). Copied events do not contain a proper
368 // PlatformEvent and should not attempt to access it.
TEST_F(EventsXTest,CopiedTouchEventNotRemovingFromXEventMapping)369 TEST_F(EventsXTest, CopiedTouchEventNotRemovingFromXEventMapping) {
370 std::vector<int> devices;
371 devices.push_back(0);
372 ui::SetUpTouchDevicesForTest(devices);
373 std::vector<Valuator> valuators;
374
375 // Create a release event which has a native touch id mapping.
376 ui::ScopedXI2Event xrelease0;
377 xrelease0.InitTouchEvent(0, x11::Input::DeviceEvent::TouchEnd, 0,
378 gfx::Point(10, 10), valuators);
379 auto urelease0 = ui::BuildTouchEventFromXEvent(*xrelease0);
380 {
381 // When the copy is destructed it should not attempt to remove the mapping.
382 // Exiting this scope should not cause a crash.
383 TouchEvent copy = *urelease0;
384 }
385 }
386
387 // Verifies that the type of events from a disabled keyboard is ET_UNKNOWN, but
388 // that an exception list of keys can still be processed.
TEST_F(EventsXTest,DisableKeyboard)389 TEST_F(EventsXTest, DisableKeyboard) {
390 DeviceDataManagerX11* device_data_manager =
391 static_cast<DeviceDataManagerX11*>(DeviceDataManager::GetInstance());
392 int blocked_device_id = 1;
393 auto blocked_device = static_cast<x11::Input::DeviceId>(blocked_device_id);
394 int other_device_id = 2;
395 int master_device_id = 3;
396 device_data_manager->DisableDevice(blocked_device);
397
398 std::unique_ptr<std::set<KeyboardCode>> excepted_keys(
399 new std::set<KeyboardCode>);
400 excepted_keys->insert(VKEY_B);
401 device_data_manager->SetDisabledKeyboardAllowedKeys(std::move(excepted_keys));
402
403 ScopedXI2Event xev;
404 // A is not allowed on the blocked keyboard, and should return ET_UNKNOWN.
405 xev.InitGenericKeyEvent(master_device_id, blocked_device_id,
406 ui::ET_KEY_PRESSED, ui::VKEY_A, 0);
407 EXPECT_EQ(ui::ET_UNKNOWN, ui::EventTypeFromXEvent(*xev));
408
409 // The B key is allowed as an exception, and should return KEY_PRESSED.
410 xev.InitGenericKeyEvent(master_device_id, blocked_device_id,
411 ui::ET_KEY_PRESSED, ui::VKEY_B, 0);
412 EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromXEvent(*xev));
413
414 // Both A and B are allowed on an unblocked keyboard device.
415 xev.InitGenericKeyEvent(master_device_id, other_device_id, ui::ET_KEY_PRESSED,
416 ui::VKEY_A, 0);
417 EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromXEvent(*xev));
418 xev.InitGenericKeyEvent(master_device_id, other_device_id, ui::ET_KEY_PRESSED,
419 ui::VKEY_B, 0);
420 EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromXEvent(*xev));
421
422 device_data_manager->EnableDevice(blocked_device);
423 device_data_manager->SetDisabledKeyboardAllowedKeys(nullptr);
424
425 // A key returns KEY_PRESSED as per usual now that keyboard was re-enabled.
426 xev.InitGenericKeyEvent(master_device_id, blocked_device_id,
427 ui::ET_KEY_PRESSED, ui::VKEY_A, 0);
428 EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromXEvent(*xev));
429 }
430
431 // Verifies that the type of events from a disabled mouse is ET_UNKNOWN.
TEST_F(EventsXTest,DisableMouse)432 TEST_F(EventsXTest, DisableMouse) {
433 DeviceDataManagerX11* device_data_manager =
434 static_cast<DeviceDataManagerX11*>(DeviceDataManager::GetInstance());
435 int blocked_device_id = 1;
436 auto blocked_device = static_cast<x11::Input::DeviceId>(blocked_device_id);
437 int other_device_id = 2;
438 std::vector<int> device_list;
439 device_list.push_back(blocked_device_id);
440 device_list.push_back(other_device_id);
441 TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
442
443 device_data_manager->DisableDevice(blocked_device);
444
445 ScopedXI2Event xev;
446 xev.InitGenericButtonEvent(blocked_device_id, ET_MOUSE_PRESSED, gfx::Point(),
447 EF_LEFT_MOUSE_BUTTON);
448 EXPECT_EQ(ui::ET_UNKNOWN, ui::EventTypeFromXEvent(*xev));
449
450 xev.InitGenericButtonEvent(other_device_id, ET_MOUSE_PRESSED, gfx::Point(),
451 EF_LEFT_MOUSE_BUTTON);
452 EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromXEvent(*xev));
453
454 device_data_manager->EnableDevice(blocked_device);
455
456 xev.InitGenericButtonEvent(blocked_device_id, ET_MOUSE_PRESSED, gfx::Point(),
457 EF_LEFT_MOUSE_BUTTON);
458 EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromXEvent(*xev));
459 }
460
461 #if !defined(OS_CHROMEOS)
TEST_F(EventsXTest,ImeFabricatedKeyEvents)462 TEST_F(EventsXTest, ImeFabricatedKeyEvents) {
463 x11::KeyButMask state_to_be_fabricated[] = {
464 {},
465 x11::KeyButMask::Shift,
466 x11::KeyButMask::Lock,
467 x11::KeyButMask::Shift | x11::KeyButMask::Lock,
468 };
469 for (auto state : state_to_be_fabricated) {
470 for (int is_char = 0; is_char < 2; ++is_char) {
471 x11::Event x_event;
472 InitKeyEvent(&x_event, true, 0, state);
473 auto key_event = ui::BuildKeyEventFromXEvent(x_event);
474 if (is_char) {
475 KeyEventTestApi test_event(key_event.get());
476 test_event.set_is_char(true);
477 }
478 EXPECT_TRUE(key_event->flags() & ui::EF_IME_FABRICATED_KEY);
479 }
480 }
481
482 x11::KeyButMask state_to_be_not_fabricated[] = {
483 x11::KeyButMask::Control,
484 x11::KeyButMask::Mod1,
485 x11::KeyButMask::Mod2,
486 x11::KeyButMask::Shift | x11::KeyButMask::Control,
487 };
488 for (auto state : state_to_be_not_fabricated) {
489 for (int is_char = 0; is_char < 2; ++is_char) {
490 x11::Event x_event;
491 InitKeyEvent(&x_event, true, 0, state);
492 auto key_event = ui::BuildKeyEventFromXEvent(x_event);
493 if (is_char) {
494 KeyEventTestApi test_event(key_event.get());
495 test_event.set_is_char(true);
496 }
497 EXPECT_FALSE(key_event->flags() & ui::EF_IME_FABRICATED_KEY);
498 }
499 }
500 }
501 #endif
502
TEST_F(EventsXTest,IgnoresMotionEventForMouseWheelScroll)503 TEST_F(EventsXTest, IgnoresMotionEventForMouseWheelScroll) {
504 int device_id = 1;
505 std::vector<int> devices;
506 devices.push_back(device_id);
507 ui::SetUpPointerDevicesForTest(devices);
508
509 ScopedXI2Event xev;
510 xev.InitScrollEvent(device_id, 1, 2, 3, 4, 1);
511 // We shouldn't produce a mouse move event on a mouse wheel
512 // scroll. These events are only produced for some mice.
513 EXPECT_EQ(ui::ET_UNKNOWN, ui::EventTypeFromXEvent(*xev));
514 }
515
516 namespace {
517
518 // Returns a fake TimeTicks based on the given millisecond offset.
TimeTicksFromMillis(int64_t millis)519 base::TimeTicks TimeTicksFromMillis(int64_t millis) {
520 return base::TimeTicks() + base::TimeDelta::FromMilliseconds(millis);
521 }
522
523 } // namespace
524
TEST_F(EventsXTest,TimestampRolloverAndAdjustWhenDecreasing)525 TEST_F(EventsXTest, TimestampRolloverAndAdjustWhenDecreasing) {
526 x11::Event event;
527 InitButtonEvent(&event, true, gfx::Point(5, 10), 1, {});
528
529 test::ScopedEventTestTickClock clock;
530 clock.SetNowTicks(TimeTicksFromMillis(0x100000001));
531 ResetTimestampRolloverCountersForTesting();
532
533 event.As<x11::ButtonEvent>()->time = static_cast<x11::Time>(0xFFFFFFFF);
534 EXPECT_EQ(TimeTicksFromMillis(0xFFFFFFFF), ui::EventTimeFromXEvent(event));
535
536 clock.SetNowTicks(TimeTicksFromMillis(0x100000007));
537 ResetTimestampRolloverCountersForTesting();
538
539 event.As<x11::ButtonEvent>()->time = static_cast<x11::Time>(3);
540 EXPECT_EQ(TimeTicksFromMillis(0x100000000 + 3),
541 ui::EventTimeFromXEvent(event));
542 }
543
TEST_F(EventsXTest,NoTimestampRolloverWhenMonotonicIncreasing)544 TEST_F(EventsXTest, NoTimestampRolloverWhenMonotonicIncreasing) {
545 x11::Event event;
546 InitButtonEvent(&event, true, gfx::Point(5, 10), 1, {});
547
548 test::ScopedEventTestTickClock clock;
549 clock.SetNowTicks(TimeTicksFromMillis(10));
550 ResetTimestampRolloverCountersForTesting();
551
552 event.As<x11::ButtonEvent>()->time = static_cast<x11::Time>(6);
553 EXPECT_EQ(TimeTicksFromMillis(6), ui::EventTimeFromXEvent(event));
554 event.As<x11::ButtonEvent>()->time = static_cast<x11::Time>(7);
555 EXPECT_EQ(TimeTicksFromMillis(7), ui::EventTimeFromXEvent(event));
556
557 clock.SetNowTicks(TimeTicksFromMillis(0x100000005));
558 ResetTimestampRolloverCountersForTesting();
559
560 event.As<x11::ButtonEvent>()->time = static_cast<x11::Time>(0xFFFFFFFF);
561 EXPECT_EQ(TimeTicksFromMillis(0xFFFFFFFF), ui::EventTimeFromXEvent(event));
562 }
563
564 // Moved from event_unittest.cc
565
TEST_F(EventsXTest,NativeEvent)566 TEST_F(EventsXTest, NativeEvent) {
567 ScopedXI2Event event;
568 event.InitKeyEvent(ET_KEY_RELEASED, VKEY_A, EF_NONE);
569 auto keyev = ui::BuildKeyEventFromXEvent(*event);
570 EXPECT_FALSE(keyev->HasNativeEvent());
571 }
572
TEST_F(EventsXTest,GetCharacter)573 TEST_F(EventsXTest, GetCharacter) {
574 ui::ScopedKeyboardLayout keyboard_layout(ui::KEYBOARD_LAYOUT_ENGLISH_US);
575
576 // For X11, test the functions with native_event() as well. crbug.com/107837
577 ScopedXI2Event event;
578 event.InitKeyEvent(ET_KEY_PRESSED, VKEY_RETURN, EF_CONTROL_DOWN);
579 auto keyev3 = ui::BuildKeyEventFromXEvent(*event);
580 EXPECT_EQ(10, keyev3->GetCharacter());
581
582 event.InitKeyEvent(ET_KEY_PRESSED, VKEY_RETURN, EF_NONE);
583 auto keyev4 = ui::BuildKeyEventFromXEvent(*event);
584 EXPECT_EQ(13, keyev4->GetCharacter());
585 }
586
TEST_F(EventsXTest,NormalizeKeyEventFlags)587 TEST_F(EventsXTest, NormalizeKeyEventFlags) {
588 // Normalize flags when KeyEvent is created from XEvent.
589 ScopedXI2Event event;
590 {
591 event.InitKeyEvent(ET_KEY_PRESSED, VKEY_SHIFT, EF_SHIFT_DOWN);
592 auto keyev = ui::BuildKeyEventFromXEvent(*event);
593 EXPECT_EQ(EF_SHIFT_DOWN, keyev->flags());
594 }
595 {
596 event.InitKeyEvent(ET_KEY_RELEASED, VKEY_SHIFT, EF_SHIFT_DOWN);
597 auto keyev = ui::BuildKeyEventFromXEvent(*event);
598 EXPECT_EQ(EF_NONE, keyev->flags());
599 }
600 {
601 event.InitKeyEvent(ET_KEY_PRESSED, VKEY_CONTROL, EF_CONTROL_DOWN);
602 auto keyev = ui::BuildKeyEventFromXEvent(*event);
603 EXPECT_EQ(EF_CONTROL_DOWN, keyev->flags());
604 }
605 {
606 event.InitKeyEvent(ET_KEY_RELEASED, VKEY_CONTROL, EF_CONTROL_DOWN);
607 auto keyev = ui::BuildKeyEventFromXEvent(*event);
608 EXPECT_EQ(EF_NONE, keyev->flags());
609 }
610 {
611 event.InitKeyEvent(ET_KEY_PRESSED, VKEY_MENU, EF_ALT_DOWN);
612 auto keyev = ui::BuildKeyEventFromXEvent(*event);
613 EXPECT_EQ(EF_ALT_DOWN, keyev->flags());
614 }
615 {
616 event.InitKeyEvent(ET_KEY_RELEASED, VKEY_MENU, EF_ALT_DOWN);
617 auto keyev = ui::BuildKeyEventFromXEvent(*event);
618 EXPECT_EQ(EF_NONE, keyev->flags());
619 }
620 }
621
TEST_F(EventsXTest,KeyEventCode)622 TEST_F(EventsXTest, KeyEventCode) {
623 const DomCode kDomCodeForSpace = DomCode::SPACE;
624 const char kCodeForSpace[] = "Space";
625 ASSERT_EQ(kDomCodeForSpace,
626 ui::KeycodeConverter::CodeStringToDomCode(kCodeForSpace));
627 const uint16_t kNativeCodeSpace =
628 ui::KeycodeConverter::DomCodeToNativeKeycode(kDomCodeForSpace);
629 ASSERT_NE(ui::KeycodeConverter::InvalidNativeKeycode(), kNativeCodeSpace);
630 ASSERT_EQ(kNativeCodeSpace,
631 ui::KeycodeConverter::DomCodeToNativeKeycode(kDomCodeForSpace));
632
633 // KeyEvent converts from the native keycode (XKB) to the code.
634 ScopedXI2Event xevent;
635 xevent.InitKeyEvent(ET_KEY_PRESSED, VKEY_SPACE, kNativeCodeSpace);
636 auto keyev = ui::BuildKeyEventFromXEvent(*xevent);
637 EXPECT_EQ(kCodeForSpace, keyev->GetCodeString());
638 }
639
640 namespace {
641
SetKeyEventTimestamp(x11::Event * event,int64_t time64)642 void SetKeyEventTimestamp(x11::Event* event, int64_t time64) {
643 uint32_t time = time64 & UINT32_MAX;
644 event->As<x11::KeyEvent>()->time = static_cast<x11::Time>(time);
645 }
646
AdvanceKeyEventTimestamp(x11::Event * event)647 void AdvanceKeyEventTimestamp(x11::Event* event) {
648 auto time = static_cast<uint32_t>(event->As<x11::KeyEvent>()->time) + 1;
649 event->As<x11::KeyEvent>()->time = static_cast<x11::Time>(time);
650 }
651
652 } // namespace
653
TEST_F(EventsXTest,AutoRepeat)654 TEST_F(EventsXTest, AutoRepeat) {
655 const uint16_t kNativeCodeA =
656 ui::KeycodeConverter::DomCodeToNativeKeycode(DomCode::US_A);
657 const uint16_t kNativeCodeB =
658 ui::KeycodeConverter::DomCodeToNativeKeycode(DomCode::US_B);
659
660 ScopedXI2Event native_event_a_pressed;
661 native_event_a_pressed.InitKeyEvent(ET_KEY_PRESSED, VKEY_A, kNativeCodeA);
662 ScopedXI2Event native_event_a_pressed_1500;
663 native_event_a_pressed_1500.InitKeyEvent(ET_KEY_PRESSED, VKEY_A,
664 kNativeCodeA);
665 ScopedXI2Event native_event_a_pressed_3000;
666 native_event_a_pressed_3000.InitKeyEvent(ET_KEY_PRESSED, VKEY_A,
667 kNativeCodeA);
668
669 ScopedXI2Event native_event_a_released;
670 native_event_a_released.InitKeyEvent(ET_KEY_RELEASED, VKEY_A, kNativeCodeA);
671 ScopedXI2Event native_event_b_pressed;
672 native_event_b_pressed.InitKeyEvent(ET_KEY_PRESSED, VKEY_B, kNativeCodeB);
673 ScopedXI2Event native_event_a_pressed_nonstandard_state;
674 native_event_a_pressed_nonstandard_state.InitKeyEvent(ET_KEY_PRESSED, VKEY_A,
675 kNativeCodeA);
676 // IBUS-GTK uses the mask (1 << 25) to detect reposted event.
677 {
678 x11::Event& event = *native_event_a_pressed_nonstandard_state;
679 int mask = static_cast<int>(event.As<x11::KeyEvent>()->state) | 1 << 25;
680 event.As<x11::KeyEvent>()->state = static_cast<x11::KeyButMask>(mask);
681 }
682
683 int64_t ticks_base =
684 (base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds() - 5000;
685 SetKeyEventTimestamp(native_event_a_pressed, ticks_base);
686 SetKeyEventTimestamp(native_event_a_pressed_1500, ticks_base + 1500);
687 SetKeyEventTimestamp(native_event_a_pressed_3000, ticks_base + 3000);
688
689 {
690 auto key_a1 = BuildKeyEventFromXEvent(*native_event_a_pressed);
691 EXPECT_FALSE(key_a1->is_repeat());
692
693 auto key_a1_released = BuildKeyEventFromXEvent(*native_event_a_released);
694 EXPECT_FALSE(key_a1_released->is_repeat());
695
696 auto key_a2 = BuildKeyEventFromXEvent(*native_event_a_pressed);
697 EXPECT_FALSE(key_a2->is_repeat());
698
699 AdvanceKeyEventTimestamp(native_event_a_pressed);
700 auto key_a2_repeated = BuildKeyEventFromXEvent(*native_event_a_pressed);
701 EXPECT_TRUE(key_a2_repeated->is_repeat());
702
703 auto key_a2_released = BuildKeyEventFromXEvent(*native_event_a_released);
704 EXPECT_FALSE(key_a2_released->is_repeat());
705 }
706
707 // Interleaved with different key press.
708 {
709 auto key_a3 = BuildKeyEventFromXEvent(*native_event_a_pressed);
710 EXPECT_FALSE(key_a3->is_repeat());
711
712 auto key_b = BuildKeyEventFromXEvent(*native_event_b_pressed);
713 EXPECT_FALSE(key_b->is_repeat());
714
715 AdvanceKeyEventTimestamp(native_event_a_pressed);
716 auto key_a3_again = BuildKeyEventFromXEvent(*native_event_a_pressed);
717 EXPECT_FALSE(key_a3_again->is_repeat());
718
719 AdvanceKeyEventTimestamp(native_event_a_pressed);
720 auto key_a3_repeated = BuildKeyEventFromXEvent(*native_event_a_pressed);
721 EXPECT_TRUE(key_a3_repeated->is_repeat());
722
723 AdvanceKeyEventTimestamp(native_event_a_pressed);
724 auto key_a3_repeated2 = BuildKeyEventFromXEvent(*native_event_a_pressed);
725 EXPECT_TRUE(key_a3_repeated2->is_repeat());
726
727 auto key_a3_released = BuildKeyEventFromXEvent(*native_event_a_released);
728 EXPECT_FALSE(key_a3_released->is_repeat());
729 }
730
731 // Hold the key longer than max auto repeat timeout.
732 {
733 auto key_a4_0 = BuildKeyEventFromXEvent(*native_event_a_pressed);
734 EXPECT_FALSE(key_a4_0->is_repeat());
735
736 auto key_a4_1500 = BuildKeyEventFromXEvent(*native_event_a_pressed_1500);
737 EXPECT_TRUE(key_a4_1500->is_repeat());
738
739 auto key_a4_3000 = BuildKeyEventFromXEvent(*native_event_a_pressed_3000);
740 EXPECT_TRUE(key_a4_3000->is_repeat());
741
742 auto key_a4_released = BuildKeyEventFromXEvent(*native_event_a_released);
743 EXPECT_FALSE(key_a4_released->is_repeat());
744 }
745
746 {
747 auto key_a4_pressed = BuildKeyEventFromXEvent(*native_event_a_pressed);
748 EXPECT_FALSE(key_a4_pressed->is_repeat());
749
750 auto key_a4_pressed_nonstandard_state =
751 BuildKeyEventFromXEvent(*native_event_a_pressed_nonstandard_state);
752 EXPECT_FALSE(key_a4_pressed_nonstandard_state->is_repeat());
753 }
754
755 {
756 auto key_a1 = BuildKeyEventFromXEvent(*native_event_a_pressed);
757 EXPECT_FALSE(key_a1->is_repeat());
758
759 auto key_a1_with_same_event =
760 BuildKeyEventFromXEvent(*native_event_a_pressed);
761 EXPECT_FALSE(key_a1_with_same_event->is_repeat());
762 }
763 }
764
765 // Checks that Event.Latency.OS.TOUCH_PRESSED, TOUCH_MOVED,
766 // and TOUCH_RELEASED histograms are computed properly.
TEST_F(EventsXTest,EventLatencyOSTouchHistograms)767 TEST_F(EventsXTest, EventLatencyOSTouchHistograms) {
768 base::HistogramTester histogram_tester;
769 ScopedXI2Event scoped_xevent;
770
771 // SetUp for test
772 DeviceDataManagerX11::CreateInstance();
773 std::vector<int> devices;
774 devices.push_back(0);
775 ui::SetUpTouchDevicesForTest(devices);
776
777 // Init touch begin, update, and end events with tracking id 5, touch id 0.
778 scoped_xevent.InitTouchEvent(0, x11::Input::DeviceEvent::TouchBegin, 5,
779 gfx::Point(10, 10), {});
780 auto touch_begin = ui::BuildTouchEventFromXEvent(*scoped_xevent);
781 histogram_tester.ExpectTotalCount("Event.Latency.OS.TOUCH_PRESSED", 1);
782 scoped_xevent.InitTouchEvent(0, x11::Input::DeviceEvent::TouchUpdate, 5,
783 gfx::Point(20, 20), {});
784 auto touch_update = ui::BuildTouchEventFromXEvent(*scoped_xevent);
785 histogram_tester.ExpectTotalCount("Event.Latency.OS.TOUCH_MOVED", 1);
786 scoped_xevent.InitTouchEvent(0, x11::Input::DeviceEvent::TouchEnd, 5,
787 gfx::Point(30, 30), {});
788 auto touch_end = ui::BuildTouchEventFromXEvent(*scoped_xevent);
789 histogram_tester.ExpectTotalCount("Event.Latency.OS.TOUCH_RELEASED", 1);
790 }
791
TEST_F(EventsXTest,EventLatencyOSMouseWheelHistogram)792 TEST_F(EventsXTest, EventLatencyOSMouseWheelHistogram) {
793 base::HistogramTester histogram_tester;
794 DeviceDataManagerX11::CreateInstance();
795
796 // Initializes a native event and uses it to generate a MouseWheel event.
797 x11::Event native_event(x11::ButtonEvent{
798 .opcode = x11::ButtonEvent::Press,
799 // A valid wheel button number between min and max.
800 .detail = static_cast<x11::Button>(4),
801 });
802 auto mouse_ev = ui::BuildMouseWheelEventFromXEvent(native_event);
803 histogram_tester.ExpectTotalCount("Event.Latency.OS.MOUSE_WHEEL", 1);
804 }
805
806 } // namespace ui
807