Move StartsWith[ASCII] to base namespace.
[chromium-blink-merge.git] / chrome / browser / chromeos / events / event_rewriter_unittest.cc
blob711042272b0a6b81b81dd2190fbefe9eabd595ca
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 const int kMasterKeyboardDeviceId = 3;
54 #endif
55 const int kKeyboardDeviceId = 2;
57 std::string GetExpectedResultAsString(ui::EventType ui_type,
58 ui::KeyboardCode ui_keycode,
59 ui::DomCode code,
60 int ui_flags, // ui::EventFlags
61 ui::DomKey key,
62 base::char16 character) {
63 return base::StringPrintf("ui_keycode=0x%X ui_flags=0x%X ui_type=%d",
64 ui_keycode,
65 ui_flags & ~ui::EF_IS_REPEAT,
66 ui_type);
69 std::string GetKeyEventAsString(const ui::KeyEvent& keyevent) {
70 return GetExpectedResultAsString(
71 keyevent.type(), keyevent.key_code(), keyevent.code(), keyevent.flags(),
72 keyevent.GetDomKey(), keyevent.GetCharacter());
75 std::string GetRewrittenEventAsString(chromeos::EventRewriter* rewriter,
76 ui::EventType ui_type,
77 ui::KeyboardCode ui_keycode,
78 ui::DomCode code,
79 int ui_flags, // ui::EventFlags
80 ui::DomKey key,
81 base::char16 character) {
82 const ui::KeyEvent event(ui_type, ui_keycode, code, ui_flags, key, character,
83 ui::EventTimeForNow());
84 scoped_ptr<ui::Event> new_event;
85 rewriter->RewriteEvent(event, &new_event);
86 if (new_event)
87 return GetKeyEventAsString(
88 static_cast<const ui::KeyEvent&>(*new_event.get()));
89 return GetKeyEventAsString(event);
92 // Table entry for simple single key event rewriting tests.
93 struct KeyTestCase {
94 enum {
95 // Test types:
96 TEST_VKEY = 1 << 0, // Test ui::KeyEvent with no native event
97 TEST_X11 = 1 << 1, // Test ui::KeyEvent with native XKeyEvent
98 TEST_ALL = TEST_VKEY | TEST_X11,
99 // Special test flags:
100 NUMPAD = 1 << 8, // Reset the XKB scan code on an X11 event based
101 // on the test DomCode, because
102 // |XKeysymForWindowsKeyCode()| can not distinguish
103 // between pairs like XK_Insert and XK_KP_Insert.
105 int test;
106 ui::EventType type;
107 struct Event {
108 ui::KeyboardCode key_code;
109 ui::DomCode code;
110 int flags; // ui::EventFlags
111 ui::DomKey key;
112 base::char16 character;
113 } input, expected;
116 std::string GetTestCaseAsString(ui::EventType ui_type,
117 const KeyTestCase::Event& test) {
118 return GetExpectedResultAsString(ui_type, test.key_code, test.code,
119 test.flags, test.key, test.character);
122 #if defined(USE_X11)
123 // Check rewriting of an X11-based key event.
124 void CheckX11KeyTestCase(const std::string& expected,
125 chromeos::EventRewriter* rewriter,
126 const KeyTestCase& test,
127 XEvent* xevent) {
128 ui::KeyEvent xkey_event(xevent);
129 // Rewrite the event and check the result.
130 scoped_ptr<ui::Event> new_event;
131 rewriter->RewriteEvent(xkey_event, &new_event);
132 ui::KeyEvent& rewritten_key_event =
133 new_event ? *static_cast<ui::KeyEvent*>(new_event.get()) : xkey_event;
134 EXPECT_EQ(expected, GetKeyEventAsString(rewritten_key_event));
135 if ((rewritten_key_event.key_code() != ui::VKEY_UNKNOWN) &&
136 (rewritten_key_event.native_event()->xkey.keycode != 0)) {
137 // Build a new ui::KeyEvent from the rewritten native component,
138 // and check that it also matches the rewritten event.
139 EXPECT_TRUE(rewritten_key_event.native_event());
140 ui::KeyEvent from_native_event(rewritten_key_event.native_event());
141 EXPECT_EQ(expected, GetKeyEventAsString(from_native_event));
144 #endif
146 // Tests a single stateless key rewrite operation.
147 void CheckKeyTestCase(chromeos::EventRewriter* rewriter,
148 const KeyTestCase& test) {
149 std::string expected = GetTestCaseAsString(test.type, test.expected);
151 if (test.test & KeyTestCase::TEST_VKEY) {
152 // Check rewriting of a non-native-based key event.
153 EXPECT_EQ(expected,
154 GetRewrittenEventAsString(
155 rewriter, test.type, test.input.key_code, test.input.code,
156 test.input.flags, test.input.key, test.input.character));
159 #if defined(USE_X11)
160 if (test.test & KeyTestCase::TEST_X11) {
161 ui::ScopedXI2Event xev;
162 // Test an XKeyEvent.
163 xev.InitKeyEvent(test.type, test.input.key_code, test.input.flags);
164 XEvent* xevent = xev;
165 DCHECK((xevent->type == KeyPress) || (xevent->type == KeyRelease));
166 if (test.test & KeyTestCase::NUMPAD) {
167 xevent->xkey.keycode =
168 ui::KeycodeConverter::DomCodeToNativeKeycode(test.input.code);
170 int keycode = xevent->xkey.keycode;
171 if (keycode) {
172 CheckX11KeyTestCase(expected, rewriter, test, xevent);
173 // Test an XI2 GenericEvent.
174 xev.InitGenericKeyEvent(kMasterKeyboardDeviceId, kKeyboardDeviceId,
175 test.type, test.input.key_code, test.input.flags);
176 xevent = xev;
177 DCHECK(xevent->type == GenericEvent);
178 XIDeviceEvent* xievent =
179 static_cast<XIDeviceEvent*>(xevent->xcookie.data);
180 DCHECK((xievent->evtype == XI_KeyPress) ||
181 (xievent->evtype == XI_KeyRelease));
182 xievent->detail = keycode;
183 CheckX11KeyTestCase(expected, rewriter, test, xevent);
186 #endif
189 } // namespace
191 namespace chromeos {
193 class EventRewriterTest : public ash::test::AshTestBase {
194 public:
195 EventRewriterTest()
196 : fake_user_manager_(new user_manager::FakeUserManager),
197 user_manager_enabler_(fake_user_manager_),
198 input_method_manager_mock_(NULL) {}
199 ~EventRewriterTest() override {}
201 void SetUp() override {
202 input_method_manager_mock_ =
203 new chromeos::input_method::MockInputMethodManager;
204 chromeos::input_method::InitializeForTesting(
205 input_method_manager_mock_); // pass ownership
207 AshTestBase::SetUp();
210 void TearDown() override {
211 AshTestBase::TearDown();
212 // Shutdown() deletes the IME mock object.
213 chromeos::input_method::Shutdown();
216 protected:
217 void TestRewriteNumPadKeys();
218 void TestRewriteNumPadKeysOnAppleKeyboard();
220 const ui::MouseEvent* RewriteMouseButtonEvent(
221 chromeos::EventRewriter* rewriter,
222 const ui::MouseEvent& event,
223 scoped_ptr<ui::Event>* new_event) {
224 rewriter->RewriteMouseButtonEventForTesting(event, new_event);
225 return *new_event ? static_cast<const ui::MouseEvent*>(new_event->get())
226 : &event;
229 user_manager::FakeUserManager* fake_user_manager_; // Not owned.
230 chromeos::ScopedUserManagerEnabler user_manager_enabler_;
231 chromeos::input_method::MockInputMethodManager* input_method_manager_mock_;
234 TEST_F(EventRewriterTest, TestRewriteCommandToControl) {
235 // First, test with a PC keyboard.
236 TestingPrefServiceSyncable prefs;
237 EventRewriter rewriter(NULL);
238 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
239 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
240 rewriter.set_pref_service_for_testing(&prefs);
242 KeyTestCase pc_keyboard_tests[] = {
243 // VKEY_A, Alt modifier.
244 {KeyTestCase::TEST_ALL,
245 ui::ET_KEY_PRESSED,
246 {ui::VKEY_A,
247 ui::DomCode::KEY_A,
248 ui::EF_ALT_DOWN,
249 ui::DomKey::CHARACTER,
250 'a'},
251 {ui::VKEY_A,
252 ui::DomCode::KEY_A,
253 ui::EF_ALT_DOWN,
254 ui::DomKey::CHARACTER,
255 'a'}},
257 // VKEY_A, Win modifier.
258 {KeyTestCase::TEST_ALL,
259 ui::ET_KEY_PRESSED,
260 {ui::VKEY_A,
261 ui::DomCode::KEY_A,
262 ui::EF_COMMAND_DOWN,
263 ui::DomKey::CHARACTER,
264 'a'},
265 {ui::VKEY_A,
266 ui::DomCode::KEY_A,
267 ui::EF_COMMAND_DOWN,
268 ui::DomKey::CHARACTER,
269 'a'}},
271 // VKEY_A, Alt+Win modifier.
272 {KeyTestCase::TEST_ALL,
273 ui::ET_KEY_PRESSED,
274 {ui::VKEY_A,
275 ui::DomCode::KEY_A,
276 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
277 ui::DomKey::CHARACTER,
278 'a'},
279 {ui::VKEY_A,
280 ui::DomCode::KEY_A,
281 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
282 ui::DomKey::CHARACTER,
283 'a'}},
285 // VKEY_LWIN (left Windows key), Alt modifier.
286 {KeyTestCase::TEST_ALL,
287 ui::ET_KEY_PRESSED,
288 {ui::VKEY_LWIN,
289 ui::DomCode::OS_LEFT,
290 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
291 ui::DomKey::OS,
293 {ui::VKEY_LWIN,
294 ui::DomCode::OS_LEFT,
295 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
296 ui::DomKey::OS,
297 0}},
299 // VKEY_RWIN (right Windows key), Alt modifier.
300 {KeyTestCase::TEST_ALL,
301 ui::ET_KEY_PRESSED,
302 {ui::VKEY_RWIN,
303 ui::DomCode::OS_RIGHT,
304 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
305 ui::DomKey::OS,
307 {ui::VKEY_RWIN,
308 ui::DomCode::OS_RIGHT,
309 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
310 ui::DomKey::OS,
311 0}},
314 for (size_t i = 0; i < arraysize(pc_keyboard_tests); ++i) {
315 SCOPED_TRACE(i);
316 CheckKeyTestCase(&rewriter, pc_keyboard_tests[i]);
319 // An Apple keyboard reusing the ID, zero.
320 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "Apple Keyboard");
321 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
323 KeyTestCase apple_keyboard_tests[] = {
324 // VKEY_A, Alt modifier.
325 {KeyTestCase::TEST_ALL,
326 ui::ET_KEY_PRESSED,
327 {ui::VKEY_A,
328 ui::DomCode::KEY_A,
329 ui::EF_ALT_DOWN,
330 ui::DomKey::CHARACTER,
331 'a'},
332 {ui::VKEY_A,
333 ui::DomCode::KEY_A,
334 ui::EF_ALT_DOWN,
335 ui::DomKey::CHARACTER,
336 'a'}},
338 // VKEY_A, Win modifier.
339 {KeyTestCase::TEST_ALL,
340 ui::ET_KEY_PRESSED,
341 {ui::VKEY_A,
342 ui::DomCode::KEY_A,
343 ui::EF_COMMAND_DOWN,
344 ui::DomKey::CHARACTER,
345 'a'},
346 {ui::VKEY_A,
347 ui::DomCode::KEY_A,
348 ui::EF_CONTROL_DOWN,
349 ui::DomKey::CHARACTER,
350 'a'}},
352 // VKEY_A, Alt+Win modifier.
353 {KeyTestCase::TEST_ALL,
354 ui::ET_KEY_PRESSED,
355 {ui::VKEY_A,
356 ui::DomCode::KEY_A,
357 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
358 ui::DomKey::CHARACTER,
359 'a'},
360 {ui::VKEY_A,
361 ui::DomCode::KEY_A,
362 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
363 ui::DomKey::CHARACTER,
364 'a'}},
366 // VKEY_LWIN (left Windows key), Alt modifier.
367 {KeyTestCase::TEST_ALL,
368 ui::ET_KEY_PRESSED,
369 {ui::VKEY_LWIN,
370 ui::DomCode::OS_LEFT,
371 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
372 ui::DomKey::OS,
374 {ui::VKEY_CONTROL,
375 ui::DomCode::CONTROL_LEFT,
376 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
377 ui::DomKey::CONTROL,
378 0}},
380 // VKEY_RWIN (right Windows key), Alt modifier.
381 {KeyTestCase::TEST_ALL,
382 ui::ET_KEY_PRESSED,
383 {ui::VKEY_RWIN,
384 ui::DomCode::OS_RIGHT,
385 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
386 ui::DomKey::OS,
388 {ui::VKEY_CONTROL,
389 ui::DomCode::CONTROL_LEFT,
390 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
391 ui::DomKey::CONTROL,
392 0}},
395 for (size_t i = 0; i < arraysize(apple_keyboard_tests); ++i) {
396 SCOPED_TRACE(i);
397 CheckKeyTestCase(&rewriter, apple_keyboard_tests[i]);
401 // For crbug.com/133896.
402 TEST_F(EventRewriterTest, TestRewriteCommandToControlWithControlRemapped) {
403 // Remap Control to Alt.
404 TestingPrefServiceSyncable prefs;
405 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
406 IntegerPrefMember control;
407 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
408 control.SetValue(chromeos::input_method::kAltKey);
410 EventRewriter rewriter(NULL);
411 rewriter.set_pref_service_for_testing(&prefs);
412 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
413 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
415 KeyTestCase pc_keyboard_tests[] = {
416 // Control should be remapped to Alt.
417 {KeyTestCase::TEST_ALL,
418 ui::ET_KEY_PRESSED,
419 {ui::VKEY_CONTROL,
420 ui::DomCode::CONTROL_LEFT,
421 ui::EF_CONTROL_DOWN,
422 ui::DomKey::CONTROL,
424 {ui::VKEY_MENU,
425 ui::DomCode::ALT_LEFT,
426 ui::EF_ALT_DOWN,
427 ui::DomKey::ALT,
428 0}},
431 for (size_t i = 0; i < arraysize(pc_keyboard_tests); ++i) {
432 SCOPED_TRACE(i);
433 CheckKeyTestCase(&rewriter, pc_keyboard_tests[i]);
436 // An Apple keyboard reusing the ID, zero.
437 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "Apple Keyboard");
438 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
440 KeyTestCase apple_keyboard_tests[] = {
441 // VKEY_LWIN (left Command key) with Alt modifier. The remapped Command
442 // key should never be re-remapped to Alt.
443 {KeyTestCase::TEST_ALL,
444 ui::ET_KEY_PRESSED,
445 {ui::VKEY_LWIN,
446 ui::DomCode::OS_LEFT,
447 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
448 ui::DomKey::OS,
450 {ui::VKEY_CONTROL,
451 ui::DomCode::CONTROL_LEFT,
452 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
453 ui::DomKey::CONTROL,
454 0}},
456 // VKEY_RWIN (right Command key) with Alt modifier. The remapped Command
457 // key should never be re-remapped to Alt.
458 {KeyTestCase::TEST_ALL,
459 ui::ET_KEY_PRESSED,
460 {ui::VKEY_RWIN,
461 ui::DomCode::OS_RIGHT,
462 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
463 ui::DomKey::OS,
465 {ui::VKEY_CONTROL,
466 ui::DomCode::CONTROL_LEFT,
467 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
468 ui::DomKey::CONTROL,
469 0}},
472 for (size_t i = 0; i < arraysize(apple_keyboard_tests); ++i) {
473 SCOPED_TRACE(i);
474 CheckKeyTestCase(&rewriter, apple_keyboard_tests[i]);
478 void EventRewriterTest::TestRewriteNumPadKeys() {
479 TestingPrefServiceSyncable prefs;
480 EventRewriter rewriter(NULL);
481 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
482 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
483 rewriter.set_pref_service_for_testing(&prefs);
485 KeyTestCase tests[] = {
486 // XK_KP_Insert (= NumPad 0 without Num Lock), no modifier.
487 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
488 ui::ET_KEY_PRESSED,
489 {ui::VKEY_INSERT,
490 ui::DomCode::NUMPAD0,
491 ui::EF_NONE,
492 ui::DomKey::INSERT,
494 {ui::VKEY_NUMPAD0,
495 ui::DomCode::NUMPAD0,
496 ui::EF_NONE,
497 ui::DomKey::CHARACTER,
498 '0'}},
500 // XK_KP_Insert (= NumPad 0 without Num Lock), Alt modifier.
501 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
502 ui::ET_KEY_PRESSED,
503 {ui::VKEY_INSERT,
504 ui::DomCode::NUMPAD0,
505 ui::EF_ALT_DOWN,
506 ui::DomKey::INSERT,
508 {ui::VKEY_NUMPAD0,
509 ui::DomCode::NUMPAD0,
510 ui::EF_ALT_DOWN,
511 ui::DomKey::CHARACTER,
512 '0'}},
514 // XK_KP_Delete (= NumPad . without Num Lock), Alt modifier.
515 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
516 ui::ET_KEY_PRESSED,
517 {ui::VKEY_DELETE,
518 ui::DomCode::NUMPAD_DECIMAL,
519 ui::EF_ALT_DOWN,
520 ui::DomKey::DEL,
522 {ui::VKEY_DECIMAL,
523 ui::DomCode::NUMPAD_DECIMAL,
524 ui::EF_ALT_DOWN,
525 ui::DomKey::CHARACTER,
526 '.'}},
528 // XK_KP_End (= NumPad 1 without Num Lock), Alt modifier.
529 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
530 ui::ET_KEY_PRESSED,
531 {ui::VKEY_END,
532 ui::DomCode::NUMPAD1,
533 ui::EF_ALT_DOWN,
534 ui::DomKey::END,
536 {ui::VKEY_NUMPAD1,
537 ui::DomCode::NUMPAD1,
538 ui::EF_ALT_DOWN,
539 ui::DomKey::CHARACTER,
540 '1'}},
542 // XK_KP_Down (= NumPad 2 without Num Lock), Alt modifier.
543 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
544 ui::ET_KEY_PRESSED,
545 {ui::VKEY_DOWN,
546 ui::DomCode::NUMPAD2,
547 ui::EF_ALT_DOWN,
548 ui::DomKey::ARROW_DOWN,
550 {ui::VKEY_NUMPAD2,
551 ui::DomCode::NUMPAD2,
552 ui::EF_ALT_DOWN,
553 ui::DomKey::CHARACTER,
554 '2'}},
556 // XK_KP_Next (= NumPad 3 without Num Lock), Alt modifier.
557 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
558 ui::ET_KEY_PRESSED,
559 {ui::VKEY_NEXT,
560 ui::DomCode::NUMPAD3,
561 ui::EF_ALT_DOWN,
562 ui::DomKey::PAGE_DOWN,
564 {ui::VKEY_NUMPAD3,
565 ui::DomCode::NUMPAD3,
566 ui::EF_ALT_DOWN,
567 ui::DomKey::CHARACTER,
568 '3'}},
570 // XK_KP_Left (= NumPad 4 without Num Lock), Alt modifier.
571 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
572 ui::ET_KEY_PRESSED,
573 {ui::VKEY_LEFT,
574 ui::DomCode::NUMPAD4,
575 ui::EF_ALT_DOWN,
576 ui::DomKey::ARROW_LEFT,
578 {ui::VKEY_NUMPAD4,
579 ui::DomCode::NUMPAD4,
580 ui::EF_ALT_DOWN,
581 ui::DomKey::CHARACTER,
582 '4'}},
584 // XK_KP_Begin (= NumPad 5 without Num Lock), Alt modifier.
585 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
586 ui::ET_KEY_PRESSED,
587 {ui::VKEY_CLEAR,
588 ui::DomCode::NUMPAD5,
589 ui::EF_ALT_DOWN,
590 ui::DomKey::CLEAR,
592 {ui::VKEY_NUMPAD5,
593 ui::DomCode::NUMPAD5,
594 ui::EF_ALT_DOWN,
595 ui::DomKey::CHARACTER,
596 '5'}},
598 // XK_KP_Right (= NumPad 6 without Num Lock), Alt modifier.
599 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
600 ui::ET_KEY_PRESSED,
601 {ui::VKEY_RIGHT,
602 ui::DomCode::NUMPAD6,
603 ui::EF_ALT_DOWN,
604 ui::DomKey::ARROW_RIGHT,
606 {ui::VKEY_NUMPAD6,
607 ui::DomCode::NUMPAD6,
608 ui::EF_ALT_DOWN,
609 ui::DomKey::CHARACTER,
610 '6'}},
612 // XK_KP_Home (= NumPad 7 without Num Lock), Alt modifier.
613 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
614 ui::ET_KEY_PRESSED,
615 {ui::VKEY_HOME,
616 ui::DomCode::NUMPAD7,
617 ui::EF_ALT_DOWN,
618 ui::DomKey::HOME,
620 {ui::VKEY_NUMPAD7,
621 ui::DomCode::NUMPAD7,
622 ui::EF_ALT_DOWN,
623 ui::DomKey::CHARACTER,
624 '7'}},
626 // XK_KP_Up (= NumPad 8 without Num Lock), Alt modifier.
627 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
628 ui::ET_KEY_PRESSED,
629 {ui::VKEY_UP,
630 ui::DomCode::NUMPAD8,
631 ui::EF_ALT_DOWN,
632 ui::DomKey::ARROW_UP,
634 {ui::VKEY_NUMPAD8,
635 ui::DomCode::NUMPAD8,
636 ui::EF_ALT_DOWN,
637 ui::DomKey::CHARACTER,
638 '8'}},
640 // XK_KP_Prior (= NumPad 9 without Num Lock), Alt modifier.
641 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
642 ui::ET_KEY_PRESSED,
643 {ui::VKEY_PRIOR,
644 ui::DomCode::NUMPAD9,
645 ui::EF_ALT_DOWN,
646 ui::DomKey::PAGE_UP,
648 {ui::VKEY_NUMPAD9,
649 ui::DomCode::NUMPAD9,
650 ui::EF_ALT_DOWN,
651 ui::DomKey::CHARACTER,
652 '9'}},
654 // XK_KP_0 (= NumPad 0 with Num Lock), Num Lock modifier.
655 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
656 ui::ET_KEY_PRESSED,
657 {ui::VKEY_NUMPAD0,
658 ui::DomCode::NUMPAD0,
659 ui::EF_NONE,
660 ui::DomKey::CHARACTER,
661 '0'},
662 {ui::VKEY_NUMPAD0,
663 ui::DomCode::NUMPAD0,
664 ui::EF_NONE,
665 ui::DomKey::CHARACTER,
666 '0'}},
668 // XK_KP_DECIMAL (= NumPad . with Num Lock), Num Lock modifier.
669 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
670 ui::ET_KEY_PRESSED,
671 {ui::VKEY_DECIMAL,
672 ui::DomCode::NUMPAD_DECIMAL,
673 ui::EF_NONE,
674 ui::DomKey::CHARACTER,
675 '.'},
676 {ui::VKEY_DECIMAL,
677 ui::DomCode::NUMPAD_DECIMAL,
678 ui::EF_NONE,
679 ui::DomKey::CHARACTER,
680 '.'}},
682 // XK_KP_1 (= NumPad 1 with Num Lock), Num Lock modifier.
683 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
684 ui::ET_KEY_PRESSED,
685 {ui::VKEY_NUMPAD1,
686 ui::DomCode::NUMPAD1,
687 ui::EF_NONE,
688 ui::DomKey::CHARACTER,
689 '1'},
690 {ui::VKEY_NUMPAD1,
691 ui::DomCode::NUMPAD1,
692 ui::EF_NONE,
693 ui::DomKey::CHARACTER,
694 '1'}},
696 // XK_KP_2 (= NumPad 2 with Num Lock), Num Lock modifier.
697 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
698 ui::ET_KEY_PRESSED,
699 {ui::VKEY_NUMPAD2,
700 ui::DomCode::NUMPAD2,
701 ui::EF_NONE,
702 ui::DomKey::CHARACTER,
703 '2'},
704 {ui::VKEY_NUMPAD2,
705 ui::DomCode::NUMPAD2,
706 ui::EF_NONE,
707 ui::DomKey::CHARACTER,
708 '2'}},
710 // XK_KP_3 (= NumPad 3 with Num Lock), Num Lock modifier.
711 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
712 ui::ET_KEY_PRESSED,
713 {ui::VKEY_NUMPAD3,
714 ui::DomCode::NUMPAD3,
715 ui::EF_NONE,
716 ui::DomKey::CHARACTER,
717 '3'},
718 {ui::VKEY_NUMPAD3,
719 ui::DomCode::NUMPAD3,
720 ui::EF_NONE,
721 ui::DomKey::CHARACTER,
722 '3'}},
724 // XK_KP_4 (= NumPad 4 with Num Lock), Num Lock modifier.
725 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
726 ui::ET_KEY_PRESSED,
727 {ui::VKEY_NUMPAD4,
728 ui::DomCode::NUMPAD4,
729 ui::EF_NONE,
730 ui::DomKey::CHARACTER,
731 '4'},
732 {ui::VKEY_NUMPAD4,
733 ui::DomCode::NUMPAD4,
734 ui::EF_NONE,
735 ui::DomKey::CHARACTER,
736 '4'}},
738 // XK_KP_5 (= NumPad 5 with Num Lock), Num Lock
739 // modifier.
740 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
741 ui::ET_KEY_PRESSED,
742 {ui::VKEY_NUMPAD5,
743 ui::DomCode::NUMPAD5,
744 ui::EF_NONE,
745 ui::DomKey::CHARACTER,
746 '5'},
747 {ui::VKEY_NUMPAD5,
748 ui::DomCode::NUMPAD5,
749 ui::EF_NONE,
750 ui::DomKey::CHARACTER,
751 '5'}},
753 // XK_KP_6 (= NumPad 6 with Num Lock), Num Lock
754 // modifier.
755 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
756 ui::ET_KEY_PRESSED,
757 {ui::VKEY_NUMPAD6,
758 ui::DomCode::NUMPAD6,
759 ui::EF_NONE,
760 ui::DomKey::CHARACTER,
761 '6'},
762 {ui::VKEY_NUMPAD6,
763 ui::DomCode::NUMPAD6,
764 ui::EF_NONE,
765 ui::DomKey::CHARACTER,
766 '6'}},
768 // XK_KP_7 (= NumPad 7 with Num Lock), Num Lock
769 // modifier.
770 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
771 ui::ET_KEY_PRESSED,
772 {ui::VKEY_NUMPAD7,
773 ui::DomCode::NUMPAD7,
774 ui::EF_NONE,
775 ui::DomKey::CHARACTER,
776 '7'},
777 {ui::VKEY_NUMPAD7,
778 ui::DomCode::NUMPAD7,
779 ui::EF_NONE,
780 ui::DomKey::CHARACTER,
781 '7'}},
783 // XK_KP_8 (= NumPad 8 with Num Lock), Num Lock
784 // modifier.
785 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
786 ui::ET_KEY_PRESSED,
787 {ui::VKEY_NUMPAD8,
788 ui::DomCode::NUMPAD8,
789 ui::EF_NONE,
790 ui::DomKey::CHARACTER,
791 '8'},
792 {ui::VKEY_NUMPAD8,
793 ui::DomCode::NUMPAD8,
794 ui::EF_NONE,
795 ui::DomKey::CHARACTER,
796 '8'}},
798 // XK_KP_9 (= NumPad 9 with Num Lock), Num Lock
799 // modifier.
800 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
801 ui::ET_KEY_PRESSED,
802 {ui::VKEY_NUMPAD9,
803 ui::DomCode::NUMPAD9,
804 ui::EF_NONE,
805 ui::DomKey::CHARACTER,
806 '9'},
807 {ui::VKEY_NUMPAD9,
808 ui::DomCode::NUMPAD9,
809 ui::EF_NONE,
810 ui::DomKey::CHARACTER,
811 '9'}},
814 for (size_t i = 0; i < arraysize(tests); ++i) {
815 SCOPED_TRACE(i);
816 CheckKeyTestCase(&rewriter, tests[i]);
820 TEST_F(EventRewriterTest, TestRewriteNumPadKeys) {
821 TestRewriteNumPadKeys();
824 TEST_F(EventRewriterTest, TestRewriteNumPadKeysWithDiamondKeyFlag) {
825 // Make sure the num lock works correctly even when Diamond key exists.
826 const base::CommandLine original_cl(*base::CommandLine::ForCurrentProcess());
827 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
828 chromeos::switches::kHasChromeOSDiamondKey, "");
830 TestRewriteNumPadKeys();
831 *base::CommandLine::ForCurrentProcess() = original_cl;
834 // Tests if the rewriter can handle a Command + Num Pad event.
835 void EventRewriterTest::TestRewriteNumPadKeysOnAppleKeyboard() {
836 TestingPrefServiceSyncable prefs;
837 EventRewriter rewriter(NULL);
838 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "Apple Keyboard");
839 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
840 rewriter.set_pref_service_for_testing(&prefs);
842 KeyTestCase tests[] = {
843 // XK_KP_End (= NumPad 1 without Num Lock), Win modifier.
844 // The result should be "Num Pad 1 with Control + Num Lock modifiers".
845 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
846 ui::ET_KEY_PRESSED,
847 {ui::VKEY_END,
848 ui::DomCode::NUMPAD1,
849 ui::EF_COMMAND_DOWN,
850 ui::DomKey::END,
852 {ui::VKEY_NUMPAD1,
853 ui::DomCode::NUMPAD1,
854 ui::EF_CONTROL_DOWN,
855 ui::DomKey::CHARACTER,
856 '1'}},
858 // XK_KP_1 (= NumPad 1 with Num Lock), Win modifier.
859 // The result should also be "Num Pad 1 with Control + Num Lock
860 // modifiers".
861 {KeyTestCase::TEST_ALL | KeyTestCase::NUMPAD,
862 ui::ET_KEY_PRESSED,
863 {ui::VKEY_NUMPAD1,
864 ui::DomCode::NUMPAD1,
865 ui::EF_COMMAND_DOWN,
866 ui::DomKey::CHARACTER,
867 '1'},
868 {ui::VKEY_NUMPAD1,
869 ui::DomCode::NUMPAD1,
870 ui::EF_CONTROL_DOWN,
871 ui::DomKey::CHARACTER,
872 '1'}}};
874 for (size_t i = 0; i < arraysize(tests); ++i) {
875 SCOPED_TRACE(i);
876 CheckKeyTestCase(&rewriter, tests[i]);
880 TEST_F(EventRewriterTest, TestRewriteNumPadKeysOnAppleKeyboard) {
881 TestRewriteNumPadKeysOnAppleKeyboard();
884 TEST_F(EventRewriterTest,
885 TestRewriteNumPadKeysOnAppleKeyboardWithDiamondKeyFlag) {
886 // Makes sure the num lock works correctly even when Diamond key exists.
887 const base::CommandLine original_cl(*base::CommandLine::ForCurrentProcess());
888 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
889 chromeos::switches::kHasChromeOSDiamondKey, "");
891 TestRewriteNumPadKeysOnAppleKeyboard();
892 *base::CommandLine::ForCurrentProcess() = original_cl;
895 TEST_F(EventRewriterTest, TestRewriteModifiersNoRemap) {
896 TestingPrefServiceSyncable prefs;
897 EventRewriter rewriter(NULL);
898 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
899 rewriter.set_pref_service_for_testing(&prefs);
901 KeyTestCase tests[] = {
902 // Press Search. Confirm the event is not rewritten.
903 {KeyTestCase::TEST_ALL,
904 ui::ET_KEY_PRESSED,
905 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_NONE, ui::DomKey::OS, 0},
906 {ui::VKEY_LWIN,
907 ui::DomCode::OS_LEFT,
908 ui::EF_COMMAND_DOWN,
909 ui::DomKey::OS,
910 0}},
912 // Press left Control. Confirm the event is not rewritten.
913 {KeyTestCase::TEST_ALL,
914 ui::ET_KEY_PRESSED,
915 {ui::VKEY_CONTROL,
916 ui::DomCode::CONTROL_LEFT,
917 ui::EF_CONTROL_DOWN,
918 ui::DomKey::CONTROL,
920 {ui::VKEY_CONTROL,
921 ui::DomCode::CONTROL_LEFT,
922 ui::EF_CONTROL_DOWN,
923 ui::DomKey::CONTROL,
924 0}},
926 // Press right Control. Confirm the event is not rewritten.
927 {KeyTestCase::TEST_ALL,
928 ui::ET_KEY_PRESSED,
929 {ui::VKEY_CONTROL,
930 ui::DomCode::CONTROL_LEFT,
931 ui::EF_CONTROL_DOWN,
932 ui::DomKey::CONTROL,
934 {ui::VKEY_CONTROL,
935 ui::DomCode::CONTROL_LEFT,
936 ui::EF_CONTROL_DOWN,
937 ui::DomKey::CONTROL,
938 0}},
940 // Press left Alt. Confirm the event is not rewritten.
941 {KeyTestCase::TEST_ALL,
942 ui::ET_KEY_PRESSED,
943 {ui::VKEY_MENU,
944 ui::DomCode::ALT_LEFT,
945 ui::EF_ALT_DOWN,
946 ui::DomKey::ALT,
948 {ui::VKEY_MENU,
949 ui::DomCode::ALT_LEFT,
950 ui::EF_ALT_DOWN,
951 ui::DomKey::ALT,
952 0}},
954 // Press right Alt. Confirm the event is not rewritten.
955 {KeyTestCase::TEST_ALL,
956 ui::ET_KEY_PRESSED,
957 {ui::VKEY_MENU,
958 ui::DomCode::ALT_LEFT,
959 ui::EF_ALT_DOWN,
960 ui::DomKey::ALT,
962 {ui::VKEY_MENU,
963 ui::DomCode::ALT_LEFT,
964 ui::EF_ALT_DOWN,
965 ui::DomKey::ALT,
966 0}},
968 // Test KeyRelease event, just in case.
969 // Release Search. Confirm the release event is not rewritten.
970 {KeyTestCase::TEST_ALL,
971 ui::ET_KEY_RELEASED,
972 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_NONE, ui::DomKey::OS, 0},
973 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_NONE, ui::DomKey::OS, 0}},
976 for (size_t i = 0; i < arraysize(tests); ++i) {
977 SCOPED_TRACE(i);
978 CheckKeyTestCase(&rewriter, tests[i]);
982 TEST_F(EventRewriterTest, TestRewriteModifiersNoRemapMultipleKeys) {
983 TestingPrefServiceSyncable prefs;
984 EventRewriter rewriter(NULL);
985 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
986 rewriter.set_pref_service_for_testing(&prefs);
988 KeyTestCase tests[] = {
989 // Press Alt with Shift. Confirm the event is not rewritten.
990 {KeyTestCase::TEST_ALL,
991 ui::ET_KEY_PRESSED,
992 {ui::VKEY_MENU,
993 ui::DomCode::ALT_LEFT,
994 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
995 ui::DomKey::ALT,
997 {ui::VKEY_MENU,
998 ui::DomCode::ALT_LEFT,
999 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
1000 ui::DomKey::ALT,
1001 0}},
1003 // Press Search with Caps Lock mask. Confirm the event is not rewritten.
1004 {KeyTestCase::TEST_ALL,
1005 ui::ET_KEY_PRESSED,
1006 {ui::VKEY_LWIN,
1007 ui::DomCode::OS_LEFT,
1008 ui::EF_CAPS_LOCK_DOWN | ui::EF_COMMAND_DOWN,
1009 ui::DomKey::OS,
1011 {ui::VKEY_LWIN,
1012 ui::DomCode::OS_LEFT,
1013 ui::EF_CAPS_LOCK_DOWN | ui::EF_COMMAND_DOWN,
1014 ui::DomKey::OS,
1015 0}},
1017 // Release Search with Caps Lock mask. Confirm the event is not rewritten.
1018 {KeyTestCase::TEST_ALL,
1019 ui::ET_KEY_RELEASED,
1020 {ui::VKEY_LWIN,
1021 ui::DomCode::OS_LEFT,
1022 ui::EF_CAPS_LOCK_DOWN,
1023 ui::DomKey::OS,
1025 {ui::VKEY_LWIN,
1026 ui::DomCode::OS_LEFT,
1027 ui::EF_CAPS_LOCK_DOWN,
1028 ui::DomKey::OS,
1029 0}},
1031 // Press Shift+Ctrl+Alt+Search+A. Confirm the event is not rewritten.
1032 {KeyTestCase::TEST_ALL,
1033 ui::ET_KEY_PRESSED,
1034 {ui::VKEY_B,
1035 ui::DomCode::KEY_B,
1036 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
1037 ui::EF_COMMAND_DOWN,
1038 ui::DomKey::CHARACTER,
1039 'B'},
1040 {ui::VKEY_B,
1041 ui::DomCode::KEY_B,
1042 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
1043 ui::EF_COMMAND_DOWN,
1044 ui::DomKey::CHARACTER,
1045 'B'}},
1048 for (size_t i = 0; i < arraysize(tests); ++i) {
1049 SCOPED_TRACE(i);
1050 CheckKeyTestCase(&rewriter, tests[i]);
1054 TEST_F(EventRewriterTest, TestRewriteModifiersDisableSome) {
1055 // Disable Search and Control keys.
1056 TestingPrefServiceSyncable prefs;
1057 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1058 IntegerPrefMember search;
1059 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
1060 search.SetValue(chromeos::input_method::kVoidKey);
1061 IntegerPrefMember control;
1062 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
1063 control.SetValue(chromeos::input_method::kVoidKey);
1065 EventRewriter rewriter(NULL);
1066 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1067 rewriter.set_pref_service_for_testing(&prefs);
1069 KeyTestCase disabled_modifier_tests[] = {
1070 // Press Alt with Shift. This key press shouldn't be affected by the
1071 // pref. Confirm the event is not rewritten.
1072 {KeyTestCase::TEST_ALL,
1073 ui::ET_KEY_PRESSED,
1074 {ui::VKEY_MENU,
1075 ui::DomCode::ALT_LEFT,
1076 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
1077 ui::DomKey::ALT,
1079 {ui::VKEY_MENU,
1080 ui::DomCode::ALT_LEFT,
1081 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
1082 ui::DomKey::ALT,
1083 0}},
1085 // Press Search. Confirm the event is now VKEY_UNKNOWN.
1086 {KeyTestCase::TEST_ALL,
1087 ui::ET_KEY_PRESSED,
1088 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_NONE, ui::DomKey::OS, 0},
1089 {ui::VKEY_UNKNOWN,
1090 ui::DomCode::NONE,
1091 ui::EF_NONE,
1092 ui::DomKey::UNIDENTIFIED,
1093 0}},
1095 // Press Control. Confirm the event is now VKEY_UNKNOWN.
1096 {KeyTestCase::TEST_ALL,
1097 ui::ET_KEY_PRESSED,
1098 {ui::VKEY_CONTROL,
1099 ui::DomCode::CONTROL_LEFT,
1100 ui::EF_CONTROL_DOWN,
1101 ui::DomKey::CONTROL,
1103 {ui::VKEY_UNKNOWN,
1104 ui::DomCode::NONE,
1105 ui::EF_NONE,
1106 ui::DomKey::UNIDENTIFIED,
1107 0}},
1109 // Press Control+Search. Confirm the event is now VKEY_UNKNOWN
1110 // without any modifiers.
1111 {KeyTestCase::TEST_ALL,
1112 ui::ET_KEY_PRESSED,
1113 {ui::VKEY_LWIN,
1114 ui::DomCode::OS_LEFT,
1115 ui::EF_CONTROL_DOWN,
1116 ui::DomKey::OS,
1118 {ui::VKEY_UNKNOWN,
1119 ui::DomCode::NONE,
1120 ui::EF_NONE,
1121 ui::DomKey::UNIDENTIFIED,
1122 0}},
1124 // Press Control+Search+a. Confirm the event is now VKEY_A without any
1125 // modifiers.
1126 {KeyTestCase::TEST_ALL,
1127 ui::ET_KEY_PRESSED,
1128 {ui::VKEY_A,
1129 ui::DomCode::KEY_A,
1130 ui::EF_CONTROL_DOWN,
1131 ui::DomKey::CHARACTER,
1132 'a'},
1133 {ui::VKEY_A,
1134 ui::DomCode::KEY_A,
1135 ui::EF_NONE,
1136 ui::DomKey::CHARACTER,
1137 'a'}},
1139 // Press Control+Search+Alt+a. Confirm the event is now VKEY_A only with
1140 // the Alt modifier.
1141 {KeyTestCase::TEST_ALL,
1142 ui::ET_KEY_PRESSED,
1143 {ui::VKEY_A,
1144 ui::DomCode::KEY_A,
1145 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
1146 ui::DomKey::CHARACTER,
1147 'a'},
1148 {ui::VKEY_A,
1149 ui::DomCode::KEY_A,
1150 ui::EF_ALT_DOWN,
1151 ui::DomKey::CHARACTER,
1152 'a'}},
1155 for (size_t i = 0; i < arraysize(disabled_modifier_tests); ++i) {
1156 SCOPED_TRACE(i);
1157 CheckKeyTestCase(&rewriter, disabled_modifier_tests[i]);
1160 // Remap Alt to Control.
1161 IntegerPrefMember alt;
1162 alt.Init(prefs::kLanguageRemapAltKeyTo, &prefs);
1163 alt.SetValue(chromeos::input_method::kControlKey);
1165 KeyTestCase tests[] = {
1166 // Press left Alt. Confirm the event is now VKEY_CONTROL
1167 // even though the Control key itself is disabled.
1168 {KeyTestCase::TEST_ALL,
1169 ui::ET_KEY_PRESSED,
1170 {ui::VKEY_MENU,
1171 ui::DomCode::ALT_LEFT,
1172 ui::EF_ALT_DOWN,
1173 ui::DomKey::ALT,
1175 {ui::VKEY_CONTROL,
1176 ui::DomCode::CONTROL_LEFT,
1177 ui::EF_CONTROL_DOWN,
1178 ui::DomKey::CONTROL,
1179 0}},
1181 // Press Alt+a. Confirm the event is now Control+a even though the Control
1182 // key itself is disabled.
1183 {KeyTestCase::TEST_ALL,
1184 ui::ET_KEY_PRESSED,
1185 {ui::VKEY_A,
1186 ui::DomCode::KEY_A,
1187 ui::EF_ALT_DOWN,
1188 ui::DomKey::CHARACTER,
1189 'a'},
1190 {ui::VKEY_A,
1191 ui::DomCode::KEY_A,
1192 ui::EF_CONTROL_DOWN,
1193 ui::DomKey::CHARACTER,
1194 'a'}},
1197 for (size_t i = 0; i < arraysize(tests); ++i) {
1198 SCOPED_TRACE(i);
1199 CheckKeyTestCase(&rewriter, tests[i]);
1203 TEST_F(EventRewriterTest, TestRewriteModifiersRemapToControl) {
1204 // Remap Search to Control.
1205 TestingPrefServiceSyncable prefs;
1206 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1207 IntegerPrefMember search;
1208 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
1209 search.SetValue(chromeos::input_method::kControlKey);
1211 EventRewriter rewriter(NULL);
1212 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1213 rewriter.set_pref_service_for_testing(&prefs);
1215 KeyTestCase s_tests[] = {
1216 // Press Search. Confirm the event is now VKEY_CONTROL.
1217 {KeyTestCase::TEST_ALL,
1218 ui::ET_KEY_PRESSED,
1219 {ui::VKEY_LWIN,
1220 ui::DomCode::OS_LEFT,
1221 ui::EF_COMMAND_DOWN,
1222 ui::DomKey::OS,
1224 {ui::VKEY_CONTROL,
1225 ui::DomCode::CONTROL_LEFT,
1226 ui::EF_CONTROL_DOWN,
1227 ui::DomKey::CONTROL,
1228 0}},
1231 for (size_t i = 0; i < arraysize(s_tests); ++i) {
1232 SCOPED_TRACE(i);
1233 CheckKeyTestCase(&rewriter, s_tests[i]);
1236 // Remap Alt to Control too.
1237 IntegerPrefMember alt;
1238 alt.Init(prefs::kLanguageRemapAltKeyTo, &prefs);
1239 alt.SetValue(chromeos::input_method::kControlKey);
1241 KeyTestCase sa_tests[] = {
1242 // Press Alt. Confirm the event is now VKEY_CONTROL.
1243 {KeyTestCase::TEST_ALL,
1244 ui::ET_KEY_PRESSED,
1245 {ui::VKEY_MENU,
1246 ui::DomCode::ALT_LEFT,
1247 ui::EF_ALT_DOWN,
1248 ui::DomKey::ALT,
1250 {ui::VKEY_CONTROL,
1251 ui::DomCode::CONTROL_LEFT,
1252 ui::EF_CONTROL_DOWN,
1253 ui::DomKey::CONTROL,
1254 0}},
1256 // Press Alt+Search. Confirm the event is now VKEY_CONTROL.
1257 {KeyTestCase::TEST_ALL,
1258 ui::ET_KEY_PRESSED,
1259 {ui::VKEY_LWIN,
1260 ui::DomCode::OS_LEFT,
1261 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
1262 ui::DomKey::OS,
1264 {ui::VKEY_CONTROL,
1265 ui::DomCode::CONTROL_LEFT,
1266 ui::EF_CONTROL_DOWN,
1267 ui::DomKey::CONTROL,
1268 0}},
1270 // Press Control+Alt+Search. Confirm the event is now VKEY_CONTROL.
1271 {KeyTestCase::TEST_ALL,
1272 ui::ET_KEY_PRESSED,
1273 {ui::VKEY_LWIN,
1274 ui::DomCode::OS_LEFT,
1275 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
1276 ui::DomKey::OS,
1278 {ui::VKEY_CONTROL,
1279 ui::DomCode::CONTROL_LEFT,
1280 ui::EF_CONTROL_DOWN,
1281 ui::DomKey::CONTROL,
1282 0}},
1284 // Press Shift+Control+Alt+Search. Confirm the event is now Control with
1285 // Shift and Control modifiers.
1286 {KeyTestCase::TEST_ALL,
1287 ui::ET_KEY_PRESSED,
1288 {ui::VKEY_LWIN,
1289 ui::DomCode::OS_LEFT,
1290 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
1291 ui::EF_COMMAND_DOWN,
1292 ui::DomKey::OS,
1294 {ui::VKEY_CONTROL,
1295 ui::DomCode::CONTROL_LEFT,
1296 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
1297 ui::DomKey::CONTROL,
1298 0}},
1300 // Press Shift+Control+Alt+Search+B. Confirm the event is now B with Shift
1301 // and Control modifiers.
1302 {KeyTestCase::TEST_ALL,
1303 ui::ET_KEY_PRESSED,
1304 {ui::VKEY_B,
1305 ui::DomCode::KEY_B,
1306 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
1307 ui::EF_COMMAND_DOWN,
1308 ui::DomKey::CHARACTER,
1309 'B'},
1310 {ui::VKEY_B,
1311 ui::DomCode::KEY_B,
1312 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
1313 ui::DomKey::CHARACTER,
1314 'B'}},
1317 for (size_t i = 0; i < arraysize(sa_tests); ++i) {
1318 SCOPED_TRACE(i);
1319 CheckKeyTestCase(&rewriter, sa_tests[i]);
1323 TEST_F(EventRewriterTest, TestRewriteModifiersRemapToEscape) {
1324 // Remap Search to ESC.
1325 TestingPrefServiceSyncable prefs;
1326 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1327 IntegerPrefMember search;
1328 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
1329 search.SetValue(chromeos::input_method::kEscapeKey);
1331 EventRewriter rewriter(NULL);
1332 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1333 rewriter.set_pref_service_for_testing(&prefs);
1335 KeyTestCase tests[] = {
1336 // Press Search. Confirm the event is now VKEY_ESCAPE.
1337 {KeyTestCase::TEST_ALL,
1338 ui::ET_KEY_PRESSED,
1339 {ui::VKEY_LWIN,
1340 ui::DomCode::OS_LEFT,
1341 ui::EF_COMMAND_DOWN,
1342 ui::DomKey::OS,
1344 {ui::VKEY_ESCAPE,
1345 ui::DomCode::ESCAPE,
1346 ui::EF_NONE,
1347 ui::DomKey::ESCAPE,
1348 0}},
1351 for (size_t i = 0; i < arraysize(tests); ++i) {
1352 SCOPED_TRACE(i);
1353 CheckKeyTestCase(&rewriter, tests[i]);
1357 TEST_F(EventRewriterTest, TestRewriteModifiersRemapMany) {
1358 // Remap Search to Alt.
1359 TestingPrefServiceSyncable prefs;
1360 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1361 IntegerPrefMember search;
1362 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
1363 search.SetValue(chromeos::input_method::kAltKey);
1365 EventRewriter rewriter(NULL);
1366 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1367 rewriter.set_pref_service_for_testing(&prefs);
1369 KeyTestCase s2a_tests[] = {
1370 // Press Search. Confirm the event is now VKEY_MENU.
1371 {KeyTestCase::TEST_ALL,
1372 ui::ET_KEY_PRESSED,
1373 {ui::VKEY_LWIN,
1374 ui::DomCode::OS_LEFT,
1375 ui::EF_COMMAND_DOWN,
1376 ui::DomKey::OS,
1378 {ui::VKEY_MENU,
1379 ui::DomCode::ALT_LEFT,
1380 ui::EF_ALT_DOWN,
1381 ui::DomKey::ALT,
1382 0}},
1385 for (size_t i = 0; i < arraysize(s2a_tests); ++i) {
1386 SCOPED_TRACE(i);
1387 CheckKeyTestCase(&rewriter, s2a_tests[i]);
1390 // Remap Alt to Control.
1391 IntegerPrefMember alt;
1392 alt.Init(prefs::kLanguageRemapAltKeyTo, &prefs);
1393 alt.SetValue(chromeos::input_method::kControlKey);
1395 KeyTestCase a2c_tests[] = {
1396 // Press left Alt. Confirm the event is now VKEY_CONTROL.
1397 {KeyTestCase::TEST_ALL,
1398 ui::ET_KEY_PRESSED,
1399 {ui::VKEY_MENU,
1400 ui::DomCode::ALT_LEFT,
1401 ui::EF_ALT_DOWN,
1402 ui::DomKey::ALT,
1404 {ui::VKEY_CONTROL,
1405 ui::DomCode::CONTROL_LEFT,
1406 ui::EF_CONTROL_DOWN,
1407 ui::DomKey::CONTROL,
1408 0}},
1409 // Press Shift+comma. Verify that only the flags are changed.
1410 // The X11 portion of the test addresses crbug.com/390263 by verifying
1411 // that the X keycode remains that for ',<' and not for 105-key '<>'.
1412 {KeyTestCase::TEST_ALL,
1413 ui::ET_KEY_PRESSED,
1414 {ui::VKEY_OEM_COMMA,
1415 ui::DomCode::COMMA,
1416 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
1417 ui::DomKey::UNIDENTIFIED,
1419 {ui::VKEY_OEM_COMMA,
1420 ui::DomCode::COMMA,
1421 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
1422 ui::DomKey::UNIDENTIFIED,
1423 0}},
1424 // Press Shift+9. Verify that only the flags are changed.
1425 {KeyTestCase::TEST_ALL,
1426 ui::ET_KEY_PRESSED,
1427 {ui::VKEY_9,
1428 ui::DomCode::DIGIT9,
1429 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
1430 ui::DomKey::CHARACTER,
1431 '9'},
1432 {ui::VKEY_9,
1433 ui::DomCode::DIGIT9,
1434 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
1435 ui::DomKey::CHARACTER,
1436 '9'}},
1439 for (size_t i = 0; i < arraysize(a2c_tests); ++i) {
1440 SCOPED_TRACE(i);
1441 CheckKeyTestCase(&rewriter, a2c_tests[i]);
1444 // Remap Control to Search.
1445 IntegerPrefMember control;
1446 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
1447 control.SetValue(chromeos::input_method::kSearchKey);
1449 KeyTestCase c2s_tests[] = {
1450 // Press left Control. Confirm the event is now VKEY_LWIN.
1451 {KeyTestCase::TEST_ALL,
1452 ui::ET_KEY_PRESSED,
1453 {ui::VKEY_CONTROL,
1454 ui::DomCode::CONTROL_LEFT,
1455 ui::EF_CONTROL_DOWN,
1456 ui::DomKey::CONTROL,
1458 {ui::VKEY_LWIN,
1459 ui::DomCode::OS_LEFT,
1460 ui::EF_COMMAND_DOWN,
1461 ui::DomKey::OS,
1462 0}},
1464 // Then, press all of the three, Control+Alt+Search.
1465 {KeyTestCase::TEST_ALL,
1466 ui::ET_KEY_PRESSED,
1467 {ui::VKEY_LWIN,
1468 ui::DomCode::OS_LEFT,
1469 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
1470 ui::DomKey::OS,
1472 {ui::VKEY_MENU,
1473 ui::DomCode::ALT_LEFT,
1474 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
1475 ui::DomKey::ALT,
1476 0}},
1478 // Press Shift+Control+Alt+Search.
1479 {KeyTestCase::TEST_ALL,
1480 ui::ET_KEY_PRESSED,
1481 {ui::VKEY_LWIN,
1482 ui::DomCode::OS_LEFT,
1483 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
1484 ui::EF_COMMAND_DOWN,
1485 ui::DomKey::OS,
1487 {ui::VKEY_MENU,
1488 ui::DomCode::ALT_LEFT,
1489 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
1490 ui::EF_COMMAND_DOWN,
1491 ui::DomKey::ALT,
1492 0}},
1494 // Press Shift+Control+Alt+Search+B
1495 {KeyTestCase::TEST_ALL,
1496 ui::ET_KEY_PRESSED,
1497 {ui::VKEY_B,
1498 ui::DomCode::KEY_B,
1499 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
1500 ui::EF_COMMAND_DOWN,
1501 ui::DomKey::CHARACTER,
1502 'B'},
1503 {ui::VKEY_B,
1504 ui::DomCode::KEY_B,
1505 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
1506 ui::EF_COMMAND_DOWN,
1507 ui::DomKey::CHARACTER,
1508 'B'}},
1511 for (size_t i = 0; i < arraysize(c2s_tests); ++i) {
1512 SCOPED_TRACE(i);
1513 CheckKeyTestCase(&rewriter, c2s_tests[i]);
1517 TEST_F(EventRewriterTest, TestRewriteModifiersRemapToCapsLock) {
1518 // Remap Search to Caps Lock.
1519 TestingPrefServiceSyncable prefs;
1520 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1521 IntegerPrefMember search;
1522 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
1523 search.SetValue(chromeos::input_method::kCapsLockKey);
1525 chromeos::input_method::FakeImeKeyboard ime_keyboard;
1526 EventRewriter rewriter(NULL);
1527 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1528 rewriter.set_pref_service_for_testing(&prefs);
1529 rewriter.set_ime_keyboard_for_testing(&ime_keyboard);
1530 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1532 // Press Search.
1533 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_CAPITAL,
1534 ui::DomCode::CAPS_LOCK,
1535 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1536 ui::DomKey::CAPS_LOCK, 0),
1537 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1538 ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
1539 ui::EF_COMMAND_DOWN, ui::DomKey::OS, 0));
1540 // Confirm that the Caps Lock status is changed.
1541 EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
1543 // Release Search.
1544 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CAPITAL,
1545 ui::DomCode::CAPS_LOCK, ui::EF_NONE,
1546 ui::DomKey::CAPS_LOCK, 0),
1547 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1548 ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
1549 ui::EF_NONE, ui::DomKey::OS, 0));
1550 // Confirm that the Caps Lock status is not changed.
1551 EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
1553 // Press Search.
1554 EXPECT_EQ(
1555 GetExpectedResultAsString(
1556 ui::ET_KEY_PRESSED, ui::VKEY_CAPITAL, ui::DomCode::CAPS_LOCK,
1557 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN, ui::DomKey::CAPS_LOCK, 0),
1558 GetRewrittenEventAsString(
1559 &rewriter, ui::ET_KEY_PRESSED, ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
1560 ui::EF_COMMAND_DOWN | ui::EF_CAPS_LOCK_DOWN, ui::DomKey::OS, 0));
1561 // Confirm that the Caps Lock status is changed.
1562 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1564 // Release Search.
1565 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CAPITAL,
1566 ui::DomCode::CAPS_LOCK, ui::EF_NONE,
1567 ui::DomKey::CAPS_LOCK, 0),
1568 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1569 ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
1570 ui::EF_NONE, ui::DomKey::OS, 0));
1571 // Confirm that the Caps Lock status is not changed.
1572 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1574 // Press Caps Lock (on an external keyboard).
1575 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_CAPITAL,
1576 ui::DomCode::CAPS_LOCK,
1577 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1578 ui::DomKey::CAPS_LOCK, 0),
1579 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1580 ui::VKEY_CAPITAL, ui::DomCode::CAPS_LOCK,
1581 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1582 ui::DomKey::CAPS_LOCK, 0));
1584 // Confirm that calling RewriteForTesting() does not change the state of
1585 // |ime_keyboard|. In this case, X Window system itself should change the
1586 // Caps Lock state, not ash::EventRewriter.
1587 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1589 // Release Caps Lock (on an external keyboard).
1590 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CAPITAL,
1591 ui::DomCode::CAPS_LOCK, ui::EF_NONE,
1592 ui::DomKey::CAPS_LOCK, 0),
1593 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1594 ui::VKEY_CAPITAL, ui::DomCode::CAPS_LOCK,
1595 ui::EF_NONE, ui::DomKey::CAPS_LOCK, 0));
1596 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1599 TEST_F(EventRewriterTest, TestRewriteCapsLock) {
1600 TestingPrefServiceSyncable prefs;
1601 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1603 chromeos::input_method::FakeImeKeyboard ime_keyboard;
1604 EventRewriter rewriter(NULL);
1605 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1606 rewriter.set_pref_service_for_testing(&prefs);
1607 rewriter.set_ime_keyboard_for_testing(&ime_keyboard);
1608 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1610 // On Chrome OS, CapsLock is mapped to F16 with Mod3Mask.
1611 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_CAPITAL,
1612 ui::DomCode::CAPS_LOCK,
1613 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1614 ui::DomKey::CAPS_LOCK, 0),
1615 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1616 ui::VKEY_F16, ui::DomCode::F16,
1617 ui::EF_MOD3_DOWN, ui::DomKey::F16, 0));
1618 EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
1621 TEST_F(EventRewriterTest, TestRewriteDiamondKey) {
1622 TestingPrefServiceSyncable prefs;
1623 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1625 chromeos::input_method::FakeImeKeyboard ime_keyboard;
1626 EventRewriter rewriter(NULL);
1627 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1628 rewriter.set_pref_service_for_testing(&prefs);
1629 rewriter.set_ime_keyboard_for_testing(&ime_keyboard);
1631 KeyTestCase tests[] = {
1632 // F15 should work as Ctrl when --has-chromeos-diamond-key is not
1633 // specified.
1634 {KeyTestCase::TEST_VKEY,
1635 ui::ET_KEY_PRESSED,
1636 {ui::VKEY_F15, ui::DomCode::F15, ui::EF_NONE, ui::DomKey::F15, 0},
1637 {ui::VKEY_CONTROL,
1638 ui::DomCode::CONTROL_LEFT,
1639 ui::EF_CONTROL_DOWN,
1640 ui::DomKey::CONTROL,
1641 0}},
1643 {KeyTestCase::TEST_VKEY,
1644 ui::ET_KEY_RELEASED,
1645 {ui::VKEY_F15, ui::DomCode::F15, ui::EF_NONE, ui::DomKey::F15, 0},
1646 {ui::VKEY_CONTROL,
1647 ui::DomCode::CONTROL_LEFT,
1648 ui::EF_NONE,
1649 ui::DomKey::CONTROL,
1650 0}},
1652 // However, Mod2Mask should not be rewritten to CtrlMask when
1653 // --has-chromeos-diamond-key is not specified.
1654 {KeyTestCase::TEST_VKEY,
1655 ui::ET_KEY_PRESSED,
1656 {ui::VKEY_A,
1657 ui::DomCode::KEY_A,
1658 ui::EF_NONE,
1659 ui::DomKey::CHARACTER,
1660 'a'},
1661 {ui::VKEY_A,
1662 ui::DomCode::KEY_A,
1663 ui::EF_NONE,
1664 ui::DomKey::CHARACTER,
1665 'a'}},
1668 for (size_t i = 0; i < arraysize(tests); ++i) {
1669 SCOPED_TRACE(i);
1670 CheckKeyTestCase(&rewriter, tests[i]);
1674 TEST_F(EventRewriterTest, TestRewriteDiamondKeyWithFlag) {
1675 const base::CommandLine original_cl(*base::CommandLine::ForCurrentProcess());
1676 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1677 chromeos::switches::kHasChromeOSDiamondKey, "");
1679 TestingPrefServiceSyncable prefs;
1680 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1682 chromeos::input_method::FakeImeKeyboard ime_keyboard;
1683 EventRewriter rewriter(NULL);
1684 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1685 rewriter.set_pref_service_for_testing(&prefs);
1686 rewriter.set_ime_keyboard_for_testing(&ime_keyboard);
1688 // By default, F15 should work as Control.
1689 EXPECT_EQ(GetExpectedResultAsString(
1690 ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
1691 ui::EF_CONTROL_DOWN, ui::DomKey::CONTROL, 0),
1692 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1693 ui::VKEY_F15, ui::DomCode::F15,
1694 ui::EF_NONE, ui::DomKey::F15, 0));
1695 // Check that Control is applied to a subsequent key press.
1696 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1697 ui::DomCode::KEY_A, ui::EF_CONTROL_DOWN,
1698 ui::DomKey::CHARACTER, 'a'),
1699 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1700 ui::DomCode::KEY_A, ui::EF_NONE,
1701 ui::DomKey::CHARACTER, 'a'));
1702 // Release F15
1703 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL,
1704 ui::DomCode::CONTROL_LEFT, ui::EF_NONE,
1705 ui::DomKey::CONTROL, 0),
1706 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1707 ui::VKEY_F15, ui::DomCode::F15,
1708 ui::EF_NONE, ui::DomKey::F15, 0));
1709 // Check that Control is no longer applied to a subsequent key press.
1710 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1711 ui::DomCode::KEY_A, ui::EF_NONE,
1712 ui::DomKey::CHARACTER, 'a'),
1713 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1714 ui::DomCode::KEY_A, ui::EF_NONE,
1715 ui::DomKey::CHARACTER, 'a'));
1717 IntegerPrefMember diamond;
1718 diamond.Init(prefs::kLanguageRemapDiamondKeyTo, &prefs);
1719 diamond.SetValue(chromeos::input_method::kVoidKey);
1721 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN,
1722 ui::DomCode::NONE, ui::EF_NONE,
1723 ui::DomKey::NONE, 0),
1724 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1725 ui::VKEY_F15, ui::DomCode::F15,
1726 ui::EF_NONE, ui::DomKey::F15, 0));
1727 // Check that no modifier is applied to another key.
1728 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1729 ui::DomCode::KEY_A, ui::EF_NONE,
1730 ui::DomKey::CHARACTER, 'a'),
1731 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1732 ui::DomCode::KEY_A, ui::EF_NONE,
1733 ui::DomKey::CHARACTER, 'a'));
1735 diamond.SetValue(chromeos::input_method::kControlKey);
1737 EXPECT_EQ(GetExpectedResultAsString(
1738 ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
1739 ui::EF_CONTROL_DOWN, ui::DomKey::CONTROL, 0),
1740 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1741 ui::VKEY_F15, ui::DomCode::F15,
1742 ui::EF_NONE, ui::DomKey::F15, 0));
1743 // Check that Control is applied to a subsequent key press.
1744 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1745 ui::DomCode::KEY_A, ui::EF_CONTROL_DOWN,
1746 ui::DomKey::CHARACTER, 'a'),
1747 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1748 ui::DomCode::KEY_A, ui::EF_NONE,
1749 ui::DomKey::CHARACTER, 'a'));
1750 // Release F15
1751 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL,
1752 ui::DomCode::CONTROL_LEFT, ui::EF_NONE,
1753 ui::DomKey::CONTROL, 0),
1754 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1755 ui::VKEY_F15, ui::DomCode::F15,
1756 ui::EF_NONE, ui::DomKey::F15, 0));
1757 // Check that Control is no longer applied to a subsequent key press.
1758 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1759 ui::DomCode::KEY_A, ui::EF_NONE,
1760 ui::DomKey::CHARACTER, 'a'),
1761 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1762 ui::DomCode::KEY_A, ui::EF_NONE,
1763 ui::DomKey::CHARACTER, 'a'));
1765 diamond.SetValue(chromeos::input_method::kAltKey);
1767 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_MENU,
1768 ui::DomCode::ALT_LEFT, ui::EF_ALT_DOWN,
1769 ui::DomKey::ALT, 0),
1770 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1771 ui::VKEY_F15, ui::DomCode::F15,
1772 ui::EF_NONE, ui::DomKey::F15, 0));
1773 // Check that Alt is applied to a subsequent key press.
1774 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1775 ui::DomCode::KEY_A, ui::EF_ALT_DOWN,
1776 ui::DomKey::CHARACTER, 'a'),
1777 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1778 ui::DomCode::KEY_A, ui::EF_NONE,
1779 ui::DomKey::CHARACTER, 'a'));
1780 // Release F15
1781 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_MENU,
1782 ui::DomCode::ALT_LEFT, ui::EF_NONE,
1783 ui::DomKey::ALT, 0),
1784 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1785 ui::VKEY_F15, ui::DomCode::F15,
1786 ui::EF_NONE, ui::DomKey::F15, 0));
1787 // Check that Alt is no longer applied to a subsequent key press.
1788 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1789 ui::DomCode::KEY_A, ui::EF_NONE,
1790 ui::DomKey::CHARACTER, 'a'),
1791 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1792 ui::DomCode::KEY_A, ui::EF_NONE,
1793 ui::DomKey::CHARACTER, 'a'));
1795 diamond.SetValue(chromeos::input_method::kCapsLockKey);
1797 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_CAPITAL,
1798 ui::DomCode::CAPS_LOCK,
1799 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1800 ui::DomKey::CAPS_LOCK, 0),
1801 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1802 ui::VKEY_F15, ui::DomCode::F15,
1803 ui::EF_NONE, ui::DomKey::F15, 0));
1804 // Check that Caps is applied to a subsequent key press.
1805 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1806 ui::DomCode::KEY_A,
1807 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1808 ui::DomKey::CHARACTER, 'a'),
1809 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1810 ui::DomCode::KEY_A, ui::EF_NONE,
1811 ui::DomKey::CHARACTER, 'a'));
1812 // Release F15
1813 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CAPITAL,
1814 ui::DomCode::CAPS_LOCK, ui::EF_NONE,
1815 ui::DomKey::CAPS_LOCK, 0),
1816 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1817 ui::VKEY_F15, ui::DomCode::F15,
1818 ui::EF_NONE, ui::DomKey::F15, 0));
1819 // Check that Control is no longer applied to a subsequent key press.
1820 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1821 ui::DomCode::KEY_A, ui::EF_NONE,
1822 ui::DomKey::CHARACTER, 'a'),
1823 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1824 ui::DomCode::KEY_A, ui::EF_NONE,
1825 ui::DomKey::CHARACTER, 'a'));
1827 *base::CommandLine::ForCurrentProcess() = original_cl;
1830 TEST_F(EventRewriterTest, TestRewriteCapsLockToControl) {
1831 // Remap CapsLock to Control.
1832 TestingPrefServiceSyncable prefs;
1833 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1834 IntegerPrefMember control;
1835 control.Init(prefs::kLanguageRemapCapsLockKeyTo, &prefs);
1836 control.SetValue(chromeos::input_method::kControlKey);
1838 EventRewriter rewriter(NULL);
1839 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1840 rewriter.set_pref_service_for_testing(&prefs);
1842 KeyTestCase tests[] = {
1843 // Press CapsLock+a. Confirm that Mod3Mask is rewritten to ControlMask.
1844 // On Chrome OS, CapsLock works as a Mod3 modifier.
1845 {KeyTestCase::TEST_ALL,
1846 ui::ET_KEY_PRESSED,
1847 {ui::VKEY_A,
1848 ui::DomCode::KEY_A,
1849 ui::EF_MOD3_DOWN,
1850 ui::DomKey::CHARACTER,
1851 'a'},
1852 {ui::VKEY_A,
1853 ui::DomCode::KEY_A,
1854 ui::EF_CONTROL_DOWN,
1855 ui::DomKey::CHARACTER,
1856 'a'}},
1858 // Press Control+CapsLock+a. Confirm that Mod3Mask is rewritten to
1859 // ControlMask
1860 {KeyTestCase::TEST_ALL,
1861 ui::ET_KEY_PRESSED,
1862 {ui::VKEY_A,
1863 ui::DomCode::KEY_A,
1864 ui::EF_CONTROL_DOWN | ui::EF_MOD3_DOWN,
1865 ui::DomKey::CHARACTER,
1866 'a'},
1867 {ui::VKEY_A,
1868 ui::DomCode::KEY_A,
1869 ui::EF_CONTROL_DOWN,
1870 ui::DomKey::CHARACTER,
1871 'a'}},
1873 // Press Alt+CapsLock+a. Confirm that Mod3Mask is rewritten to
1874 // ControlMask.
1875 {KeyTestCase::TEST_ALL,
1876 ui::ET_KEY_PRESSED,
1877 {ui::VKEY_A,
1878 ui::DomCode::KEY_A,
1879 ui::EF_ALT_DOWN | ui::EF_MOD3_DOWN,
1880 ui::DomKey::CHARACTER,
1881 'a'},
1882 {ui::VKEY_A,
1883 ui::DomCode::KEY_A,
1884 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1885 ui::DomKey::CHARACTER,
1886 'a'}},
1889 for (size_t i = 0; i < arraysize(tests); ++i) {
1890 SCOPED_TRACE(i);
1891 CheckKeyTestCase(&rewriter, tests[i]);
1895 TEST_F(EventRewriterTest, TestRewriteCapsLockMod3InUse) {
1896 // Remap CapsLock to Control.
1897 TestingPrefServiceSyncable prefs;
1898 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1899 IntegerPrefMember control;
1900 control.Init(prefs::kLanguageRemapCapsLockKeyTo, &prefs);
1901 control.SetValue(chromeos::input_method::kControlKey);
1903 EventRewriter rewriter(NULL);
1904 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1905 rewriter.set_pref_service_for_testing(&prefs);
1906 input_method_manager_mock_->set_mod3_used(true);
1908 // Press CapsLock+a. Confirm that Mod3Mask is NOT rewritten to ControlMask
1909 // when Mod3Mask is already in use by the current XKB layout.
1910 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1911 ui::DomCode::KEY_A, ui::EF_NONE,
1912 ui::DomKey::CHARACTER, 'a'),
1913 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1914 ui::DomCode::KEY_A, ui::EF_NONE,
1915 ui::DomKey::CHARACTER, 'a'));
1917 input_method_manager_mock_->set_mod3_used(false);
1920 TEST_F(EventRewriterTest, TestRewriteExtendedKeys) {
1921 TestingPrefServiceSyncable prefs;
1922 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1923 EventRewriter rewriter(NULL);
1924 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1925 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
1926 rewriter.set_pref_service_for_testing(&prefs);
1928 KeyTestCase tests[] = {
1929 // Alt+Backspace -> Delete
1930 {KeyTestCase::TEST_ALL,
1931 ui::ET_KEY_PRESSED,
1932 {ui::VKEY_BACK,
1933 ui::DomCode::BACKSPACE,
1934 ui::EF_ALT_DOWN,
1935 ui::DomKey::BACKSPACE,
1937 {ui::VKEY_DELETE, ui::DomCode::DEL, ui::EF_NONE, ui::DomKey::DEL, 0}},
1938 // Control+Alt+Backspace -> Control+Delete
1939 {KeyTestCase::TEST_ALL,
1940 ui::ET_KEY_PRESSED,
1941 {ui::VKEY_BACK,
1942 ui::DomCode::BACKSPACE,
1943 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1944 ui::DomKey::BACKSPACE,
1946 {ui::VKEY_DELETE,
1947 ui::DomCode::DEL,
1948 ui::EF_CONTROL_DOWN,
1949 ui::DomKey::DEL,
1950 0}},
1951 // Search+Alt+Backspace -> Alt+Backspace
1952 {KeyTestCase::TEST_ALL,
1953 ui::ET_KEY_PRESSED,
1954 {ui::VKEY_BACK,
1955 ui::DomCode::BACKSPACE,
1956 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
1957 ui::DomKey::BACKSPACE,
1959 {ui::VKEY_BACK,
1960 ui::DomCode::BACKSPACE,
1961 ui::EF_ALT_DOWN,
1962 ui::DomKey::BACKSPACE,
1963 0}},
1964 // Search+Control+Alt+Backspace -> Control+Alt+Backspace
1965 {KeyTestCase::TEST_ALL,
1966 ui::ET_KEY_PRESSED,
1967 {ui::VKEY_BACK,
1968 ui::DomCode::BACKSPACE,
1969 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1970 ui::DomKey::BACKSPACE,
1972 {ui::VKEY_BACK,
1973 ui::DomCode::BACKSPACE,
1974 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1975 ui::DomKey::BACKSPACE,
1976 0}},
1977 // Alt+Up -> Prior
1978 {KeyTestCase::TEST_ALL,
1979 ui::ET_KEY_PRESSED,
1980 {ui::VKEY_UP,
1981 ui::DomCode::ARROW_UP,
1982 ui::EF_ALT_DOWN,
1983 ui::DomKey::ARROW_UP,
1985 {ui::VKEY_PRIOR,
1986 ui::DomCode::PAGE_UP,
1987 ui::EF_NONE,
1988 ui::DomKey::PAGE_UP,
1989 0}},
1990 // Alt+Down -> Next
1991 {KeyTestCase::TEST_ALL,
1992 ui::ET_KEY_PRESSED,
1993 {ui::VKEY_DOWN,
1994 ui::DomCode::ARROW_DOWN,
1995 ui::EF_ALT_DOWN,
1996 ui::DomKey::ARROW_DOWN,
1998 {ui::VKEY_NEXT,
1999 ui::DomCode::PAGE_DOWN,
2000 ui::EF_NONE,
2001 ui::DomKey::PAGE_DOWN,
2002 0}},
2003 // Ctrl+Alt+Up -> Home
2004 {KeyTestCase::TEST_ALL,
2005 ui::ET_KEY_PRESSED,
2006 {ui::VKEY_UP,
2007 ui::DomCode::ARROW_UP,
2008 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
2009 ui::DomKey::ARROW_UP,
2011 {ui::VKEY_HOME, ui::DomCode::HOME, ui::EF_NONE, ui::DomKey::HOME, 0}},
2012 // Ctrl+Alt+Down -> End
2013 {KeyTestCase::TEST_ALL,
2014 ui::ET_KEY_PRESSED,
2015 {ui::VKEY_DOWN,
2016 ui::DomCode::ARROW_DOWN,
2017 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
2018 ui::DomKey::ARROW_DOWN,
2020 {ui::VKEY_END, ui::DomCode::END, ui::EF_NONE, ui::DomKey::END, 0}},
2022 // Search+Alt+Up -> Alt+Up
2023 {KeyTestCase::TEST_ALL,
2024 ui::ET_KEY_PRESSED,
2025 {ui::VKEY_UP,
2026 ui::DomCode::ARROW_UP,
2027 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
2028 ui::DomKey::ARROW_UP,
2030 {ui::VKEY_UP,
2031 ui::DomCode::ARROW_UP,
2032 ui::EF_ALT_DOWN,
2033 ui::DomKey::ARROW_UP,
2034 0}},
2035 // Search+Alt+Down -> Alt+Down
2036 {KeyTestCase::TEST_ALL,
2037 ui::ET_KEY_PRESSED,
2038 {ui::VKEY_DOWN,
2039 ui::DomCode::ARROW_DOWN,
2040 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
2041 ui::DomKey::ARROW_DOWN,
2043 {ui::VKEY_DOWN,
2044 ui::DomCode::ARROW_DOWN,
2045 ui::EF_ALT_DOWN,
2046 ui::DomKey::ARROW_DOWN,
2047 0}},
2048 // Search+Ctrl+Alt+Up -> Search+Ctrl+Alt+Up
2049 {KeyTestCase::TEST_ALL,
2050 ui::ET_KEY_PRESSED,
2051 {ui::VKEY_UP,
2052 ui::DomCode::ARROW_UP,
2053 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
2054 ui::DomKey::ARROW_UP,
2056 {ui::VKEY_UP,
2057 ui::DomCode::ARROW_UP,
2058 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
2059 ui::DomKey::ARROW_UP,
2060 0}},
2061 // Search+Ctrl+Alt+Down -> Ctrl+Alt+Down
2062 {KeyTestCase::TEST_ALL,
2063 ui::ET_KEY_PRESSED,
2064 {ui::VKEY_DOWN,
2065 ui::DomCode::ARROW_DOWN,
2066 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
2067 ui::DomKey::ARROW_DOWN,
2069 {ui::VKEY_DOWN,
2070 ui::DomCode::ARROW_DOWN,
2071 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
2072 ui::DomKey::ARROW_DOWN,
2073 0}},
2075 // Period -> Period
2076 {KeyTestCase::TEST_ALL,
2077 ui::ET_KEY_PRESSED,
2078 {ui::VKEY_OEM_PERIOD,
2079 ui::DomCode::PERIOD,
2080 ui::EF_NONE,
2081 ui::DomKey::CHARACTER,
2082 '.'},
2083 {ui::VKEY_OEM_PERIOD,
2084 ui::DomCode::PERIOD,
2085 ui::EF_NONE,
2086 ui::DomKey::CHARACTER,
2087 '.'}},
2089 // Search+Backspace -> Delete
2090 {KeyTestCase::TEST_ALL,
2091 ui::ET_KEY_PRESSED,
2092 {ui::VKEY_BACK,
2093 ui::DomCode::BACKSPACE,
2094 ui::EF_COMMAND_DOWN,
2095 ui::DomKey::BACKSPACE,
2097 {ui::VKEY_DELETE, ui::DomCode::DEL, ui::EF_NONE, ui::DomKey::DEL, 0}},
2098 // Search+Up -> Prior
2099 {KeyTestCase::TEST_ALL,
2100 ui::ET_KEY_PRESSED,
2101 {ui::VKEY_UP,
2102 ui::DomCode::ARROW_UP,
2103 ui::EF_COMMAND_DOWN,
2104 ui::DomKey::ARROW_UP,
2106 {ui::VKEY_PRIOR,
2107 ui::DomCode::PAGE_UP,
2108 ui::EF_NONE,
2109 ui::DomKey::PAGE_UP,
2110 0}},
2111 // Search+Down -> Next
2112 {KeyTestCase::TEST_ALL,
2113 ui::ET_KEY_PRESSED,
2114 {ui::VKEY_DOWN,
2115 ui::DomCode::ARROW_DOWN,
2116 ui::EF_COMMAND_DOWN,
2117 ui::DomKey::ARROW_DOWN,
2119 {ui::VKEY_NEXT,
2120 ui::DomCode::PAGE_DOWN,
2121 ui::EF_NONE,
2122 ui::DomKey::PAGE_DOWN,
2123 0}},
2124 // Search+Left -> Home
2125 {KeyTestCase::TEST_ALL,
2126 ui::ET_KEY_PRESSED,
2127 {ui::VKEY_LEFT,
2128 ui::DomCode::ARROW_LEFT,
2129 ui::EF_COMMAND_DOWN,
2130 ui::DomKey::ARROW_LEFT,
2132 {ui::VKEY_HOME, ui::DomCode::HOME, ui::EF_NONE, ui::DomKey::HOME, 0}},
2133 // Control+Search+Left -> Home
2134 {KeyTestCase::TEST_ALL,
2135 ui::ET_KEY_PRESSED,
2136 {ui::VKEY_LEFT,
2137 ui::DomCode::ARROW_LEFT,
2138 ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN,
2139 ui::DomKey::ARROW_LEFT,
2141 {ui::VKEY_HOME,
2142 ui::DomCode::HOME,
2143 ui::EF_CONTROL_DOWN,
2144 ui::DomKey::HOME,
2145 0}},
2146 // Search+Right -> End
2147 {KeyTestCase::TEST_ALL,
2148 ui::ET_KEY_PRESSED,
2149 {ui::VKEY_RIGHT,
2150 ui::DomCode::ARROW_RIGHT,
2151 ui::EF_COMMAND_DOWN,
2152 ui::DomKey::ARROW_RIGHT,
2154 {ui::VKEY_END, ui::DomCode::END, ui::EF_NONE, ui::DomKey::END, 0}},
2155 // Control+Search+Right -> End
2156 {KeyTestCase::TEST_ALL,
2157 ui::ET_KEY_PRESSED,
2158 {ui::VKEY_RIGHT,
2159 ui::DomCode::ARROW_RIGHT,
2160 ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN,
2161 ui::DomKey::ARROW_RIGHT,
2163 {ui::VKEY_END,
2164 ui::DomCode::END,
2165 ui::EF_CONTROL_DOWN,
2166 ui::DomKey::END,
2167 0}},
2168 // Search+Period -> Insert
2169 {KeyTestCase::TEST_ALL,
2170 ui::ET_KEY_PRESSED,
2171 {ui::VKEY_OEM_PERIOD,
2172 ui::DomCode::PERIOD,
2173 ui::EF_COMMAND_DOWN,
2174 ui::DomKey::CHARACTER,
2175 '.'},
2176 {ui::VKEY_INSERT,
2177 ui::DomCode::INSERT,
2178 ui::EF_NONE,
2179 ui::DomKey::INSERT,
2180 0}},
2181 // Control+Search+Period -> Control+Insert
2182 {KeyTestCase::TEST_ALL,
2183 ui::ET_KEY_PRESSED,
2184 {ui::VKEY_OEM_PERIOD,
2185 ui::DomCode::PERIOD,
2186 ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN,
2187 ui::DomKey::CHARACTER,
2188 '.'},
2189 {ui::VKEY_INSERT,
2190 ui::DomCode::INSERT,
2191 ui::EF_CONTROL_DOWN,
2192 ui::DomKey::INSERT,
2193 0}}};
2195 for (size_t i = 0; i < arraysize(tests); ++i) {
2196 SCOPED_TRACE(i);
2197 CheckKeyTestCase(&rewriter, tests[i]);
2201 TEST_F(EventRewriterTest, TestRewriteFunctionKeys) {
2202 TestingPrefServiceSyncable prefs;
2203 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
2204 EventRewriter rewriter(NULL);
2205 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
2206 rewriter.set_pref_service_for_testing(&prefs);
2208 KeyTestCase tests[] = {
2209 // F1 -> Back
2210 {KeyTestCase::TEST_ALL,
2211 ui::ET_KEY_PRESSED,
2212 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_NONE, ui::DomKey::F1, 0},
2213 {ui::VKEY_BROWSER_BACK,
2214 ui::DomCode::BROWSER_BACK,
2215 ui::EF_NONE,
2216 ui::DomKey::BROWSER_BACK,
2217 0}},
2218 {KeyTestCase::TEST_ALL,
2219 ui::ET_KEY_PRESSED,
2220 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_CONTROL_DOWN, ui::DomKey::F1, 0},
2221 {ui::VKEY_BROWSER_BACK,
2222 ui::DomCode::BROWSER_BACK,
2223 ui::EF_CONTROL_DOWN,
2224 ui::DomKey::BROWSER_BACK,
2225 0}},
2226 {KeyTestCase::TEST_ALL,
2227 ui::ET_KEY_PRESSED,
2228 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_ALT_DOWN, ui::DomKey::F1, 0},
2229 {ui::VKEY_BROWSER_BACK,
2230 ui::DomCode::BROWSER_BACK,
2231 ui::EF_ALT_DOWN,
2232 ui::DomKey::BROWSER_BACK,
2233 0}},
2234 // F2 -> Forward
2235 {KeyTestCase::TEST_ALL,
2236 ui::ET_KEY_PRESSED,
2237 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_NONE, ui::DomKey::F2, 0},
2238 {ui::VKEY_BROWSER_FORWARD,
2239 ui::DomCode::BROWSER_FORWARD,
2240 ui::EF_NONE,
2241 ui::DomKey::BROWSER_FORWARD,
2242 0}},
2243 {KeyTestCase::TEST_ALL,
2244 ui::ET_KEY_PRESSED,
2245 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_CONTROL_DOWN, ui::DomKey::F2, 0},
2246 {ui::VKEY_BROWSER_FORWARD,
2247 ui::DomCode::BROWSER_FORWARD,
2248 ui::EF_CONTROL_DOWN,
2249 ui::DomKey::BROWSER_FORWARD,
2250 0}},
2251 {KeyTestCase::TEST_ALL,
2252 ui::ET_KEY_PRESSED,
2253 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_ALT_DOWN, ui::DomKey::F2, 0},
2254 {ui::VKEY_BROWSER_FORWARD,
2255 ui::DomCode::BROWSER_FORWARD,
2256 ui::EF_ALT_DOWN,
2257 ui::DomKey::BROWSER_FORWARD,
2258 0}},
2259 // F3 -> Refresh
2260 {KeyTestCase::TEST_ALL,
2261 ui::ET_KEY_PRESSED,
2262 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_NONE, ui::DomKey::F3, 0},
2263 {ui::VKEY_BROWSER_REFRESH,
2264 ui::DomCode::BROWSER_REFRESH,
2265 ui::EF_NONE,
2266 ui::DomKey::BROWSER_REFRESH,
2267 0}},
2268 {KeyTestCase::TEST_ALL,
2269 ui::ET_KEY_PRESSED,
2270 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_CONTROL_DOWN, ui::DomKey::F3, 0},
2271 {ui::VKEY_BROWSER_REFRESH,
2272 ui::DomCode::BROWSER_REFRESH,
2273 ui::EF_CONTROL_DOWN,
2274 ui::DomKey::BROWSER_REFRESH,
2275 0}},
2276 {KeyTestCase::TEST_ALL,
2277 ui::ET_KEY_PRESSED,
2278 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_ALT_DOWN, ui::DomKey::F3, 0},
2279 {ui::VKEY_BROWSER_REFRESH,
2280 ui::DomCode::BROWSER_REFRESH,
2281 ui::EF_ALT_DOWN,
2282 ui::DomKey::BROWSER_REFRESH,
2283 0}},
2284 // F4 -> Launch App 2
2285 {KeyTestCase::TEST_ALL,
2286 ui::ET_KEY_PRESSED,
2287 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_NONE, ui::DomKey::F4, 0},
2288 {ui::VKEY_MEDIA_LAUNCH_APP2,
2289 ui::DomCode::ZOOM_TOGGLE,
2290 ui::EF_NONE,
2291 ui::DomKey::ZOOM_TOGGLE,
2292 0}},
2293 {KeyTestCase::TEST_ALL,
2294 ui::ET_KEY_PRESSED,
2295 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_CONTROL_DOWN, ui::DomKey::F4, 0},
2296 {ui::VKEY_MEDIA_LAUNCH_APP2,
2297 ui::DomCode::ZOOM_TOGGLE,
2298 ui::EF_CONTROL_DOWN,
2299 ui::DomKey::ZOOM_TOGGLE,
2300 0}},
2301 {KeyTestCase::TEST_ALL,
2302 ui::ET_KEY_PRESSED,
2303 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_ALT_DOWN, ui::DomKey::F4, 0},
2304 {ui::VKEY_MEDIA_LAUNCH_APP2,
2305 ui::DomCode::ZOOM_TOGGLE,
2306 ui::EF_ALT_DOWN,
2307 ui::DomKey::ZOOM_TOGGLE,
2308 0}},
2309 // F5 -> Launch App 1
2310 {KeyTestCase::TEST_ALL,
2311 ui::ET_KEY_PRESSED,
2312 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_NONE, ui::DomKey::F5, 0},
2313 {ui::VKEY_MEDIA_LAUNCH_APP1,
2314 ui::DomCode::SELECT_TASK,
2315 ui::EF_NONE,
2316 ui::DomKey::LAUNCH_MY_COMPUTER,
2317 0}},
2318 {KeyTestCase::TEST_ALL,
2319 ui::ET_KEY_PRESSED,
2320 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_CONTROL_DOWN, ui::DomKey::F5, 0},
2321 {ui::VKEY_MEDIA_LAUNCH_APP1,
2322 ui::DomCode::SELECT_TASK,
2323 ui::EF_CONTROL_DOWN,
2324 ui::DomKey::LAUNCH_MY_COMPUTER,
2325 0}},
2326 {KeyTestCase::TEST_ALL,
2327 ui::ET_KEY_PRESSED,
2328 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_ALT_DOWN, ui::DomKey::F5, 0},
2329 {ui::VKEY_MEDIA_LAUNCH_APP1,
2330 ui::DomCode::SELECT_TASK,
2331 ui::EF_ALT_DOWN,
2332 ui::DomKey::LAUNCH_MY_COMPUTER,
2333 0}},
2334 // F6 -> Brightness down
2335 {KeyTestCase::TEST_ALL,
2336 ui::ET_KEY_PRESSED,
2337 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_NONE, ui::DomKey::F6, 0},
2338 {ui::VKEY_BRIGHTNESS_DOWN,
2339 ui::DomCode::BRIGHTNESS_DOWN,
2340 ui::EF_NONE,
2341 ui::DomKey::BRIGHTNESS_DOWN,
2342 0}},
2343 {KeyTestCase::TEST_ALL,
2344 ui::ET_KEY_PRESSED,
2345 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_CONTROL_DOWN, ui::DomKey::F6, 0},
2346 {ui::VKEY_BRIGHTNESS_DOWN,
2347 ui::DomCode::BRIGHTNESS_DOWN,
2348 ui::EF_CONTROL_DOWN,
2349 ui::DomKey::BRIGHTNESS_DOWN,
2350 0}},
2351 {KeyTestCase::TEST_ALL,
2352 ui::ET_KEY_PRESSED,
2353 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_ALT_DOWN, ui::DomKey::F6, 0},
2354 {ui::VKEY_BRIGHTNESS_DOWN,
2355 ui::DomCode::BRIGHTNESS_DOWN,
2356 ui::EF_ALT_DOWN,
2357 ui::DomKey::BRIGHTNESS_DOWN,
2358 0}},
2359 // F7 -> Brightness up
2360 {KeyTestCase::TEST_ALL,
2361 ui::ET_KEY_PRESSED,
2362 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_NONE, ui::DomKey::F7, 0},
2363 {ui::VKEY_BRIGHTNESS_UP,
2364 ui::DomCode::BRIGHTNESS_UP,
2365 ui::EF_NONE,
2366 ui::DomKey::BRIGHTNESS_UP,
2367 0}},
2368 {KeyTestCase::TEST_ALL,
2369 ui::ET_KEY_PRESSED,
2370 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_CONTROL_DOWN, ui::DomKey::F7, 0},
2371 {ui::VKEY_BRIGHTNESS_UP,
2372 ui::DomCode::BRIGHTNESS_UP,
2373 ui::EF_CONTROL_DOWN,
2374 ui::DomKey::BRIGHTNESS_UP,
2375 0}},
2376 {KeyTestCase::TEST_ALL,
2377 ui::ET_KEY_PRESSED,
2378 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_ALT_DOWN, ui::DomKey::F7, 0},
2379 {ui::VKEY_BRIGHTNESS_UP,
2380 ui::DomCode::BRIGHTNESS_UP,
2381 ui::EF_ALT_DOWN,
2382 ui::DomKey::BRIGHTNESS_UP,
2383 0}},
2384 // F8 -> Volume Mute
2385 {KeyTestCase::TEST_ALL,
2386 ui::ET_KEY_PRESSED,
2387 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_NONE, ui::DomKey::F8, 0},
2388 {ui::VKEY_VOLUME_MUTE,
2389 ui::DomCode::VOLUME_MUTE,
2390 ui::EF_NONE,
2391 ui::DomKey::VOLUME_MUTE,
2392 0}},
2393 {KeyTestCase::TEST_ALL,
2394 ui::ET_KEY_PRESSED,
2395 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_CONTROL_DOWN, ui::DomKey::F8, 0},
2396 {ui::VKEY_VOLUME_MUTE,
2397 ui::DomCode::VOLUME_MUTE,
2398 ui::EF_CONTROL_DOWN,
2399 ui::DomKey::VOLUME_MUTE,
2400 0}},
2401 {KeyTestCase::TEST_ALL,
2402 ui::ET_KEY_PRESSED,
2403 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_ALT_DOWN, ui::DomKey::F8, 0},
2404 {ui::VKEY_VOLUME_MUTE,
2405 ui::DomCode::VOLUME_MUTE,
2406 ui::EF_ALT_DOWN,
2407 ui::DomKey::VOLUME_MUTE,
2408 0}},
2409 // F9 -> Volume Down
2410 {KeyTestCase::TEST_ALL,
2411 ui::ET_KEY_PRESSED,
2412 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_NONE, ui::DomKey::F9, 0},
2413 {ui::VKEY_VOLUME_DOWN,
2414 ui::DomCode::VOLUME_DOWN,
2415 ui::EF_NONE,
2416 ui::DomKey::VOLUME_DOWN,
2417 0}},
2418 {KeyTestCase::TEST_ALL,
2419 ui::ET_KEY_PRESSED,
2420 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_CONTROL_DOWN, ui::DomKey::F9, 0},
2421 {ui::VKEY_VOLUME_DOWN,
2422 ui::DomCode::VOLUME_DOWN,
2423 ui::EF_CONTROL_DOWN,
2424 ui::DomKey::VOLUME_DOWN,
2425 0}},
2426 {KeyTestCase::TEST_ALL,
2427 ui::ET_KEY_PRESSED,
2428 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_ALT_DOWN, ui::DomKey::F9, 0},
2429 {ui::VKEY_VOLUME_DOWN,
2430 ui::DomCode::VOLUME_DOWN,
2431 ui::EF_ALT_DOWN,
2432 ui::DomKey::VOLUME_DOWN,
2433 0}},
2434 // F10 -> Volume Up
2435 {KeyTestCase::TEST_ALL,
2436 ui::ET_KEY_PRESSED,
2437 {ui::VKEY_F10, ui::DomCode::F10, ui::EF_NONE, ui::DomKey::F10, 0},
2438 {ui::VKEY_VOLUME_UP,
2439 ui::DomCode::VOLUME_UP,
2440 ui::EF_NONE,
2441 ui::DomKey::VOLUME_UP,
2442 0}},
2443 {KeyTestCase::TEST_ALL,
2444 ui::ET_KEY_PRESSED,
2445 {ui::VKEY_F10,
2446 ui::DomCode::F10,
2447 ui::EF_CONTROL_DOWN,
2448 ui::DomKey::F10,
2450 {ui::VKEY_VOLUME_UP,
2451 ui::DomCode::VOLUME_UP,
2452 ui::EF_CONTROL_DOWN,
2453 ui::DomKey::VOLUME_UP,
2454 0}},
2455 {KeyTestCase::TEST_ALL,
2456 ui::ET_KEY_PRESSED,
2457 {ui::VKEY_F10, ui::DomCode::F10, ui::EF_ALT_DOWN, ui::DomKey::F10, 0},
2458 {ui::VKEY_VOLUME_UP,
2459 ui::DomCode::VOLUME_UP,
2460 ui::EF_ALT_DOWN,
2461 ui::DomKey::VOLUME_UP,
2462 0}},
2463 // F11 -> F11
2464 {KeyTestCase::TEST_ALL,
2465 ui::ET_KEY_PRESSED,
2466 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_NONE, ui::DomKey::F11, 0},
2467 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_NONE, ui::DomKey::F11, 0}},
2468 {KeyTestCase::TEST_ALL,
2469 ui::ET_KEY_PRESSED,
2470 {ui::VKEY_F11,
2471 ui::DomCode::F11,
2472 ui::EF_CONTROL_DOWN,
2473 ui::DomKey::F11,
2475 {ui::VKEY_F11,
2476 ui::DomCode::F11,
2477 ui::EF_CONTROL_DOWN,
2478 ui::DomKey::F11,
2479 0}},
2480 {KeyTestCase::TEST_ALL,
2481 ui::ET_KEY_PRESSED,
2482 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_ALT_DOWN, ui::DomKey::F11, 0},
2483 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_ALT_DOWN, ui::DomKey::F11, 0}},
2484 // F12 -> F12
2485 {KeyTestCase::TEST_ALL,
2486 ui::ET_KEY_PRESSED,
2487 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_NONE, ui::DomKey::F12, 0},
2488 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_NONE, ui::DomKey::F12, 0}},
2489 {KeyTestCase::TEST_ALL,
2490 ui::ET_KEY_PRESSED,
2491 {ui::VKEY_F12,
2492 ui::DomCode::F12,
2493 ui::EF_CONTROL_DOWN,
2494 ui::DomKey::F12,
2496 {ui::VKEY_F12,
2497 ui::DomCode::F12,
2498 ui::EF_CONTROL_DOWN,
2499 ui::DomKey::F12,
2500 0}},
2501 {KeyTestCase::TEST_ALL,
2502 ui::ET_KEY_PRESSED,
2503 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_ALT_DOWN, ui::DomKey::F12, 0},
2504 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_ALT_DOWN, ui::DomKey::F12, 0}},
2506 // The number row should not be rewritten without Search key.
2507 {KeyTestCase::TEST_ALL,
2508 ui::ET_KEY_PRESSED,
2509 {ui::VKEY_1,
2510 ui::DomCode::DIGIT1,
2511 ui::EF_NONE,
2512 ui::DomKey::CHARACTER,
2513 '1'},
2514 {ui::VKEY_1,
2515 ui::DomCode::DIGIT1,
2516 ui::EF_NONE,
2517 ui::DomKey::CHARACTER,
2518 '1'}},
2519 {KeyTestCase::TEST_ALL,
2520 ui::ET_KEY_PRESSED,
2521 {ui::VKEY_2,
2522 ui::DomCode::DIGIT2,
2523 ui::EF_NONE,
2524 ui::DomKey::CHARACTER,
2525 '2'},
2526 {ui::VKEY_2,
2527 ui::DomCode::DIGIT2,
2528 ui::EF_NONE,
2529 ui::DomKey::CHARACTER,
2530 '2'}},
2531 {KeyTestCase::TEST_ALL,
2532 ui::ET_KEY_PRESSED,
2533 {ui::VKEY_3,
2534 ui::DomCode::DIGIT3,
2535 ui::EF_NONE,
2536 ui::DomKey::CHARACTER,
2537 '3'},
2538 {ui::VKEY_3,
2539 ui::DomCode::DIGIT3,
2540 ui::EF_NONE,
2541 ui::DomKey::CHARACTER,
2542 '3'}},
2543 {KeyTestCase::TEST_ALL,
2544 ui::ET_KEY_PRESSED,
2545 {ui::VKEY_4,
2546 ui::DomCode::DIGIT4,
2547 ui::EF_NONE,
2548 ui::DomKey::CHARACTER,
2549 '4'},
2550 {ui::VKEY_4,
2551 ui::DomCode::DIGIT4,
2552 ui::EF_NONE,
2553 ui::DomKey::CHARACTER,
2554 '4'}},
2555 {KeyTestCase::TEST_ALL,
2556 ui::ET_KEY_PRESSED,
2557 {ui::VKEY_5,
2558 ui::DomCode::DIGIT5,
2559 ui::EF_NONE,
2560 ui::DomKey::CHARACTER,
2561 '5'},
2562 {ui::VKEY_5,
2563 ui::DomCode::DIGIT5,
2564 ui::EF_NONE,
2565 ui::DomKey::CHARACTER,
2566 '5'}},
2567 {KeyTestCase::TEST_ALL,
2568 ui::ET_KEY_PRESSED,
2569 {ui::VKEY_6,
2570 ui::DomCode::DIGIT6,
2571 ui::EF_NONE,
2572 ui::DomKey::CHARACTER,
2573 '6'},
2574 {ui::VKEY_6,
2575 ui::DomCode::DIGIT6,
2576 ui::EF_NONE,
2577 ui::DomKey::CHARACTER,
2578 '6'}},
2579 {KeyTestCase::TEST_ALL,
2580 ui::ET_KEY_PRESSED,
2581 {ui::VKEY_7,
2582 ui::DomCode::DIGIT7,
2583 ui::EF_NONE,
2584 ui::DomKey::CHARACTER,
2585 '7'},
2586 {ui::VKEY_7,
2587 ui::DomCode::DIGIT7,
2588 ui::EF_NONE,
2589 ui::DomKey::CHARACTER,
2590 '7'}},
2591 {KeyTestCase::TEST_ALL,
2592 ui::ET_KEY_PRESSED,
2593 {ui::VKEY_8,
2594 ui::DomCode::DIGIT8,
2595 ui::EF_NONE,
2596 ui::DomKey::CHARACTER,
2597 '8'},
2598 {ui::VKEY_8,
2599 ui::DomCode::DIGIT8,
2600 ui::EF_NONE,
2601 ui::DomKey::CHARACTER,
2602 '8'}},
2603 {KeyTestCase::TEST_ALL,
2604 ui::ET_KEY_PRESSED,
2605 {ui::VKEY_9,
2606 ui::DomCode::DIGIT9,
2607 ui::EF_NONE,
2608 ui::DomKey::CHARACTER,
2609 '9'},
2610 {ui::VKEY_9,
2611 ui::DomCode::DIGIT9,
2612 ui::EF_NONE,
2613 ui::DomKey::CHARACTER,
2614 '9'}},
2615 {KeyTestCase::TEST_ALL,
2616 ui::ET_KEY_PRESSED,
2617 {ui::VKEY_0,
2618 ui::DomCode::DIGIT0,
2619 ui::EF_NONE,
2620 ui::DomKey::CHARACTER,
2621 '0'},
2622 {ui::VKEY_0,
2623 ui::DomCode::DIGIT0,
2624 ui::EF_NONE,
2625 ui::DomKey::CHARACTER,
2626 '0'}},
2627 {KeyTestCase::TEST_ALL,
2628 ui::ET_KEY_PRESSED,
2629 {ui::VKEY_OEM_MINUS,
2630 ui::DomCode::MINUS,
2631 ui::EF_NONE,
2632 ui::DomKey::CHARACTER,
2633 '-'},
2634 {ui::VKEY_OEM_MINUS,
2635 ui::DomCode::MINUS,
2636 ui::EF_NONE,
2637 ui::DomKey::CHARACTER,
2638 '-'}},
2639 {KeyTestCase::TEST_ALL,
2640 ui::ET_KEY_PRESSED,
2641 {ui::VKEY_OEM_PLUS,
2642 ui::DomCode::EQUAL,
2643 ui::EF_NONE,
2644 ui::DomKey::CHARACTER,
2645 '='},
2646 {ui::VKEY_OEM_PLUS,
2647 ui::DomCode::EQUAL,
2648 ui::EF_NONE,
2649 ui::DomKey::CHARACTER,
2650 '='}},
2652 // The number row should be rewritten as the F<number> row with Search
2653 // key.
2654 {KeyTestCase::TEST_ALL,
2655 ui::ET_KEY_PRESSED,
2656 {ui::VKEY_1,
2657 ui::DomCode::DIGIT1,
2658 ui::EF_COMMAND_DOWN,
2659 ui::DomKey::CHARACTER,
2660 '1'},
2661 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_NONE, ui::DomKey::F1, 0}},
2662 {KeyTestCase::TEST_ALL,
2663 ui::ET_KEY_PRESSED,
2664 {ui::VKEY_2,
2665 ui::DomCode::DIGIT2,
2666 ui::EF_COMMAND_DOWN,
2667 ui::DomKey::CHARACTER,
2668 '2'},
2669 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_NONE, ui::DomKey::F2, 0}},
2670 {KeyTestCase::TEST_ALL,
2671 ui::ET_KEY_PRESSED,
2672 {ui::VKEY_3,
2673 ui::DomCode::DIGIT3,
2674 ui::EF_COMMAND_DOWN,
2675 ui::DomKey::CHARACTER,
2676 '3'},
2677 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_NONE, ui::DomKey::F3, 0}},
2678 {KeyTestCase::TEST_ALL,
2679 ui::ET_KEY_PRESSED,
2680 {ui::VKEY_4,
2681 ui::DomCode::DIGIT4,
2682 ui::EF_COMMAND_DOWN,
2683 ui::DomKey::CHARACTER,
2684 '4'},
2685 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_NONE, ui::DomKey::F4, 0}},
2686 {KeyTestCase::TEST_ALL,
2687 ui::ET_KEY_PRESSED,
2688 {ui::VKEY_5,
2689 ui::DomCode::DIGIT5,
2690 ui::EF_COMMAND_DOWN,
2691 ui::DomKey::CHARACTER,
2692 '5'},
2693 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_NONE, ui::DomKey::F5, 0}},
2694 {KeyTestCase::TEST_ALL,
2695 ui::ET_KEY_PRESSED,
2696 {ui::VKEY_6,
2697 ui::DomCode::DIGIT6,
2698 ui::EF_COMMAND_DOWN,
2699 ui::DomKey::CHARACTER,
2700 '6'},
2701 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_NONE, ui::DomKey::F6, 0}},
2702 {KeyTestCase::TEST_ALL,
2703 ui::ET_KEY_PRESSED,
2704 {ui::VKEY_7,
2705 ui::DomCode::DIGIT7,
2706 ui::EF_COMMAND_DOWN,
2707 ui::DomKey::CHARACTER,
2708 '7'},
2709 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_NONE, ui::DomKey::F7, 0}},
2710 {KeyTestCase::TEST_ALL,
2711 ui::ET_KEY_PRESSED,
2712 {ui::VKEY_8,
2713 ui::DomCode::DIGIT8,
2714 ui::EF_COMMAND_DOWN,
2715 ui::DomKey::CHARACTER,
2716 '8'},
2717 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_NONE, ui::DomKey::F8, 0}},
2718 {KeyTestCase::TEST_ALL,
2719 ui::ET_KEY_PRESSED,
2720 {ui::VKEY_9,
2721 ui::DomCode::DIGIT9,
2722 ui::EF_COMMAND_DOWN,
2723 ui::DomKey::CHARACTER,
2724 '9'},
2725 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_NONE, ui::DomKey::F9, 0}},
2726 {KeyTestCase::TEST_ALL,
2727 ui::ET_KEY_PRESSED,
2728 {ui::VKEY_0,
2729 ui::DomCode::DIGIT0,
2730 ui::EF_COMMAND_DOWN,
2731 ui::DomKey::CHARACTER,
2732 '0'},
2733 {ui::VKEY_F10, ui::DomCode::F10, ui::EF_NONE, ui::DomKey::F10, 0}},
2734 {KeyTestCase::TEST_ALL,
2735 ui::ET_KEY_PRESSED,
2736 {ui::VKEY_OEM_MINUS,
2737 ui::DomCode::MINUS,
2738 ui::EF_COMMAND_DOWN,
2739 ui::DomKey::CHARACTER,
2740 '-'},
2741 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_NONE, ui::DomKey::F11, 0}},
2742 {KeyTestCase::TEST_ALL,
2743 ui::ET_KEY_PRESSED,
2744 {ui::VKEY_OEM_PLUS,
2745 ui::DomCode::EQUAL,
2746 ui::EF_COMMAND_DOWN,
2747 ui::DomKey::CHARACTER,
2748 '='},
2749 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_NONE, ui::DomKey::F12, 0}},
2751 // The function keys should not be rewritten with Search key pressed.
2752 {KeyTestCase::TEST_ALL,
2753 ui::ET_KEY_PRESSED,
2754 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_COMMAND_DOWN, ui::DomKey::F1, 0},
2755 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_NONE, ui::DomKey::F1, 0}},
2756 {KeyTestCase::TEST_ALL,
2757 ui::ET_KEY_PRESSED,
2758 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_COMMAND_DOWN, ui::DomKey::F2, 0},
2759 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_NONE, ui::DomKey::F2, 0}},
2760 {KeyTestCase::TEST_ALL,
2761 ui::ET_KEY_PRESSED,
2762 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_COMMAND_DOWN, ui::DomKey::F3, 0},
2763 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_NONE, ui::DomKey::F3, 0}},
2764 {KeyTestCase::TEST_ALL,
2765 ui::ET_KEY_PRESSED,
2766 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_COMMAND_DOWN, ui::DomKey::F4, 0},
2767 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_NONE, ui::DomKey::F4, 0}},
2768 {KeyTestCase::TEST_ALL,
2769 ui::ET_KEY_PRESSED,
2770 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_COMMAND_DOWN, ui::DomKey::F5, 0},
2771 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_NONE, ui::DomKey::F5, 0}},
2772 {KeyTestCase::TEST_ALL,
2773 ui::ET_KEY_PRESSED,
2774 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_COMMAND_DOWN, ui::DomKey::F6, 0},
2775 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_NONE, ui::DomKey::F6, 0}},
2776 {KeyTestCase::TEST_ALL,
2777 ui::ET_KEY_PRESSED,
2778 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_COMMAND_DOWN, ui::DomKey::F7, 0},
2779 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_NONE, ui::DomKey::F7, 0}},
2780 {KeyTestCase::TEST_ALL,
2781 ui::ET_KEY_PRESSED,
2782 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_COMMAND_DOWN, ui::DomKey::F8, 0},
2783 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_NONE, ui::DomKey::F8, 0}},
2784 {KeyTestCase::TEST_ALL,
2785 ui::ET_KEY_PRESSED,
2786 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_COMMAND_DOWN, ui::DomKey::F9, 0},
2787 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_NONE, ui::DomKey::F9, 0}},
2788 {KeyTestCase::TEST_ALL,
2789 ui::ET_KEY_PRESSED,
2790 {ui::VKEY_F10,
2791 ui::DomCode::F10,
2792 ui::EF_COMMAND_DOWN,
2793 ui::DomKey::F10,
2795 {ui::VKEY_F10, ui::DomCode::F10, ui::EF_NONE, ui::DomKey::F10, 0}},
2796 {KeyTestCase::TEST_ALL,
2797 ui::ET_KEY_PRESSED,
2798 {ui::VKEY_F11,
2799 ui::DomCode::F11,
2800 ui::EF_COMMAND_DOWN,
2801 ui::DomKey::F11,
2803 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_NONE, ui::DomKey::F11, 0}},
2804 {KeyTestCase::TEST_ALL,
2805 ui::ET_KEY_PRESSED,
2806 {ui::VKEY_F12,
2807 ui::DomCode::F12,
2808 ui::EF_COMMAND_DOWN,
2809 ui::DomKey::F12,
2811 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_NONE, ui::DomKey::F12, 0}}};
2813 for (size_t i = 0; i < arraysize(tests); ++i) {
2814 SCOPED_TRACE(i);
2815 CheckKeyTestCase(&rewriter, tests[i]);
2819 TEST_F(EventRewriterTest, TestRewriteExtendedKeysWithSearchRemapped) {
2820 const base::CommandLine original_cl(*base::CommandLine::ForCurrentProcess());
2822 // Remap Search to Control.
2823 TestingPrefServiceSyncable prefs;
2824 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
2825 IntegerPrefMember search;
2826 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
2827 search.SetValue(chromeos::input_method::kControlKey);
2829 EventRewriter rewriter(NULL);
2830 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
2831 rewriter.set_pref_service_for_testing(&prefs);
2833 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
2834 chromeos::switches::kHasChromeOSKeyboard, "");
2836 KeyTestCase tests[] = {
2837 // Alt+Search+Down -> End
2838 {KeyTestCase::TEST_ALL,
2839 ui::ET_KEY_PRESSED,
2840 {ui::VKEY_DOWN,
2841 ui::DomCode::ARROW_DOWN,
2842 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
2843 ui::DomKey::ARROW_DOWN,
2845 {ui::VKEY_END, ui::DomCode::END, ui::EF_NONE, ui::DomKey::END, 0}},
2847 // Shift+Alt+Search+Down -> Shift+End
2848 {KeyTestCase::TEST_ALL,
2849 ui::ET_KEY_PRESSED,
2850 {ui::VKEY_DOWN,
2851 ui::DomCode::ARROW_DOWN,
2852 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
2853 ui::DomKey::ARROW_DOWN,
2855 {ui::VKEY_END, ui::DomCode::END, ui::EF_SHIFT_DOWN, ui::DomKey::END, 0}},
2858 for (size_t i = 0; i < arraysize(tests); ++i) {
2859 SCOPED_TRACE(i);
2860 CheckKeyTestCase(&rewriter, tests[i]);
2863 *base::CommandLine::ForCurrentProcess() = original_cl;
2866 TEST_F(EventRewriterTest, TestRewriteKeyEventSentByXSendEvent) {
2867 // Remap Control to Alt.
2868 TestingPrefServiceSyncable prefs;
2869 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
2870 IntegerPrefMember control;
2871 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
2872 control.SetValue(chromeos::input_method::kAltKey);
2874 EventRewriter rewriter(NULL);
2875 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
2876 rewriter.set_pref_service_for_testing(&prefs);
2878 // Send left control press.
2880 ui::KeyEvent keyevent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL,
2881 ui::DomCode::CONTROL_LEFT, ui::EF_FINAL,
2882 ui::DomKey::CONTROL, 0, ui::EventTimeForNow());
2883 scoped_ptr<ui::Event> new_event;
2884 // Control should NOT be remapped to Alt if EF_FINAL is set.
2885 EXPECT_EQ(ui::EVENT_REWRITE_CONTINUE,
2886 rewriter.RewriteEvent(keyevent, &new_event));
2887 EXPECT_FALSE(new_event);
2889 #if defined(USE_X11)
2890 // Send left control press, using XI2 native events.
2892 ui::ScopedXI2Event xev;
2893 xev.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, 0);
2894 XEvent* xevent = xev;
2895 xevent->xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), XK_Control_L);
2896 xevent->xkey.send_event = True; // XSendEvent() always does this.
2897 ui::KeyEvent keyevent(xev);
2898 scoped_ptr<ui::Event> new_event;
2899 // Control should NOT be remapped to Alt if send_event
2900 // flag in the event is True.
2901 EXPECT_EQ(ui::EVENT_REWRITE_CONTINUE,
2902 rewriter.RewriteEvent(keyevent, &new_event));
2903 EXPECT_FALSE(new_event);
2905 #endif
2908 TEST_F(EventRewriterTest, TestRewriteNonNativeEvent) {
2909 // Remap Control to Alt.
2910 TestingPrefServiceSyncable prefs;
2911 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
2912 IntegerPrefMember control;
2913 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
2914 control.SetValue(chromeos::input_method::kAltKey);
2916 EventRewriter rewriter(NULL);
2917 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
2918 rewriter.set_pref_service_for_testing(&prefs);
2920 const int kTouchId = 2;
2921 gfx::Point location(0, 0);
2922 ui::TouchEvent press(ui::ET_TOUCH_PRESSED, location, kTouchId,
2923 base::TimeDelta());
2924 press.set_flags(ui::EF_CONTROL_DOWN);
2925 #if defined(USE_X11)
2926 ui::UpdateX11EventForFlags(&press);
2927 #endif
2929 scoped_ptr<ui::Event> new_event;
2930 rewriter.RewriteEvent(press, &new_event);
2931 EXPECT_TRUE(new_event);
2932 // Control should be remapped to Alt.
2933 EXPECT_EQ(ui::EF_ALT_DOWN,
2934 new_event->flags() & (ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN));
2937 // Keeps a buffer of handled events.
2938 class EventBuffer : public ui::test::TestEventProcessor {
2939 public:
2940 EventBuffer() {}
2941 ~EventBuffer() override {}
2943 void PopEvents(ScopedVector<ui::Event>* events) {
2944 events->clear();
2945 events->swap(events_);
2948 private:
2949 // ui::EventProcessor overrides:
2950 ui::EventDispatchDetails OnEventFromSource(ui::Event* event) override {
2951 if (event->IsKeyEvent()) {
2952 events_.push_back(new ui::KeyEvent(*static_cast<ui::KeyEvent*>(event)));
2953 } else if (event->IsMouseWheelEvent()) {
2954 events_.push_back(
2955 new ui::MouseWheelEvent(*static_cast<ui::MouseWheelEvent*>(event)));
2956 } else if (event->IsMouseEvent()) {
2957 events_.push_back(
2958 new ui::MouseEvent(*static_cast<ui::MouseEvent*>(event)));
2960 return ui::EventDispatchDetails();
2963 ScopedVector<ui::Event> events_;
2965 DISALLOW_COPY_AND_ASSIGN(EventBuffer);
2968 // Trivial EventSource that does nothing but send events.
2969 class TestEventSource : public ui::EventSource {
2970 public:
2971 explicit TestEventSource(ui::EventProcessor* processor)
2972 : processor_(processor) {}
2973 ui::EventProcessor* GetEventProcessor() override { return processor_; }
2974 ui::EventDispatchDetails Send(ui::Event* event) {
2975 return SendEventToProcessor(event);
2978 private:
2979 ui::EventProcessor* processor_;
2982 // Tests of event rewriting that depend on the Ash window manager.
2983 class EventRewriterAshTest : public ash::test::AshTestBase {
2984 public:
2985 EventRewriterAshTest()
2986 : source_(&buffer_),
2987 fake_user_manager_(new user_manager::FakeUserManager),
2988 user_manager_enabler_(fake_user_manager_) {}
2989 ~EventRewriterAshTest() override {}
2991 bool RewriteFunctionKeys(const ui::Event& event,
2992 scoped_ptr<ui::Event>* rewritten_event) {
2993 return rewriter_->RewriteEvent(event, rewritten_event);
2996 ui::EventDispatchDetails Send(ui::Event* event) {
2997 return source_.Send(event);
3000 void SendKeyEvent(ui::EventType type,
3001 ui::KeyboardCode key_code,
3002 ui::DomCode code,
3003 ui::DomKey key,
3004 base::char16 character) {
3005 ui::KeyEvent press(type, key_code, code, ui::EF_NONE, key, character,
3006 ui::EventTimeForNow());
3007 ui::EventDispatchDetails details = Send(&press);
3008 CHECK(!details.dispatcher_destroyed);
3011 void SendActivateStickyKeyPattern(ui::KeyboardCode key_code,
3012 ui::DomCode code,
3013 ui::DomKey key,
3014 base::char16 character) {
3015 SendKeyEvent(ui::ET_KEY_PRESSED, key_code, code, key, character);
3016 SendKeyEvent(ui::ET_KEY_RELEASED, key_code, code, key, character);
3019 protected:
3020 TestingPrefServiceSyncable* prefs() { return &prefs_; }
3022 void PopEvents(ScopedVector<ui::Event>* events) { buffer_.PopEvents(events); }
3024 void SetUp() override {
3025 AshTestBase::SetUp();
3026 sticky_keys_controller_ =
3027 ash::Shell::GetInstance()->sticky_keys_controller();
3028 rewriter_.reset(new EventRewriter(sticky_keys_controller_));
3029 chromeos::Preferences::RegisterProfilePrefs(prefs_.registry());
3030 rewriter_->set_pref_service_for_testing(&prefs_);
3031 #if defined(USE_X11)
3032 ui::SetUpTouchPadForTest(kTouchPadDeviceId);
3033 #endif
3034 source_.AddEventRewriter(rewriter_.get());
3035 sticky_keys_controller_->Enable(true);
3038 void TearDown() override {
3039 rewriter_.reset();
3040 AshTestBase::TearDown();
3043 protected:
3044 ash::StickyKeysController* sticky_keys_controller_;
3046 private:
3047 scoped_ptr<EventRewriter> rewriter_;
3049 EventBuffer buffer_;
3050 TestEventSource source_;
3052 user_manager::FakeUserManager* fake_user_manager_; // Not owned.
3053 chromeos::ScopedUserManagerEnabler user_manager_enabler_;
3054 TestingPrefServiceSyncable prefs_;
3056 DISALLOW_COPY_AND_ASSIGN(EventRewriterAshTest);
3059 TEST_F(EventRewriterAshTest, TopRowKeysAreFunctionKeys) {
3060 scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(1));
3061 ash::wm::WindowState* window_state = ash::wm::GetWindowState(window.get());
3062 window_state->Activate();
3063 ScopedVector<ui::Event> events;
3065 // Create a simulated keypress of F1 targetted at the window.
3066 ui::KeyEvent press_f1(ui::ET_KEY_PRESSED, ui::VKEY_F1, ui::DomCode::F1,
3067 ui::EF_NONE, ui::DomKey::F1, 0, ui::EventTimeForNow());
3069 // Simulate an apps v2 window that has requested top row keys as function
3070 // keys. The event should not be rewritten.
3071 window_state->set_top_row_keys_are_function_keys(true);
3072 ui::EventDispatchDetails details = Send(&press_f1);
3073 ASSERT_FALSE(details.dispatcher_destroyed);
3074 PopEvents(&events);
3075 EXPECT_EQ(1u, events.size());
3076 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_F1,
3077 ui::DomCode::F1, ui::EF_NONE,
3078 ui::DomKey::F1, 0),
3079 GetKeyEventAsString(*static_cast<ui::KeyEvent*>(events[0])));
3081 // The event should also not be rewritten if the send-function-keys pref is
3082 // additionally set, for both apps v2 and regular windows.
3083 BooleanPrefMember send_function_keys_pref;
3084 send_function_keys_pref.Init(prefs::kLanguageSendFunctionKeys, prefs());
3085 send_function_keys_pref.SetValue(true);
3086 window_state->set_top_row_keys_are_function_keys(false);
3087 details = Send(&press_f1);
3088 ASSERT_FALSE(details.dispatcher_destroyed);
3089 PopEvents(&events);
3090 EXPECT_EQ(1u, events.size());
3091 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_F1,
3092 ui::DomCode::F1, ui::EF_NONE,
3093 ui::DomKey::F1, 0),
3094 GetKeyEventAsString(*static_cast<ui::KeyEvent*>(events[0])));
3096 // If the pref isn't set when an event is sent to a regular window, F1 is
3097 // rewritten to the back key.
3098 send_function_keys_pref.SetValue(false);
3099 details = Send(&press_f1);
3100 ASSERT_FALSE(details.dispatcher_destroyed);
3101 PopEvents(&events);
3102 EXPECT_EQ(1u, events.size());
3103 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_BROWSER_BACK,
3104 ui::DomCode::BROWSER_BACK, ui::EF_NONE,
3105 ui::DomKey::BROWSER_BACK, 0),
3106 GetKeyEventAsString(*static_cast<ui::KeyEvent*>(events[0])));
3109 TEST_F(EventRewriterTest, TestRewrittenModifierClick) {
3110 #if defined(USE_X11)
3111 std::vector<int> device_list;
3112 device_list.push_back(10);
3113 ui::TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
3115 // Remap Control to Alt.
3116 TestingPrefServiceSyncable prefs;
3117 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
3118 IntegerPrefMember control;
3119 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
3120 control.SetValue(chromeos::input_method::kAltKey);
3122 EventRewriter rewriter(NULL);
3123 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
3124 rewriter.set_pref_service_for_testing(&prefs);
3126 // Check that Control + Left Button is converted (via Alt + Left Button)
3127 // to Right Button.
3128 ui::ScopedXI2Event xev;
3129 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_PRESSED, gfx::Point(),
3130 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_CONTROL_DOWN);
3131 ui::MouseEvent press(xev);
3132 // Sanity check.
3133 EXPECT_EQ(ui::ET_MOUSE_PRESSED, press.type());
3134 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON | ui::EF_CONTROL_DOWN, press.flags());
3135 scoped_ptr<ui::Event> new_event;
3136 const ui::MouseEvent* result =
3137 RewriteMouseButtonEvent(&rewriter, press, &new_event);
3138 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
3139 EXPECT_FALSE(ui::EF_LEFT_MOUSE_BUTTON & result->flags());
3140 EXPECT_FALSE(ui::EF_CONTROL_DOWN & result->flags());
3141 EXPECT_FALSE(ui::EF_ALT_DOWN & result->flags());
3142 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
3143 #endif
3146 TEST_F(EventRewriterTest, DontRewriteIfNotRewritten) {
3147 // TODO(kpschoedel): pending changes for crbug.com/360377
3148 // to |chromeos::EventRewriter::RewriteLocatedEvent()
3149 #if defined(USE_X11)
3150 std::vector<int> device_list;
3151 device_list.push_back(10);
3152 device_list.push_back(11);
3153 ui::TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
3154 #endif
3155 TestingPrefServiceSyncable prefs;
3156 EventRewriter rewriter(NULL);
3157 rewriter.set_pref_service_for_testing(&prefs);
3158 const int kLeftAndAltFlag = ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN;
3160 // Test Alt + Left click.
3162 ui::MouseEvent press(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
3163 ui::EventTimeForNow(), kLeftAndAltFlag,
3164 ui::EF_LEFT_MOUSE_BUTTON);
3165 ui::EventTestApi test_press(&press);
3166 test_press.set_source_device_id(10);
3167 // Sanity check.
3168 EXPECT_EQ(ui::ET_MOUSE_PRESSED, press.type());
3169 EXPECT_EQ(kLeftAndAltFlag, press.flags());
3170 scoped_ptr<ui::Event> new_event;
3171 const ui::MouseEvent* result =
3172 RewriteMouseButtonEvent(&rewriter, press, &new_event);
3173 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
3174 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
3175 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
3178 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
3179 ui::EventTimeForNow(), kLeftAndAltFlag,
3180 ui::EF_LEFT_MOUSE_BUTTON);
3181 ui::EventTestApi test_release(&release);
3182 test_release.set_source_device_id(10);
3183 scoped_ptr<ui::Event> new_event;
3184 const ui::MouseEvent* result =
3185 RewriteMouseButtonEvent(&rewriter, release, &new_event);
3186 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
3187 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
3188 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
3190 #if defined(USE_X11)
3191 // Test Alt + Left click, using XI2 native events.
3193 ui::ScopedXI2Event xev;
3194 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_PRESSED, gfx::Point(),
3195 kLeftAndAltFlag);
3196 ui::MouseEvent press(xev);
3197 // Sanity check.
3198 EXPECT_EQ(ui::ET_MOUSE_PRESSED, press.type());
3199 EXPECT_EQ(kLeftAndAltFlag, press.flags());
3200 scoped_ptr<ui::Event> new_event;
3201 const ui::MouseEvent* result =
3202 RewriteMouseButtonEvent(&rewriter, press, &new_event);
3203 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
3204 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
3205 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
3208 ui::ScopedXI2Event xev;
3209 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_RELEASED, gfx::Point(),
3210 kLeftAndAltFlag);
3211 ui::MouseEvent release(xev);
3212 scoped_ptr<ui::Event> new_event;
3213 const ui::MouseEvent* result =
3214 RewriteMouseButtonEvent(&rewriter, release, &new_event);
3215 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
3216 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
3217 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
3219 #endif
3221 // No ALT in frst click.
3223 ui::MouseEvent press(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
3224 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
3225 ui::EF_LEFT_MOUSE_BUTTON);
3226 ui::EventTestApi test_press(&press);
3227 test_press.set_source_device_id(10);
3228 scoped_ptr<ui::Event> new_event;
3229 const ui::MouseEvent* result =
3230 RewriteMouseButtonEvent(&rewriter, press, &new_event);
3231 EXPECT_TRUE(ui::EF_LEFT_MOUSE_BUTTON & result->flags());
3232 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
3235 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
3236 ui::EventTimeForNow(), kLeftAndAltFlag,
3237 ui::EF_LEFT_MOUSE_BUTTON);
3238 ui::EventTestApi test_release(&release);
3239 test_release.set_source_device_id(10);
3240 scoped_ptr<ui::Event> new_event;
3241 const ui::MouseEvent* result =
3242 RewriteMouseButtonEvent(&rewriter, release, &new_event);
3243 EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & result->flags());
3244 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
3246 #if defined(USE_X11)
3247 // No ALT in frst click, using XI2 native events.
3249 ui::ScopedXI2Event xev;
3250 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_PRESSED, gfx::Point(),
3251 ui::EF_LEFT_MOUSE_BUTTON);
3252 ui::MouseEvent press(xev);
3253 scoped_ptr<ui::Event> new_event;
3254 const ui::MouseEvent* result =
3255 RewriteMouseButtonEvent(&rewriter, press, &new_event);
3256 EXPECT_TRUE(ui::EF_LEFT_MOUSE_BUTTON & result->flags());
3257 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
3260 ui::ScopedXI2Event xev;
3261 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_RELEASED, gfx::Point(),
3262 kLeftAndAltFlag);
3263 ui::MouseEvent release(xev);
3264 scoped_ptr<ui::Event> new_event;
3265 const ui::MouseEvent* result =
3266 RewriteMouseButtonEvent(&rewriter, release, &new_event);
3267 EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & result->flags());
3268 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
3270 #endif
3272 // ALT on different device.
3274 ui::MouseEvent press(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
3275 ui::EventTimeForNow(), kLeftAndAltFlag,
3276 ui::EF_LEFT_MOUSE_BUTTON);
3277 ui::EventTestApi test_press(&press);
3278 test_press.set_source_device_id(11);
3279 scoped_ptr<ui::Event> new_event;
3280 const ui::MouseEvent* result =
3281 RewriteMouseButtonEvent(&rewriter, press, &new_event);
3282 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
3283 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
3284 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
3287 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
3288 ui::EventTimeForNow(), kLeftAndAltFlag,
3289 ui::EF_LEFT_MOUSE_BUTTON);
3290 ui::EventTestApi test_release(&release);
3291 test_release.set_source_device_id(10);
3292 scoped_ptr<ui::Event> new_event;
3293 const ui::MouseEvent* result =
3294 RewriteMouseButtonEvent(&rewriter, release, &new_event);
3295 EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & result->flags());
3296 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
3299 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
3300 ui::EventTimeForNow(), kLeftAndAltFlag,
3301 ui::EF_LEFT_MOUSE_BUTTON);
3302 ui::EventTestApi test_release(&release);
3303 test_release.set_source_device_id(11);
3304 scoped_ptr<ui::Event> new_event;
3305 const ui::MouseEvent* result =
3306 RewriteMouseButtonEvent(&rewriter, release, &new_event);
3307 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
3308 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
3309 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
3311 #if defined(USE_X11)
3312 // ALT on different device, using XI2 native events.
3314 ui::ScopedXI2Event xev;
3315 xev.InitGenericButtonEvent(11, ui::ET_MOUSE_PRESSED, gfx::Point(),
3316 kLeftAndAltFlag);
3317 ui::MouseEvent press(xev);
3318 scoped_ptr<ui::Event> new_event;
3319 const ui::MouseEvent* result =
3320 RewriteMouseButtonEvent(&rewriter, press, &new_event);
3321 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
3322 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
3323 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
3326 ui::ScopedXI2Event xev;
3327 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_RELEASED, gfx::Point(),
3328 kLeftAndAltFlag);
3329 ui::MouseEvent release(xev);
3330 scoped_ptr<ui::Event> new_event;
3331 const ui::MouseEvent* result =
3332 RewriteMouseButtonEvent(&rewriter, release, &new_event);
3333 EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & result->flags());
3334 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
3337 ui::ScopedXI2Event xev;
3338 xev.InitGenericButtonEvent(11, ui::ET_MOUSE_RELEASED, gfx::Point(),
3339 kLeftAndAltFlag);
3340 ui::MouseEvent release(xev);
3341 scoped_ptr<ui::Event> new_event;
3342 const ui::MouseEvent* result =
3343 RewriteMouseButtonEvent(&rewriter, release, &new_event);
3344 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
3345 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
3346 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
3348 #endif
3351 TEST_F(EventRewriterAshTest, StickyKeyEventDispatchImpl) {
3352 // Test the actual key event dispatch implementation.
3353 ScopedVector<ui::Event> events;
3355 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3356 ui::DomKey::CONTROL, 0);
3357 PopEvents(&events);
3358 EXPECT_EQ(1u, events.size());
3359 EXPECT_EQ(ui::ET_KEY_PRESSED, events[0]->type());
3360 EXPECT_EQ(ui::VKEY_CONTROL,
3361 static_cast<ui::KeyEvent*>(events[0])->key_code());
3363 // Test key press event is correctly modified and modifier release
3364 // event is sent.
3365 ui::KeyEvent press(ui::ET_KEY_PRESSED, ui::VKEY_C, ui::DomCode::KEY_C,
3366 ui::EF_NONE, ui::DomKey::CHARACTER, 'c',
3367 ui::EventTimeForNow());
3368 ui::EventDispatchDetails details = Send(&press);
3369 PopEvents(&events);
3370 EXPECT_EQ(2u, events.size());
3371 EXPECT_EQ(ui::ET_KEY_PRESSED, events[0]->type());
3372 EXPECT_EQ(ui::VKEY_C, static_cast<ui::KeyEvent*>(events[0])->key_code());
3373 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
3374 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
3375 EXPECT_EQ(ui::VKEY_CONTROL,
3376 static_cast<ui::KeyEvent*>(events[1])->key_code());
3378 // Test key release event is not modified.
3379 ui::KeyEvent release(ui::ET_KEY_RELEASED, ui::VKEY_C, ui::DomCode::KEY_C,
3380 ui::EF_NONE, ui::DomKey::CHARACTER, 'c',
3381 ui::EventTimeForNow());
3382 details = Send(&release);
3383 ASSERT_FALSE(details.dispatcher_destroyed);
3384 PopEvents(&events);
3385 EXPECT_EQ(1u, events.size());
3386 EXPECT_EQ(ui::ET_KEY_RELEASED, events[0]->type());
3387 EXPECT_EQ(ui::VKEY_C, static_cast<ui::KeyEvent*>(events[0])->key_code());
3388 EXPECT_FALSE(events[0]->flags() & ui::EF_CONTROL_DOWN);
3391 TEST_F(EventRewriterAshTest, MouseEventDispatchImpl) {
3392 ScopedVector<ui::Event> events;
3394 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3395 ui::DomKey::CONTROL, 0);
3396 PopEvents(&events);
3398 // Test mouse press event is correctly modified.
3399 gfx::Point location(0, 0);
3400 ui::MouseEvent press(ui::ET_MOUSE_PRESSED, location, location,
3401 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
3402 ui::EF_LEFT_MOUSE_BUTTON);
3403 ui::EventDispatchDetails details = Send(&press);
3404 ASSERT_FALSE(details.dispatcher_destroyed);
3405 PopEvents(&events);
3406 EXPECT_EQ(1u, events.size());
3407 EXPECT_EQ(ui::ET_MOUSE_PRESSED, events[0]->type());
3408 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
3410 // Test mouse release event is correctly modified and modifier release
3411 // event is sent. The mouse event should have the correct DIP location.
3412 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, location, location,
3413 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
3414 ui::EF_LEFT_MOUSE_BUTTON);
3415 details = Send(&release);
3416 ASSERT_FALSE(details.dispatcher_destroyed);
3417 PopEvents(&events);
3418 EXPECT_EQ(2u, events.size());
3419 EXPECT_EQ(ui::ET_MOUSE_RELEASED, events[0]->type());
3420 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
3421 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
3422 EXPECT_EQ(ui::VKEY_CONTROL,
3423 static_cast<ui::KeyEvent*>(events[1])->key_code());
3426 TEST_F(EventRewriterAshTest, MouseWheelEventDispatchImpl) {
3427 ScopedVector<ui::Event> events;
3429 // Test positive mouse wheel event is correctly modified and modifier release
3430 // event is sent.
3431 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3432 ui::DomKey::CONTROL, 0);
3433 PopEvents(&events);
3434 gfx::Point location(0, 0);
3435 ui::MouseEvent mev(ui::ET_MOUSEWHEEL, location, location,
3436 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
3437 ui::EF_LEFT_MOUSE_BUTTON);
3438 ui::MouseWheelEvent positive(mev, 0, ui::MouseWheelEvent::kWheelDelta);
3439 ui::EventDispatchDetails details = Send(&positive);
3440 ASSERT_FALSE(details.dispatcher_destroyed);
3441 PopEvents(&events);
3442 EXPECT_EQ(2u, events.size());
3443 EXPECT_TRUE(events[0]->IsMouseWheelEvent());
3444 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
3445 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
3446 EXPECT_EQ(ui::VKEY_CONTROL,
3447 static_cast<ui::KeyEvent*>(events[1])->key_code());
3449 // Test negative mouse wheel event is correctly modified and modifier release
3450 // event is sent.
3451 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3452 ui::DomKey::CONTROL, 0);
3453 PopEvents(&events);
3454 ui::MouseWheelEvent negative(mev, 0, -ui::MouseWheelEvent::kWheelDelta);
3455 details = Send(&negative);
3456 ASSERT_FALSE(details.dispatcher_destroyed);
3457 PopEvents(&events);
3458 EXPECT_EQ(2u, events.size());
3459 EXPECT_TRUE(events[0]->IsMouseWheelEvent());
3460 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
3461 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
3462 EXPECT_EQ(ui::VKEY_CONTROL,
3463 static_cast<ui::KeyEvent*>(events[1])->key_code());
3466 class StickyKeysOverlayTest : public EventRewriterAshTest {
3467 public:
3468 StickyKeysOverlayTest() : overlay_(NULL) {}
3470 ~StickyKeysOverlayTest() override {}
3472 void SetUp() override {
3473 EventRewriterAshTest::SetUp();
3474 overlay_ = sticky_keys_controller_->GetOverlayForTest();
3475 ASSERT_TRUE(overlay_);
3478 ash::StickyKeysOverlay* overlay_;
3481 TEST_F(StickyKeysOverlayTest, OneModifierEnabled) {
3482 EXPECT_FALSE(overlay_->is_visible());
3483 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3484 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3486 // Pressing modifier key should show overlay.
3487 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3488 ui::DomKey::CONTROL, 0);
3489 EXPECT_TRUE(overlay_->is_visible());
3490 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
3491 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3493 // Pressing a normal key should hide overlay.
3494 SendActivateStickyKeyPattern(ui::VKEY_T, ui::DomCode::KEY_T,
3495 ui::DomKey::CHARACTER, 't');
3496 EXPECT_FALSE(overlay_->is_visible());
3497 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3498 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3501 TEST_F(StickyKeysOverlayTest, TwoModifiersEnabled) {
3502 EXPECT_FALSE(overlay_->is_visible());
3503 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3504 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3505 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3506 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3508 // Pressing two modifiers should show overlay.
3509 SendActivateStickyKeyPattern(ui::VKEY_SHIFT, ui::DomCode::SHIFT_LEFT,
3510 ui::DomKey::SHIFT, 0);
3511 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3512 ui::DomKey::CONTROL, 0);
3513 EXPECT_TRUE(overlay_->is_visible());
3514 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
3515 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3516 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
3517 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3519 // Pressing a normal key should hide overlay.
3520 SendActivateStickyKeyPattern(ui::VKEY_N, ui::DomCode::KEY_N,
3521 ui::DomKey::CHARACTER, 'n');
3522 EXPECT_FALSE(overlay_->is_visible());
3523 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3524 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3525 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3526 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3529 TEST_F(StickyKeysOverlayTest, LockedModifier) {
3530 EXPECT_FALSE(overlay_->is_visible());
3531 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3532 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
3534 // Pressing a modifier key twice should lock modifier and show overlay.
3535 SendActivateStickyKeyPattern(ui::VKEY_LMENU, ui::DomCode::ALT_LEFT,
3536 ui::DomKey::ALT, 0);
3537 SendActivateStickyKeyPattern(ui::VKEY_LMENU, ui::DomCode::ALT_LEFT,
3538 ui::DomKey::ALT, 0);
3539 EXPECT_TRUE(overlay_->is_visible());
3540 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
3541 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
3543 // Pressing a normal key should not hide overlay.
3544 SendActivateStickyKeyPattern(ui::VKEY_D, ui::DomCode::KEY_D,
3545 ui::DomKey::CHARACTER, 'd');
3546 EXPECT_TRUE(overlay_->is_visible());
3547 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
3548 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
3551 TEST_F(StickyKeysOverlayTest, LockedAndNormalModifier) {
3552 EXPECT_FALSE(overlay_->is_visible());
3553 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3554 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3555 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3556 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3558 // Pressing a modifier key twice should lock modifier and show overlay.
3559 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3560 ui::DomKey::CONTROL, 0);
3561 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3562 ui::DomKey::CONTROL, 0);
3563 EXPECT_TRUE(overlay_->is_visible());
3564 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
3565 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3567 // Pressing another modifier key should still show overlay.
3568 SendActivateStickyKeyPattern(ui::VKEY_SHIFT, ui::DomCode::SHIFT_LEFT,
3569 ui::DomKey::SHIFT, 0);
3570 EXPECT_TRUE(overlay_->is_visible());
3571 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
3572 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3573 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
3574 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3576 // Pressing a normal key should not hide overlay but disable normal modifier.
3577 SendActivateStickyKeyPattern(ui::VKEY_D, ui::DomCode::KEY_D,
3578 ui::DomKey::CHARACTER, 'd');
3579 EXPECT_TRUE(overlay_->is_visible());
3580 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
3581 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3582 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3583 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3586 TEST_F(StickyKeysOverlayTest, ModifiersDisabled) {
3587 EXPECT_FALSE(overlay_->is_visible());
3588 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3589 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3590 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3591 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3592 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3593 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
3594 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3595 overlay_->GetModifierKeyState(ui::EF_COMMAND_DOWN));
3597 // Enable modifiers.
3598 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3599 ui::DomKey::CONTROL, 0);
3600 SendActivateStickyKeyPattern(ui::VKEY_SHIFT, ui::DomCode::SHIFT_LEFT,
3601 ui::DomKey::SHIFT, 0);
3602 SendActivateStickyKeyPattern(ui::VKEY_SHIFT, ui::DomCode::SHIFT_LEFT,
3603 ui::DomKey::SHIFT, 0);
3604 SendActivateStickyKeyPattern(ui::VKEY_LMENU, ui::DomCode::ALT_LEFT,
3605 ui::DomKey::ALT, 0);
3606 SendActivateStickyKeyPattern(ui::VKEY_COMMAND, ui::DomCode::OS_LEFT,
3607 ui::DomKey::OS, 0);
3608 SendActivateStickyKeyPattern(ui::VKEY_COMMAND, ui::DomCode::OS_LEFT,
3609 ui::DomKey::OS, 0);
3611 EXPECT_TRUE(overlay_->is_visible());
3612 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
3613 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3614 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
3615 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3616 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
3617 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
3618 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
3619 overlay_->GetModifierKeyState(ui::EF_COMMAND_DOWN));
3621 // Disable modifiers and overlay should be hidden.
3622 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3623 ui::DomKey::CONTROL, 0);
3624 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
3625 ui::DomKey::CONTROL, 0);
3626 SendActivateStickyKeyPattern(ui::VKEY_SHIFT, ui::DomCode::SHIFT_LEFT,
3627 ui::DomKey::SHIFT, 0);
3628 SendActivateStickyKeyPattern(ui::VKEY_LMENU, ui::DomCode::ALT_LEFT,
3629 ui::DomKey::ALT, 0);
3630 SendActivateStickyKeyPattern(ui::VKEY_LMENU, ui::DomCode::ALT_LEFT,
3631 ui::DomKey::ALT, 0);
3632 SendActivateStickyKeyPattern(ui::VKEY_COMMAND, ui::DomCode::OS_LEFT,
3633 ui::DomKey::OS, 0);
3635 EXPECT_FALSE(overlay_->is_visible());
3636 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3637 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
3638 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3639 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
3640 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3641 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
3642 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
3643 overlay_->GetModifierKeyState(ui::EF_COMMAND_DOWN));
3646 TEST_F(StickyKeysOverlayTest, ModifierVisibility) {
3647 // All but AltGr and Mod3 should initially be visible.
3648 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_CONTROL_DOWN));
3649 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_SHIFT_DOWN));
3650 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALT_DOWN));
3651 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_COMMAND_DOWN));
3652 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
3653 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
3655 // Turn all modifiers on.
3656 sticky_keys_controller_->SetModifiersEnabled(true, true);
3657 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_CONTROL_DOWN));
3658 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_SHIFT_DOWN));
3659 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALT_DOWN));
3660 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_COMMAND_DOWN));
3661 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
3662 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
3664 // Turn off Mod3.
3665 sticky_keys_controller_->SetModifiersEnabled(false, true);
3666 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
3667 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
3669 // Turn off AltGr.
3670 sticky_keys_controller_->SetModifiersEnabled(true, false);
3671 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
3672 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
3674 // Turn off AltGr and Mod3.
3675 sticky_keys_controller_->SetModifiersEnabled(false, false);
3676 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
3677 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
3680 } // namespace chromeos