Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / chromeos / events / event_rewriter_unittest.cc
blob3e5b5a9703ba9df85a798c89ef1c285593863dd3
1 // Copyright 2014 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.
5 #include "chrome/browser/chromeos/events/event_rewriter.h"
7 #include <vector>
9 #include "ash/shell.h"
10 #include "ash/sticky_keys/sticky_keys_controller.h"
11 #include "ash/sticky_keys/sticky_keys_overlay.h"
12 #include "ash/test/ash_test_base.h"
13 #include "ash/wm/window_state.h"
14 #include "base/basictypes.h"
15 #include "base/command_line.h"
16 #include "base/prefs/pref_member.h"
17 #include "base/strings/stringprintf.h"
18 #include "chrome/browser/chromeos/input_method/input_method_configuration.h"
19 #include "chrome/browser/chromeos/input_method/mock_input_method_manager.h"
20 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
21 #include "chrome/browser/chromeos/preferences.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/test/base/testing_pref_service_syncable.h"
24 #include "chromeos/chromeos_switches.h"
25 #include "components/user_manager/fake_user_manager.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "ui/aura/window.h"
28 #include "ui/aura/window_tree_host.h"
29 #include "ui/base/ime/chromeos/fake_ime_keyboard.h"
30 #include "ui/events/event.h"
31 #include "ui/events/event_rewriter.h"
32 #include "ui/events/event_utils.h"
33 #include "ui/events/keycodes/dom/dom_code.h"
34 #include "ui/events/keycodes/dom/dom_key.h"
35 #include "ui/events/keycodes/dom/keycode_converter.h"
36 #include "ui/events/test/events_test_utils.h"
37 #include "ui/events/test/test_event_processor.h"
39 #if defined(USE_X11)
40 #include <X11/keysym.h>
42 #include "ui/events/devices/x11/touch_factory_x11.h"
43 #include "ui/events/event_utils.h"
44 #include "ui/events/test/events_test_utils_x11.h"
45 #include "ui/gfx/x/x11_types.h"
46 #endif
48 namespace {
50 // The device id of the test touchpad device.
51 #if defined(USE_X11)
52 const int kTouchPadDeviceId = 1;
53 #endif
54 const int kKeyboardDeviceId = 2;
56 std::string GetExpectedResultAsString(ui::EventType ui_type,
57 ui::KeyboardCode ui_keycode,
58 ui::DomCode code,
59 int ui_flags, // ui::EventFlags
60 ui::DomKey key,
61 base::char16 character) {
62 return base::StringPrintf(
63 "type=%d code=0x%06X flags=0x%X vk=0x%02X key=0x%03X c=0x%02X", ui_type,
64 static_cast<unsigned int>(code), ui_flags & ~ui::EF_IS_REPEAT, ui_keycode,
65 static_cast<unsigned int>(key), character);
68 std::string GetKeyEventAsString(const ui::KeyEvent& keyevent) {
69 return GetExpectedResultAsString(
70 keyevent.type(), keyevent.key_code(), keyevent.code(), keyevent.flags(),
71 keyevent.GetDomKey(), keyevent.GetCharacter());
74 std::string GetRewrittenEventAsString(chromeos::EventRewriter* rewriter,
75 ui::EventType ui_type,
76 ui::KeyboardCode ui_keycode,
77 ui::DomCode code,
78 int ui_flags, // ui::EventFlags
79 ui::DomKey key,
80 base::char16 character) {
81 const ui::KeyEvent event(ui_type, ui_keycode, code, ui_flags, key, character,
82 ui::EventTimeForNow());
83 scoped_ptr<ui::Event> new_event;
84 rewriter->RewriteEvent(event, &new_event);
85 if (new_event)
86 return GetKeyEventAsString(
87 static_cast<const ui::KeyEvent&>(*new_event.get()));
88 return GetKeyEventAsString(event);
91 // Table entry for simple single key event rewriting tests.
92 struct KeyTestCase {
93 ui::EventType type;
94 struct Event {
95 ui::KeyboardCode key_code;
96 ui::DomCode code;
97 int flags; // ui::EventFlags
98 ui::DomKey key;
99 base::char16 character;
100 } input, expected;
103 std::string GetTestCaseAsString(ui::EventType ui_type,
104 const KeyTestCase::Event& test) {
105 return GetExpectedResultAsString(ui_type, test.key_code, test.code,
106 test.flags, test.key, test.character);
109 // Tests a single stateless key rewrite operation.
110 void CheckKeyTestCase(chromeos::EventRewriter* rewriter,
111 const KeyTestCase& test) {
112 SCOPED_TRACE("\nSource: " + GetTestCaseAsString(test.type, test.input));
113 std::string expected = GetTestCaseAsString(test.type, test.expected);
114 EXPECT_EQ(expected,
115 GetRewrittenEventAsString(rewriter, test.type, test.input.key_code,
116 test.input.code, test.input.flags,
117 test.input.key, test.input.character));
120 } // namespace
122 namespace chromeos {
124 class EventRewriterTest : public ash::test::AshTestBase {
125 public:
126 EventRewriterTest()
127 : fake_user_manager_(new user_manager::FakeUserManager),
128 user_manager_enabler_(fake_user_manager_),
129 input_method_manager_mock_(NULL) {}
130 ~EventRewriterTest() override {}
132 void SetUp() override {
133 input_method_manager_mock_ =
134 new chromeos::input_method::MockInputMethodManager;
135 chromeos::input_method::InitializeForTesting(
136 input_method_manager_mock_); // pass ownership
138 AshTestBase::SetUp();
141 void TearDown() override {
142 AshTestBase::TearDown();
143 // Shutdown() deletes the IME mock object.
144 chromeos::input_method::Shutdown();
147 protected:
148 void TestRewriteNumPadKeys();
149 void TestRewriteNumPadKeysOnAppleKeyboard();
151 const ui::MouseEvent* RewriteMouseButtonEvent(
152 chromeos::EventRewriter* rewriter,
153 const ui::MouseEvent& event,
154 scoped_ptr<ui::Event>* new_event) {
155 rewriter->RewriteMouseButtonEventForTesting(event, new_event);
156 return *new_event ? static_cast<const ui::MouseEvent*>(new_event->get())
157 : &event;
160 user_manager::FakeUserManager* fake_user_manager_; // Not owned.
161 chromeos::ScopedUserManagerEnabler user_manager_enabler_;
162 chromeos::input_method::MockInputMethodManager* input_method_manager_mock_;
165 TEST_F(EventRewriterTest, TestRewriteCommandToControl) {
166 // First, test with a PC keyboard.
167 TestingPrefServiceSyncable prefs;
168 EventRewriter rewriter(NULL);
169 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
170 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
171 rewriter.set_pref_service_for_testing(&prefs);
173 KeyTestCase pc_keyboard_tests[] = {
174 // VKEY_A, Alt modifier.
175 {ui::ET_KEY_PRESSED,
176 {ui::VKEY_A,
177 ui::DomCode::KEY_A,
178 ui::EF_ALT_DOWN,
179 ui::DomKey::UNIDENTIFIED,
181 {ui::VKEY_A,
182 ui::DomCode::KEY_A,
183 ui::EF_ALT_DOWN,
184 ui::DomKey::UNIDENTIFIED,
185 0}},
187 // VKEY_A, Win modifier.
188 {ui::ET_KEY_PRESSED,
189 {ui::VKEY_A,
190 ui::DomCode::KEY_A,
191 ui::EF_COMMAND_DOWN,
192 ui::DomKey::UNIDENTIFIED,
194 {ui::VKEY_A,
195 ui::DomCode::KEY_A,
196 ui::EF_COMMAND_DOWN,
197 ui::DomKey::UNIDENTIFIED,
198 0}},
200 // VKEY_A, Alt+Win modifier.
201 {ui::ET_KEY_PRESSED,
202 {ui::VKEY_A,
203 ui::DomCode::KEY_A,
204 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
205 ui::DomKey::UNIDENTIFIED,
207 {ui::VKEY_A,
208 ui::DomCode::KEY_A,
209 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
210 ui::DomKey::UNIDENTIFIED,
211 0}},
213 // VKEY_LWIN (left Windows key), Alt modifier.
214 {ui::ET_KEY_PRESSED,
215 {ui::VKEY_LWIN,
216 ui::DomCode::OS_LEFT,
217 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
218 ui::DomKey::OS,
220 {ui::VKEY_LWIN,
221 ui::DomCode::OS_LEFT,
222 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
223 ui::DomKey::OS,
224 0}},
226 // VKEY_RWIN (right Windows key), Alt modifier.
227 {ui::ET_KEY_PRESSED,
228 {ui::VKEY_RWIN,
229 ui::DomCode::OS_RIGHT,
230 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
231 ui::DomKey::OS,
233 {ui::VKEY_RWIN,
234 ui::DomCode::OS_RIGHT,
235 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
236 ui::DomKey::OS,
237 0}},
240 for (const auto& test : pc_keyboard_tests) {
241 CheckKeyTestCase(&rewriter, test);
244 // An Apple keyboard reusing the ID, zero.
245 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "Apple Keyboard");
246 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
248 KeyTestCase apple_keyboard_tests[] = {
249 // VKEY_A, Alt modifier.
250 {ui::ET_KEY_PRESSED,
251 {ui::VKEY_A,
252 ui::DomCode::KEY_A,
253 ui::EF_ALT_DOWN,
254 ui::DomKey::UNIDENTIFIED,
256 {ui::VKEY_A,
257 ui::DomCode::KEY_A,
258 ui::EF_ALT_DOWN,
259 ui::DomKey::UNIDENTIFIED,
260 0}},
262 // VKEY_A, Win modifier.
263 {ui::ET_KEY_PRESSED,
264 {ui::VKEY_A,
265 ui::DomCode::KEY_A,
266 ui::EF_COMMAND_DOWN,
267 ui::DomKey::UNIDENTIFIED,
269 {ui::VKEY_A,
270 ui::DomCode::KEY_A,
271 ui::EF_CONTROL_DOWN,
272 ui::DomKey::CHARACTER,
273 0x01}},
275 // VKEY_A, Alt+Win modifier.
276 {ui::ET_KEY_PRESSED,
277 {ui::VKEY_A,
278 ui::DomCode::KEY_A,
279 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
280 ui::DomKey::UNIDENTIFIED,
282 {ui::VKEY_A,
283 ui::DomCode::KEY_A,
284 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
285 ui::DomKey::CHARACTER,
286 0x01}},
288 // VKEY_LWIN (left Windows key), Alt modifier.
289 {ui::ET_KEY_PRESSED,
290 {ui::VKEY_LWIN,
291 ui::DomCode::OS_LEFT,
292 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
293 ui::DomKey::OS,
295 {ui::VKEY_CONTROL,
296 ui::DomCode::CONTROL_LEFT,
297 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
298 ui::DomKey::CONTROL,
299 0}},
301 // VKEY_RWIN (right Windows key), Alt modifier.
302 {ui::ET_KEY_PRESSED,
303 {ui::VKEY_RWIN,
304 ui::DomCode::OS_RIGHT,
305 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
306 ui::DomKey::OS,
308 {ui::VKEY_CONTROL,
309 ui::DomCode::CONTROL_RIGHT,
310 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
311 ui::DomKey::CONTROL,
312 0}},
315 for (const auto& test : apple_keyboard_tests) {
316 CheckKeyTestCase(&rewriter, test);
320 // For crbug.com/133896.
321 TEST_F(EventRewriterTest, TestRewriteCommandToControlWithControlRemapped) {
322 // Remap Control to Alt.
323 TestingPrefServiceSyncable prefs;
324 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
325 IntegerPrefMember control;
326 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
327 control.SetValue(chromeos::input_method::kAltKey);
329 EventRewriter rewriter(NULL);
330 rewriter.set_pref_service_for_testing(&prefs);
331 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
332 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
334 KeyTestCase pc_keyboard_tests[] = {
335 // Control should be remapped to Alt.
336 {ui::ET_KEY_PRESSED,
337 {ui::VKEY_CONTROL,
338 ui::DomCode::CONTROL_LEFT,
339 ui::EF_CONTROL_DOWN,
340 ui::DomKey::CONTROL,
342 {ui::VKEY_MENU,
343 ui::DomCode::ALT_LEFT,
344 ui::EF_ALT_DOWN,
345 ui::DomKey::ALT,
346 0}},
349 for (const auto& test : pc_keyboard_tests) {
350 CheckKeyTestCase(&rewriter, test);
353 // An Apple keyboard reusing the ID, zero.
354 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "Apple Keyboard");
355 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
357 KeyTestCase apple_keyboard_tests[] = {
358 // VKEY_LWIN (left Command key) with Alt modifier. The remapped Command
359 // key should never be re-remapped to Alt.
360 {ui::ET_KEY_PRESSED,
361 {ui::VKEY_LWIN,
362 ui::DomCode::OS_LEFT,
363 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
364 ui::DomKey::OS,
366 {ui::VKEY_CONTROL,
367 ui::DomCode::CONTROL_LEFT,
368 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
369 ui::DomKey::CONTROL,
370 0}},
372 // VKEY_RWIN (right Command key) with Alt modifier. The remapped Command
373 // key should never be re-remapped to Alt.
374 {ui::ET_KEY_PRESSED,
375 {ui::VKEY_RWIN,
376 ui::DomCode::OS_RIGHT,
377 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
378 ui::DomKey::OS,
380 {ui::VKEY_CONTROL,
381 ui::DomCode::CONTROL_RIGHT,
382 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
383 ui::DomKey::CONTROL,
384 0}},
387 for (const auto& test : apple_keyboard_tests) {
388 CheckKeyTestCase(&rewriter, test);
392 void EventRewriterTest::TestRewriteNumPadKeys() {
393 TestingPrefServiceSyncable prefs;
394 EventRewriter rewriter(NULL);
395 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
396 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
397 rewriter.set_pref_service_for_testing(&prefs);
399 KeyTestCase tests[] = {
400 // XK_KP_Insert (= NumPad 0 without Num Lock), no modifier.
401 {ui::ET_KEY_PRESSED,
402 {ui::VKEY_INSERT,
403 ui::DomCode::NUMPAD0,
404 ui::EF_NONE,
405 ui::DomKey::INSERT,
407 {ui::VKEY_NUMPAD0,
408 ui::DomCode::NUMPAD0,
409 ui::EF_NONE,
410 ui::DomKey::CHARACTER,
411 '0'}},
413 // XK_KP_Insert (= NumPad 0 without Num Lock), Alt modifier.
414 {ui::ET_KEY_PRESSED,
415 {ui::VKEY_INSERT,
416 ui::DomCode::NUMPAD0,
417 ui::EF_ALT_DOWN,
418 ui::DomKey::INSERT,
420 {ui::VKEY_NUMPAD0,
421 ui::DomCode::NUMPAD0,
422 ui::EF_ALT_DOWN,
423 ui::DomKey::CHARACTER,
424 '0'}},
426 // XK_KP_Delete (= NumPad . without Num Lock), Alt modifier.
427 {ui::ET_KEY_PRESSED,
428 {ui::VKEY_DELETE,
429 ui::DomCode::NUMPAD_DECIMAL,
430 ui::EF_ALT_DOWN,
431 ui::DomKey::DEL,
432 0x7F},
433 {ui::VKEY_DECIMAL,
434 ui::DomCode::NUMPAD_DECIMAL,
435 ui::EF_ALT_DOWN,
436 ui::DomKey::CHARACTER,
437 '.'}},
439 // XK_KP_End (= NumPad 1 without Num Lock), Alt modifier.
440 {ui::ET_KEY_PRESSED,
441 {ui::VKEY_END,
442 ui::DomCode::NUMPAD1,
443 ui::EF_ALT_DOWN,
444 ui::DomKey::END,
446 {ui::VKEY_NUMPAD1,
447 ui::DomCode::NUMPAD1,
448 ui::EF_ALT_DOWN,
449 ui::DomKey::CHARACTER,
450 '1'}},
452 // XK_KP_Down (= NumPad 2 without Num Lock), Alt modifier.
453 {ui::ET_KEY_PRESSED,
454 {ui::VKEY_DOWN,
455 ui::DomCode::NUMPAD2,
456 ui::EF_ALT_DOWN,
457 ui::DomKey::ARROW_DOWN,
459 {ui::VKEY_NUMPAD2,
460 ui::DomCode::NUMPAD2,
461 ui::EF_ALT_DOWN,
462 ui::DomKey::CHARACTER,
463 '2'}},
465 // XK_KP_Next (= NumPad 3 without Num Lock), Alt modifier.
466 {ui::ET_KEY_PRESSED,
467 {ui::VKEY_NEXT,
468 ui::DomCode::NUMPAD3,
469 ui::EF_ALT_DOWN,
470 ui::DomKey::PAGE_DOWN,
472 {ui::VKEY_NUMPAD3,
473 ui::DomCode::NUMPAD3,
474 ui::EF_ALT_DOWN,
475 ui::DomKey::CHARACTER,
476 '3'}},
478 // XK_KP_Left (= NumPad 4 without Num Lock), Alt modifier.
479 {ui::ET_KEY_PRESSED,
480 {ui::VKEY_LEFT,
481 ui::DomCode::NUMPAD4,
482 ui::EF_ALT_DOWN,
483 ui::DomKey::ARROW_LEFT,
485 {ui::VKEY_NUMPAD4,
486 ui::DomCode::NUMPAD4,
487 ui::EF_ALT_DOWN,
488 ui::DomKey::CHARACTER,
489 '4'}},
491 // XK_KP_Begin (= NumPad 5 without Num Lock), Alt modifier.
492 {ui::ET_KEY_PRESSED,
493 {ui::VKEY_CLEAR,
494 ui::DomCode::NUMPAD5,
495 ui::EF_ALT_DOWN,
496 ui::DomKey::CLEAR,
498 {ui::VKEY_NUMPAD5,
499 ui::DomCode::NUMPAD5,
500 ui::EF_ALT_DOWN,
501 ui::DomKey::CHARACTER,
502 '5'}},
504 // XK_KP_Right (= NumPad 6 without Num Lock), Alt modifier.
505 {ui::ET_KEY_PRESSED,
506 {ui::VKEY_RIGHT,
507 ui::DomCode::NUMPAD6,
508 ui::EF_ALT_DOWN,
509 ui::DomKey::ARROW_RIGHT,
511 {ui::VKEY_NUMPAD6,
512 ui::DomCode::NUMPAD6,
513 ui::EF_ALT_DOWN,
514 ui::DomKey::CHARACTER,
515 '6'}},
517 // XK_KP_Home (= NumPad 7 without Num Lock), Alt modifier.
518 {ui::ET_KEY_PRESSED,
519 {ui::VKEY_HOME,
520 ui::DomCode::NUMPAD7,
521 ui::EF_ALT_DOWN,
522 ui::DomKey::HOME,
524 {ui::VKEY_NUMPAD7,
525 ui::DomCode::NUMPAD7,
526 ui::EF_ALT_DOWN,
527 ui::DomKey::CHARACTER,
528 '7'}},
530 // XK_KP_Up (= NumPad 8 without Num Lock), Alt modifier.
531 {ui::ET_KEY_PRESSED,
532 {ui::VKEY_UP,
533 ui::DomCode::NUMPAD8,
534 ui::EF_ALT_DOWN,
535 ui::DomKey::ARROW_UP,
537 {ui::VKEY_NUMPAD8,
538 ui::DomCode::NUMPAD8,
539 ui::EF_ALT_DOWN,
540 ui::DomKey::CHARACTER,
541 '8'}},
543 // XK_KP_Prior (= NumPad 9 without Num Lock), Alt modifier.
544 {ui::ET_KEY_PRESSED,
545 {ui::VKEY_PRIOR,
546 ui::DomCode::NUMPAD9,
547 ui::EF_ALT_DOWN,
548 ui::DomKey::PAGE_UP,
550 {ui::VKEY_NUMPAD9,
551 ui::DomCode::NUMPAD9,
552 ui::EF_ALT_DOWN,
553 ui::DomKey::CHARACTER,
554 '9'}},
556 // XK_KP_0 (= NumPad 0 with Num Lock), Num Lock modifier.
557 {ui::ET_KEY_PRESSED,
558 {ui::VKEY_NUMPAD0,
559 ui::DomCode::NUMPAD0,
560 ui::EF_NONE,
561 ui::DomKey::CHARACTER,
562 '0'},
563 {ui::VKEY_NUMPAD0,
564 ui::DomCode::NUMPAD0,
565 ui::EF_NONE,
566 ui::DomKey::CHARACTER,
567 '0'}},
569 // XK_KP_DECIMAL (= NumPad . with Num Lock), Num Lock modifier.
570 {ui::ET_KEY_PRESSED,
571 {ui::VKEY_DECIMAL,
572 ui::DomCode::NUMPAD_DECIMAL,
573 ui::EF_NONE,
574 ui::DomKey::CHARACTER,
575 '.'},
576 {ui::VKEY_DECIMAL,
577 ui::DomCode::NUMPAD_DECIMAL,
578 ui::EF_NONE,
579 ui::DomKey::CHARACTER,
580 '.'}},
582 // XK_KP_1 (= NumPad 1 with Num Lock), Num Lock modifier.
583 {ui::ET_KEY_PRESSED,
584 {ui::VKEY_NUMPAD1,
585 ui::DomCode::NUMPAD1,
586 ui::EF_NONE,
587 ui::DomKey::CHARACTER,
588 '1'},
589 {ui::VKEY_NUMPAD1,
590 ui::DomCode::NUMPAD1,
591 ui::EF_NONE,
592 ui::DomKey::CHARACTER,
593 '1'}},
595 // XK_KP_2 (= NumPad 2 with Num Lock), Num Lock modifier.
596 {ui::ET_KEY_PRESSED,
597 {ui::VKEY_NUMPAD2,
598 ui::DomCode::NUMPAD2,
599 ui::EF_NONE,
600 ui::DomKey::CHARACTER,
601 '2'},
602 {ui::VKEY_NUMPAD2,
603 ui::DomCode::NUMPAD2,
604 ui::EF_NONE,
605 ui::DomKey::CHARACTER,
606 '2'}},
608 // XK_KP_3 (= NumPad 3 with Num Lock), Num Lock modifier.
609 {ui::ET_KEY_PRESSED,
610 {ui::VKEY_NUMPAD3,
611 ui::DomCode::NUMPAD3,
612 ui::EF_NONE,
613 ui::DomKey::CHARACTER,
614 '3'},
615 {ui::VKEY_NUMPAD3,
616 ui::DomCode::NUMPAD3,
617 ui::EF_NONE,
618 ui::DomKey::CHARACTER,
619 '3'}},
621 // XK_KP_4 (= NumPad 4 with Num Lock), Num Lock modifier.
622 {ui::ET_KEY_PRESSED,
623 {ui::VKEY_NUMPAD4,
624 ui::DomCode::NUMPAD4,
625 ui::EF_NONE,
626 ui::DomKey::CHARACTER,
627 '4'},
628 {ui::VKEY_NUMPAD4,
629 ui::DomCode::NUMPAD4,
630 ui::EF_NONE,
631 ui::DomKey::CHARACTER,
632 '4'}},
634 // XK_KP_5 (= NumPad 5 with Num Lock), Num Lock
635 // modifier.
636 {ui::ET_KEY_PRESSED,
637 {ui::VKEY_NUMPAD5,
638 ui::DomCode::NUMPAD5,
639 ui::EF_NONE,
640 ui::DomKey::CHARACTER,
641 '5'},
642 {ui::VKEY_NUMPAD5,
643 ui::DomCode::NUMPAD5,
644 ui::EF_NONE,
645 ui::DomKey::CHARACTER,
646 '5'}},
648 // XK_KP_6 (= NumPad 6 with Num Lock), Num Lock
649 // modifier.
650 {ui::ET_KEY_PRESSED,
651 {ui::VKEY_NUMPAD6,
652 ui::DomCode::NUMPAD6,
653 ui::EF_NONE,
654 ui::DomKey::CHARACTER,
655 '6'},
656 {ui::VKEY_NUMPAD6,
657 ui::DomCode::NUMPAD6,
658 ui::EF_NONE,
659 ui::DomKey::CHARACTER,
660 '6'}},
662 // XK_KP_7 (= NumPad 7 with Num Lock), Num Lock
663 // modifier.
664 {ui::ET_KEY_PRESSED,
665 {ui::VKEY_NUMPAD7,
666 ui::DomCode::NUMPAD7,
667 ui::EF_NONE,
668 ui::DomKey::CHARACTER,
669 '7'},
670 {ui::VKEY_NUMPAD7,
671 ui::DomCode::NUMPAD7,
672 ui::EF_NONE,
673 ui::DomKey::CHARACTER,
674 '7'}},
676 // XK_KP_8 (= NumPad 8 with Num Lock), Num Lock
677 // modifier.
678 {ui::ET_KEY_PRESSED,
679 {ui::VKEY_NUMPAD8,
680 ui::DomCode::NUMPAD8,
681 ui::EF_NONE,
682 ui::DomKey::CHARACTER,
683 '8'},
684 {ui::VKEY_NUMPAD8,
685 ui::DomCode::NUMPAD8,
686 ui::EF_NONE,
687 ui::DomKey::CHARACTER,
688 '8'}},
690 // XK_KP_9 (= NumPad 9 with Num Lock), Num Lock
691 // modifier.
692 {ui::ET_KEY_PRESSED,
693 {ui::VKEY_NUMPAD9,
694 ui::DomCode::NUMPAD9,
695 ui::EF_NONE,
696 ui::DomKey::CHARACTER,
697 '9'},
698 {ui::VKEY_NUMPAD9,
699 ui::DomCode::NUMPAD9,
700 ui::EF_NONE,
701 ui::DomKey::CHARACTER,
702 '9'}},
705 for (const auto& test : tests) {
706 CheckKeyTestCase(&rewriter, test);
710 TEST_F(EventRewriterTest, TestRewriteNumPadKeys) {
711 TestRewriteNumPadKeys();
714 TEST_F(EventRewriterTest, TestRewriteNumPadKeysWithDiamondKeyFlag) {
715 // Make sure the num lock works correctly even when Diamond key exists.
716 const base::CommandLine original_cl(*base::CommandLine::ForCurrentProcess());
717 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
718 chromeos::switches::kHasChromeOSDiamondKey, "");
720 TestRewriteNumPadKeys();
721 *base::CommandLine::ForCurrentProcess() = original_cl;
724 // Tests if the rewriter can handle a Command + Num Pad event.
725 void EventRewriterTest::TestRewriteNumPadKeysOnAppleKeyboard() {
726 TestingPrefServiceSyncable prefs;
727 EventRewriter rewriter(NULL);
728 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "Apple Keyboard");
729 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
730 rewriter.set_pref_service_for_testing(&prefs);
732 KeyTestCase tests[] = {
733 // XK_KP_End (= NumPad 1 without Num Lock), Win modifier.
734 // The result should be "Num Pad 1 with Control + Num Lock modifiers".
735 {ui::ET_KEY_PRESSED,
736 {ui::VKEY_END,
737 ui::DomCode::NUMPAD1,
738 ui::EF_COMMAND_DOWN,
739 ui::DomKey::END,
741 {ui::VKEY_NUMPAD1,
742 ui::DomCode::NUMPAD1,
743 ui::EF_CONTROL_DOWN,
744 ui::DomKey::UNIDENTIFIED,
745 0}},
747 // XK_KP_1 (= NumPad 1 with Num Lock), Win modifier.
748 // The result should also be "Num Pad 1 with Control + Num Lock
749 // modifiers".
750 {ui::ET_KEY_PRESSED,
751 {ui::VKEY_NUMPAD1,
752 ui::DomCode::NUMPAD1,
753 ui::EF_COMMAND_DOWN,
754 ui::DomKey::CHARACTER,
755 '1'},
756 {ui::VKEY_NUMPAD1,
757 ui::DomCode::NUMPAD1,
758 ui::EF_CONTROL_DOWN,
759 ui::DomKey::UNIDENTIFIED,
760 0}}};
762 for (const auto& test : tests) {
763 CheckKeyTestCase(&rewriter, test);
767 TEST_F(EventRewriterTest, TestRewriteNumPadKeysOnAppleKeyboard) {
768 TestRewriteNumPadKeysOnAppleKeyboard();
771 TEST_F(EventRewriterTest,
772 TestRewriteNumPadKeysOnAppleKeyboardWithDiamondKeyFlag) {
773 // Makes sure the num lock works correctly even when Diamond key exists.
774 const base::CommandLine original_cl(*base::CommandLine::ForCurrentProcess());
775 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
776 chromeos::switches::kHasChromeOSDiamondKey, "");
778 TestRewriteNumPadKeysOnAppleKeyboard();
779 *base::CommandLine::ForCurrentProcess() = original_cl;
782 TEST_F(EventRewriterTest, TestRewriteModifiersNoRemap) {
783 TestingPrefServiceSyncable prefs;
784 EventRewriter rewriter(NULL);
785 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
786 rewriter.set_pref_service_for_testing(&prefs);
788 KeyTestCase tests[] = {
789 // Press Search. Confirm the event is not rewritten.
790 {ui::ET_KEY_PRESSED,
791 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_NONE, ui::DomKey::OS, 0},
792 {ui::VKEY_LWIN,
793 ui::DomCode::OS_LEFT,
794 ui::EF_COMMAND_DOWN,
795 ui::DomKey::OS,
796 0}},
798 // Press left Control. Confirm the event is not rewritten.
799 {ui::ET_KEY_PRESSED,
800 {ui::VKEY_CONTROL,
801 ui::DomCode::CONTROL_LEFT,
802 ui::EF_CONTROL_DOWN,
803 ui::DomKey::CONTROL,
805 {ui::VKEY_CONTROL,
806 ui::DomCode::CONTROL_LEFT,
807 ui::EF_CONTROL_DOWN,
808 ui::DomKey::CONTROL,
809 0}},
811 // Press right Control. Confirm the event is not rewritten.
812 {ui::ET_KEY_PRESSED,
813 {ui::VKEY_CONTROL,
814 ui::DomCode::CONTROL_LEFT,
815 ui::EF_CONTROL_DOWN,
816 ui::DomKey::CONTROL,
818 {ui::VKEY_CONTROL,
819 ui::DomCode::CONTROL_LEFT,
820 ui::EF_CONTROL_DOWN,
821 ui::DomKey::CONTROL,
822 0}},
824 // Press left Alt. Confirm the event is not rewritten.
825 {ui::ET_KEY_PRESSED,
826 {ui::VKEY_MENU,
827 ui::DomCode::ALT_LEFT,
828 ui::EF_ALT_DOWN,
829 ui::DomKey::ALT,
831 {ui::VKEY_MENU,
832 ui::DomCode::ALT_LEFT,
833 ui::EF_ALT_DOWN,
834 ui::DomKey::ALT,
835 0}},
837 // Press right Alt. Confirm the event is not rewritten.
838 {ui::ET_KEY_PRESSED,
839 {ui::VKEY_MENU,
840 ui::DomCode::ALT_LEFT,
841 ui::EF_ALT_DOWN,
842 ui::DomKey::ALT,
844 {ui::VKEY_MENU,
845 ui::DomCode::ALT_LEFT,
846 ui::EF_ALT_DOWN,
847 ui::DomKey::ALT,
848 0}},
850 // Test KeyRelease event, just in case.
851 // Release Search. Confirm the release event is not rewritten.
852 {ui::ET_KEY_RELEASED,
853 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_NONE, ui::DomKey::OS, 0},
854 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_NONE, ui::DomKey::OS, 0}},
857 for (const auto& test : tests) {
858 CheckKeyTestCase(&rewriter, test);
862 TEST_F(EventRewriterTest, TestRewriteModifiersNoRemapMultipleKeys) {
863 TestingPrefServiceSyncable prefs;
864 EventRewriter rewriter(NULL);
865 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
866 rewriter.set_pref_service_for_testing(&prefs);
868 KeyTestCase tests[] = {
869 // Press Alt with Shift. Confirm the event is not rewritten.
870 {ui::ET_KEY_PRESSED,
871 {ui::VKEY_MENU,
872 ui::DomCode::ALT_LEFT,
873 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
874 ui::DomKey::ALT,
876 {ui::VKEY_MENU,
877 ui::DomCode::ALT_LEFT,
878 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
879 ui::DomKey::ALT,
880 0}},
882 // Press Search with Caps Lock mask. Confirm the event is not rewritten.
883 {ui::ET_KEY_PRESSED,
884 {ui::VKEY_LWIN,
885 ui::DomCode::OS_LEFT,
886 ui::EF_CAPS_LOCK_DOWN | ui::EF_COMMAND_DOWN,
887 ui::DomKey::OS,
889 {ui::VKEY_LWIN,
890 ui::DomCode::OS_LEFT,
891 ui::EF_CAPS_LOCK_DOWN | ui::EF_COMMAND_DOWN,
892 ui::DomKey::OS,
893 0}},
895 // Release Search with Caps Lock mask. Confirm the event is not rewritten.
896 {ui::ET_KEY_RELEASED,
897 {ui::VKEY_LWIN,
898 ui::DomCode::OS_LEFT,
899 ui::EF_CAPS_LOCK_DOWN,
900 ui::DomKey::OS,
902 {ui::VKEY_LWIN,
903 ui::DomCode::OS_LEFT,
904 ui::EF_CAPS_LOCK_DOWN,
905 ui::DomKey::OS,
906 0}},
908 // Press Shift+Ctrl+Alt+Search+A. Confirm the event is not rewritten.
909 {ui::ET_KEY_PRESSED,
910 {ui::VKEY_B,
911 ui::DomCode::KEY_B,
912 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
913 ui::EF_COMMAND_DOWN,
914 ui::DomKey::CHARACTER,
915 'B'},
916 {ui::VKEY_B,
917 ui::DomCode::KEY_B,
918 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
919 ui::EF_COMMAND_DOWN,
920 ui::DomKey::CHARACTER,
921 'B'}},
924 for (const auto& test : tests) {
925 CheckKeyTestCase(&rewriter, test);
929 TEST_F(EventRewriterTest, TestRewriteModifiersDisableSome) {
930 // Disable Search and Control keys.
931 TestingPrefServiceSyncable prefs;
932 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
933 IntegerPrefMember search;
934 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
935 search.SetValue(chromeos::input_method::kVoidKey);
936 IntegerPrefMember control;
937 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
938 control.SetValue(chromeos::input_method::kVoidKey);
940 EventRewriter rewriter(NULL);
941 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
942 rewriter.set_pref_service_for_testing(&prefs);
944 KeyTestCase disabled_modifier_tests[] = {
945 // Press Alt with Shift. This key press shouldn't be affected by the
946 // pref. Confirm the event is not rewritten.
947 {ui::ET_KEY_PRESSED,
948 {ui::VKEY_MENU,
949 ui::DomCode::ALT_LEFT,
950 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
951 ui::DomKey::ALT,
953 {ui::VKEY_MENU,
954 ui::DomCode::ALT_LEFT,
955 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
956 ui::DomKey::ALT,
957 0}},
959 // Press Search. Confirm the event is now VKEY_UNKNOWN.
960 {ui::ET_KEY_PRESSED,
961 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_NONE, ui::DomKey::OS, 0},
962 {ui::VKEY_UNKNOWN,
963 ui::DomCode::NONE,
964 ui::EF_NONE,
965 ui::DomKey::UNIDENTIFIED,
966 0}},
968 // Press Control. Confirm the event is now VKEY_UNKNOWN.
969 {ui::ET_KEY_PRESSED,
970 {ui::VKEY_CONTROL,
971 ui::DomCode::CONTROL_LEFT,
972 ui::EF_CONTROL_DOWN,
973 ui::DomKey::CONTROL,
975 {ui::VKEY_UNKNOWN,
976 ui::DomCode::NONE,
977 ui::EF_NONE,
978 ui::DomKey::UNIDENTIFIED,
979 0}},
981 // Press Control+Search. Confirm the event is now VKEY_UNKNOWN
982 // without any modifiers.
983 {ui::ET_KEY_PRESSED,
984 {ui::VKEY_LWIN,
985 ui::DomCode::OS_LEFT,
986 ui::EF_CONTROL_DOWN,
987 ui::DomKey::OS,
989 {ui::VKEY_UNKNOWN,
990 ui::DomCode::NONE,
991 ui::EF_NONE,
992 ui::DomKey::UNIDENTIFIED,
993 0}},
995 // Press Control+Search+a. Confirm the event is now VKEY_A without any
996 // modifiers.
997 {ui::ET_KEY_PRESSED,
998 {ui::VKEY_A,
999 ui::DomCode::KEY_A,
1000 ui::EF_CONTROL_DOWN,
1001 ui::DomKey::CHARACTER,
1002 'a'},
1003 {ui::VKEY_A,
1004 ui::DomCode::KEY_A,
1005 ui::EF_NONE,
1006 ui::DomKey::CHARACTER,
1007 'a'}},
1009 // Press Control+Search+Alt+a. Confirm the event is now VKEY_A only with
1010 // the Alt modifier.
1011 {ui::ET_KEY_PRESSED,
1012 {ui::VKEY_A,
1013 ui::DomCode::KEY_A,
1014 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
1015 ui::DomKey::CHARACTER,
1016 'a'},
1017 {ui::VKEY_A,
1018 ui::DomCode::KEY_A,
1019 ui::EF_ALT_DOWN,
1020 ui::DomKey::CHARACTER,
1021 'a'}},
1024 for (const auto& test : disabled_modifier_tests) {
1025 CheckKeyTestCase(&rewriter, test);
1028 // Remap Alt to Control.
1029 IntegerPrefMember alt;
1030 alt.Init(prefs::kLanguageRemapAltKeyTo, &prefs);
1031 alt.SetValue(chromeos::input_method::kControlKey);
1033 KeyTestCase tests[] = {
1034 // Press left Alt. Confirm the event is now VKEY_CONTROL
1035 // even though the Control key itself is disabled.
1036 {ui::ET_KEY_PRESSED,
1037 {ui::VKEY_MENU,
1038 ui::DomCode::ALT_LEFT,
1039 ui::EF_ALT_DOWN,
1040 ui::DomKey::ALT,
1042 {ui::VKEY_CONTROL,
1043 ui::DomCode::CONTROL_LEFT,
1044 ui::EF_CONTROL_DOWN,
1045 ui::DomKey::CONTROL,
1046 0}},
1048 // Press Alt+a. Confirm the event is now Control+a even though the Control
1049 // key itself is disabled.
1050 {ui::ET_KEY_PRESSED,
1051 {ui::VKEY_A,
1052 ui::DomCode::KEY_A,
1053 ui::EF_ALT_DOWN,
1054 ui::DomKey::CHARACTER,
1055 'a'},
1056 {ui::VKEY_A,
1057 ui::DomCode::KEY_A,
1058 ui::EF_CONTROL_DOWN,
1059 ui::DomKey::CHARACTER,
1060 0x01}},
1063 for (const auto& test : tests) {
1064 CheckKeyTestCase(&rewriter, test);
1068 TEST_F(EventRewriterTest, TestRewriteModifiersRemapToControl) {
1069 // Remap Search to Control.
1070 TestingPrefServiceSyncable prefs;
1071 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1072 IntegerPrefMember search;
1073 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
1074 search.SetValue(chromeos::input_method::kControlKey);
1076 EventRewriter rewriter(NULL);
1077 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1078 rewriter.set_pref_service_for_testing(&prefs);
1080 KeyTestCase s_tests[] = {
1081 // Press Search. Confirm the event is now VKEY_CONTROL.
1082 {ui::ET_KEY_PRESSED,
1083 {ui::VKEY_LWIN,
1084 ui::DomCode::OS_LEFT,
1085 ui::EF_COMMAND_DOWN,
1086 ui::DomKey::OS,
1088 {ui::VKEY_CONTROL,
1089 ui::DomCode::CONTROL_LEFT,
1090 ui::EF_CONTROL_DOWN,
1091 ui::DomKey::CONTROL,
1092 0}},
1095 for (const auto& test : s_tests) {
1096 CheckKeyTestCase(&rewriter, test);
1099 // Remap Alt to Control too.
1100 IntegerPrefMember alt;
1101 alt.Init(prefs::kLanguageRemapAltKeyTo, &prefs);
1102 alt.SetValue(chromeos::input_method::kControlKey);
1104 KeyTestCase sa_tests[] = {
1105 // Press Alt. Confirm the event is now VKEY_CONTROL.
1106 {ui::ET_KEY_PRESSED,
1107 {ui::VKEY_MENU,
1108 ui::DomCode::ALT_LEFT,
1109 ui::EF_ALT_DOWN,
1110 ui::DomKey::ALT,
1112 {ui::VKEY_CONTROL,
1113 ui::DomCode::CONTROL_LEFT,
1114 ui::EF_CONTROL_DOWN,
1115 ui::DomKey::CONTROL,
1116 0}},
1118 // Press Alt+Search. Confirm the event is now VKEY_CONTROL.
1119 {ui::ET_KEY_PRESSED,
1120 {ui::VKEY_LWIN,
1121 ui::DomCode::OS_LEFT,
1122 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
1123 ui::DomKey::OS,
1125 {ui::VKEY_CONTROL,
1126 ui::DomCode::CONTROL_LEFT,
1127 ui::EF_CONTROL_DOWN,
1128 ui::DomKey::CONTROL,
1129 0}},
1131 // Press Control+Alt+Search. Confirm the event is now VKEY_CONTROL.
1132 {ui::ET_KEY_PRESSED,
1133 {ui::VKEY_LWIN,
1134 ui::DomCode::OS_LEFT,
1135 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
1136 ui::DomKey::OS,
1138 {ui::VKEY_CONTROL,
1139 ui::DomCode::CONTROL_LEFT,
1140 ui::EF_CONTROL_DOWN,
1141 ui::DomKey::CONTROL,
1142 0}},
1144 // Press Shift+Control+Alt+Search. Confirm the event is now Control with
1145 // Shift and Control modifiers.
1146 {ui::ET_KEY_PRESSED,
1147 {ui::VKEY_LWIN,
1148 ui::DomCode::OS_LEFT,
1149 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
1150 ui::EF_COMMAND_DOWN,
1151 ui::DomKey::OS,
1153 {ui::VKEY_CONTROL,
1154 ui::DomCode::CONTROL_LEFT,
1155 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
1156 ui::DomKey::CONTROL,
1157 0}},
1159 // Press Shift+Control+Alt+Search+B. Confirm the event is now B with Shift
1160 // and Control modifiers.
1161 {ui::ET_KEY_PRESSED,
1162 {ui::VKEY_B,
1163 ui::DomCode::KEY_B,
1164 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
1165 ui::EF_COMMAND_DOWN,
1166 ui::DomKey::CHARACTER,
1167 'B'},
1168 {ui::VKEY_B,
1169 ui::DomCode::KEY_B,
1170 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
1171 ui::DomKey::CHARACTER,
1172 0x02}},
1175 for (const auto& test : sa_tests) {
1176 CheckKeyTestCase(&rewriter, test);
1180 TEST_F(EventRewriterTest, TestRewriteModifiersRemapToEscape) {
1181 // Remap Search to ESC.
1182 TestingPrefServiceSyncable prefs;
1183 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1184 IntegerPrefMember search;
1185 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
1186 search.SetValue(chromeos::input_method::kEscapeKey);
1188 EventRewriter rewriter(NULL);
1189 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1190 rewriter.set_pref_service_for_testing(&prefs);
1192 KeyTestCase tests[] = {
1193 // Press Search. Confirm the event is now VKEY_ESCAPE.
1194 {ui::ET_KEY_PRESSED,
1195 {ui::VKEY_LWIN,
1196 ui::DomCode::OS_LEFT,
1197 ui::EF_COMMAND_DOWN,
1198 ui::DomKey::OS,
1200 {ui::VKEY_ESCAPE,
1201 ui::DomCode::ESCAPE,
1202 ui::EF_NONE,
1203 ui::DomKey::ESCAPE,
1204 0x1B}},
1207 for (const auto& test : tests) {
1208 CheckKeyTestCase(&rewriter, test);
1212 TEST_F(EventRewriterTest, TestRewriteModifiersRemapMany) {
1213 // Remap Search to Alt.
1214 TestingPrefServiceSyncable prefs;
1215 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1216 IntegerPrefMember search;
1217 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
1218 search.SetValue(chromeos::input_method::kAltKey);
1220 EventRewriter rewriter(NULL);
1221 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1222 rewriter.set_pref_service_for_testing(&prefs);
1224 KeyTestCase s2a_tests[] = {
1225 // Press Search. Confirm the event is now VKEY_MENU.
1226 {ui::ET_KEY_PRESSED,
1227 {ui::VKEY_LWIN,
1228 ui::DomCode::OS_LEFT,
1229 ui::EF_COMMAND_DOWN,
1230 ui::DomKey::OS,
1232 {ui::VKEY_MENU,
1233 ui::DomCode::ALT_LEFT,
1234 ui::EF_ALT_DOWN,
1235 ui::DomKey::ALT,
1236 0}},
1239 for (const auto& test : s2a_tests) {
1240 CheckKeyTestCase(&rewriter, test);
1243 // Remap Alt to Control.
1244 IntegerPrefMember alt;
1245 alt.Init(prefs::kLanguageRemapAltKeyTo, &prefs);
1246 alt.SetValue(chromeos::input_method::kControlKey);
1248 KeyTestCase a2c_tests[] = {
1249 // Press left Alt. Confirm the event is now VKEY_CONTROL.
1250 {ui::ET_KEY_PRESSED,
1251 {ui::VKEY_MENU,
1252 ui::DomCode::ALT_LEFT,
1253 ui::EF_ALT_DOWN,
1254 ui::DomKey::ALT,
1256 {ui::VKEY_CONTROL,
1257 ui::DomCode::CONTROL_LEFT,
1258 ui::EF_CONTROL_DOWN,
1259 ui::DomKey::CONTROL,
1260 0}},
1261 // Press Shift+comma. Verify that only the flags are changed.
1262 // The X11 portion of the test addresses crbug.com/390263 by verifying
1263 // that the X keycode remains that for ',<' and not for 105-key '<>'.
1264 {ui::ET_KEY_PRESSED,
1265 {ui::VKEY_OEM_COMMA,
1266 ui::DomCode::COMMA,
1267 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
1268 ui::DomKey::UNIDENTIFIED,
1270 {ui::VKEY_OEM_COMMA,
1271 ui::DomCode::COMMA,
1272 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
1273 ui::DomKey::UNIDENTIFIED,
1274 0}},
1275 // Press Shift+9. Verify that only the flags are changed.
1276 {ui::ET_KEY_PRESSED,
1277 {ui::VKEY_9,
1278 ui::DomCode::DIGIT9,
1279 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
1280 ui::DomKey::UNIDENTIFIED,
1282 {ui::VKEY_9,
1283 ui::DomCode::DIGIT9,
1284 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
1285 ui::DomKey::UNIDENTIFIED,
1286 0}},
1289 for (const auto& test : a2c_tests) {
1290 CheckKeyTestCase(&rewriter, test);
1293 // Remap Control to Search.
1294 IntegerPrefMember control;
1295 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
1296 control.SetValue(chromeos::input_method::kSearchKey);
1298 KeyTestCase c2s_tests[] = {
1299 // Press left Control. Confirm the event is now VKEY_LWIN.
1300 {ui::ET_KEY_PRESSED,
1301 {ui::VKEY_CONTROL,
1302 ui::DomCode::CONTROL_LEFT,
1303 ui::EF_CONTROL_DOWN,
1304 ui::DomKey::CONTROL,
1306 {ui::VKEY_LWIN,
1307 ui::DomCode::OS_LEFT,
1308 ui::EF_COMMAND_DOWN,
1309 ui::DomKey::OS,
1310 0}},
1312 // Then, press all of the three, Control+Alt+Search.
1313 {ui::ET_KEY_PRESSED,
1314 {ui::VKEY_LWIN,
1315 ui::DomCode::OS_LEFT,
1316 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
1317 ui::DomKey::OS,
1319 {ui::VKEY_MENU,
1320 ui::DomCode::ALT_LEFT,
1321 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
1322 ui::DomKey::ALT,
1323 0}},
1325 // Press Shift+Control+Alt+Search.
1326 {ui::ET_KEY_PRESSED,
1327 {ui::VKEY_LWIN,
1328 ui::DomCode::OS_LEFT,
1329 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
1330 ui::EF_COMMAND_DOWN,
1331 ui::DomKey::OS,
1333 {ui::VKEY_MENU,
1334 ui::DomCode::ALT_LEFT,
1335 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
1336 ui::EF_COMMAND_DOWN,
1337 ui::DomKey::ALT,
1338 0}},
1340 // Press Shift+Control+Alt+Search+B
1341 {ui::ET_KEY_PRESSED,
1342 {ui::VKEY_B,
1343 ui::DomCode::KEY_B,
1344 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
1345 ui::EF_COMMAND_DOWN,
1346 ui::DomKey::CHARACTER,
1347 'B'},
1348 {ui::VKEY_B,
1349 ui::DomCode::KEY_B,
1350 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
1351 ui::EF_COMMAND_DOWN,
1352 ui::DomKey::CHARACTER,
1353 'B'}},
1356 for (const auto& test : c2s_tests) {
1357 CheckKeyTestCase(&rewriter, test);
1361 TEST_F(EventRewriterTest, TestRewriteModifiersRemapToCapsLock) {
1362 // Remap Search to Caps Lock.
1363 TestingPrefServiceSyncable prefs;
1364 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1365 IntegerPrefMember search;
1366 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
1367 search.SetValue(chromeos::input_method::kCapsLockKey);
1369 chromeos::input_method::FakeImeKeyboard ime_keyboard;
1370 EventRewriter rewriter(NULL);
1371 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1372 rewriter.set_pref_service_for_testing(&prefs);
1373 rewriter.set_ime_keyboard_for_testing(&ime_keyboard);
1374 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1376 // Press Search.
1377 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_CAPITAL,
1378 ui::DomCode::CAPS_LOCK, ui::EF_MOD3_DOWN,
1379 ui::DomKey::CAPS_LOCK, 0),
1380 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1381 ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
1382 ui::EF_COMMAND_DOWN, ui::DomKey::OS, 0));
1383 // Confirm that the Caps Lock status is changed.
1384 EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
1386 // Release Search.
1387 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CAPITAL,
1388 ui::DomCode::CAPS_LOCK, ui::EF_NONE,
1389 ui::DomKey::CAPS_LOCK, 0),
1390 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1391 ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
1392 ui::EF_NONE, ui::DomKey::OS, 0));
1393 // Confirm that the Caps Lock status is not changed.
1394 EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
1396 // Press Search.
1397 EXPECT_EQ(
1398 GetExpectedResultAsString(
1399 ui::ET_KEY_PRESSED, ui::VKEY_CAPITAL, ui::DomCode::CAPS_LOCK,
1400 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN, ui::DomKey::CAPS_LOCK, 0),
1401 GetRewrittenEventAsString(
1402 &rewriter, ui::ET_KEY_PRESSED, ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
1403 ui::EF_COMMAND_DOWN | ui::EF_CAPS_LOCK_DOWN, ui::DomKey::OS, 0));
1404 // Confirm that the Caps Lock status is changed.
1405 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1407 // Release Search.
1408 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CAPITAL,
1409 ui::DomCode::CAPS_LOCK, ui::EF_NONE,
1410 ui::DomKey::CAPS_LOCK, 0),
1411 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1412 ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
1413 ui::EF_NONE, ui::DomKey::OS, 0));
1414 // Confirm that the Caps Lock status is not changed.
1415 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1417 // Press Caps Lock (on an external keyboard).
1418 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_CAPITAL,
1419 ui::DomCode::CAPS_LOCK,
1420 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1421 ui::DomKey::CAPS_LOCK, 0),
1422 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1423 ui::VKEY_CAPITAL, ui::DomCode::CAPS_LOCK,
1424 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1425 ui::DomKey::CAPS_LOCK, 0));
1427 #if defined(USE_X11)
1428 // Confirm that calling RewriteForTesting() does not change the state of
1429 // |ime_keyboard|. In this case, X Window system itself should change the
1430 // Caps Lock state, not ash::EventRewriter.
1431 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1432 #elif defined(USE_OZONE)
1433 // Under Ozone the rewriter is responsible for changing the caps lock
1434 // state when the final key is Caps Lock, regardless of whether the
1435 // initial key is Caps Lock.
1436 EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
1437 #endif
1439 // Release Caps Lock (on an external keyboard).
1440 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CAPITAL,
1441 ui::DomCode::CAPS_LOCK, ui::EF_NONE,
1442 ui::DomKey::CAPS_LOCK, 0),
1443 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1444 ui::VKEY_CAPITAL, ui::DomCode::CAPS_LOCK,
1445 ui::EF_NONE, ui::DomKey::CAPS_LOCK, 0));
1446 #if defined(USE_X11)
1447 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1448 #elif defined(USE_OZONE)
1449 EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
1450 #endif
1453 TEST_F(EventRewriterTest, TestRewriteCapsLock) {
1454 TestingPrefServiceSyncable prefs;
1455 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1457 chromeos::input_method::FakeImeKeyboard ime_keyboard;
1458 EventRewriter rewriter(NULL);
1459 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1460 rewriter.set_pref_service_for_testing(&prefs);
1461 rewriter.set_ime_keyboard_for_testing(&ime_keyboard);
1462 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1464 // On Chrome OS, CapsLock is mapped to F16 with Mod3Mask.
1465 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_CAPITAL,
1466 ui::DomCode::CAPS_LOCK,
1467 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1468 ui::DomKey::CAPS_LOCK, 0),
1469 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1470 ui::VKEY_F16, ui::DomCode::F16,
1471 ui::EF_MOD3_DOWN, ui::DomKey::F16, 0));
1472 EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
1475 TEST_F(EventRewriterTest, TestRewriteDiamondKey) {
1476 TestingPrefServiceSyncable prefs;
1477 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1479 chromeos::input_method::FakeImeKeyboard ime_keyboard;
1480 EventRewriter rewriter(NULL);
1481 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1482 rewriter.set_pref_service_for_testing(&prefs);
1483 rewriter.set_ime_keyboard_for_testing(&ime_keyboard);
1485 KeyTestCase tests[] = {
1486 // F15 should work as Ctrl when --has-chromeos-diamond-key is not
1487 // specified.
1488 {ui::ET_KEY_PRESSED,
1489 {ui::VKEY_F15, ui::DomCode::F15, ui::EF_NONE, ui::DomKey::F15, 0},
1490 {ui::VKEY_CONTROL,
1491 ui::DomCode::CONTROL_LEFT,
1492 ui::EF_CONTROL_DOWN,
1493 ui::DomKey::CONTROL,
1494 0}},
1496 {ui::ET_KEY_RELEASED,
1497 {ui::VKEY_F15, ui::DomCode::F15, ui::EF_NONE, ui::DomKey::F15, 0},
1498 {ui::VKEY_CONTROL,
1499 ui::DomCode::CONTROL_LEFT,
1500 ui::EF_NONE,
1501 ui::DomKey::CONTROL,
1502 0}},
1504 // However, Mod2Mask should not be rewritten to CtrlMask when
1505 // --has-chromeos-diamond-key is not specified.
1506 {ui::ET_KEY_PRESSED,
1507 {ui::VKEY_A,
1508 ui::DomCode::KEY_A,
1509 ui::EF_NONE,
1510 ui::DomKey::CHARACTER,
1511 'a'},
1512 {ui::VKEY_A,
1513 ui::DomCode::KEY_A,
1514 ui::EF_NONE,
1515 ui::DomKey::CHARACTER,
1516 'a'}},
1519 for (const auto& test : tests) {
1520 CheckKeyTestCase(&rewriter, test);
1524 TEST_F(EventRewriterTest, TestRewriteDiamondKeyWithFlag) {
1525 const base::CommandLine original_cl(*base::CommandLine::ForCurrentProcess());
1526 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1527 chromeos::switches::kHasChromeOSDiamondKey, "");
1529 TestingPrefServiceSyncable prefs;
1530 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1532 chromeos::input_method::FakeImeKeyboard ime_keyboard;
1533 EventRewriter rewriter(NULL);
1534 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1535 rewriter.set_pref_service_for_testing(&prefs);
1536 rewriter.set_ime_keyboard_for_testing(&ime_keyboard);
1538 // By default, F15 should work as Control.
1539 EXPECT_EQ(GetExpectedResultAsString(
1540 ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
1541 ui::EF_CONTROL_DOWN, ui::DomKey::CONTROL, 0),
1542 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1543 ui::VKEY_F15, ui::DomCode::F15,
1544 ui::EF_NONE, ui::DomKey::F15, 0));
1545 // Check that Control is applied to a subsequent key press.
1546 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1547 ui::DomCode::KEY_A, ui::EF_CONTROL_DOWN,
1548 ui::DomKey::CHARACTER, 0x01),
1549 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1550 ui::DomCode::KEY_A, ui::EF_NONE,
1551 ui::DomKey::CHARACTER, 'a'));
1552 // Release F15
1553 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL,
1554 ui::DomCode::CONTROL_LEFT, ui::EF_NONE,
1555 ui::DomKey::CONTROL, 0),
1556 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1557 ui::VKEY_F15, ui::DomCode::F15,
1558 ui::EF_NONE, ui::DomKey::F15, 0));
1559 // Check that Control is no longer applied to a subsequent key press.
1560 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1561 ui::DomCode::KEY_A, ui::EF_NONE,
1562 ui::DomKey::CHARACTER, 'a'),
1563 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1564 ui::DomCode::KEY_A, ui::EF_NONE,
1565 ui::DomKey::CHARACTER, 'a'));
1567 IntegerPrefMember diamond;
1568 diamond.Init(prefs::kLanguageRemapDiamondKeyTo, &prefs);
1569 diamond.SetValue(chromeos::input_method::kVoidKey);
1571 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN,
1572 ui::DomCode::NONE, ui::EF_NONE,
1573 ui::DomKey::UNIDENTIFIED, 0),
1574 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1575 ui::VKEY_F15, ui::DomCode::F15,
1576 ui::EF_NONE, ui::DomKey::F15, 0));
1577 // Check that no modifier is applied to another key.
1578 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1579 ui::DomCode::KEY_A, ui::EF_NONE,
1580 ui::DomKey::CHARACTER, 'a'),
1581 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1582 ui::DomCode::KEY_A, ui::EF_NONE,
1583 ui::DomKey::CHARACTER, 'a'));
1585 diamond.SetValue(chromeos::input_method::kControlKey);
1587 EXPECT_EQ(GetExpectedResultAsString(
1588 ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
1589 ui::EF_CONTROL_DOWN, ui::DomKey::CONTROL, 0),
1590 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1591 ui::VKEY_F15, ui::DomCode::F15,
1592 ui::EF_NONE, ui::DomKey::F15, 0));
1593 // Check that Control is applied to a subsequent key press.
1594 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1595 ui::DomCode::KEY_A, ui::EF_CONTROL_DOWN,
1596 ui::DomKey::CHARACTER, 0x01),
1597 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1598 ui::DomCode::KEY_A, ui::EF_NONE,
1599 ui::DomKey::CHARACTER, 'a'));
1600 // Release F15
1601 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL,
1602 ui::DomCode::CONTROL_LEFT, ui::EF_NONE,
1603 ui::DomKey::CONTROL, 0),
1604 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1605 ui::VKEY_F15, ui::DomCode::F15,
1606 ui::EF_NONE, ui::DomKey::F15, 0));
1607 // Check that Control is no longer applied to a subsequent key press.
1608 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1609 ui::DomCode::KEY_A, ui::EF_NONE,
1610 ui::DomKey::CHARACTER, 'a'),
1611 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1612 ui::DomCode::KEY_A, ui::EF_NONE,
1613 ui::DomKey::CHARACTER, 'a'));
1615 diamond.SetValue(chromeos::input_method::kAltKey);
1617 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_MENU,
1618 ui::DomCode::ALT_LEFT, ui::EF_ALT_DOWN,
1619 ui::DomKey::ALT, 0),
1620 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1621 ui::VKEY_F15, ui::DomCode::F15,
1622 ui::EF_NONE, ui::DomKey::F15, 0));
1623 // Check that Alt is applied to a subsequent key press.
1624 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1625 ui::DomCode::KEY_A, ui::EF_ALT_DOWN,
1626 ui::DomKey::CHARACTER, 'a'),
1627 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1628 ui::DomCode::KEY_A, ui::EF_NONE,
1629 ui::DomKey::CHARACTER, 'a'));
1630 // Release F15
1631 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_MENU,
1632 ui::DomCode::ALT_LEFT, ui::EF_NONE,
1633 ui::DomKey::ALT, 0),
1634 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1635 ui::VKEY_F15, ui::DomCode::F15,
1636 ui::EF_NONE, ui::DomKey::F15, 0));
1637 // Check that Alt is no longer applied to a subsequent key press.
1638 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1639 ui::DomCode::KEY_A, ui::EF_NONE,
1640 ui::DomKey::CHARACTER, 'a'),
1641 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1642 ui::DomCode::KEY_A, ui::EF_NONE,
1643 ui::DomKey::CHARACTER, 'a'));
1645 diamond.SetValue(chromeos::input_method::kCapsLockKey);
1647 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_CAPITAL,
1648 ui::DomCode::CAPS_LOCK,
1649 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1650 ui::DomKey::CAPS_LOCK, 0),
1651 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1652 ui::VKEY_F15, ui::DomCode::F15,
1653 ui::EF_NONE, ui::DomKey::F15, 0));
1654 // Check that Caps is applied to a subsequent key press.
1655 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1656 ui::DomCode::KEY_A,
1657 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1658 ui::DomKey::CHARACTER, 'A'),
1659 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1660 ui::DomCode::KEY_A, ui::EF_NONE,
1661 ui::DomKey::CHARACTER, 'a'));
1662 // Release F15
1663 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CAPITAL,
1664 ui::DomCode::CAPS_LOCK, ui::EF_NONE,
1665 ui::DomKey::CAPS_LOCK, 0),
1666 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1667 ui::VKEY_F15, ui::DomCode::F15,
1668 ui::EF_NONE, ui::DomKey::F15, 0));
1669 // Check that Control is no longer applied to a subsequent key press.
1670 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1671 ui::DomCode::KEY_A, ui::EF_NONE,
1672 ui::DomKey::CHARACTER, 'a'),
1673 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1674 ui::DomCode::KEY_A, ui::EF_NONE,
1675 ui::DomKey::CHARACTER, 'a'));
1677 *base::CommandLine::ForCurrentProcess() = original_cl;
1680 TEST_F(EventRewriterTest, TestRewriteCapsLockToControl) {
1681 // Remap CapsLock to Control.
1682 TestingPrefServiceSyncable prefs;
1683 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1684 IntegerPrefMember control;
1685 control.Init(prefs::kLanguageRemapCapsLockKeyTo, &prefs);
1686 control.SetValue(chromeos::input_method::kControlKey);
1688 EventRewriter rewriter(NULL);
1689 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1690 rewriter.set_pref_service_for_testing(&prefs);
1692 KeyTestCase tests[] = {
1693 // Press CapsLock+a. Confirm that Mod3Mask is rewritten to ControlMask.
1694 // On Chrome OS, CapsLock works as a Mod3 modifier.
1695 {ui::ET_KEY_PRESSED,
1696 {ui::VKEY_A,
1697 ui::DomCode::KEY_A,
1698 ui::EF_MOD3_DOWN,
1699 ui::DomKey::CHARACTER,
1700 'a'},
1701 {ui::VKEY_A,
1702 ui::DomCode::KEY_A,
1703 ui::EF_CONTROL_DOWN,
1704 ui::DomKey::CHARACTER,
1705 0x01}},
1707 // Press Control+CapsLock+a. Confirm that Mod3Mask is rewritten to
1708 // ControlMask
1709 {ui::ET_KEY_PRESSED,
1710 {ui::VKEY_A,
1711 ui::DomCode::KEY_A,
1712 ui::EF_CONTROL_DOWN | ui::EF_MOD3_DOWN,
1713 ui::DomKey::CHARACTER,
1714 'a'},
1715 {ui::VKEY_A,
1716 ui::DomCode::KEY_A,
1717 ui::EF_CONTROL_DOWN,
1718 ui::DomKey::CHARACTER,
1719 0x01}},
1721 // Press Alt+CapsLock+a. Confirm that Mod3Mask is rewritten to
1722 // ControlMask.
1723 {ui::ET_KEY_PRESSED,
1724 {ui::VKEY_A,
1725 ui::DomCode::KEY_A,
1726 ui::EF_ALT_DOWN | ui::EF_MOD3_DOWN,
1727 ui::DomKey::CHARACTER,
1728 'a'},
1729 {ui::VKEY_A,
1730 ui::DomCode::KEY_A,
1731 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1732 ui::DomKey::CHARACTER,
1733 0x01}},
1736 for (const auto& test : tests) {
1737 CheckKeyTestCase(&rewriter, test);
1741 TEST_F(EventRewriterTest, TestRewriteCapsLockMod3InUse) {
1742 // Remap CapsLock to Control.
1743 TestingPrefServiceSyncable prefs;
1744 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1745 IntegerPrefMember control;
1746 control.Init(prefs::kLanguageRemapCapsLockKeyTo, &prefs);
1747 control.SetValue(chromeos::input_method::kControlKey);
1749 EventRewriter rewriter(NULL);
1750 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1751 rewriter.set_pref_service_for_testing(&prefs);
1752 input_method_manager_mock_->set_mod3_used(true);
1754 // Press CapsLock+a. Confirm that Mod3Mask is NOT rewritten to ControlMask
1755 // when Mod3Mask is already in use by the current XKB layout.
1756 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1757 ui::DomCode::KEY_A, ui::EF_NONE,
1758 ui::DomKey::CHARACTER, 'a'),
1759 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1760 ui::DomCode::KEY_A, ui::EF_NONE,
1761 ui::DomKey::CHARACTER, 'a'));
1763 input_method_manager_mock_->set_mod3_used(false);
1766 TEST_F(EventRewriterTest, TestRewriteExtendedKeys) {
1767 TestingPrefServiceSyncable prefs;
1768 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1769 EventRewriter rewriter(NULL);
1770 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1771 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
1772 rewriter.set_pref_service_for_testing(&prefs);
1774 KeyTestCase tests[] = {
1775 // Alt+Backspace -> Delete
1776 {ui::ET_KEY_PRESSED,
1777 {ui::VKEY_BACK,
1778 ui::DomCode::BACKSPACE,
1779 ui::EF_ALT_DOWN,
1780 ui::DomKey::BACKSPACE,
1781 '\b'},
1782 {ui::VKEY_DELETE, ui::DomCode::DEL, ui::EF_NONE, ui::DomKey::DEL, 0x7F}},
1783 // Control+Alt+Backspace -> Control+Delete
1784 {ui::ET_KEY_PRESSED,
1785 {ui::VKEY_BACK,
1786 ui::DomCode::BACKSPACE,
1787 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1788 ui::DomKey::BACKSPACE,
1789 '\b'},
1790 {ui::VKEY_DELETE,
1791 ui::DomCode::DEL,
1792 ui::EF_CONTROL_DOWN,
1793 ui::DomKey::DEL,
1794 0x7F}},
1795 // Search+Alt+Backspace -> Alt+Backspace
1796 {ui::ET_KEY_PRESSED,
1797 {ui::VKEY_BACK,
1798 ui::DomCode::BACKSPACE,
1799 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
1800 ui::DomKey::BACKSPACE,
1801 '\b'},
1802 {ui::VKEY_BACK,
1803 ui::DomCode::BACKSPACE,
1804 ui::EF_ALT_DOWN,
1805 ui::DomKey::BACKSPACE,
1806 '\b'}},
1807 // Search+Control+Alt+Backspace -> Control+Alt+Backspace
1808 {ui::ET_KEY_PRESSED,
1809 {ui::VKEY_BACK,
1810 ui::DomCode::BACKSPACE,
1811 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1812 ui::DomKey::BACKSPACE,
1813 '\b'},
1814 {ui::VKEY_BACK,
1815 ui::DomCode::BACKSPACE,
1816 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1817 ui::DomKey::BACKSPACE,
1818 '\b'}},
1819 // Alt+Up -> Prior
1820 {ui::ET_KEY_PRESSED,
1821 {ui::VKEY_UP,
1822 ui::DomCode::ARROW_UP,
1823 ui::EF_ALT_DOWN,
1824 ui::DomKey::ARROW_UP,
1826 {ui::VKEY_PRIOR,
1827 ui::DomCode::PAGE_UP,
1828 ui::EF_NONE,
1829 ui::DomKey::PAGE_UP,
1830 0}},
1831 // Alt+Down -> Next
1832 {ui::ET_KEY_PRESSED,
1833 {ui::VKEY_DOWN,
1834 ui::DomCode::ARROW_DOWN,
1835 ui::EF_ALT_DOWN,
1836 ui::DomKey::ARROW_DOWN,
1838 {ui::VKEY_NEXT,
1839 ui::DomCode::PAGE_DOWN,
1840 ui::EF_NONE,
1841 ui::DomKey::PAGE_DOWN,
1842 0}},
1843 // Ctrl+Alt+Up -> Home
1844 {ui::ET_KEY_PRESSED,
1845 {ui::VKEY_UP,
1846 ui::DomCode::ARROW_UP,
1847 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1848 ui::DomKey::ARROW_UP,
1850 {ui::VKEY_HOME, ui::DomCode::HOME, ui::EF_NONE, ui::DomKey::HOME, 0}},
1851 // Ctrl+Alt+Down -> End
1852 {ui::ET_KEY_PRESSED,
1853 {ui::VKEY_DOWN,
1854 ui::DomCode::ARROW_DOWN,
1855 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1856 ui::DomKey::ARROW_DOWN,
1858 {ui::VKEY_END, ui::DomCode::END, ui::EF_NONE, ui::DomKey::END, 0}},
1860 // Search+Alt+Up -> Alt+Up
1861 {ui::ET_KEY_PRESSED,
1862 {ui::VKEY_UP,
1863 ui::DomCode::ARROW_UP,
1864 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
1865 ui::DomKey::ARROW_UP,
1867 {ui::VKEY_UP,
1868 ui::DomCode::ARROW_UP,
1869 ui::EF_ALT_DOWN,
1870 ui::DomKey::ARROW_UP,
1871 0}},
1872 // Search+Alt+Down -> Alt+Down
1873 {ui::ET_KEY_PRESSED,
1874 {ui::VKEY_DOWN,
1875 ui::DomCode::ARROW_DOWN,
1876 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
1877 ui::DomKey::ARROW_DOWN,
1879 {ui::VKEY_DOWN,
1880 ui::DomCode::ARROW_DOWN,
1881 ui::EF_ALT_DOWN,
1882 ui::DomKey::ARROW_DOWN,
1883 0}},
1884 // Search+Ctrl+Alt+Up -> Search+Ctrl+Alt+Up
1885 {ui::ET_KEY_PRESSED,
1886 {ui::VKEY_UP,
1887 ui::DomCode::ARROW_UP,
1888 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1889 ui::DomKey::ARROW_UP,
1891 {ui::VKEY_UP,
1892 ui::DomCode::ARROW_UP,
1893 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1894 ui::DomKey::ARROW_UP,
1895 0}},
1896 // Search+Ctrl+Alt+Down -> Ctrl+Alt+Down
1897 {ui::ET_KEY_PRESSED,
1898 {ui::VKEY_DOWN,
1899 ui::DomCode::ARROW_DOWN,
1900 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1901 ui::DomKey::ARROW_DOWN,
1903 {ui::VKEY_DOWN,
1904 ui::DomCode::ARROW_DOWN,
1905 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1906 ui::DomKey::ARROW_DOWN,
1907 0}},
1909 // Period -> Period
1910 {ui::ET_KEY_PRESSED,
1911 {ui::VKEY_OEM_PERIOD,
1912 ui::DomCode::PERIOD,
1913 ui::EF_NONE,
1914 ui::DomKey::CHARACTER,
1915 '.'},
1916 {ui::VKEY_OEM_PERIOD,
1917 ui::DomCode::PERIOD,
1918 ui::EF_NONE,
1919 ui::DomKey::CHARACTER,
1920 '.'}},
1922 // Search+Backspace -> Delete
1923 {ui::ET_KEY_PRESSED,
1924 {ui::VKEY_BACK,
1925 ui::DomCode::BACKSPACE,
1926 ui::EF_COMMAND_DOWN,
1927 ui::DomKey::BACKSPACE,
1928 '\b'},
1929 {ui::VKEY_DELETE, ui::DomCode::DEL, ui::EF_NONE, ui::DomKey::DEL, 0x7F}},
1930 // Search+Up -> Prior
1931 {ui::ET_KEY_PRESSED,
1932 {ui::VKEY_UP,
1933 ui::DomCode::ARROW_UP,
1934 ui::EF_COMMAND_DOWN,
1935 ui::DomKey::ARROW_UP,
1937 {ui::VKEY_PRIOR,
1938 ui::DomCode::PAGE_UP,
1939 ui::EF_NONE,
1940 ui::DomKey::PAGE_UP,
1941 0}},
1942 // Search+Down -> Next
1943 {ui::ET_KEY_PRESSED,
1944 {ui::VKEY_DOWN,
1945 ui::DomCode::ARROW_DOWN,
1946 ui::EF_COMMAND_DOWN,
1947 ui::DomKey::ARROW_DOWN,
1949 {ui::VKEY_NEXT,
1950 ui::DomCode::PAGE_DOWN,
1951 ui::EF_NONE,
1952 ui::DomKey::PAGE_DOWN,
1953 0}},
1954 // Search+Left -> Home
1955 {ui::ET_KEY_PRESSED,
1956 {ui::VKEY_LEFT,
1957 ui::DomCode::ARROW_LEFT,
1958 ui::EF_COMMAND_DOWN,
1959 ui::DomKey::ARROW_LEFT,
1961 {ui::VKEY_HOME, ui::DomCode::HOME, ui::EF_NONE, ui::DomKey::HOME, 0}},
1962 // Control+Search+Left -> Home
1963 {ui::ET_KEY_PRESSED,
1964 {ui::VKEY_LEFT,
1965 ui::DomCode::ARROW_LEFT,
1966 ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN,
1967 ui::DomKey::ARROW_LEFT,
1969 {ui::VKEY_HOME,
1970 ui::DomCode::HOME,
1971 ui::EF_CONTROL_DOWN,
1972 ui::DomKey::HOME,
1973 0}},
1974 // Search+Right -> End
1975 {ui::ET_KEY_PRESSED,
1976 {ui::VKEY_RIGHT,
1977 ui::DomCode::ARROW_RIGHT,
1978 ui::EF_COMMAND_DOWN,
1979 ui::DomKey::ARROW_RIGHT,
1981 {ui::VKEY_END, ui::DomCode::END, ui::EF_NONE, ui::DomKey::END, 0}},
1982 // Control+Search+Right -> End
1983 {ui::ET_KEY_PRESSED,
1984 {ui::VKEY_RIGHT,
1985 ui::DomCode::ARROW_RIGHT,
1986 ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN,
1987 ui::DomKey::ARROW_RIGHT,
1989 {ui::VKEY_END,
1990 ui::DomCode::END,
1991 ui::EF_CONTROL_DOWN,
1992 ui::DomKey::END,
1993 0}},
1994 // Search+Period -> Insert
1995 {ui::ET_KEY_PRESSED,
1996 {ui::VKEY_OEM_PERIOD,
1997 ui::DomCode::PERIOD,
1998 ui::EF_COMMAND_DOWN,
1999 ui::DomKey::CHARACTER,
2000 '.'},
2001 {ui::VKEY_INSERT,
2002 ui::DomCode::INSERT,
2003 ui::EF_NONE,
2004 ui::DomKey::INSERT,
2005 0}},
2006 // Control+Search+Period -> Control+Insert
2007 {ui::ET_KEY_PRESSED,
2008 {ui::VKEY_OEM_PERIOD,
2009 ui::DomCode::PERIOD,
2010 ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN,
2011 ui::DomKey::CHARACTER,
2012 '.'},
2013 {ui::VKEY_INSERT,
2014 ui::DomCode::INSERT,
2015 ui::EF_CONTROL_DOWN,
2016 ui::DomKey::INSERT,
2017 0}}};
2019 for (const auto& test : tests) {
2020 CheckKeyTestCase(&rewriter, test);
2024 TEST_F(EventRewriterTest, TestRewriteFunctionKeys) {
2025 TestingPrefServiceSyncable prefs;
2026 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
2027 EventRewriter rewriter(NULL);
2028 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
2029 rewriter.set_pref_service_for_testing(&prefs);
2031 KeyTestCase tests[] = {
2032 // F1 -> Back
2033 {ui::ET_KEY_PRESSED,
2034 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_NONE, ui::DomKey::F1, 0},
2035 {ui::VKEY_BROWSER_BACK,
2036 ui::DomCode::BROWSER_BACK,
2037 ui::EF_NONE,
2038 ui::DomKey::BROWSER_BACK,
2039 0}},
2040 {ui::ET_KEY_PRESSED,
2041 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_CONTROL_DOWN, ui::DomKey::F1, 0},
2042 {ui::VKEY_BROWSER_BACK,
2043 ui::DomCode::BROWSER_BACK,
2044 ui::EF_CONTROL_DOWN,
2045 ui::DomKey::BROWSER_BACK,
2046 0}},
2047 {ui::ET_KEY_PRESSED,
2048 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_ALT_DOWN, ui::DomKey::F1, 0},
2049 {ui::VKEY_BROWSER_BACK,
2050 ui::DomCode::BROWSER_BACK,
2051 ui::EF_ALT_DOWN,
2052 ui::DomKey::BROWSER_BACK,
2053 0}},
2054 // F2 -> Forward
2055 {ui::ET_KEY_PRESSED,
2056 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_NONE, ui::DomKey::F2, 0},
2057 {ui::VKEY_BROWSER_FORWARD,
2058 ui::DomCode::BROWSER_FORWARD,
2059 ui::EF_NONE,
2060 ui::DomKey::BROWSER_FORWARD,
2061 0}},
2062 {ui::ET_KEY_PRESSED,
2063 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_CONTROL_DOWN, ui::DomKey::F2, 0},
2064 {ui::VKEY_BROWSER_FORWARD,
2065 ui::DomCode::BROWSER_FORWARD,
2066 ui::EF_CONTROL_DOWN,
2067 ui::DomKey::BROWSER_FORWARD,
2068 0}},
2069 {ui::ET_KEY_PRESSED,
2070 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_ALT_DOWN, ui::DomKey::F2, 0},
2071 {ui::VKEY_BROWSER_FORWARD,
2072 ui::DomCode::BROWSER_FORWARD,
2073 ui::EF_ALT_DOWN,
2074 ui::DomKey::BROWSER_FORWARD,
2075 0}},
2076 // F3 -> Refresh
2077 {ui::ET_KEY_PRESSED,
2078 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_NONE, ui::DomKey::F3, 0},
2079 {ui::VKEY_BROWSER_REFRESH,
2080 ui::DomCode::BROWSER_REFRESH,
2081 ui::EF_NONE,
2082 ui::DomKey::BROWSER_REFRESH,
2083 0}},
2084 {ui::ET_KEY_PRESSED,
2085 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_CONTROL_DOWN, ui::DomKey::F3, 0},
2086 {ui::VKEY_BROWSER_REFRESH,
2087 ui::DomCode::BROWSER_REFRESH,
2088 ui::EF_CONTROL_DOWN,
2089 ui::DomKey::BROWSER_REFRESH,
2090 0}},
2091 {ui::ET_KEY_PRESSED,
2092 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_ALT_DOWN, ui::DomKey::F3, 0},
2093 {ui::VKEY_BROWSER_REFRESH,
2094 ui::DomCode::BROWSER_REFRESH,
2095 ui::EF_ALT_DOWN,
2096 ui::DomKey::BROWSER_REFRESH,
2097 0}},
2098 // F4 -> Launch App 2
2099 {ui::ET_KEY_PRESSED,
2100 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_NONE, ui::DomKey::F4, 0},
2101 {ui::VKEY_MEDIA_LAUNCH_APP2,
2102 ui::DomCode::ZOOM_TOGGLE,
2103 ui::EF_NONE,
2104 ui::DomKey::ZOOM_TOGGLE,
2105 0}},
2106 {ui::ET_KEY_PRESSED,
2107 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_CONTROL_DOWN, ui::DomKey::F4, 0},
2108 {ui::VKEY_MEDIA_LAUNCH_APP2,
2109 ui::DomCode::ZOOM_TOGGLE,
2110 ui::EF_CONTROL_DOWN,
2111 ui::DomKey::ZOOM_TOGGLE,
2112 0}},
2113 {ui::ET_KEY_PRESSED,
2114 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_ALT_DOWN, ui::DomKey::F4, 0},
2115 {ui::VKEY_MEDIA_LAUNCH_APP2,
2116 ui::DomCode::ZOOM_TOGGLE,
2117 ui::EF_ALT_DOWN,
2118 ui::DomKey::ZOOM_TOGGLE,
2119 0}},
2120 // F5 -> Launch App 1
2121 {ui::ET_KEY_PRESSED,
2122 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_NONE, ui::DomKey::F5, 0},
2123 {ui::VKEY_MEDIA_LAUNCH_APP1,
2124 ui::DomCode::SELECT_TASK,
2125 ui::EF_NONE,
2126 ui::DomKey::LAUNCH_MY_COMPUTER,
2127 0}},
2128 {ui::ET_KEY_PRESSED,
2129 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_CONTROL_DOWN, ui::DomKey::F5, 0},
2130 {ui::VKEY_MEDIA_LAUNCH_APP1,
2131 ui::DomCode::SELECT_TASK,
2132 ui::EF_CONTROL_DOWN,
2133 ui::DomKey::LAUNCH_MY_COMPUTER,
2134 0}},
2135 {ui::ET_KEY_PRESSED,
2136 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_ALT_DOWN, ui::DomKey::F5, 0},
2137 {ui::VKEY_MEDIA_LAUNCH_APP1,
2138 ui::DomCode::SELECT_TASK,
2139 ui::EF_ALT_DOWN,
2140 ui::DomKey::LAUNCH_MY_COMPUTER,
2141 0}},
2142 // F6 -> Brightness down
2143 {ui::ET_KEY_PRESSED,
2144 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_NONE, ui::DomKey::F6, 0},
2145 {ui::VKEY_BRIGHTNESS_DOWN,
2146 ui::DomCode::BRIGHTNESS_DOWN,
2147 ui::EF_NONE,
2148 ui::DomKey::BRIGHTNESS_DOWN,
2149 0}},
2150 {ui::ET_KEY_PRESSED,
2151 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_CONTROL_DOWN, ui::DomKey::F6, 0},
2152 {ui::VKEY_BRIGHTNESS_DOWN,
2153 ui::DomCode::BRIGHTNESS_DOWN,
2154 ui::EF_CONTROL_DOWN,
2155 ui::DomKey::BRIGHTNESS_DOWN,
2156 0}},
2157 {ui::ET_KEY_PRESSED,
2158 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_ALT_DOWN, ui::DomKey::F6, 0},
2159 {ui::VKEY_BRIGHTNESS_DOWN,
2160 ui::DomCode::BRIGHTNESS_DOWN,
2161 ui::EF_ALT_DOWN,
2162 ui::DomKey::BRIGHTNESS_DOWN,
2163 0}},
2164 // F7 -> Brightness up
2165 {ui::ET_KEY_PRESSED,
2166 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_NONE, ui::DomKey::F7, 0},
2167 {ui::VKEY_BRIGHTNESS_UP,
2168 ui::DomCode::BRIGHTNESS_UP,
2169 ui::EF_NONE,
2170 ui::DomKey::BRIGHTNESS_UP,
2171 0}},
2172 {ui::ET_KEY_PRESSED,
2173 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_CONTROL_DOWN, ui::DomKey::F7, 0},
2174 {ui::VKEY_BRIGHTNESS_UP,
2175 ui::DomCode::BRIGHTNESS_UP,
2176 ui::EF_CONTROL_DOWN,
2177 ui::DomKey::BRIGHTNESS_UP,
2178 0}},
2179 {ui::ET_KEY_PRESSED,
2180 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_ALT_DOWN, ui::DomKey::F7, 0},
2181 {ui::VKEY_BRIGHTNESS_UP,
2182 ui::DomCode::BRIGHTNESS_UP,
2183 ui::EF_ALT_DOWN,
2184 ui::DomKey::BRIGHTNESS_UP,
2185 0}},
2186 // F8 -> Volume Mute
2187 {ui::ET_KEY_PRESSED,
2188 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_NONE, ui::DomKey::F8, 0},
2189 {ui::VKEY_VOLUME_MUTE,
2190 ui::DomCode::VOLUME_MUTE,
2191 ui::EF_NONE,
2192 ui::DomKey::VOLUME_MUTE,
2193 0}},
2194 {ui::ET_KEY_PRESSED,
2195 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_CONTROL_DOWN, ui::DomKey::F8, 0},
2196 {ui::VKEY_VOLUME_MUTE,
2197 ui::DomCode::VOLUME_MUTE,
2198 ui::EF_CONTROL_DOWN,
2199 ui::DomKey::VOLUME_MUTE,
2200 0}},
2201 {ui::ET_KEY_PRESSED,
2202 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_ALT_DOWN, ui::DomKey::F8, 0},
2203 {ui::VKEY_VOLUME_MUTE,
2204 ui::DomCode::VOLUME_MUTE,
2205 ui::EF_ALT_DOWN,
2206 ui::DomKey::VOLUME_MUTE,
2207 0}},
2208 // F9 -> Volume Down
2209 {ui::ET_KEY_PRESSED,
2210 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_NONE, ui::DomKey::F9, 0},
2211 {ui::VKEY_VOLUME_DOWN,
2212 ui::DomCode::VOLUME_DOWN,
2213 ui::EF_NONE,
2214 ui::DomKey::VOLUME_DOWN,
2215 0}},
2216 {ui::ET_KEY_PRESSED,
2217 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_CONTROL_DOWN, ui::DomKey::F9, 0},
2218 {ui::VKEY_VOLUME_DOWN,
2219 ui::DomCode::VOLUME_DOWN,
2220 ui::EF_CONTROL_DOWN,
2221 ui::DomKey::VOLUME_DOWN,
2222 0}},
2223 {ui::ET_KEY_PRESSED,
2224 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_ALT_DOWN, ui::DomKey::F9, 0},
2225 {ui::VKEY_VOLUME_DOWN,
2226 ui::DomCode::VOLUME_DOWN,
2227 ui::EF_ALT_DOWN,
2228 ui::DomKey::VOLUME_DOWN,
2229 0}},
2230 // F10 -> Volume Up
2231 {ui::ET_KEY_PRESSED,
2232 {ui::VKEY_F10, ui::DomCode::F10, ui::EF_NONE, ui::DomKey::F10, 0},
2233 {ui::VKEY_VOLUME_UP,
2234 ui::DomCode::VOLUME_UP,
2235 ui::EF_NONE,
2236 ui::DomKey::VOLUME_UP,
2237 0}},
2238 {ui::ET_KEY_PRESSED,
2239 {ui::VKEY_F10,
2240 ui::DomCode::F10,
2241 ui::EF_CONTROL_DOWN,
2242 ui::DomKey::F10,
2244 {ui::VKEY_VOLUME_UP,
2245 ui::DomCode::VOLUME_UP,
2246 ui::EF_CONTROL_DOWN,
2247 ui::DomKey::VOLUME_UP,
2248 0}},
2249 {ui::ET_KEY_PRESSED,
2250 {ui::VKEY_F10, ui::DomCode::F10, ui::EF_ALT_DOWN, ui::DomKey::F10, 0},
2251 {ui::VKEY_VOLUME_UP,
2252 ui::DomCode::VOLUME_UP,
2253 ui::EF_ALT_DOWN,
2254 ui::DomKey::VOLUME_UP,
2255 0}},
2256 // F11 -> F11
2257 {ui::ET_KEY_PRESSED,
2258 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_NONE, ui::DomKey::F11, 0},
2259 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_NONE, ui::DomKey::F11, 0}},
2260 {ui::ET_KEY_PRESSED,
2261 {ui::VKEY_F11,
2262 ui::DomCode::F11,
2263 ui::EF_CONTROL_DOWN,
2264 ui::DomKey::F11,
2266 {ui::VKEY_F11,
2267 ui::DomCode::F11,
2268 ui::EF_CONTROL_DOWN,
2269 ui::DomKey::F11,
2270 0}},
2271 {ui::ET_KEY_PRESSED,
2272 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_ALT_DOWN, ui::DomKey::F11, 0},
2273 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_ALT_DOWN, ui::DomKey::F11, 0}},
2274 // F12 -> F12
2275 {ui::ET_KEY_PRESSED,
2276 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_NONE, ui::DomKey::F12, 0},
2277 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_NONE, ui::DomKey::F12, 0}},
2278 {ui::ET_KEY_PRESSED,
2279 {ui::VKEY_F12,
2280 ui::DomCode::F12,
2281 ui::EF_CONTROL_DOWN,
2282 ui::DomKey::F12,
2284 {ui::VKEY_F12,
2285 ui::DomCode::F12,
2286 ui::EF_CONTROL_DOWN,
2287 ui::DomKey::F12,
2288 0}},
2289 {ui::ET_KEY_PRESSED,
2290 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_ALT_DOWN, ui::DomKey::F12, 0},
2291 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_ALT_DOWN, ui::DomKey::F12, 0}},
2293 // The number row should not be rewritten without Search key.
2294 {ui::ET_KEY_PRESSED,
2295 {ui::VKEY_1,
2296 ui::DomCode::DIGIT1,
2297 ui::EF_NONE,
2298 ui::DomKey::CHARACTER,
2299 '1'},
2300 {ui::VKEY_1,
2301 ui::DomCode::DIGIT1,
2302 ui::EF_NONE,
2303 ui::DomKey::CHARACTER,
2304 '1'}},
2305 {ui::ET_KEY_PRESSED,
2306 {ui::VKEY_2,
2307 ui::DomCode::DIGIT2,
2308 ui::EF_NONE,
2309 ui::DomKey::CHARACTER,
2310 '2'},
2311 {ui::VKEY_2,
2312 ui::DomCode::DIGIT2,
2313 ui::EF_NONE,
2314 ui::DomKey::CHARACTER,
2315 '2'}},
2316 {ui::ET_KEY_PRESSED,
2317 {ui::VKEY_3,
2318 ui::DomCode::DIGIT3,
2319 ui::EF_NONE,
2320 ui::DomKey::CHARACTER,
2321 '3'},
2322 {ui::VKEY_3,
2323 ui::DomCode::DIGIT3,
2324 ui::EF_NONE,
2325 ui::DomKey::CHARACTER,
2326 '3'}},
2327 {ui::ET_KEY_PRESSED,
2328 {ui::VKEY_4,
2329 ui::DomCode::DIGIT4,
2330 ui::EF_NONE,
2331 ui::DomKey::CHARACTER,
2332 '4'},
2333 {ui::VKEY_4,
2334 ui::DomCode::DIGIT4,
2335 ui::EF_NONE,
2336 ui::DomKey::CHARACTER,
2337 '4'}},
2338 {ui::ET_KEY_PRESSED,
2339 {ui::VKEY_5,
2340 ui::DomCode::DIGIT5,
2341 ui::EF_NONE,
2342 ui::DomKey::CHARACTER,
2343 '5'},
2344 {ui::VKEY_5,
2345 ui::DomCode::DIGIT5,
2346 ui::EF_NONE,
2347 ui::DomKey::CHARACTER,
2348 '5'}},
2349 {ui::ET_KEY_PRESSED,
2350 {ui::VKEY_6,
2351 ui::DomCode::DIGIT6,
2352 ui::EF_NONE,
2353 ui::DomKey::CHARACTER,
2354 '6'},
2355 {ui::VKEY_6,
2356 ui::DomCode::DIGIT6,
2357 ui::EF_NONE,
2358 ui::DomKey::CHARACTER,
2359 '6'}},
2360 {ui::ET_KEY_PRESSED,
2361 {ui::VKEY_7,
2362 ui::DomCode::DIGIT7,
2363 ui::EF_NONE,
2364 ui::DomKey::CHARACTER,
2365 '7'},
2366 {ui::VKEY_7,
2367 ui::DomCode::DIGIT7,
2368 ui::EF_NONE,
2369 ui::DomKey::CHARACTER,
2370 '7'}},
2371 {ui::ET_KEY_PRESSED,
2372 {ui::VKEY_8,
2373 ui::DomCode::DIGIT8,
2374 ui::EF_NONE,
2375 ui::DomKey::CHARACTER,
2376 '8'},
2377 {ui::VKEY_8,
2378 ui::DomCode::DIGIT8,
2379 ui::EF_NONE,
2380 ui::DomKey::CHARACTER,
2381 '8'}},
2382 {ui::ET_KEY_PRESSED,
2383 {ui::VKEY_9,
2384 ui::DomCode::DIGIT9,
2385 ui::EF_NONE,
2386 ui::DomKey::CHARACTER,
2387 '9'},
2388 {ui::VKEY_9,
2389 ui::DomCode::DIGIT9,
2390 ui::EF_NONE,
2391 ui::DomKey::CHARACTER,
2392 '9'}},
2393 {ui::ET_KEY_PRESSED,
2394 {ui::VKEY_0,
2395 ui::DomCode::DIGIT0,
2396 ui::EF_NONE,
2397 ui::DomKey::CHARACTER,
2398 '0'},
2399 {ui::VKEY_0,
2400 ui::DomCode::DIGIT0,
2401 ui::EF_NONE,
2402 ui::DomKey::CHARACTER,
2403 '0'}},
2404 {ui::ET_KEY_PRESSED,
2405 {ui::VKEY_OEM_MINUS,
2406 ui::DomCode::MINUS,
2407 ui::EF_NONE,
2408 ui::DomKey::CHARACTER,
2409 '-'},
2410 {ui::VKEY_OEM_MINUS,
2411 ui::DomCode::MINUS,
2412 ui::EF_NONE,
2413 ui::DomKey::CHARACTER,
2414 '-'}},
2415 {ui::ET_KEY_PRESSED,
2416 {ui::VKEY_OEM_PLUS,
2417 ui::DomCode::EQUAL,
2418 ui::EF_NONE,
2419 ui::DomKey::CHARACTER,
2420 '='},
2421 {ui::VKEY_OEM_PLUS,
2422 ui::DomCode::EQUAL,
2423 ui::EF_NONE,
2424 ui::DomKey::CHARACTER,
2425 '='}},
2427 // The number row should be rewritten as the F<number> row with Search
2428 // key.
2429 {ui::ET_KEY_PRESSED,
2430 {ui::VKEY_1,
2431 ui::DomCode::DIGIT1,
2432 ui::EF_COMMAND_DOWN,
2433 ui::DomKey::CHARACTER,
2434 '1'},
2435 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_NONE, ui::DomKey::F1, 0}},
2436 {ui::ET_KEY_PRESSED,
2437 {ui::VKEY_2,
2438 ui::DomCode::DIGIT2,
2439 ui::EF_COMMAND_DOWN,
2440 ui::DomKey::CHARACTER,
2441 '2'},
2442 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_NONE, ui::DomKey::F2, 0}},
2443 {ui::ET_KEY_PRESSED,
2444 {ui::VKEY_3,
2445 ui::DomCode::DIGIT3,
2446 ui::EF_COMMAND_DOWN,
2447 ui::DomKey::CHARACTER,
2448 '3'},
2449 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_NONE, ui::DomKey::F3, 0}},
2450 {ui::ET_KEY_PRESSED,
2451 {ui::VKEY_4,
2452 ui::DomCode::DIGIT4,
2453 ui::EF_COMMAND_DOWN,
2454 ui::DomKey::CHARACTER,
2455 '4'},
2456 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_NONE, ui::DomKey::F4, 0}},
2457 {ui::ET_KEY_PRESSED,
2458 {ui::VKEY_5,
2459 ui::DomCode::DIGIT5,
2460 ui::EF_COMMAND_DOWN,
2461 ui::DomKey::CHARACTER,
2462 '5'},
2463 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_NONE, ui::DomKey::F5, 0}},
2464 {ui::ET_KEY_PRESSED,
2465 {ui::VKEY_6,
2466 ui::DomCode::DIGIT6,
2467 ui::EF_COMMAND_DOWN,
2468 ui::DomKey::CHARACTER,
2469 '6'},
2470 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_NONE, ui::DomKey::F6, 0}},
2471 {ui::ET_KEY_PRESSED,
2472 {ui::VKEY_7,
2473 ui::DomCode::DIGIT7,
2474 ui::EF_COMMAND_DOWN,
2475 ui::DomKey::CHARACTER,
2476 '7'},
2477 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_NONE, ui::DomKey::F7, 0}},
2478 {ui::ET_KEY_PRESSED,
2479 {ui::VKEY_8,
2480 ui::DomCode::DIGIT8,
2481 ui::EF_COMMAND_DOWN,
2482 ui::DomKey::CHARACTER,
2483 '8'},
2484 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_NONE, ui::DomKey::F8, 0}},
2485 {ui::ET_KEY_PRESSED,
2486 {ui::VKEY_9,
2487 ui::DomCode::DIGIT9,
2488 ui::EF_COMMAND_DOWN,
2489 ui::DomKey::CHARACTER,
2490 '9'},
2491 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_NONE, ui::DomKey::F9, 0}},
2492 {ui::ET_KEY_PRESSED,
2493 {ui::VKEY_0,
2494 ui::DomCode::DIGIT0,
2495 ui::EF_COMMAND_DOWN,
2496 ui::DomKey::CHARACTER,
2497 '0'},
2498 {ui::VKEY_F10, ui::DomCode::F10, ui::EF_NONE, ui::DomKey::F10, 0}},
2499 {ui::ET_KEY_PRESSED,
2500 {ui::VKEY_OEM_MINUS,
2501 ui::DomCode::MINUS,
2502 ui::EF_COMMAND_DOWN,
2503 ui::DomKey::CHARACTER,
2504 '-'},
2505 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_NONE, ui::DomKey::F11, 0}},
2506 {ui::ET_KEY_PRESSED,
2507 {ui::VKEY_OEM_PLUS,
2508 ui::DomCode::EQUAL,
2509 ui::EF_COMMAND_DOWN,
2510 ui::DomKey::CHARACTER,
2511 '='},
2512 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_NONE, ui::DomKey::F12, 0}},
2514 // The function keys should not be rewritten with Search key pressed.
2515 {ui::ET_KEY_PRESSED,
2516 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_COMMAND_DOWN, ui::DomKey::F1, 0},
2517 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_NONE, ui::DomKey::F1, 0}},
2518 {ui::ET_KEY_PRESSED,
2519 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_COMMAND_DOWN, ui::DomKey::F2, 0},
2520 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_NONE, ui::DomKey::F2, 0}},
2521 {ui::ET_KEY_PRESSED,
2522 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_COMMAND_DOWN, ui::DomKey::F3, 0},
2523 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_NONE, ui::DomKey::F3, 0}},
2524 {ui::ET_KEY_PRESSED,
2525 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_COMMAND_DOWN, ui::DomKey::F4, 0},
2526 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_NONE, ui::DomKey::F4, 0}},
2527 {ui::ET_KEY_PRESSED,
2528 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_COMMAND_DOWN, ui::DomKey::F5, 0},
2529 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_NONE, ui::DomKey::F5, 0}},
2530 {ui::ET_KEY_PRESSED,
2531 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_COMMAND_DOWN, ui::DomKey::F6, 0},
2532 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_NONE, ui::DomKey::F6, 0}},
2533 {ui::ET_KEY_PRESSED,
2534 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_COMMAND_DOWN, ui::DomKey::F7, 0},
2535 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_NONE, ui::DomKey::F7, 0}},
2536 {ui::ET_KEY_PRESSED,
2537 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_COMMAND_DOWN, ui::DomKey::F8, 0},
2538 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_NONE, ui::DomKey::F8, 0}},
2539 {ui::ET_KEY_PRESSED,
2540 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_COMMAND_DOWN, ui::DomKey::F9, 0},
2541 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_NONE, ui::DomKey::F9, 0}},
2542 {ui::ET_KEY_PRESSED,
2543 {ui::VKEY_F10,
2544 ui::DomCode::F10,
2545 ui::EF_COMMAND_DOWN,
2546 ui::DomKey::F10,
2548 {ui::VKEY_F10, ui::DomCode::F10, ui::EF_NONE, ui::DomKey::F10, 0}},
2549 {ui::ET_KEY_PRESSED,
2550 {ui::VKEY_F11,
2551 ui::DomCode::F11,
2552 ui::EF_COMMAND_DOWN,
2553 ui::DomKey::F11,
2555 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_NONE, ui::DomKey::F11, 0}},
2556 {ui::ET_KEY_PRESSED,
2557 {ui::VKEY_F12,
2558 ui::DomCode::F12,
2559 ui::EF_COMMAND_DOWN,
2560 ui::DomKey::F12,
2562 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_NONE, ui::DomKey::F12, 0}}};
2564 for (const auto& test : tests) {
2565 CheckKeyTestCase(&rewriter, test);
2569 TEST_F(EventRewriterTest, TestRewriteExtendedKeysWithSearchRemapped) {
2570 const base::CommandLine original_cl(*base::CommandLine::ForCurrentProcess());
2572 // Remap Search to Control.
2573 TestingPrefServiceSyncable prefs;
2574 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
2575 IntegerPrefMember search;
2576 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
2577 search.SetValue(chromeos::input_method::kControlKey);
2579 EventRewriter rewriter(NULL);
2580 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
2581 rewriter.set_pref_service_for_testing(&prefs);
2583 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
2584 chromeos::switches::kHasChromeOSKeyboard, "");
2586 KeyTestCase tests[] = {
2587 // Alt+Search+Down -> End
2588 {ui::ET_KEY_PRESSED,
2589 {ui::VKEY_DOWN,
2590 ui::DomCode::ARROW_DOWN,
2591 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
2592 ui::DomKey::ARROW_DOWN,
2594 {ui::VKEY_END, ui::DomCode::END, ui::EF_NONE, ui::DomKey::END, 0}},
2596 // Shift+Alt+Search+Down -> Shift+End
2597 {ui::ET_KEY_PRESSED,
2598 {ui::VKEY_DOWN,
2599 ui::DomCode::ARROW_DOWN,
2600 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
2601 ui::DomKey::ARROW_DOWN,
2603 {ui::VKEY_END, ui::DomCode::END, ui::EF_SHIFT_DOWN, ui::DomKey::END, 0}},
2606 for (const auto& test : tests) {
2607 CheckKeyTestCase(&rewriter, test);
2610 *base::CommandLine::ForCurrentProcess() = original_cl;
2613 TEST_F(EventRewriterTest, TestRewriteKeyEventSentByXSendEvent) {
2614 // Remap Control to Alt.
2615 TestingPrefServiceSyncable prefs;
2616 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
2617 IntegerPrefMember control;
2618 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
2619 control.SetValue(chromeos::input_method::kAltKey);
2621 EventRewriter rewriter(NULL);
2622 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
2623 rewriter.set_pref_service_for_testing(&prefs);
2625 // Send left control press.
2627 ui::KeyEvent keyevent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL,
2628 ui::DomCode::CONTROL_LEFT, ui::EF_FINAL,
2629 ui::DomKey::CONTROL, 0, ui::EventTimeForNow());
2630 scoped_ptr<ui::Event> new_event;
2631 // Control should NOT be remapped to Alt if EF_FINAL is set.
2632 EXPECT_EQ(ui::EVENT_REWRITE_CONTINUE,
2633 rewriter.RewriteEvent(keyevent, &new_event));
2634 EXPECT_FALSE(new_event);
2636 #if defined(USE_X11)
2637 // Send left control press, using XI2 native events.
2639 ui::ScopedXI2Event xev;
2640 xev.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, 0);
2641 XEvent* xevent = xev;
2642 xevent->xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), XK_Control_L);
2643 xevent->xkey.send_event = True; // XSendEvent() always does this.
2644 ui::KeyEvent keyevent(xev);
2645 scoped_ptr<ui::Event> new_event;
2646 // Control should NOT be remapped to Alt if send_event
2647 // flag in the event is True.
2648 EXPECT_EQ(ui::EVENT_REWRITE_CONTINUE,
2649 rewriter.RewriteEvent(keyevent, &new_event));
2650 EXPECT_FALSE(new_event);
2652 #endif
2655 TEST_F(EventRewriterTest, TestRewriteNonNativeEvent) {
2656 // Remap Control to Alt.
2657 TestingPrefServiceSyncable prefs;
2658 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
2659 IntegerPrefMember control;
2660 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
2661 control.SetValue(chromeos::input_method::kAltKey);
2663 EventRewriter rewriter(NULL);
2664 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
2665 rewriter.set_pref_service_for_testing(&prefs);
2667 const int kTouchId = 2;
2668 gfx::Point location(0, 0);
2669 ui::TouchEvent press(ui::ET_TOUCH_PRESSED, location, kTouchId,
2670 base::TimeDelta());
2671 press.set_flags(ui::EF_CONTROL_DOWN);
2672 #if defined(USE_X11)
2673 ui::UpdateX11EventForFlags(&press);
2674 #endif
2676 scoped_ptr<ui::Event> new_event;
2677 rewriter.RewriteEvent(press, &new_event);
2678 EXPECT_TRUE(new_event);
2679 // Control should be remapped to Alt.
2680 EXPECT_EQ(ui::EF_ALT_DOWN,
2681 new_event->flags() & (ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN));
2684 // Keeps a buffer of handled events.
2685 class EventBuffer : public ui::test::TestEventProcessor {
2686 public:
2687 EventBuffer() {}
2688 ~EventBuffer() override {}
2690 void PopEvents(ScopedVector<ui::Event>* events) {
2691 events->clear();
2692 events->swap(events_);
2695 private:
2696 // ui::EventProcessor overrides:
2697 ui::EventDispatchDetails OnEventFromSource(ui::Event* event) override {
2698 if (event->IsKeyEvent()) {
2699 events_.push_back(new ui::KeyEvent(*static_cast<ui::KeyEvent*>(event)));
2700 } else if (event->IsMouseWheelEvent()) {
2701 events_.push_back(
2702 new ui::MouseWheelEvent(*static_cast<ui::MouseWheelEvent*>(event)));
2703 } else if (event->IsMouseEvent()) {
2704 events_.push_back(
2705 new ui::MouseEvent(*static_cast<ui::MouseEvent*>(event)));
2707 return ui::EventDispatchDetails();
2710 ScopedVector<ui::Event> events_;
2712 DISALLOW_COPY_AND_ASSIGN(EventBuffer);
2715 // Trivial EventSource that does nothing but send events.
2716 class TestEventSource : public ui::EventSource {
2717 public:
2718 explicit TestEventSource(ui::EventProcessor* processor)
2719 : processor_(processor) {}
2720 ui::EventProcessor* GetEventProcessor() override { return processor_; }
2721 ui::EventDispatchDetails Send(ui::Event* event) {
2722 return SendEventToProcessor(event);
2725 private:
2726 ui::EventProcessor* processor_;
2729 // Tests of event rewriting that depend on the Ash window manager.
2730 class EventRewriterAshTest : public ash::test::AshTestBase {
2731 public:
2732 EventRewriterAshTest()
2733 : source_(&buffer_),
2734 fake_user_manager_(new user_manager::FakeUserManager),
2735 user_manager_enabler_(fake_user_manager_) {}
2736 ~EventRewriterAshTest() override {}
2738 bool RewriteFunctionKeys(const ui::Event& event,
2739 scoped_ptr<ui::Event>* rewritten_event) {
2740 return rewriter_->RewriteEvent(event, rewritten_event);
2743 ui::EventDispatchDetails Send(ui::Event* event) {
2744 return source_.Send(event);
2747 void SendKeyEvent(ui::EventType type,
2748 ui::KeyboardCode key_code,
2749 ui::DomCode code,
2750 ui::DomKey key,
2751 base::char16 character) {
2752 ui::KeyEvent press(type, key_code, code, ui::EF_NONE, key, character,
2753 ui::EventTimeForNow());
2754 ui::EventDispatchDetails details = Send(&press);
2755 CHECK(!details.dispatcher_destroyed);
2758 void SendActivateStickyKeyPattern(ui::KeyboardCode key_code,
2759 ui::DomCode code,
2760 ui::DomKey key,
2761 base::char16 character) {
2762 SendKeyEvent(ui::ET_KEY_PRESSED, key_code, code, key, character);
2763 SendKeyEvent(ui::ET_KEY_RELEASED, key_code, code, key, character);
2766 protected:
2767 TestingPrefServiceSyncable* prefs() { return &prefs_; }
2769 void PopEvents(ScopedVector<ui::Event>* events) { buffer_.PopEvents(events); }
2771 void SetUp() override {
2772 AshTestBase::SetUp();
2773 sticky_keys_controller_ =
2774 ash::Shell::GetInstance()->sticky_keys_controller();
2775 rewriter_.reset(new EventRewriter(sticky_keys_controller_));
2776 chromeos::Preferences::RegisterProfilePrefs(prefs_.registry());
2777 rewriter_->set_pref_service_for_testing(&prefs_);
2778 #if defined(USE_X11)
2779 ui::SetUpTouchPadForTest(kTouchPadDeviceId);
2780 #endif
2781 source_.AddEventRewriter(rewriter_.get());
2782 sticky_keys_controller_->Enable(true);
2785 void TearDown() override {
2786 rewriter_.reset();
2787 AshTestBase::TearDown();
2790 protected:
2791 ash::StickyKeysController* sticky_keys_controller_;
2793 private:
2794 scoped_ptr<EventRewriter> rewriter_;
2796 EventBuffer buffer_;
2797 TestEventSource source_;
2799 user_manager::FakeUserManager* fake_user_manager_; // Not owned.
2800 chromeos::ScopedUserManagerEnabler user_manager_enabler_;
2801 TestingPrefServiceSyncable prefs_;
2803 DISALLOW_COPY_AND_ASSIGN(EventRewriterAshTest);
2806 TEST_F(EventRewriterAshTest, TopRowKeysAreFunctionKeys) {
2807 scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(1));
2808 ash::wm::WindowState* window_state = ash::wm::GetWindowState(window.get());
2809 window_state->Activate();
2810 ScopedVector<ui::Event> events;
2812 // Create a simulated keypress of F1 targetted at the window.
2813 ui::KeyEvent press_f1(ui::ET_KEY_PRESSED, ui::VKEY_F1, ui::DomCode::F1,
2814 ui::EF_NONE, ui::DomKey::F1, 0, ui::EventTimeForNow());
2816 // Simulate an apps v2 window that has requested top row keys as function
2817 // keys. The event should not be rewritten.
2818 window_state->set_top_row_keys_are_function_keys(true);
2819 ui::EventDispatchDetails details = Send(&press_f1);
2820 ASSERT_FALSE(details.dispatcher_destroyed);
2821 PopEvents(&events);
2822 EXPECT_EQ(1u, events.size());
2823 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_F1,
2824 ui::DomCode::F1, ui::EF_NONE,
2825 ui::DomKey::F1, 0),
2826 GetKeyEventAsString(*static_cast<ui::KeyEvent*>(events[0])));
2828 // The event should also not be rewritten if the send-function-keys pref is
2829 // additionally set, for both apps v2 and regular windows.
2830 BooleanPrefMember send_function_keys_pref;
2831 send_function_keys_pref.Init(prefs::kLanguageSendFunctionKeys, prefs());
2832 send_function_keys_pref.SetValue(true);
2833 window_state->set_top_row_keys_are_function_keys(false);
2834 details = Send(&press_f1);
2835 ASSERT_FALSE(details.dispatcher_destroyed);
2836 PopEvents(&events);
2837 EXPECT_EQ(1u, events.size());
2838 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_F1,
2839 ui::DomCode::F1, ui::EF_NONE,
2840 ui::DomKey::F1, 0),
2841 GetKeyEventAsString(*static_cast<ui::KeyEvent*>(events[0])));
2843 // If the pref isn't set when an event is sent to a regular window, F1 is
2844 // rewritten to the back key.
2845 send_function_keys_pref.SetValue(false);
2846 details = Send(&press_f1);
2847 ASSERT_FALSE(details.dispatcher_destroyed);
2848 PopEvents(&events);
2849 EXPECT_EQ(1u, events.size());
2850 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_BROWSER_BACK,
2851 ui::DomCode::BROWSER_BACK, ui::EF_NONE,
2852 ui::DomKey::BROWSER_BACK, 0),
2853 GetKeyEventAsString(*static_cast<ui::KeyEvent*>(events[0])));
2856 TEST_F(EventRewriterTest, TestRewrittenModifierClick) {
2857 #if defined(USE_X11)
2858 std::vector<int> device_list;
2859 device_list.push_back(10);
2860 ui::TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
2862 // Remap Control to Alt.
2863 TestingPrefServiceSyncable prefs;
2864 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
2865 IntegerPrefMember control;
2866 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
2867 control.SetValue(chromeos::input_method::kAltKey);
2869 EventRewriter rewriter(NULL);
2870 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
2871 rewriter.set_pref_service_for_testing(&prefs);
2873 // Check that Control + Left Button is converted (via Alt + Left Button)
2874 // to Right Button.
2875 ui::ScopedXI2Event xev;
2876 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_PRESSED, gfx::Point(),
2877 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_CONTROL_DOWN);
2878 ui::MouseEvent press(xev);
2879 // Sanity check.
2880 EXPECT_EQ(ui::ET_MOUSE_PRESSED, press.type());
2881 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON | ui::EF_CONTROL_DOWN, press.flags());
2882 scoped_ptr<ui::Event> new_event;
2883 const ui::MouseEvent* result =
2884 RewriteMouseButtonEvent(&rewriter, press, &new_event);
2885 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2886 EXPECT_FALSE(ui::EF_LEFT_MOUSE_BUTTON & result->flags());
2887 EXPECT_FALSE(ui::EF_CONTROL_DOWN & result->flags());
2888 EXPECT_FALSE(ui::EF_ALT_DOWN & result->flags());
2889 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2890 #endif
2893 TEST_F(EventRewriterTest, DontRewriteIfNotRewritten) {
2894 // TODO(kpschoedel): pending changes for crbug.com/360377
2895 // to |chromeos::EventRewriter::RewriteLocatedEvent()
2896 #if defined(USE_X11)
2897 std::vector<int> device_list;
2898 device_list.push_back(10);
2899 device_list.push_back(11);
2900 ui::TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
2901 #endif
2902 TestingPrefServiceSyncable prefs;
2903 EventRewriter rewriter(NULL);
2904 rewriter.set_pref_service_for_testing(&prefs);
2905 const int kLeftAndAltFlag = ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN;
2907 // Test Alt + Left click.
2909 ui::MouseEvent press(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
2910 ui::EventTimeForNow(), kLeftAndAltFlag,
2911 ui::EF_LEFT_MOUSE_BUTTON);
2912 ui::EventTestApi test_press(&press);
2913 test_press.set_source_device_id(10);
2914 // Sanity check.
2915 EXPECT_EQ(ui::ET_MOUSE_PRESSED, press.type());
2916 EXPECT_EQ(kLeftAndAltFlag, press.flags());
2917 scoped_ptr<ui::Event> new_event;
2918 const ui::MouseEvent* result =
2919 RewriteMouseButtonEvent(&rewriter, press, &new_event);
2920 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2921 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2922 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2925 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
2926 ui::EventTimeForNow(), kLeftAndAltFlag,
2927 ui::EF_LEFT_MOUSE_BUTTON);
2928 ui::EventTestApi test_release(&release);
2929 test_release.set_source_device_id(10);
2930 scoped_ptr<ui::Event> new_event;
2931 const ui::MouseEvent* result =
2932 RewriteMouseButtonEvent(&rewriter, release, &new_event);
2933 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2934 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2935 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2937 #if defined(USE_X11)
2938 // Test Alt + Left click, using XI2 native events.
2940 ui::ScopedXI2Event xev;
2941 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_PRESSED, gfx::Point(),
2942 kLeftAndAltFlag);
2943 ui::MouseEvent press(xev);
2944 // Sanity check.
2945 EXPECT_EQ(ui::ET_MOUSE_PRESSED, press.type());
2946 EXPECT_EQ(kLeftAndAltFlag, press.flags());
2947 scoped_ptr<ui::Event> new_event;
2948 const ui::MouseEvent* result =
2949 RewriteMouseButtonEvent(&rewriter, press, &new_event);
2950 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2951 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2952 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2955 ui::ScopedXI2Event xev;
2956 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_RELEASED, gfx::Point(),
2957 kLeftAndAltFlag);
2958 ui::MouseEvent release(xev);
2959 scoped_ptr<ui::Event> new_event;
2960 const ui::MouseEvent* result =
2961 RewriteMouseButtonEvent(&rewriter, release, &new_event);
2962 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2963 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2964 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2966 #endif
2968 // No ALT in frst click.
2970 ui::MouseEvent press(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
2971 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2972 ui::EF_LEFT_MOUSE_BUTTON);
2973 ui::EventTestApi test_press(&press);
2974 test_press.set_source_device_id(10);
2975 scoped_ptr<ui::Event> new_event;
2976 const ui::MouseEvent* result =
2977 RewriteMouseButtonEvent(&rewriter, press, &new_event);
2978 EXPECT_TRUE(ui::EF_LEFT_MOUSE_BUTTON & result->flags());
2979 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
2982 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
2983 ui::EventTimeForNow(), kLeftAndAltFlag,
2984 ui::EF_LEFT_MOUSE_BUTTON);
2985 ui::EventTestApi test_release(&release);
2986 test_release.set_source_device_id(10);
2987 scoped_ptr<ui::Event> new_event;
2988 const ui::MouseEvent* result =
2989 RewriteMouseButtonEvent(&rewriter, release, &new_event);
2990 EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & result->flags());
2991 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
2993 #if defined(USE_X11)
2994 // No ALT in frst click, using XI2 native events.
2996 ui::ScopedXI2Event xev;
2997 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_PRESSED, gfx::Point(),
2998 ui::EF_LEFT_MOUSE_BUTTON);
2999 ui::MouseEvent press(xev);
3000 scoped_ptr<ui::Event> new_event;
3001 const ui::MouseEvent* result =
3002 RewriteMouseButtonEvent(&rewriter, press, &new_event);
3003 EXPECT_TRUE(ui::EF_LEFT_MOUSE_BUTTON & result->flags());
3004 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
3007 ui::ScopedXI2Event xev;
3008 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_RELEASED, gfx::Point(),
3009 kLeftAndAltFlag);
3010 ui::MouseEvent release(xev);
3011 scoped_ptr<ui::Event> new_event;
3012 const ui::MouseEvent* result =
3013 RewriteMouseButtonEvent(&rewriter, release, &new_event);
3014 EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & result->flags());
3015 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
3017 #endif
3019 // ALT on different device.
3021 ui::MouseEvent press(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
3022 ui::EventTimeForNow(), kLeftAndAltFlag,
3023 ui::EF_LEFT_MOUSE_BUTTON);
3024 ui::EventTestApi test_press(&press);
3025 test_press.set_source_device_id(11);
3026 scoped_ptr<ui::Event> new_event;
3027 const ui::MouseEvent* result =
3028 RewriteMouseButtonEvent(&rewriter, press, &new_event);
3029 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
3030 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
3031 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
3034 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
3035 ui::EventTimeForNow(), kLeftAndAltFlag,
3036 ui::EF_LEFT_MOUSE_BUTTON);
3037 ui::EventTestApi test_release(&release);
3038 test_release.set_source_device_id(10);
3039 scoped_ptr<ui::Event> new_event;
3040 const ui::MouseEvent* result =
3041 RewriteMouseButtonEvent(&rewriter, release, &new_event);
3042 EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & result->flags());
3043 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
3046 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
3047 ui::EventTimeForNow(), kLeftAndAltFlag,
3048 ui::EF_LEFT_MOUSE_BUTTON);
3049 ui::EventTestApi test_release(&release);
3050 test_release.set_source_device_id(11);
3051 scoped_ptr<ui::Event> new_event;
3052 const ui::MouseEvent* result =
3053 RewriteMouseButtonEvent(&rewriter, release, &new_event);
3054 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
3055 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
3056 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
3058 #if defined(USE_X11)
3059 // ALT on different device, using XI2 native events.
3061 ui::ScopedXI2Event xev;
3062 xev.InitGenericButtonEvent(11, ui::ET_MOUSE_PRESSED, gfx::Point(),
3063 kLeftAndAltFlag);
3064 ui::MouseEvent press(xev);
3065 scoped_ptr<ui::Event> new_event;
3066 const ui::MouseEvent* result =
3067 RewriteMouseButtonEvent(&rewriter, press, &new_event);
3068 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
3069 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
3070 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
3073 ui::ScopedXI2Event xev;
3074 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_RELEASED, gfx::Point(),
3075 kLeftAndAltFlag);
3076 ui::MouseEvent release(xev);
3077 scoped_ptr<ui::Event> new_event;
3078 const ui::MouseEvent* result =
3079 RewriteMouseButtonEvent(&rewriter, release, &new_event);
3080 EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & result->flags());
3081 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
3084 ui::ScopedXI2Event xev;
3085 xev.InitGenericButtonEvent(11, ui::ET_MOUSE_RELEASED, gfx::Point(),
3086 kLeftAndAltFlag);
3087 ui::MouseEvent release(xev);
3088 scoped_ptr<ui::Event> new_event;
3089 const ui::MouseEvent* result =
3090 RewriteMouseButtonEvent(&rewriter, release, &new_event);
3091 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
3092 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
3093 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
3095 #endif
3098 TEST_F(EventRewriterAshTest, StickyKeyEventDispatchImpl) {
3099 // Test the actual key event dispatch implementation.
3100 ScopedVector<ui::Event> events;
3102 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3103 ui::DomKey::CONTROL, 0);
3104 PopEvents(&events);
3105 EXPECT_EQ(1u, events.size());
3106 EXPECT_EQ(ui::ET_KEY_PRESSED, events[0]->type());
3107 EXPECT_EQ(ui::VKEY_CONTROL,
3108 static_cast<ui::KeyEvent*>(events[0])->key_code());
3110 // Test key press event is correctly modified and modifier release
3111 // event is sent.
3112 ui::KeyEvent press(ui::ET_KEY_PRESSED, ui::VKEY_C, ui::DomCode::KEY_C,
3113 ui::EF_NONE, ui::DomKey::CHARACTER, 'c',
3114 ui::EventTimeForNow());
3115 ui::EventDispatchDetails details = Send(&press);
3116 PopEvents(&events);
3117 EXPECT_EQ(2u, events.size());
3118 EXPECT_EQ(ui::ET_KEY_PRESSED, events[0]->type());
3119 EXPECT_EQ(ui::VKEY_C, static_cast<ui::KeyEvent*>(events[0])->key_code());
3120 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
3121 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
3122 EXPECT_EQ(ui::VKEY_CONTROL,
3123 static_cast<ui::KeyEvent*>(events[1])->key_code());
3125 // Test key release event is not modified.
3126 ui::KeyEvent release(ui::ET_KEY_RELEASED, ui::VKEY_C, ui::DomCode::KEY_C,
3127 ui::EF_NONE, ui::DomKey::CHARACTER, 'c',
3128 ui::EventTimeForNow());
3129 details = Send(&release);
3130 ASSERT_FALSE(details.dispatcher_destroyed);
3131 PopEvents(&events);
3132 EXPECT_EQ(1u, events.size());
3133 EXPECT_EQ(ui::ET_KEY_RELEASED, events[0]->type());
3134 EXPECT_EQ(ui::VKEY_C, static_cast<ui::KeyEvent*>(events[0])->key_code());
3135 EXPECT_FALSE(events[0]->flags() & ui::EF_CONTROL_DOWN);
3138 TEST_F(EventRewriterAshTest, MouseEventDispatchImpl) {
3139 ScopedVector<ui::Event> events;
3141 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3142 ui::DomKey::CONTROL, 0);
3143 PopEvents(&events);
3145 // Test mouse press event is correctly modified.
3146 gfx::Point location(0, 0);
3147 ui::MouseEvent press(ui::ET_MOUSE_PRESSED, location, location,
3148 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
3149 ui::EF_LEFT_MOUSE_BUTTON);
3150 ui::EventDispatchDetails details = Send(&press);
3151 ASSERT_FALSE(details.dispatcher_destroyed);
3152 PopEvents(&events);
3153 EXPECT_EQ(1u, events.size());
3154 EXPECT_EQ(ui::ET_MOUSE_PRESSED, events[0]->type());
3155 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
3157 // Test mouse release event is correctly modified and modifier release
3158 // event is sent. The mouse event should have the correct DIP location.
3159 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, location, location,
3160 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
3161 ui::EF_LEFT_MOUSE_BUTTON);
3162 details = Send(&release);
3163 ASSERT_FALSE(details.dispatcher_destroyed);
3164 PopEvents(&events);
3165 EXPECT_EQ(2u, events.size());
3166 EXPECT_EQ(ui::ET_MOUSE_RELEASED, events[0]->type());
3167 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
3168 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
3169 EXPECT_EQ(ui::VKEY_CONTROL,
3170 static_cast<ui::KeyEvent*>(events[1])->key_code());
3173 TEST_F(EventRewriterAshTest, MouseWheelEventDispatchImpl) {
3174 ScopedVector<ui::Event> events;
3176 // Test positive mouse wheel event is correctly modified and modifier release
3177 // event is sent.
3178 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3179 ui::DomKey::CONTROL, 0);
3180 PopEvents(&events);
3181 gfx::Point location(0, 0);
3182 ui::MouseEvent mev(ui::ET_MOUSEWHEEL, location, location,
3183 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
3184 ui::EF_LEFT_MOUSE_BUTTON);
3185 ui::MouseWheelEvent positive(mev, 0, ui::MouseWheelEvent::kWheelDelta);
3186 ui::EventDispatchDetails details = Send(&positive);
3187 ASSERT_FALSE(details.dispatcher_destroyed);
3188 PopEvents(&events);
3189 EXPECT_EQ(2u, events.size());
3190 EXPECT_TRUE(events[0]->IsMouseWheelEvent());
3191 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
3192 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
3193 EXPECT_EQ(ui::VKEY_CONTROL,
3194 static_cast<ui::KeyEvent*>(events[1])->key_code());
3196 // Test negative mouse wheel event is correctly modified and modifier release
3197 // event is sent.
3198 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3199 ui::DomKey::CONTROL, 0);
3200 PopEvents(&events);
3201 ui::MouseWheelEvent negative(mev, 0, -ui::MouseWheelEvent::kWheelDelta);
3202 details = Send(&negative);
3203 ASSERT_FALSE(details.dispatcher_destroyed);
3204 PopEvents(&events);
3205 EXPECT_EQ(2u, events.size());
3206 EXPECT_TRUE(events[0]->IsMouseWheelEvent());
3207 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
3208 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
3209 EXPECT_EQ(ui::VKEY_CONTROL,
3210 static_cast<ui::KeyEvent*>(events[1])->key_code());
3213 class StickyKeysOverlayTest : public EventRewriterAshTest {
3214 public:
3215 StickyKeysOverlayTest() : overlay_(NULL) {}
3217 ~StickyKeysOverlayTest() override {}
3219 void SetUp() override {
3220 EventRewriterAshTest::SetUp();
3221 overlay_ = sticky_keys_controller_->GetOverlayForTest();
3222 ASSERT_TRUE(overlay_);
3225 ash::StickyKeysOverlay* overlay_;
3228 TEST_F(StickyKeysOverlayTest, OneModifierEnabled) {
3229 EXPECT_FALSE(overlay_->is_visible());
3230 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3231 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3233 // Pressing modifier key should show overlay.
3234 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3235 ui::DomKey::CONTROL, 0);
3236 EXPECT_TRUE(overlay_->is_visible());
3237 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
3238 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3240 // Pressing a normal key should hide overlay.
3241 SendActivateStickyKeyPattern(ui::VKEY_T, ui::DomCode::KEY_T,
3242 ui::DomKey::CHARACTER, 't');
3243 EXPECT_FALSE(overlay_->is_visible());
3244 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3245 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3248 TEST_F(StickyKeysOverlayTest, TwoModifiersEnabled) {
3249 EXPECT_FALSE(overlay_->is_visible());
3250 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3251 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3252 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3253 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3255 // Pressing two modifiers should show overlay.
3256 SendActivateStickyKeyPattern(ui::VKEY_SHIFT, ui::DomCode::SHIFT_LEFT,
3257 ui::DomKey::SHIFT, 0);
3258 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3259 ui::DomKey::CONTROL, 0);
3260 EXPECT_TRUE(overlay_->is_visible());
3261 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
3262 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3263 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
3264 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3266 // Pressing a normal key should hide overlay.
3267 SendActivateStickyKeyPattern(ui::VKEY_N, ui::DomCode::KEY_N,
3268 ui::DomKey::CHARACTER, 'n');
3269 EXPECT_FALSE(overlay_->is_visible());
3270 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3271 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3272 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3273 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3276 TEST_F(StickyKeysOverlayTest, LockedModifier) {
3277 EXPECT_FALSE(overlay_->is_visible());
3278 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3279 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
3281 // Pressing a modifier key twice should lock modifier and show overlay.
3282 SendActivateStickyKeyPattern(ui::VKEY_LMENU, ui::DomCode::ALT_LEFT,
3283 ui::DomKey::ALT, 0);
3284 SendActivateStickyKeyPattern(ui::VKEY_LMENU, ui::DomCode::ALT_LEFT,
3285 ui::DomKey::ALT, 0);
3286 EXPECT_TRUE(overlay_->is_visible());
3287 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
3288 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
3290 // Pressing a normal key should not hide overlay.
3291 SendActivateStickyKeyPattern(ui::VKEY_D, ui::DomCode::KEY_D,
3292 ui::DomKey::CHARACTER, 'd');
3293 EXPECT_TRUE(overlay_->is_visible());
3294 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
3295 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
3298 TEST_F(StickyKeysOverlayTest, LockedAndNormalModifier) {
3299 EXPECT_FALSE(overlay_->is_visible());
3300 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3301 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3302 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3303 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3305 // Pressing a modifier key twice should lock modifier and show overlay.
3306 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3307 ui::DomKey::CONTROL, 0);
3308 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3309 ui::DomKey::CONTROL, 0);
3310 EXPECT_TRUE(overlay_->is_visible());
3311 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
3312 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3314 // Pressing another modifier key should still show overlay.
3315 SendActivateStickyKeyPattern(ui::VKEY_SHIFT, ui::DomCode::SHIFT_LEFT,
3316 ui::DomKey::SHIFT, 0);
3317 EXPECT_TRUE(overlay_->is_visible());
3318 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
3319 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3320 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
3321 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3323 // Pressing a normal key should not hide overlay but disable normal modifier.
3324 SendActivateStickyKeyPattern(ui::VKEY_D, ui::DomCode::KEY_D,
3325 ui::DomKey::CHARACTER, 'd');
3326 EXPECT_TRUE(overlay_->is_visible());
3327 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
3328 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3329 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3330 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3333 TEST_F(StickyKeysOverlayTest, ModifiersDisabled) {
3334 EXPECT_FALSE(overlay_->is_visible());
3335 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3336 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3337 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3338 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3339 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3340 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
3341 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3342 overlay_->GetModifierKeyState(ui::EF_COMMAND_DOWN));
3344 // Enable modifiers.
3345 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3346 ui::DomKey::CONTROL, 0);
3347 SendActivateStickyKeyPattern(ui::VKEY_SHIFT, ui::DomCode::SHIFT_LEFT,
3348 ui::DomKey::SHIFT, 0);
3349 SendActivateStickyKeyPattern(ui::VKEY_SHIFT, ui::DomCode::SHIFT_LEFT,
3350 ui::DomKey::SHIFT, 0);
3351 SendActivateStickyKeyPattern(ui::VKEY_LMENU, ui::DomCode::ALT_LEFT,
3352 ui::DomKey::ALT, 0);
3353 SendActivateStickyKeyPattern(ui::VKEY_COMMAND, ui::DomCode::OS_LEFT,
3354 ui::DomKey::OS, 0);
3355 SendActivateStickyKeyPattern(ui::VKEY_COMMAND, ui::DomCode::OS_LEFT,
3356 ui::DomKey::OS, 0);
3358 EXPECT_TRUE(overlay_->is_visible());
3359 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
3360 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3361 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
3362 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3363 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
3364 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
3365 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
3366 overlay_->GetModifierKeyState(ui::EF_COMMAND_DOWN));
3368 // Disable modifiers and overlay should be hidden.
3369 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3370 ui::DomKey::CONTROL, 0);
3371 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3372 ui::DomKey::CONTROL, 0);
3373 SendActivateStickyKeyPattern(ui::VKEY_SHIFT, ui::DomCode::SHIFT_LEFT,
3374 ui::DomKey::SHIFT, 0);
3375 SendActivateStickyKeyPattern(ui::VKEY_LMENU, ui::DomCode::ALT_LEFT,
3376 ui::DomKey::ALT, 0);
3377 SendActivateStickyKeyPattern(ui::VKEY_LMENU, ui::DomCode::ALT_LEFT,
3378 ui::DomKey::ALT, 0);
3379 SendActivateStickyKeyPattern(ui::VKEY_COMMAND, ui::DomCode::OS_LEFT,
3380 ui::DomKey::OS, 0);
3382 EXPECT_FALSE(overlay_->is_visible());
3383 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3384 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3385 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3386 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3387 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3388 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
3389 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3390 overlay_->GetModifierKeyState(ui::EF_COMMAND_DOWN));
3393 TEST_F(StickyKeysOverlayTest, ModifierVisibility) {
3394 // All but AltGr and Mod3 should initially be visible.
3395 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_CONTROL_DOWN));
3396 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_SHIFT_DOWN));
3397 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALT_DOWN));
3398 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_COMMAND_DOWN));
3399 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
3400 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
3402 // Turn all modifiers on.
3403 sticky_keys_controller_->SetModifiersEnabled(true, true);
3404 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_CONTROL_DOWN));
3405 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_SHIFT_DOWN));
3406 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALT_DOWN));
3407 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_COMMAND_DOWN));
3408 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
3409 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
3411 // Turn off Mod3.
3412 sticky_keys_controller_->SetModifiersEnabled(false, true);
3413 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
3414 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
3416 // Turn off AltGr.
3417 sticky_keys_controller_->SetModifiersEnabled(true, false);
3418 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
3419 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
3421 // Turn off AltGr and Mod3.
3422 sticky_keys_controller_->SetModifiersEnabled(false, false);
3423 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
3424 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
3427 } // namespace chromeos