Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / chrome / browser / chromeos / events / event_rewriter_unittest.cc
blob7b5b2b44bc0ed2b7109ebd66952c2c442bf6e4ae
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/events/event_rewriter.h"
7 #include <vector>
9 #include "ash/shell.h"
10 #include "ash/sticky_keys/sticky_keys_controller.h"
11 #include "ash/sticky_keys/sticky_keys_overlay.h"
12 #include "ash/test/ash_test_base.h"
13 #include "ash/wm/window_state.h"
14 #include "base/basictypes.h"
15 #include "base/command_line.h"
16 #include "base/prefs/pref_member.h"
17 #include "base/strings/stringprintf.h"
18 #include "chrome/browser/chromeos/input_method/input_method_configuration.h"
19 #include "chrome/browser/chromeos/input_method/mock_input_method_manager.h"
20 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
21 #include "chrome/browser/chromeos/preferences.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/test/base/testing_pref_service_syncable.h"
24 #include "chromeos/chromeos_switches.h"
25 #include "components/user_manager/fake_user_manager.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "ui/aura/window.h"
28 #include "ui/aura/window_tree_host.h"
29 #include "ui/base/ime/chromeos/fake_ime_keyboard.h"
30 #include "ui/events/event.h"
31 #include "ui/events/event_rewriter.h"
32 #include "ui/events/event_utils.h"
33 #include "ui/events/keycodes/dom/dom_code.h"
34 #include "ui/events/keycodes/dom/dom_key.h"
35 #include "ui/events/keycodes/dom/keycode_converter.h"
36 #include "ui/events/test/events_test_utils.h"
37 #include "ui/events/test/test_event_processor.h"
39 #if defined(USE_X11)
40 #include <X11/keysym.h>
42 #include "ui/events/devices/x11/touch_factory_x11.h"
43 #include "ui/events/event_utils.h"
44 #include "ui/events/test/events_test_utils_x11.h"
45 #include "ui/gfx/x/x11_types.h"
46 #endif
48 namespace {
50 // The device id of the test touchpad device.
51 #if defined(USE_X11)
52 const int kTouchPadDeviceId = 1;
53 #endif
54 const int kKeyboardDeviceId = 2;
56 std::string GetExpectedResultAsString(ui::EventType ui_type,
57 ui::KeyboardCode ui_keycode,
58 ui::DomCode code,
59 int ui_flags, // ui::EventFlags
60 ui::DomKey key) {
61 return base::StringPrintf(
62 "type=%d code=0x%06X flags=0x%X vk=0x%02X key=0x%08X", ui_type,
63 static_cast<unsigned int>(code), ui_flags & ~ui::EF_IS_REPEAT, ui_keycode,
64 static_cast<unsigned int>(key));
67 std::string GetKeyEventAsString(const ui::KeyEvent& keyevent) {
68 return GetExpectedResultAsString(keyevent.type(), keyevent.key_code(),
69 keyevent.code(), keyevent.flags(),
70 keyevent.GetDomKey());
73 std::string GetRewrittenEventAsString(chromeos::EventRewriter* rewriter,
74 ui::EventType ui_type,
75 ui::KeyboardCode ui_keycode,
76 ui::DomCode code,
77 int ui_flags, // ui::EventFlags
78 ui::DomKey key) {
79 const ui::KeyEvent event(ui_type, ui_keycode, code, ui_flags, key,
80 ui::EventTimeForNow());
81 scoped_ptr<ui::Event> new_event;
82 rewriter->RewriteEvent(event, &new_event);
83 if (new_event)
84 return GetKeyEventAsString(
85 static_cast<const ui::KeyEvent&>(*new_event.get()));
86 return GetKeyEventAsString(event);
89 // Table entry for simple single key event rewriting tests.
90 struct KeyTestCase {
91 ui::EventType type;
92 struct Event {
93 ui::KeyboardCode key_code;
94 ui::DomCode code;
95 int flags; // ui::EventFlags
96 ui::DomKey::Base key;
97 } input, expected;
100 std::string GetTestCaseAsString(ui::EventType ui_type,
101 const KeyTestCase::Event& test) {
102 return GetExpectedResultAsString(ui_type, test.key_code, test.code,
103 test.flags, test.key);
106 // Tests a single stateless key rewrite operation.
107 void CheckKeyTestCase(chromeos::EventRewriter* rewriter,
108 const KeyTestCase& test) {
109 SCOPED_TRACE("\nSource: " + GetTestCaseAsString(test.type, test.input));
110 std::string expected = GetTestCaseAsString(test.type, test.expected);
111 EXPECT_EQ(expected, GetRewrittenEventAsString(
112 rewriter, test.type, test.input.key_code,
113 test.input.code, test.input.flags, test.input.key));
116 } // namespace
118 namespace chromeos {
120 class EventRewriterTest : public ash::test::AshTestBase {
121 public:
122 EventRewriterTest()
123 : fake_user_manager_(new user_manager::FakeUserManager),
124 user_manager_enabler_(fake_user_manager_),
125 input_method_manager_mock_(NULL) {}
126 ~EventRewriterTest() override {}
128 void SetUp() override {
129 input_method_manager_mock_ =
130 new chromeos::input_method::MockInputMethodManager;
131 chromeos::input_method::InitializeForTesting(
132 input_method_manager_mock_); // pass ownership
134 AshTestBase::SetUp();
137 void TearDown() override {
138 AshTestBase::TearDown();
139 // Shutdown() deletes the IME mock object.
140 chromeos::input_method::Shutdown();
143 protected:
144 void TestRewriteNumPadKeys();
145 void TestRewriteNumPadKeysOnAppleKeyboard();
147 const ui::MouseEvent* RewriteMouseButtonEvent(
148 chromeos::EventRewriter* rewriter,
149 const ui::MouseEvent& event,
150 scoped_ptr<ui::Event>* new_event) {
151 rewriter->RewriteMouseButtonEventForTesting(event, new_event);
152 return *new_event ? static_cast<const ui::MouseEvent*>(new_event->get())
153 : &event;
156 user_manager::FakeUserManager* fake_user_manager_; // Not owned.
157 chromeos::ScopedUserManagerEnabler user_manager_enabler_;
158 chromeos::input_method::MockInputMethodManager* input_method_manager_mock_;
161 TEST_F(EventRewriterTest, TestRewriteCommandToControl) {
162 // First, test with a PC keyboard.
163 TestingPrefServiceSyncable prefs;
164 EventRewriter rewriter(NULL);
165 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
166 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
167 rewriter.set_pref_service_for_testing(&prefs);
169 KeyTestCase pc_keyboard_tests[] = {
170 // VKEY_A, Alt modifier.
171 {ui::ET_KEY_PRESSED,
172 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_ALT_DOWN,
173 ui::DomKey::UNIDENTIFIED},
174 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_ALT_DOWN,
175 ui::DomKey::UNIDENTIFIED}},
177 // VKEY_A, Win modifier.
178 {ui::ET_KEY_PRESSED,
179 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_COMMAND_DOWN,
180 ui::DomKey::UNIDENTIFIED},
181 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_COMMAND_DOWN,
182 ui::DomKey::UNIDENTIFIED}},
184 // VKEY_A, Alt+Win modifier.
185 {ui::ET_KEY_PRESSED,
186 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
187 ui::DomKey::UNIDENTIFIED},
188 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
189 ui::DomKey::UNIDENTIFIED}},
191 // VKEY_LWIN (left Windows key), Alt modifier.
192 {ui::ET_KEY_PRESSED,
193 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
194 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::DomKey::OS},
195 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
196 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::DomKey::OS}},
198 // VKEY_RWIN (right Windows key), Alt modifier.
199 {ui::ET_KEY_PRESSED,
200 {ui::VKEY_RWIN, ui::DomCode::OS_RIGHT,
201 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::DomKey::OS},
202 {ui::VKEY_RWIN, ui::DomCode::OS_RIGHT,
203 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::DomKey::OS}},
206 for (const auto& test : pc_keyboard_tests) {
207 CheckKeyTestCase(&rewriter, test);
210 // An Apple keyboard reusing the ID, zero.
211 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "Apple Keyboard");
212 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
214 KeyTestCase apple_keyboard_tests[] = {
215 // VKEY_A, Alt modifier.
216 {ui::ET_KEY_PRESSED,
217 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_ALT_DOWN,
218 ui::DomKey::UNIDENTIFIED},
219 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_ALT_DOWN,
220 ui::DomKey::UNIDENTIFIED}},
222 // VKEY_A, Win modifier.
223 {ui::ET_KEY_PRESSED,
224 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_COMMAND_DOWN,
225 ui::DomKey::UNIDENTIFIED},
226 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_CONTROL_DOWN,
227 ui::DomKey::Constant<0x01>::Character}},
229 // VKEY_A, Alt+Win modifier.
230 {ui::ET_KEY_PRESSED,
231 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
232 ui::DomKey::UNIDENTIFIED},
233 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
234 ui::DomKey::Constant<0x01>::Character}},
236 // VKEY_LWIN (left Windows key), Alt modifier.
237 {ui::ET_KEY_PRESSED,
238 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
239 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN, ui::DomKey::OS},
240 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
241 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, ui::DomKey::CONTROL}},
243 // VKEY_RWIN (right Windows key), Alt modifier.
244 {ui::ET_KEY_PRESSED,
245 {ui::VKEY_RWIN, ui::DomCode::OS_RIGHT,
246 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN, ui::DomKey::OS},
247 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_RIGHT,
248 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, ui::DomKey::CONTROL}},
251 for (const auto& test : apple_keyboard_tests) {
252 CheckKeyTestCase(&rewriter, test);
256 // For crbug.com/133896.
257 TEST_F(EventRewriterTest, TestRewriteCommandToControlWithControlRemapped) {
258 // Remap Control to Alt.
259 TestingPrefServiceSyncable prefs;
260 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
261 IntegerPrefMember control;
262 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
263 control.SetValue(chromeos::input_method::kAltKey);
265 EventRewriter rewriter(NULL);
266 rewriter.set_pref_service_for_testing(&prefs);
267 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
268 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
270 KeyTestCase pc_keyboard_tests[] = {
271 // Control should be remapped to Alt.
272 {ui::ET_KEY_PRESSED,
273 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT, ui::EF_CONTROL_DOWN,
274 ui::DomKey::CONTROL},
275 {ui::VKEY_MENU, ui::DomCode::ALT_LEFT, ui::EF_ALT_DOWN,
276 ui::DomKey::ALT}},
279 for (const auto& test : pc_keyboard_tests) {
280 CheckKeyTestCase(&rewriter, test);
283 // An Apple keyboard reusing the ID, zero.
284 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "Apple Keyboard");
285 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
287 KeyTestCase apple_keyboard_tests[] = {
288 // VKEY_LWIN (left Command key) with Alt modifier. The remapped Command
289 // key should never be re-remapped to Alt.
290 {ui::ET_KEY_PRESSED,
291 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
292 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN, ui::DomKey::OS},
293 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
294 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, ui::DomKey::CONTROL}},
296 // VKEY_RWIN (right Command key) with Alt modifier. The remapped Command
297 // key should never be re-remapped to Alt.
298 {ui::ET_KEY_PRESSED,
299 {ui::VKEY_RWIN, ui::DomCode::OS_RIGHT,
300 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN, ui::DomKey::OS},
301 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_RIGHT,
302 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, ui::DomKey::CONTROL}},
305 for (const auto& test : apple_keyboard_tests) {
306 CheckKeyTestCase(&rewriter, test);
310 void EventRewriterTest::TestRewriteNumPadKeys() {
311 TestingPrefServiceSyncable prefs;
312 EventRewriter rewriter(NULL);
313 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
314 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
315 rewriter.set_pref_service_for_testing(&prefs);
317 KeyTestCase tests[] = {
318 // XK_KP_Insert (= NumPad 0 without Num Lock), no modifier.
319 {ui::ET_KEY_PRESSED,
320 {ui::VKEY_INSERT, ui::DomCode::NUMPAD0, ui::EF_NONE, ui::DomKey::INSERT},
321 {ui::VKEY_NUMPAD0, ui::DomCode::NUMPAD0, ui::EF_NONE,
322 ui::DomKey::Constant<'0'>::Character}},
324 // XK_KP_Insert (= NumPad 0 without Num Lock), Alt modifier.
325 {ui::ET_KEY_PRESSED,
326 {ui::VKEY_INSERT, ui::DomCode::NUMPAD0, ui::EF_ALT_DOWN,
327 ui::DomKey::INSERT},
328 {ui::VKEY_NUMPAD0, ui::DomCode::NUMPAD0, ui::EF_ALT_DOWN,
329 ui::DomKey::Constant<'0'>::Character}},
331 // XK_KP_Delete (= NumPad . without Num Lock), Alt modifier.
332 {ui::ET_KEY_PRESSED,
333 {ui::VKEY_DELETE, ui::DomCode::NUMPAD_DECIMAL, ui::EF_ALT_DOWN,
334 ui::DomKey::DEL},
335 {ui::VKEY_DECIMAL, ui::DomCode::NUMPAD_DECIMAL, ui::EF_ALT_DOWN,
336 ui::DomKey::Constant<'.'>::Character}},
338 // XK_KP_End (= NumPad 1 without Num Lock), Alt modifier.
339 {ui::ET_KEY_PRESSED,
340 {ui::VKEY_END, ui::DomCode::NUMPAD1, ui::EF_ALT_DOWN, ui::DomKey::END},
341 {ui::VKEY_NUMPAD1, ui::DomCode::NUMPAD1, ui::EF_ALT_DOWN,
342 ui::DomKey::Constant<'1'>::Character}},
344 // XK_KP_Down (= NumPad 2 without Num Lock), Alt modifier.
345 {ui::ET_KEY_PRESSED,
346 {ui::VKEY_DOWN, ui::DomCode::NUMPAD2, ui::EF_ALT_DOWN,
347 ui::DomKey::ARROW_DOWN},
348 {ui::VKEY_NUMPAD2, ui::DomCode::NUMPAD2, ui::EF_ALT_DOWN,
349 ui::DomKey::Constant<'2'>::Character}},
351 // XK_KP_Next (= NumPad 3 without Num Lock), Alt modifier.
352 {ui::ET_KEY_PRESSED,
353 {ui::VKEY_NEXT, ui::DomCode::NUMPAD3, ui::EF_ALT_DOWN,
354 ui::DomKey::PAGE_DOWN},
355 {ui::VKEY_NUMPAD3, ui::DomCode::NUMPAD3, ui::EF_ALT_DOWN,
356 ui::DomKey::Constant<'3'>::Character}},
358 // XK_KP_Left (= NumPad 4 without Num Lock), Alt modifier.
359 {ui::ET_KEY_PRESSED,
360 {ui::VKEY_LEFT, ui::DomCode::NUMPAD4, ui::EF_ALT_DOWN,
361 ui::DomKey::ARROW_LEFT},
362 {ui::VKEY_NUMPAD4, ui::DomCode::NUMPAD4, ui::EF_ALT_DOWN,
363 ui::DomKey::Constant<'4'>::Character}},
365 // XK_KP_Begin (= NumPad 5 without Num Lock), Alt modifier.
366 {ui::ET_KEY_PRESSED,
367 {ui::VKEY_CLEAR, ui::DomCode::NUMPAD5, ui::EF_ALT_DOWN,
368 ui::DomKey::CLEAR},
369 {ui::VKEY_NUMPAD5, ui::DomCode::NUMPAD5, ui::EF_ALT_DOWN,
370 ui::DomKey::Constant<'5'>::Character}},
372 // XK_KP_Right (= NumPad 6 without Num Lock), Alt modifier.
373 {ui::ET_KEY_PRESSED,
374 {ui::VKEY_RIGHT, ui::DomCode::NUMPAD6, ui::EF_ALT_DOWN,
375 ui::DomKey::ARROW_RIGHT},
376 {ui::VKEY_NUMPAD6, ui::DomCode::NUMPAD6, ui::EF_ALT_DOWN,
377 ui::DomKey::Constant<'6'>::Character}},
379 // XK_KP_Home (= NumPad 7 without Num Lock), Alt modifier.
380 {ui::ET_KEY_PRESSED,
381 {ui::VKEY_HOME, ui::DomCode::NUMPAD7, ui::EF_ALT_DOWN, ui::DomKey::HOME},
382 {ui::VKEY_NUMPAD7, ui::DomCode::NUMPAD7, ui::EF_ALT_DOWN,
383 ui::DomKey::Constant<'7'>::Character}},
385 // XK_KP_Up (= NumPad 8 without Num Lock), Alt modifier.
386 {ui::ET_KEY_PRESSED,
387 {ui::VKEY_UP, ui::DomCode::NUMPAD8, ui::EF_ALT_DOWN,
388 ui::DomKey::ARROW_UP},
389 {ui::VKEY_NUMPAD8, ui::DomCode::NUMPAD8, ui::EF_ALT_DOWN,
390 ui::DomKey::Constant<'8'>::Character}},
392 // XK_KP_Prior (= NumPad 9 without Num Lock), Alt modifier.
393 {ui::ET_KEY_PRESSED,
394 {ui::VKEY_PRIOR, ui::DomCode::NUMPAD9, ui::EF_ALT_DOWN,
395 ui::DomKey::PAGE_UP},
396 {ui::VKEY_NUMPAD9, ui::DomCode::NUMPAD9, ui::EF_ALT_DOWN,
397 ui::DomKey::Constant<'9'>::Character}},
399 // XK_KP_0 (= NumPad 0 with Num Lock), Num Lock modifier.
400 {ui::ET_KEY_PRESSED,
401 {ui::VKEY_NUMPAD0, ui::DomCode::NUMPAD0, ui::EF_NONE,
402 ui::DomKey::Constant<'0'>::Character},
403 {ui::VKEY_NUMPAD0, ui::DomCode::NUMPAD0, ui::EF_NONE,
404 ui::DomKey::Constant<'0'>::Character}},
406 // XK_KP_DECIMAL (= NumPad . with Num Lock), Num Lock modifier.
407 {ui::ET_KEY_PRESSED,
408 {ui::VKEY_DECIMAL, ui::DomCode::NUMPAD_DECIMAL, ui::EF_NONE,
409 ui::DomKey::Constant<'.'>::Character},
410 {ui::VKEY_DECIMAL, ui::DomCode::NUMPAD_DECIMAL, ui::EF_NONE,
411 ui::DomKey::Constant<'.'>::Character}},
413 // XK_KP_1 (= NumPad 1 with Num Lock), Num Lock modifier.
414 {ui::ET_KEY_PRESSED,
415 {ui::VKEY_NUMPAD1, ui::DomCode::NUMPAD1, ui::EF_NONE,
416 ui::DomKey::Constant<'1'>::Character},
417 {ui::VKEY_NUMPAD1, ui::DomCode::NUMPAD1, ui::EF_NONE,
418 ui::DomKey::Constant<'1'>::Character}},
420 // XK_KP_2 (= NumPad 2 with Num Lock), Num Lock modifier.
421 {ui::ET_KEY_PRESSED,
422 {ui::VKEY_NUMPAD2, ui::DomCode::NUMPAD2, ui::EF_NONE,
423 ui::DomKey::Constant<'2'>::Character},
424 {ui::VKEY_NUMPAD2, ui::DomCode::NUMPAD2, ui::EF_NONE,
425 ui::DomKey::Constant<'2'>::Character}},
427 // XK_KP_3 (= NumPad 3 with Num Lock), Num Lock modifier.
428 {ui::ET_KEY_PRESSED,
429 {ui::VKEY_NUMPAD3, ui::DomCode::NUMPAD3, ui::EF_NONE,
430 ui::DomKey::Constant<'3'>::Character},
431 {ui::VKEY_NUMPAD3, ui::DomCode::NUMPAD3, ui::EF_NONE,
432 ui::DomKey::Constant<'3'>::Character}},
434 // XK_KP_4 (= NumPad 4 with Num Lock), Num Lock modifier.
435 {ui::ET_KEY_PRESSED,
436 {ui::VKEY_NUMPAD4, ui::DomCode::NUMPAD4, ui::EF_NONE,
437 ui::DomKey::Constant<'4'>::Character},
438 {ui::VKEY_NUMPAD4, ui::DomCode::NUMPAD4, ui::EF_NONE,
439 ui::DomKey::Constant<'4'>::Character}},
441 // XK_KP_5 (= NumPad 5 with Num Lock), Num Lock
442 // modifier.
443 {ui::ET_KEY_PRESSED,
444 {ui::VKEY_NUMPAD5, ui::DomCode::NUMPAD5, ui::EF_NONE,
445 ui::DomKey::Constant<'5'>::Character},
446 {ui::VKEY_NUMPAD5, ui::DomCode::NUMPAD5, ui::EF_NONE,
447 ui::DomKey::Constant<'5'>::Character}},
449 // XK_KP_6 (= NumPad 6 with Num Lock), Num Lock
450 // modifier.
451 {ui::ET_KEY_PRESSED,
452 {ui::VKEY_NUMPAD6, ui::DomCode::NUMPAD6, ui::EF_NONE,
453 ui::DomKey::Constant<'6'>::Character},
454 {ui::VKEY_NUMPAD6, ui::DomCode::NUMPAD6, ui::EF_NONE,
455 ui::DomKey::Constant<'6'>::Character}},
457 // XK_KP_7 (= NumPad 7 with Num Lock), Num Lock
458 // modifier.
459 {ui::ET_KEY_PRESSED,
460 {ui::VKEY_NUMPAD7, ui::DomCode::NUMPAD7, ui::EF_NONE,
461 ui::DomKey::Constant<'7'>::Character},
462 {ui::VKEY_NUMPAD7, ui::DomCode::NUMPAD7, ui::EF_NONE,
463 ui::DomKey::Constant<'7'>::Character}},
465 // XK_KP_8 (= NumPad 8 with Num Lock), Num Lock
466 // modifier.
467 {ui::ET_KEY_PRESSED,
468 {ui::VKEY_NUMPAD8, ui::DomCode::NUMPAD8, ui::EF_NONE,
469 ui::DomKey::Constant<'8'>::Character},
470 {ui::VKEY_NUMPAD8, ui::DomCode::NUMPAD8, ui::EF_NONE,
471 ui::DomKey::Constant<'8'>::Character}},
473 // XK_KP_9 (= NumPad 9 with Num Lock), Num Lock
474 // modifier.
475 {ui::ET_KEY_PRESSED,
476 {ui::VKEY_NUMPAD9, ui::DomCode::NUMPAD9, ui::EF_NONE,
477 ui::DomKey::Constant<'9'>::Character},
478 {ui::VKEY_NUMPAD9, ui::DomCode::NUMPAD9, ui::EF_NONE,
479 ui::DomKey::Constant<'9'>::Character}},
482 for (const auto& test : tests) {
483 CheckKeyTestCase(&rewriter, test);
487 TEST_F(EventRewriterTest, TestRewriteNumPadKeys) {
488 TestRewriteNumPadKeys();
491 TEST_F(EventRewriterTest, TestRewriteNumPadKeysWithDiamondKeyFlag) {
492 // Make sure the num lock works correctly even when Diamond key exists.
493 const base::CommandLine original_cl(*base::CommandLine::ForCurrentProcess());
494 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
495 chromeos::switches::kHasChromeOSDiamondKey, "");
497 TestRewriteNumPadKeys();
498 *base::CommandLine::ForCurrentProcess() = original_cl;
501 // Tests if the rewriter can handle a Command + Num Pad event.
502 void EventRewriterTest::TestRewriteNumPadKeysOnAppleKeyboard() {
503 TestingPrefServiceSyncable prefs;
504 EventRewriter rewriter(NULL);
505 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "Apple Keyboard");
506 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
507 rewriter.set_pref_service_for_testing(&prefs);
509 KeyTestCase tests[] = {
510 // XK_KP_End (= NumPad 1 without Num Lock), Win modifier.
511 // The result should be "Num Pad 1 with Control + Num Lock modifiers".
512 {ui::ET_KEY_PRESSED,
513 {ui::VKEY_END, ui::DomCode::NUMPAD1, ui::EF_COMMAND_DOWN,
514 ui::DomKey::END},
515 {ui::VKEY_NUMPAD1, ui::DomCode::NUMPAD1, ui::EF_CONTROL_DOWN,
516 ui::DomKey::UNIDENTIFIED}},
518 // XK_KP_1 (= NumPad 1 with Num Lock), Win modifier.
519 // The result should also be "Num Pad 1 with Control + Num Lock
520 // modifiers".
521 {ui::ET_KEY_PRESSED,
522 {ui::VKEY_NUMPAD1, ui::DomCode::NUMPAD1, ui::EF_COMMAND_DOWN,
523 ui::DomKey::Constant<'1'>::Character},
524 {ui::VKEY_NUMPAD1, ui::DomCode::NUMPAD1, ui::EF_CONTROL_DOWN,
525 ui::DomKey::UNIDENTIFIED}}};
527 for (const auto& test : tests) {
528 CheckKeyTestCase(&rewriter, test);
532 TEST_F(EventRewriterTest, TestRewriteNumPadKeysOnAppleKeyboard) {
533 TestRewriteNumPadKeysOnAppleKeyboard();
536 TEST_F(EventRewriterTest,
537 TestRewriteNumPadKeysOnAppleKeyboardWithDiamondKeyFlag) {
538 // Makes sure the num lock works correctly even when Diamond key exists.
539 const base::CommandLine original_cl(*base::CommandLine::ForCurrentProcess());
540 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
541 chromeos::switches::kHasChromeOSDiamondKey, "");
543 TestRewriteNumPadKeysOnAppleKeyboard();
544 *base::CommandLine::ForCurrentProcess() = original_cl;
547 TEST_F(EventRewriterTest, TestRewriteModifiersNoRemap) {
548 TestingPrefServiceSyncable prefs;
549 EventRewriter rewriter(NULL);
550 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
551 rewriter.set_pref_service_for_testing(&prefs);
553 KeyTestCase tests[] = {
554 // Press Search. Confirm the event is not rewritten.
555 {ui::ET_KEY_PRESSED,
556 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_NONE, ui::DomKey::OS},
557 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_COMMAND_DOWN,
558 ui::DomKey::OS}},
560 // Press left Control. Confirm the event is not rewritten.
561 {ui::ET_KEY_PRESSED,
562 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT, ui::EF_CONTROL_DOWN,
563 ui::DomKey::CONTROL},
564 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT, ui::EF_CONTROL_DOWN,
565 ui::DomKey::CONTROL}},
567 // Press right Control. Confirm the event is not rewritten.
568 {ui::ET_KEY_PRESSED,
569 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT, ui::EF_CONTROL_DOWN,
570 ui::DomKey::CONTROL},
571 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT, ui::EF_CONTROL_DOWN,
572 ui::DomKey::CONTROL}},
574 // Press left Alt. Confirm the event is not rewritten.
575 {ui::ET_KEY_PRESSED,
576 {ui::VKEY_MENU, ui::DomCode::ALT_LEFT, ui::EF_ALT_DOWN, ui::DomKey::ALT},
577 {ui::VKEY_MENU, ui::DomCode::ALT_LEFT, ui::EF_ALT_DOWN,
578 ui::DomKey::ALT}},
580 // Press right Alt. Confirm the event is not rewritten.
581 {ui::ET_KEY_PRESSED,
582 {ui::VKEY_MENU, ui::DomCode::ALT_LEFT, ui::EF_ALT_DOWN, ui::DomKey::ALT},
583 {ui::VKEY_MENU, ui::DomCode::ALT_LEFT, ui::EF_ALT_DOWN,
584 ui::DomKey::ALT}},
586 // Test KeyRelease event, just in case.
587 // Release Search. Confirm the release event is not rewritten.
588 {ui::ET_KEY_RELEASED,
589 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_NONE, ui::DomKey::OS},
590 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_NONE, ui::DomKey::OS}},
593 for (const auto& test : tests) {
594 CheckKeyTestCase(&rewriter, test);
598 TEST_F(EventRewriterTest, TestRewriteModifiersNoRemapMultipleKeys) {
599 TestingPrefServiceSyncable prefs;
600 EventRewriter rewriter(NULL);
601 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
602 rewriter.set_pref_service_for_testing(&prefs);
604 KeyTestCase tests[] = {
605 // Press Alt with Shift. Confirm the event is not rewritten.
606 {ui::ET_KEY_PRESSED,
607 {ui::VKEY_MENU, ui::DomCode::ALT_LEFT,
608 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, ui::DomKey::ALT},
609 {ui::VKEY_MENU, ui::DomCode::ALT_LEFT,
610 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, ui::DomKey::ALT}},
612 // Press Search with Caps Lock mask. Confirm the event is not rewritten.
613 {ui::ET_KEY_PRESSED,
614 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
615 ui::EF_CAPS_LOCK_DOWN | ui::EF_COMMAND_DOWN, ui::DomKey::OS},
616 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
617 ui::EF_CAPS_LOCK_DOWN | ui::EF_COMMAND_DOWN, ui::DomKey::OS}},
619 // Release Search with Caps Lock mask. Confirm the event is not rewritten.
620 {ui::ET_KEY_RELEASED,
621 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_CAPS_LOCK_DOWN,
622 ui::DomKey::OS},
623 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_CAPS_LOCK_DOWN,
624 ui::DomKey::OS}},
626 // Press Shift+Ctrl+Alt+Search+A. Confirm the event is not rewritten.
627 {ui::ET_KEY_PRESSED,
628 {ui::VKEY_B, ui::DomCode::KEY_B,
629 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
630 ui::EF_COMMAND_DOWN,
631 ui::DomKey::Constant<'B'>::Character},
632 {ui::VKEY_B, ui::DomCode::KEY_B,
633 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
634 ui::EF_COMMAND_DOWN,
635 ui::DomKey::Constant<'B'>::Character}},
638 for (const auto& test : tests) {
639 CheckKeyTestCase(&rewriter, test);
643 TEST_F(EventRewriterTest, TestRewriteModifiersDisableSome) {
644 // Disable Search and Control keys.
645 TestingPrefServiceSyncable prefs;
646 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
647 IntegerPrefMember search;
648 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
649 search.SetValue(chromeos::input_method::kVoidKey);
650 IntegerPrefMember control;
651 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
652 control.SetValue(chromeos::input_method::kVoidKey);
654 EventRewriter rewriter(NULL);
655 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
656 rewriter.set_pref_service_for_testing(&prefs);
658 KeyTestCase disabled_modifier_tests[] = {
659 // Press Alt with Shift. This key press shouldn't be affected by the
660 // pref. Confirm the event is not rewritten.
661 {ui::ET_KEY_PRESSED,
662 {ui::VKEY_MENU, ui::DomCode::ALT_LEFT,
663 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, ui::DomKey::ALT},
664 {ui::VKEY_MENU, ui::DomCode::ALT_LEFT,
665 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, ui::DomKey::ALT}},
667 // Press Search. Confirm the event is now VKEY_UNKNOWN.
668 {ui::ET_KEY_PRESSED,
669 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_NONE, ui::DomKey::OS},
670 {ui::VKEY_UNKNOWN, ui::DomCode::NONE, ui::EF_NONE,
671 ui::DomKey::UNIDENTIFIED}},
673 // Press Control. Confirm the event is now VKEY_UNKNOWN.
674 {ui::ET_KEY_PRESSED,
675 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT, ui::EF_CONTROL_DOWN,
676 ui::DomKey::CONTROL},
677 {ui::VKEY_UNKNOWN, ui::DomCode::NONE, ui::EF_NONE,
678 ui::DomKey::UNIDENTIFIED}},
680 // Press Control+Search. Confirm the event is now VKEY_UNKNOWN
681 // without any modifiers.
682 {ui::ET_KEY_PRESSED,
683 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_CONTROL_DOWN,
684 ui::DomKey::OS},
685 {ui::VKEY_UNKNOWN, ui::DomCode::NONE, ui::EF_NONE,
686 ui::DomKey::UNIDENTIFIED}},
688 // Press Control+Search+a. Confirm the event is now VKEY_A without any
689 // modifiers.
690 {ui::ET_KEY_PRESSED,
691 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_CONTROL_DOWN,
692 ui::DomKey::Constant<'a'>::Character},
693 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_NONE,
694 ui::DomKey::Constant<'a'>::Character}},
696 // Press Control+Search+Alt+a. Confirm the event is now VKEY_A only with
697 // the Alt modifier.
698 {ui::ET_KEY_PRESSED,
699 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
700 ui::DomKey::Constant<'a'>::Character},
701 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_ALT_DOWN,
702 ui::DomKey::Constant<'a'>::Character}},
705 for (const auto& test : disabled_modifier_tests) {
706 CheckKeyTestCase(&rewriter, test);
709 // Remap Alt to Control.
710 IntegerPrefMember alt;
711 alt.Init(prefs::kLanguageRemapAltKeyTo, &prefs);
712 alt.SetValue(chromeos::input_method::kControlKey);
714 KeyTestCase tests[] = {
715 // Press left Alt. Confirm the event is now VKEY_CONTROL
716 // even though the Control key itself is disabled.
717 {ui::ET_KEY_PRESSED,
718 {ui::VKEY_MENU, ui::DomCode::ALT_LEFT, ui::EF_ALT_DOWN, ui::DomKey::ALT},
719 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT, ui::EF_CONTROL_DOWN,
720 ui::DomKey::CONTROL}},
722 // Press Alt+a. Confirm the event is now Control+a even though the Control
723 // key itself is disabled.
724 {ui::ET_KEY_PRESSED,
725 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_ALT_DOWN,
726 ui::DomKey::Constant<'a'>::Character},
727 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_CONTROL_DOWN,
728 ui::DomKey::Constant<0x01>::Character}},
731 for (const auto& test : tests) {
732 CheckKeyTestCase(&rewriter, test);
736 TEST_F(EventRewriterTest, TestRewriteModifiersRemapToControl) {
737 // Remap Search to Control.
738 TestingPrefServiceSyncable prefs;
739 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
740 IntegerPrefMember search;
741 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
742 search.SetValue(chromeos::input_method::kControlKey);
744 EventRewriter rewriter(NULL);
745 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
746 rewriter.set_pref_service_for_testing(&prefs);
748 KeyTestCase s_tests[] = {
749 // Press Search. Confirm the event is now VKEY_CONTROL.
750 {ui::ET_KEY_PRESSED,
751 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_COMMAND_DOWN,
752 ui::DomKey::OS},
753 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT, ui::EF_CONTROL_DOWN,
754 ui::DomKey::CONTROL}},
757 for (const auto& test : s_tests) {
758 CheckKeyTestCase(&rewriter, test);
761 // Remap Alt to Control too.
762 IntegerPrefMember alt;
763 alt.Init(prefs::kLanguageRemapAltKeyTo, &prefs);
764 alt.SetValue(chromeos::input_method::kControlKey);
766 KeyTestCase sa_tests[] = {
767 // Press Alt. Confirm the event is now VKEY_CONTROL.
768 {ui::ET_KEY_PRESSED,
769 {ui::VKEY_MENU, ui::DomCode::ALT_LEFT, ui::EF_ALT_DOWN, ui::DomKey::ALT},
770 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT, ui::EF_CONTROL_DOWN,
771 ui::DomKey::CONTROL}},
773 // Press Alt+Search. Confirm the event is now VKEY_CONTROL.
774 {ui::ET_KEY_PRESSED,
775 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
776 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::DomKey::OS},
777 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT, ui::EF_CONTROL_DOWN,
778 ui::DomKey::CONTROL}},
780 // Press Control+Alt+Search. Confirm the event is now VKEY_CONTROL.
781 {ui::ET_KEY_PRESSED,
782 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
783 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
784 ui::DomKey::OS},
785 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT, ui::EF_CONTROL_DOWN,
786 ui::DomKey::CONTROL}},
788 // Press Shift+Control+Alt+Search. Confirm the event is now Control with
789 // Shift and Control modifiers.
790 {ui::ET_KEY_PRESSED,
791 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
792 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
793 ui::EF_COMMAND_DOWN,
794 ui::DomKey::OS},
795 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
796 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, ui::DomKey::CONTROL}},
798 // Press Shift+Control+Alt+Search+B. Confirm the event is now B with Shift
799 // and Control modifiers.
800 {ui::ET_KEY_PRESSED,
801 {ui::VKEY_B, ui::DomCode::KEY_B,
802 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
803 ui::EF_COMMAND_DOWN,
804 ui::DomKey::Constant<'B'>::Character},
805 {ui::VKEY_B, ui::DomCode::KEY_B, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
806 ui::DomKey::Constant<0x02>::Character}},
809 for (const auto& test : sa_tests) {
810 CheckKeyTestCase(&rewriter, test);
814 TEST_F(EventRewriterTest, TestRewriteModifiersRemapToEscape) {
815 // Remap Search to ESC.
816 TestingPrefServiceSyncable prefs;
817 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
818 IntegerPrefMember search;
819 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
820 search.SetValue(chromeos::input_method::kEscapeKey);
822 EventRewriter rewriter(NULL);
823 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
824 rewriter.set_pref_service_for_testing(&prefs);
826 KeyTestCase tests[] = {
827 // Press Search. Confirm the event is now VKEY_ESCAPE.
828 {ui::ET_KEY_PRESSED,
829 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_COMMAND_DOWN,
830 ui::DomKey::OS},
831 {ui::VKEY_ESCAPE, ui::DomCode::ESCAPE, ui::EF_NONE, ui::DomKey::ESCAPE}},
834 for (const auto& test : tests) {
835 CheckKeyTestCase(&rewriter, test);
839 TEST_F(EventRewriterTest, TestRewriteModifiersRemapMany) {
840 // Remap Search to Alt.
841 TestingPrefServiceSyncable prefs;
842 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
843 IntegerPrefMember search;
844 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
845 search.SetValue(chromeos::input_method::kAltKey);
847 EventRewriter rewriter(NULL);
848 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
849 rewriter.set_pref_service_for_testing(&prefs);
851 KeyTestCase s2a_tests[] = {
852 // Press Search. Confirm the event is now VKEY_MENU.
853 {ui::ET_KEY_PRESSED,
854 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_COMMAND_DOWN,
855 ui::DomKey::OS},
856 {ui::VKEY_MENU, ui::DomCode::ALT_LEFT, ui::EF_ALT_DOWN,
857 ui::DomKey::ALT}},
860 for (const auto& test : s2a_tests) {
861 CheckKeyTestCase(&rewriter, test);
864 // Remap Alt to Control.
865 IntegerPrefMember alt;
866 alt.Init(prefs::kLanguageRemapAltKeyTo, &prefs);
867 alt.SetValue(chromeos::input_method::kControlKey);
869 KeyTestCase a2c_tests[] = {
870 // Press left Alt. Confirm the event is now VKEY_CONTROL.
871 {ui::ET_KEY_PRESSED,
872 {ui::VKEY_MENU, ui::DomCode::ALT_LEFT, ui::EF_ALT_DOWN, ui::DomKey::ALT},
873 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT, ui::EF_CONTROL_DOWN,
874 ui::DomKey::CONTROL}},
875 // Press Shift+comma. Verify that only the flags are changed.
876 // The X11 portion of the test addresses crbug.com/390263 by verifying
877 // that the X keycode remains that for ',<' and not for 105-key '<>'.
878 {ui::ET_KEY_PRESSED,
879 {ui::VKEY_OEM_COMMA, ui::DomCode::COMMA,
880 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, ui::DomKey::UNIDENTIFIED},
881 {ui::VKEY_OEM_COMMA, ui::DomCode::COMMA,
882 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, ui::DomKey::UNIDENTIFIED}},
883 // Press Shift+9. Verify that only the flags are changed.
884 {ui::ET_KEY_PRESSED,
885 {ui::VKEY_9, ui::DomCode::DIGIT9, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
886 ui::DomKey::UNIDENTIFIED},
887 {ui::VKEY_9, ui::DomCode::DIGIT9,
888 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, ui::DomKey::UNIDENTIFIED}},
891 for (const auto& test : a2c_tests) {
892 CheckKeyTestCase(&rewriter, test);
895 // Remap Control to Search.
896 IntegerPrefMember control;
897 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
898 control.SetValue(chromeos::input_method::kSearchKey);
900 KeyTestCase c2s_tests[] = {
901 // Press left Control. Confirm the event is now VKEY_LWIN.
902 {ui::ET_KEY_PRESSED,
903 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT, ui::EF_CONTROL_DOWN,
904 ui::DomKey::CONTROL},
905 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT, ui::EF_COMMAND_DOWN,
906 ui::DomKey::OS}},
908 // Then, press all of the three, Control+Alt+Search.
909 {ui::ET_KEY_PRESSED,
910 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
911 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
912 ui::DomKey::OS},
913 {ui::VKEY_MENU, ui::DomCode::ALT_LEFT,
914 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
915 ui::DomKey::ALT}},
917 // Press Shift+Control+Alt+Search.
918 {ui::ET_KEY_PRESSED,
919 {ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
920 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
921 ui::EF_COMMAND_DOWN,
922 ui::DomKey::OS},
923 {ui::VKEY_MENU, ui::DomCode::ALT_LEFT,
924 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
925 ui::EF_COMMAND_DOWN,
926 ui::DomKey::ALT}},
928 // Press Shift+Control+Alt+Search+B
929 {ui::ET_KEY_PRESSED,
930 {ui::VKEY_B, ui::DomCode::KEY_B,
931 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
932 ui::EF_COMMAND_DOWN,
933 ui::DomKey::Constant<'B'>::Character},
934 {ui::VKEY_B, ui::DomCode::KEY_B,
935 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
936 ui::EF_COMMAND_DOWN,
937 ui::DomKey::Constant<'B'>::Character}},
940 for (const auto& test : c2s_tests) {
941 CheckKeyTestCase(&rewriter, test);
945 TEST_F(EventRewriterTest, TestRewriteModifiersRemapToCapsLock) {
946 // Remap Search to Caps Lock.
947 TestingPrefServiceSyncable prefs;
948 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
949 IntegerPrefMember search;
950 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
951 search.SetValue(chromeos::input_method::kCapsLockKey);
953 chromeos::input_method::FakeImeKeyboard ime_keyboard;
954 EventRewriter rewriter(NULL);
955 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
956 rewriter.set_pref_service_for_testing(&prefs);
957 rewriter.set_ime_keyboard_for_testing(&ime_keyboard);
958 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
960 // Press Search.
961 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_CAPITAL,
962 ui::DomCode::CAPS_LOCK, ui::EF_MOD3_DOWN,
963 ui::DomKey::CAPS_LOCK),
964 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
965 ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
966 ui::EF_COMMAND_DOWN, ui::DomKey::OS));
967 // Confirm that the Caps Lock status is changed.
968 EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
970 // Release Search.
971 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CAPITAL,
972 ui::DomCode::CAPS_LOCK, ui::EF_NONE,
973 ui::DomKey::CAPS_LOCK),
974 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
975 ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
976 ui::EF_NONE, ui::DomKey::OS));
977 // Confirm that the Caps Lock status is not changed.
978 EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
980 // Press Search.
981 EXPECT_EQ(
982 GetExpectedResultAsString(
983 ui::ET_KEY_PRESSED, ui::VKEY_CAPITAL, ui::DomCode::CAPS_LOCK,
984 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN, ui::DomKey::CAPS_LOCK),
985 GetRewrittenEventAsString(
986 &rewriter, ui::ET_KEY_PRESSED, ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
987 ui::EF_COMMAND_DOWN | ui::EF_CAPS_LOCK_DOWN, ui::DomKey::OS));
988 // Confirm that the Caps Lock status is changed.
989 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
991 // Release Search.
992 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CAPITAL,
993 ui::DomCode::CAPS_LOCK, ui::EF_NONE,
994 ui::DomKey::CAPS_LOCK),
995 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
996 ui::VKEY_LWIN, ui::DomCode::OS_LEFT,
997 ui::EF_NONE, ui::DomKey::OS));
998 // Confirm that the Caps Lock status is not changed.
999 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1001 // Press Caps Lock (on an external keyboard).
1002 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_CAPITAL,
1003 ui::DomCode::CAPS_LOCK,
1004 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1005 ui::DomKey::CAPS_LOCK),
1006 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1007 ui::VKEY_CAPITAL, ui::DomCode::CAPS_LOCK,
1008 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1009 ui::DomKey::CAPS_LOCK));
1011 #if defined(USE_X11)
1012 // Confirm that calling RewriteForTesting() does not change the state of
1013 // |ime_keyboard|. In this case, X Window system itself should change the
1014 // Caps Lock state, not ash::EventRewriter.
1015 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1016 #elif defined(USE_OZONE)
1017 // Under Ozone the rewriter is responsible for changing the caps lock
1018 // state when the final key is Caps Lock, regardless of whether the
1019 // initial key is Caps Lock.
1020 EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
1021 #endif
1023 // Release Caps Lock (on an external keyboard).
1024 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CAPITAL,
1025 ui::DomCode::CAPS_LOCK, ui::EF_NONE,
1026 ui::DomKey::CAPS_LOCK),
1027 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1028 ui::VKEY_CAPITAL, ui::DomCode::CAPS_LOCK,
1029 ui::EF_NONE, ui::DomKey::CAPS_LOCK));
1030 #if defined(USE_X11)
1031 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1032 #elif defined(USE_OZONE)
1033 EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
1034 #endif
1037 TEST_F(EventRewriterTest, TestRewriteCapsLock) {
1038 TestingPrefServiceSyncable prefs;
1039 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1041 chromeos::input_method::FakeImeKeyboard ime_keyboard;
1042 EventRewriter rewriter(NULL);
1043 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1044 rewriter.set_pref_service_for_testing(&prefs);
1045 rewriter.set_ime_keyboard_for_testing(&ime_keyboard);
1046 EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1048 // On Chrome OS, CapsLock is mapped to F16 with Mod3Mask.
1049 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_CAPITAL,
1050 ui::DomCode::CAPS_LOCK,
1051 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1052 ui::DomKey::CAPS_LOCK),
1053 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1054 ui::VKEY_F16, ui::DomCode::F16,
1055 ui::EF_MOD3_DOWN, ui::DomKey::F16));
1056 EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
1059 TEST_F(EventRewriterTest, TestRewriteDiamondKey) {
1060 TestingPrefServiceSyncable prefs;
1061 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1063 chromeos::input_method::FakeImeKeyboard ime_keyboard;
1064 EventRewriter rewriter(NULL);
1065 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1066 rewriter.set_pref_service_for_testing(&prefs);
1067 rewriter.set_ime_keyboard_for_testing(&ime_keyboard);
1069 KeyTestCase tests[] = {
1070 // F15 should work as Ctrl when --has-chromeos-diamond-key is not
1071 // specified.
1072 {ui::ET_KEY_PRESSED,
1073 {ui::VKEY_F15, ui::DomCode::F15, ui::EF_NONE, ui::DomKey::F15},
1074 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT, ui::EF_CONTROL_DOWN,
1075 ui::DomKey::CONTROL}},
1077 {ui::ET_KEY_RELEASED,
1078 {ui::VKEY_F15, ui::DomCode::F15, ui::EF_NONE, ui::DomKey::F15},
1079 {ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT, ui::EF_NONE,
1080 ui::DomKey::CONTROL}},
1082 // However, Mod2Mask should not be rewritten to CtrlMask when
1083 // --has-chromeos-diamond-key is not specified.
1084 {ui::ET_KEY_PRESSED,
1085 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_NONE,
1086 ui::DomKey::Constant<'a'>::Character},
1087 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_NONE,
1088 ui::DomKey::Constant<'a'>::Character}},
1091 for (const auto& test : tests) {
1092 CheckKeyTestCase(&rewriter, test);
1096 TEST_F(EventRewriterTest, TestRewriteDiamondKeyWithFlag) {
1097 const base::CommandLine original_cl(*base::CommandLine::ForCurrentProcess());
1098 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1099 chromeos::switches::kHasChromeOSDiamondKey, "");
1101 TestingPrefServiceSyncable prefs;
1102 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1104 chromeos::input_method::FakeImeKeyboard ime_keyboard;
1105 EventRewriter rewriter(NULL);
1106 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1107 rewriter.set_pref_service_for_testing(&prefs);
1108 rewriter.set_ime_keyboard_for_testing(&ime_keyboard);
1110 // By default, F15 should work as Control.
1111 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL,
1112 ui::DomCode::CONTROL_LEFT,
1113 ui::EF_CONTROL_DOWN, ui::DomKey::CONTROL),
1114 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1115 ui::VKEY_F15, ui::DomCode::F15,
1116 ui::EF_NONE, ui::DomKey::F15));
1117 // Check that Control is applied to a subsequent key press.
1118 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1119 ui::DomCode::KEY_A, ui::EF_CONTROL_DOWN,
1120 ui::DomKey::Constant<0x01>::Character),
1121 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1122 ui::DomCode::KEY_A, ui::EF_NONE,
1123 ui::DomKey::Constant<'a'>::Character));
1124 // Release F15
1125 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL,
1126 ui::DomCode::CONTROL_LEFT, ui::EF_NONE,
1127 ui::DomKey::CONTROL),
1128 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1129 ui::VKEY_F15, ui::DomCode::F15,
1130 ui::EF_NONE, ui::DomKey::F15));
1131 // Check that Control is no longer applied to a subsequent key press.
1132 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1133 ui::DomCode::KEY_A, ui::EF_NONE,
1134 ui::DomKey::Constant<'a'>::Character),
1135 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1136 ui::DomCode::KEY_A, ui::EF_NONE,
1137 ui::DomKey::Constant<'a'>::Character));
1139 IntegerPrefMember diamond;
1140 diamond.Init(prefs::kLanguageRemapDiamondKeyTo, &prefs);
1141 diamond.SetValue(chromeos::input_method::kVoidKey);
1143 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN,
1144 ui::DomCode::NONE, ui::EF_NONE,
1145 ui::DomKey::UNIDENTIFIED),
1146 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1147 ui::VKEY_F15, ui::DomCode::F15,
1148 ui::EF_NONE, ui::DomKey::F15));
1149 // Check that no modifier is applied to another key.
1150 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1151 ui::DomCode::KEY_A, ui::EF_NONE,
1152 ui::DomKey::Constant<'a'>::Character),
1153 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1154 ui::DomCode::KEY_A, ui::EF_NONE,
1155 ui::DomKey::Constant<'a'>::Character));
1157 diamond.SetValue(chromeos::input_method::kControlKey);
1159 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL,
1160 ui::DomCode::CONTROL_LEFT,
1161 ui::EF_CONTROL_DOWN, ui::DomKey::CONTROL),
1162 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1163 ui::VKEY_F15, ui::DomCode::F15,
1164 ui::EF_NONE, ui::DomKey::F15));
1165 // Check that Control is applied to a subsequent key press.
1166 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1167 ui::DomCode::KEY_A, ui::EF_CONTROL_DOWN,
1168 ui::DomKey::Constant<0x01>::Character),
1169 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1170 ui::DomCode::KEY_A, ui::EF_NONE,
1171 ui::DomKey::Constant<'a'>::Character));
1172 // Release F15
1173 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL,
1174 ui::DomCode::CONTROL_LEFT, ui::EF_NONE,
1175 ui::DomKey::CONTROL),
1176 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1177 ui::VKEY_F15, ui::DomCode::F15,
1178 ui::EF_NONE, ui::DomKey::F15));
1179 // Check that Control is no longer applied to a subsequent key press.
1180 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1181 ui::DomCode::KEY_A, ui::EF_NONE,
1182 ui::DomKey::Constant<'a'>::Character),
1183 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1184 ui::DomCode::KEY_A, ui::EF_NONE,
1185 ui::DomKey::Constant<'a'>::Character));
1187 diamond.SetValue(chromeos::input_method::kAltKey);
1189 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_MENU,
1190 ui::DomCode::ALT_LEFT, ui::EF_ALT_DOWN,
1191 ui::DomKey::ALT),
1192 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1193 ui::VKEY_F15, ui::DomCode::F15,
1194 ui::EF_NONE, ui::DomKey::F15));
1195 // Check that Alt is applied to a subsequent key press.
1196 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1197 ui::DomCode::KEY_A, ui::EF_ALT_DOWN,
1198 ui::DomKey::Constant<'a'>::Character),
1199 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1200 ui::DomCode::KEY_A, ui::EF_NONE,
1201 ui::DomKey::Constant<'a'>::Character));
1202 // Release F15
1203 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_MENU,
1204 ui::DomCode::ALT_LEFT, ui::EF_NONE,
1205 ui::DomKey::ALT),
1206 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1207 ui::VKEY_F15, ui::DomCode::F15,
1208 ui::EF_NONE, ui::DomKey::F15));
1209 // Check that Alt is no longer applied to a subsequent key press.
1210 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1211 ui::DomCode::KEY_A, ui::EF_NONE,
1212 ui::DomKey::Constant<'a'>::Character),
1213 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1214 ui::DomCode::KEY_A, ui::EF_NONE,
1215 ui::DomKey::Constant<'a'>::Character));
1217 diamond.SetValue(chromeos::input_method::kCapsLockKey);
1219 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_CAPITAL,
1220 ui::DomCode::CAPS_LOCK,
1221 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1222 ui::DomKey::CAPS_LOCK),
1223 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED,
1224 ui::VKEY_F15, ui::DomCode::F15,
1225 ui::EF_NONE, ui::DomKey::F15));
1226 // Check that Caps is applied to a subsequent key press.
1227 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1228 ui::DomCode::KEY_A,
1229 ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1230 ui::DomKey::Constant<'A'>::Character),
1231 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1232 ui::DomCode::KEY_A, ui::EF_NONE,
1233 ui::DomKey::Constant<'a'>::Character));
1234 // Release F15
1235 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CAPITAL,
1236 ui::DomCode::CAPS_LOCK, ui::EF_NONE,
1237 ui::DomKey::CAPS_LOCK),
1238 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_RELEASED,
1239 ui::VKEY_F15, ui::DomCode::F15,
1240 ui::EF_NONE, ui::DomKey::F15));
1241 // Check that Control is no longer applied to a subsequent key press.
1242 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1243 ui::DomCode::KEY_A, ui::EF_NONE,
1244 ui::DomKey::Constant<'a'>::Character),
1245 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1246 ui::DomCode::KEY_A, ui::EF_NONE,
1247 ui::DomKey::Constant<'a'>::Character));
1249 *base::CommandLine::ForCurrentProcess() = original_cl;
1252 TEST_F(EventRewriterTest, TestRewriteCapsLockToControl) {
1253 // Remap CapsLock to Control.
1254 TestingPrefServiceSyncable prefs;
1255 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1256 IntegerPrefMember control;
1257 control.Init(prefs::kLanguageRemapCapsLockKeyTo, &prefs);
1258 control.SetValue(chromeos::input_method::kControlKey);
1260 EventRewriter rewriter(NULL);
1261 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1262 rewriter.set_pref_service_for_testing(&prefs);
1264 KeyTestCase tests[] = {
1265 // Press CapsLock+a. Confirm that Mod3Mask is rewritten to ControlMask.
1266 // On Chrome OS, CapsLock works as a Mod3 modifier.
1267 {ui::ET_KEY_PRESSED,
1268 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_MOD3_DOWN,
1269 ui::DomKey::Constant<'a'>::Character},
1270 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_CONTROL_DOWN,
1271 ui::DomKey::Constant<0x01>::Character}},
1273 // Press Control+CapsLock+a. Confirm that Mod3Mask is rewritten to
1274 // ControlMask
1275 {ui::ET_KEY_PRESSED,
1276 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_CONTROL_DOWN | ui::EF_MOD3_DOWN,
1277 ui::DomKey::Constant<'a'>::Character},
1278 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_CONTROL_DOWN,
1279 ui::DomKey::Constant<0x01>::Character}},
1281 // Press Alt+CapsLock+a. Confirm that Mod3Mask is rewritten to
1282 // ControlMask.
1283 {ui::ET_KEY_PRESSED,
1284 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_ALT_DOWN | ui::EF_MOD3_DOWN,
1285 ui::DomKey::Constant<'a'>::Character},
1286 {ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1287 ui::DomKey::Constant<0x01>::Character}},
1290 for (const auto& test : tests) {
1291 CheckKeyTestCase(&rewriter, test);
1295 TEST_F(EventRewriterTest, TestRewriteCapsLockMod3InUse) {
1296 // Remap CapsLock to Control.
1297 TestingPrefServiceSyncable prefs;
1298 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1299 IntegerPrefMember control;
1300 control.Init(prefs::kLanguageRemapCapsLockKeyTo, &prefs);
1301 control.SetValue(chromeos::input_method::kControlKey);
1303 EventRewriter rewriter(NULL);
1304 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1305 rewriter.set_pref_service_for_testing(&prefs);
1306 input_method_manager_mock_->set_mod3_used(true);
1308 // Press CapsLock+a. Confirm that Mod3Mask is NOT rewritten to ControlMask
1309 // when Mod3Mask is already in use by the current XKB layout.
1310 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_A,
1311 ui::DomCode::KEY_A, ui::EF_NONE,
1312 ui::DomKey::Constant<'a'>::Character),
1313 GetRewrittenEventAsString(&rewriter, ui::ET_KEY_PRESSED, ui::VKEY_A,
1314 ui::DomCode::KEY_A, ui::EF_NONE,
1315 ui::DomKey::Constant<'a'>::Character));
1317 input_method_manager_mock_->set_mod3_used(false);
1320 TEST_F(EventRewriterTest, TestRewriteExtendedKeys) {
1321 TestingPrefServiceSyncable prefs;
1322 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1323 EventRewriter rewriter(NULL);
1324 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1325 rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
1326 rewriter.set_pref_service_for_testing(&prefs);
1328 KeyTestCase tests[] = {
1329 // Alt+Backspace -> Delete
1330 {ui::ET_KEY_PRESSED,
1331 {ui::VKEY_BACK, ui::DomCode::BACKSPACE, ui::EF_ALT_DOWN,
1332 ui::DomKey::BACKSPACE},
1333 {ui::VKEY_DELETE, ui::DomCode::DEL, ui::EF_NONE, ui::DomKey::DEL}},
1334 // Control+Alt+Backspace -> Control+Delete
1335 {ui::ET_KEY_PRESSED,
1336 {ui::VKEY_BACK, ui::DomCode::BACKSPACE,
1337 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, ui::DomKey::BACKSPACE},
1338 {ui::VKEY_DELETE, ui::DomCode::DEL, ui::EF_CONTROL_DOWN,
1339 ui::DomKey::DEL}},
1340 // Search+Alt+Backspace -> Alt+Backspace
1341 {ui::ET_KEY_PRESSED,
1342 {ui::VKEY_BACK, ui::DomCode::BACKSPACE,
1343 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN, ui::DomKey::BACKSPACE},
1344 {ui::VKEY_BACK, ui::DomCode::BACKSPACE, ui::EF_ALT_DOWN,
1345 ui::DomKey::BACKSPACE}},
1346 // Search+Control+Alt+Backspace -> Control+Alt+Backspace
1347 {ui::ET_KEY_PRESSED,
1348 {ui::VKEY_BACK, ui::DomCode::BACKSPACE,
1349 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1350 ui::DomKey::BACKSPACE},
1351 {ui::VKEY_BACK, ui::DomCode::BACKSPACE,
1352 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, ui::DomKey::BACKSPACE}},
1353 // Alt+Up -> Prior
1354 {ui::ET_KEY_PRESSED,
1355 {ui::VKEY_UP, ui::DomCode::ARROW_UP, ui::EF_ALT_DOWN,
1356 ui::DomKey::ARROW_UP},
1357 {ui::VKEY_PRIOR, ui::DomCode::PAGE_UP, ui::EF_NONE,
1358 ui::DomKey::PAGE_UP}},
1359 // Alt+Down -> Next
1360 {ui::ET_KEY_PRESSED,
1361 {ui::VKEY_DOWN, ui::DomCode::ARROW_DOWN, ui::EF_ALT_DOWN,
1362 ui::DomKey::ARROW_DOWN},
1363 {ui::VKEY_NEXT, ui::DomCode::PAGE_DOWN, ui::EF_NONE,
1364 ui::DomKey::PAGE_DOWN}},
1365 // Ctrl+Alt+Up -> Home
1366 {ui::ET_KEY_PRESSED,
1367 {ui::VKEY_UP, ui::DomCode::ARROW_UP,
1368 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, ui::DomKey::ARROW_UP},
1369 {ui::VKEY_HOME, ui::DomCode::HOME, ui::EF_NONE, ui::DomKey::HOME}},
1370 // Ctrl+Alt+Down -> End
1371 {ui::ET_KEY_PRESSED,
1372 {ui::VKEY_DOWN, ui::DomCode::ARROW_DOWN,
1373 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, ui::DomKey::ARROW_DOWN},
1374 {ui::VKEY_END, ui::DomCode::END, ui::EF_NONE, ui::DomKey::END}},
1376 // Search+Alt+Up -> Alt+Up
1377 {ui::ET_KEY_PRESSED,
1378 {ui::VKEY_UP, ui::DomCode::ARROW_UP,
1379 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN, ui::DomKey::ARROW_UP},
1380 {ui::VKEY_UP, ui::DomCode::ARROW_UP, ui::EF_ALT_DOWN,
1381 ui::DomKey::ARROW_UP}},
1382 // Search+Alt+Down -> Alt+Down
1383 {ui::ET_KEY_PRESSED,
1384 {ui::VKEY_DOWN, ui::DomCode::ARROW_DOWN,
1385 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN, ui::DomKey::ARROW_DOWN},
1386 {ui::VKEY_DOWN, ui::DomCode::ARROW_DOWN, ui::EF_ALT_DOWN,
1387 ui::DomKey::ARROW_DOWN}},
1388 // Search+Ctrl+Alt+Up -> Search+Ctrl+Alt+Up
1389 {ui::ET_KEY_PRESSED,
1390 {ui::VKEY_UP, ui::DomCode::ARROW_UP,
1391 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1392 ui::DomKey::ARROW_UP},
1393 {ui::VKEY_UP, ui::DomCode::ARROW_UP,
1394 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, ui::DomKey::ARROW_UP}},
1395 // Search+Ctrl+Alt+Down -> Ctrl+Alt+Down
1396 {ui::ET_KEY_PRESSED,
1397 {ui::VKEY_DOWN, ui::DomCode::ARROW_DOWN,
1398 ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
1399 ui::DomKey::ARROW_DOWN},
1400 {ui::VKEY_DOWN, ui::DomCode::ARROW_DOWN,
1401 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, ui::DomKey::ARROW_DOWN}},
1403 // Period -> Period
1404 {ui::ET_KEY_PRESSED,
1405 {ui::VKEY_OEM_PERIOD, ui::DomCode::PERIOD, ui::EF_NONE,
1406 ui::DomKey::Constant<'.'>::Character},
1407 {ui::VKEY_OEM_PERIOD, ui::DomCode::PERIOD, ui::EF_NONE,
1408 ui::DomKey::Constant<'.'>::Character}},
1410 // Search+Backspace -> Delete
1411 {ui::ET_KEY_PRESSED,
1412 {ui::VKEY_BACK, ui::DomCode::BACKSPACE, ui::EF_COMMAND_DOWN,
1413 ui::DomKey::BACKSPACE},
1414 {ui::VKEY_DELETE, ui::DomCode::DEL, ui::EF_NONE, ui::DomKey::DEL}},
1415 // Search+Up -> Prior
1416 {ui::ET_KEY_PRESSED,
1417 {ui::VKEY_UP, ui::DomCode::ARROW_UP, ui::EF_COMMAND_DOWN,
1418 ui::DomKey::ARROW_UP},
1419 {ui::VKEY_PRIOR, ui::DomCode::PAGE_UP, ui::EF_NONE,
1420 ui::DomKey::PAGE_UP}},
1421 // Search+Down -> Next
1422 {ui::ET_KEY_PRESSED,
1423 {ui::VKEY_DOWN, ui::DomCode::ARROW_DOWN, ui::EF_COMMAND_DOWN,
1424 ui::DomKey::ARROW_DOWN},
1425 {ui::VKEY_NEXT, ui::DomCode::PAGE_DOWN, ui::EF_NONE,
1426 ui::DomKey::PAGE_DOWN}},
1427 // Search+Left -> Home
1428 {ui::ET_KEY_PRESSED,
1429 {ui::VKEY_LEFT, ui::DomCode::ARROW_LEFT, ui::EF_COMMAND_DOWN,
1430 ui::DomKey::ARROW_LEFT},
1431 {ui::VKEY_HOME, ui::DomCode::HOME, ui::EF_NONE, ui::DomKey::HOME}},
1432 // Control+Search+Left -> Home
1433 {ui::ET_KEY_PRESSED,
1434 {ui::VKEY_LEFT, ui::DomCode::ARROW_LEFT,
1435 ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN, ui::DomKey::ARROW_LEFT},
1436 {ui::VKEY_HOME, ui::DomCode::HOME, ui::EF_CONTROL_DOWN,
1437 ui::DomKey::HOME}},
1438 // Search+Right -> End
1439 {ui::ET_KEY_PRESSED,
1440 {ui::VKEY_RIGHT, ui::DomCode::ARROW_RIGHT, ui::EF_COMMAND_DOWN,
1441 ui::DomKey::ARROW_RIGHT},
1442 {ui::VKEY_END, ui::DomCode::END, ui::EF_NONE, ui::DomKey::END}},
1443 // Control+Search+Right -> End
1444 {ui::ET_KEY_PRESSED,
1445 {ui::VKEY_RIGHT, ui::DomCode::ARROW_RIGHT,
1446 ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN, ui::DomKey::ARROW_RIGHT},
1447 {ui::VKEY_END, ui::DomCode::END, ui::EF_CONTROL_DOWN, ui::DomKey::END}},
1448 // Search+Period -> Insert
1449 {ui::ET_KEY_PRESSED,
1450 {ui::VKEY_OEM_PERIOD, ui::DomCode::PERIOD, ui::EF_COMMAND_DOWN,
1451 ui::DomKey::Constant<'.'>::Character},
1452 {ui::VKEY_INSERT, ui::DomCode::INSERT, ui::EF_NONE, ui::DomKey::INSERT}},
1453 // Control+Search+Period -> Control+Insert
1454 {ui::ET_KEY_PRESSED,
1455 {ui::VKEY_OEM_PERIOD, ui::DomCode::PERIOD,
1456 ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN,
1457 ui::DomKey::Constant<'.'>::Character},
1458 {ui::VKEY_INSERT, ui::DomCode::INSERT, ui::EF_CONTROL_DOWN,
1459 ui::DomKey::INSERT}}};
1461 for (const auto& test : tests) {
1462 CheckKeyTestCase(&rewriter, test);
1466 TEST_F(EventRewriterTest, TestRewriteFunctionKeys) {
1467 TestingPrefServiceSyncable prefs;
1468 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1469 EventRewriter rewriter(NULL);
1470 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1471 rewriter.set_pref_service_for_testing(&prefs);
1473 KeyTestCase tests[] = {
1474 // F1 -> Back
1475 {ui::ET_KEY_PRESSED,
1476 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_NONE, ui::DomKey::F1},
1477 {ui::VKEY_BROWSER_BACK, ui::DomCode::BROWSER_BACK, ui::EF_NONE,
1478 ui::DomKey::BROWSER_BACK}},
1479 {ui::ET_KEY_PRESSED,
1480 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_CONTROL_DOWN, ui::DomKey::F1},
1481 {ui::VKEY_BROWSER_BACK, ui::DomCode::BROWSER_BACK, ui::EF_CONTROL_DOWN,
1482 ui::DomKey::BROWSER_BACK}},
1483 {ui::ET_KEY_PRESSED,
1484 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_ALT_DOWN, ui::DomKey::F1},
1485 {ui::VKEY_BROWSER_BACK, ui::DomCode::BROWSER_BACK, ui::EF_ALT_DOWN,
1486 ui::DomKey::BROWSER_BACK}},
1487 // F2 -> Forward
1488 {ui::ET_KEY_PRESSED,
1489 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_NONE, ui::DomKey::F2},
1490 {ui::VKEY_BROWSER_FORWARD, ui::DomCode::BROWSER_FORWARD, ui::EF_NONE,
1491 ui::DomKey::BROWSER_FORWARD}},
1492 {ui::ET_KEY_PRESSED,
1493 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_CONTROL_DOWN, ui::DomKey::F2},
1494 {ui::VKEY_BROWSER_FORWARD, ui::DomCode::BROWSER_FORWARD,
1495 ui::EF_CONTROL_DOWN, ui::DomKey::BROWSER_FORWARD}},
1496 {ui::ET_KEY_PRESSED,
1497 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_ALT_DOWN, ui::DomKey::F2},
1498 {ui::VKEY_BROWSER_FORWARD, ui::DomCode::BROWSER_FORWARD, ui::EF_ALT_DOWN,
1499 ui::DomKey::BROWSER_FORWARD}},
1500 // F3 -> Refresh
1501 {ui::ET_KEY_PRESSED,
1502 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_NONE, ui::DomKey::F3},
1503 {ui::VKEY_BROWSER_REFRESH, ui::DomCode::BROWSER_REFRESH, ui::EF_NONE,
1504 ui::DomKey::BROWSER_REFRESH}},
1505 {ui::ET_KEY_PRESSED,
1506 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_CONTROL_DOWN, ui::DomKey::F3},
1507 {ui::VKEY_BROWSER_REFRESH, ui::DomCode::BROWSER_REFRESH,
1508 ui::EF_CONTROL_DOWN, ui::DomKey::BROWSER_REFRESH}},
1509 {ui::ET_KEY_PRESSED,
1510 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_ALT_DOWN, ui::DomKey::F3},
1511 {ui::VKEY_BROWSER_REFRESH, ui::DomCode::BROWSER_REFRESH, ui::EF_ALT_DOWN,
1512 ui::DomKey::BROWSER_REFRESH}},
1513 // F4 -> Launch App 2
1514 {ui::ET_KEY_PRESSED,
1515 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_NONE, ui::DomKey::F4},
1516 {ui::VKEY_MEDIA_LAUNCH_APP2, ui::DomCode::ZOOM_TOGGLE, ui::EF_NONE,
1517 ui::DomKey::ZOOM_TOGGLE}},
1518 {ui::ET_KEY_PRESSED,
1519 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_CONTROL_DOWN, ui::DomKey::F4},
1520 {ui::VKEY_MEDIA_LAUNCH_APP2, ui::DomCode::ZOOM_TOGGLE,
1521 ui::EF_CONTROL_DOWN, ui::DomKey::ZOOM_TOGGLE}},
1522 {ui::ET_KEY_PRESSED,
1523 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_ALT_DOWN, ui::DomKey::F4},
1524 {ui::VKEY_MEDIA_LAUNCH_APP2, ui::DomCode::ZOOM_TOGGLE, ui::EF_ALT_DOWN,
1525 ui::DomKey::ZOOM_TOGGLE}},
1526 // F5 -> Launch App 1
1527 {ui::ET_KEY_PRESSED,
1528 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_NONE, ui::DomKey::F5},
1529 {ui::VKEY_MEDIA_LAUNCH_APP1, ui::DomCode::SELECT_TASK, ui::EF_NONE,
1530 ui::DomKey::LAUNCH_MY_COMPUTER}},
1531 {ui::ET_KEY_PRESSED,
1532 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_CONTROL_DOWN, ui::DomKey::F5},
1533 {ui::VKEY_MEDIA_LAUNCH_APP1, ui::DomCode::SELECT_TASK,
1534 ui::EF_CONTROL_DOWN, ui::DomKey::LAUNCH_MY_COMPUTER}},
1535 {ui::ET_KEY_PRESSED,
1536 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_ALT_DOWN, ui::DomKey::F5},
1537 {ui::VKEY_MEDIA_LAUNCH_APP1, ui::DomCode::SELECT_TASK, ui::EF_ALT_DOWN,
1538 ui::DomKey::LAUNCH_MY_COMPUTER}},
1539 // F6 -> Brightness down
1540 {ui::ET_KEY_PRESSED,
1541 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_NONE, ui::DomKey::F6},
1542 {ui::VKEY_BRIGHTNESS_DOWN, ui::DomCode::BRIGHTNESS_DOWN, ui::EF_NONE,
1543 ui::DomKey::BRIGHTNESS_DOWN}},
1544 {ui::ET_KEY_PRESSED,
1545 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_CONTROL_DOWN, ui::DomKey::F6},
1546 {ui::VKEY_BRIGHTNESS_DOWN, ui::DomCode::BRIGHTNESS_DOWN,
1547 ui::EF_CONTROL_DOWN, ui::DomKey::BRIGHTNESS_DOWN}},
1548 {ui::ET_KEY_PRESSED,
1549 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_ALT_DOWN, ui::DomKey::F6},
1550 {ui::VKEY_BRIGHTNESS_DOWN, ui::DomCode::BRIGHTNESS_DOWN, ui::EF_ALT_DOWN,
1551 ui::DomKey::BRIGHTNESS_DOWN}},
1552 // F7 -> Brightness up
1553 {ui::ET_KEY_PRESSED,
1554 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_NONE, ui::DomKey::F7},
1555 {ui::VKEY_BRIGHTNESS_UP, ui::DomCode::BRIGHTNESS_UP, ui::EF_NONE,
1556 ui::DomKey::BRIGHTNESS_UP}},
1557 {ui::ET_KEY_PRESSED,
1558 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_CONTROL_DOWN, ui::DomKey::F7},
1559 {ui::VKEY_BRIGHTNESS_UP, ui::DomCode::BRIGHTNESS_UP, ui::EF_CONTROL_DOWN,
1560 ui::DomKey::BRIGHTNESS_UP}},
1561 {ui::ET_KEY_PRESSED,
1562 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_ALT_DOWN, ui::DomKey::F7},
1563 {ui::VKEY_BRIGHTNESS_UP, ui::DomCode::BRIGHTNESS_UP, ui::EF_ALT_DOWN,
1564 ui::DomKey::BRIGHTNESS_UP}},
1565 // F8 -> Volume Mute
1566 {ui::ET_KEY_PRESSED,
1567 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_NONE, ui::DomKey::F8},
1568 {ui::VKEY_VOLUME_MUTE, ui::DomCode::VOLUME_MUTE, ui::EF_NONE,
1569 ui::DomKey::VOLUME_MUTE}},
1570 {ui::ET_KEY_PRESSED,
1571 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_CONTROL_DOWN, ui::DomKey::F8},
1572 {ui::VKEY_VOLUME_MUTE, ui::DomCode::VOLUME_MUTE, ui::EF_CONTROL_DOWN,
1573 ui::DomKey::VOLUME_MUTE}},
1574 {ui::ET_KEY_PRESSED,
1575 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_ALT_DOWN, ui::DomKey::F8},
1576 {ui::VKEY_VOLUME_MUTE, ui::DomCode::VOLUME_MUTE, ui::EF_ALT_DOWN,
1577 ui::DomKey::VOLUME_MUTE}},
1578 // F9 -> Volume Down
1579 {ui::ET_KEY_PRESSED,
1580 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_NONE, ui::DomKey::F9},
1581 {ui::VKEY_VOLUME_DOWN, ui::DomCode::VOLUME_DOWN, ui::EF_NONE,
1582 ui::DomKey::VOLUME_DOWN}},
1583 {ui::ET_KEY_PRESSED,
1584 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_CONTROL_DOWN, ui::DomKey::F9},
1585 {ui::VKEY_VOLUME_DOWN, ui::DomCode::VOLUME_DOWN, ui::EF_CONTROL_DOWN,
1586 ui::DomKey::VOLUME_DOWN}},
1587 {ui::ET_KEY_PRESSED,
1588 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_ALT_DOWN, ui::DomKey::F9},
1589 {ui::VKEY_VOLUME_DOWN, ui::DomCode::VOLUME_DOWN, ui::EF_ALT_DOWN,
1590 ui::DomKey::VOLUME_DOWN}},
1591 // F10 -> Volume Up
1592 {ui::ET_KEY_PRESSED,
1593 {ui::VKEY_F10, ui::DomCode::F10, ui::EF_NONE, ui::DomKey::F10},
1594 {ui::VKEY_VOLUME_UP, ui::DomCode::VOLUME_UP, ui::EF_NONE,
1595 ui::DomKey::VOLUME_UP}},
1596 {ui::ET_KEY_PRESSED,
1597 {ui::VKEY_F10, ui::DomCode::F10, ui::EF_CONTROL_DOWN, ui::DomKey::F10},
1598 {ui::VKEY_VOLUME_UP, ui::DomCode::VOLUME_UP, ui::EF_CONTROL_DOWN,
1599 ui::DomKey::VOLUME_UP}},
1600 {ui::ET_KEY_PRESSED,
1601 {ui::VKEY_F10, ui::DomCode::F10, ui::EF_ALT_DOWN, ui::DomKey::F10},
1602 {ui::VKEY_VOLUME_UP, ui::DomCode::VOLUME_UP, ui::EF_ALT_DOWN,
1603 ui::DomKey::VOLUME_UP}},
1604 // F11 -> F11
1605 {ui::ET_KEY_PRESSED,
1606 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_NONE, ui::DomKey::F11},
1607 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_NONE, ui::DomKey::F11}},
1608 {ui::ET_KEY_PRESSED,
1609 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_CONTROL_DOWN, ui::DomKey::F11},
1610 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_CONTROL_DOWN, ui::DomKey::F11}},
1611 {ui::ET_KEY_PRESSED,
1612 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_ALT_DOWN, ui::DomKey::F11},
1613 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_ALT_DOWN, ui::DomKey::F11}},
1614 // F12 -> F12
1615 {ui::ET_KEY_PRESSED,
1616 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_NONE, ui::DomKey::F12},
1617 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_NONE, ui::DomKey::F12}},
1618 {ui::ET_KEY_PRESSED,
1619 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_CONTROL_DOWN, ui::DomKey::F12},
1620 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_CONTROL_DOWN, ui::DomKey::F12}},
1621 {ui::ET_KEY_PRESSED,
1622 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_ALT_DOWN, ui::DomKey::F12},
1623 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_ALT_DOWN, ui::DomKey::F12}},
1625 // The number row should not be rewritten without Search key.
1626 {ui::ET_KEY_PRESSED,
1627 {ui::VKEY_1, ui::DomCode::DIGIT1, ui::EF_NONE,
1628 ui::DomKey::Constant<'1'>::Character},
1629 {ui::VKEY_1, ui::DomCode::DIGIT1, ui::EF_NONE,
1630 ui::DomKey::Constant<'1'>::Character}},
1631 {ui::ET_KEY_PRESSED,
1632 {ui::VKEY_2, ui::DomCode::DIGIT2, ui::EF_NONE,
1633 ui::DomKey::Constant<'2'>::Character},
1634 {ui::VKEY_2, ui::DomCode::DIGIT2, ui::EF_NONE,
1635 ui::DomKey::Constant<'2'>::Character}},
1636 {ui::ET_KEY_PRESSED,
1637 {ui::VKEY_3, ui::DomCode::DIGIT3, ui::EF_NONE,
1638 ui::DomKey::Constant<'3'>::Character},
1639 {ui::VKEY_3, ui::DomCode::DIGIT3, ui::EF_NONE,
1640 ui::DomKey::Constant<'3'>::Character}},
1641 {ui::ET_KEY_PRESSED,
1642 {ui::VKEY_4, ui::DomCode::DIGIT4, ui::EF_NONE,
1643 ui::DomKey::Constant<'4'>::Character},
1644 {ui::VKEY_4, ui::DomCode::DIGIT4, ui::EF_NONE,
1645 ui::DomKey::Constant<'4'>::Character}},
1646 {ui::ET_KEY_PRESSED,
1647 {ui::VKEY_5, ui::DomCode::DIGIT5, ui::EF_NONE,
1648 ui::DomKey::Constant<'5'>::Character},
1649 {ui::VKEY_5, ui::DomCode::DIGIT5, ui::EF_NONE,
1650 ui::DomKey::Constant<'5'>::Character}},
1651 {ui::ET_KEY_PRESSED,
1652 {ui::VKEY_6, ui::DomCode::DIGIT6, ui::EF_NONE,
1653 ui::DomKey::Constant<'6'>::Character},
1654 {ui::VKEY_6, ui::DomCode::DIGIT6, ui::EF_NONE,
1655 ui::DomKey::Constant<'6'>::Character}},
1656 {ui::ET_KEY_PRESSED,
1657 {ui::VKEY_7, ui::DomCode::DIGIT7, ui::EF_NONE,
1658 ui::DomKey::Constant<'7'>::Character},
1659 {ui::VKEY_7, ui::DomCode::DIGIT7, ui::EF_NONE,
1660 ui::DomKey::Constant<'7'>::Character}},
1661 {ui::ET_KEY_PRESSED,
1662 {ui::VKEY_8, ui::DomCode::DIGIT8, ui::EF_NONE,
1663 ui::DomKey::Constant<'8'>::Character},
1664 {ui::VKEY_8, ui::DomCode::DIGIT8, ui::EF_NONE,
1665 ui::DomKey::Constant<'8'>::Character}},
1666 {ui::ET_KEY_PRESSED,
1667 {ui::VKEY_9, ui::DomCode::DIGIT9, ui::EF_NONE,
1668 ui::DomKey::Constant<'9'>::Character},
1669 {ui::VKEY_9, ui::DomCode::DIGIT9, ui::EF_NONE,
1670 ui::DomKey::Constant<'9'>::Character}},
1671 {ui::ET_KEY_PRESSED,
1672 {ui::VKEY_0, ui::DomCode::DIGIT0, ui::EF_NONE,
1673 ui::DomKey::Constant<'0'>::Character},
1674 {ui::VKEY_0, ui::DomCode::DIGIT0, ui::EF_NONE,
1675 ui::DomKey::Constant<'0'>::Character}},
1676 {ui::ET_KEY_PRESSED,
1677 {ui::VKEY_OEM_MINUS, ui::DomCode::MINUS, ui::EF_NONE,
1678 ui::DomKey::Constant<'-'>::Character},
1679 {ui::VKEY_OEM_MINUS, ui::DomCode::MINUS, ui::EF_NONE,
1680 ui::DomKey::Constant<'-'>::Character}},
1681 {ui::ET_KEY_PRESSED,
1682 {ui::VKEY_OEM_PLUS, ui::DomCode::EQUAL, ui::EF_NONE,
1683 ui::DomKey::Constant<'='>::Character},
1684 {ui::VKEY_OEM_PLUS, ui::DomCode::EQUAL, ui::EF_NONE,
1685 ui::DomKey::Constant<'='>::Character}},
1687 // The number row should be rewritten as the F<number> row with Search
1688 // key.
1689 {ui::ET_KEY_PRESSED,
1690 {ui::VKEY_1, ui::DomCode::DIGIT1, ui::EF_COMMAND_DOWN,
1691 ui::DomKey::Constant<'1'>::Character},
1692 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_NONE, ui::DomKey::F1}},
1693 {ui::ET_KEY_PRESSED,
1694 {ui::VKEY_2, ui::DomCode::DIGIT2, ui::EF_COMMAND_DOWN,
1695 ui::DomKey::Constant<'2'>::Character},
1696 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_NONE, ui::DomKey::F2}},
1697 {ui::ET_KEY_PRESSED,
1698 {ui::VKEY_3, ui::DomCode::DIGIT3, ui::EF_COMMAND_DOWN,
1699 ui::DomKey::Constant<'3'>::Character},
1700 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_NONE, ui::DomKey::F3}},
1701 {ui::ET_KEY_PRESSED,
1702 {ui::VKEY_4, ui::DomCode::DIGIT4, ui::EF_COMMAND_DOWN,
1703 ui::DomKey::Constant<'4'>::Character},
1704 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_NONE, ui::DomKey::F4}},
1705 {ui::ET_KEY_PRESSED,
1706 {ui::VKEY_5, ui::DomCode::DIGIT5, ui::EF_COMMAND_DOWN,
1707 ui::DomKey::Constant<'5'>::Character},
1708 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_NONE, ui::DomKey::F5}},
1709 {ui::ET_KEY_PRESSED,
1710 {ui::VKEY_6, ui::DomCode::DIGIT6, ui::EF_COMMAND_DOWN,
1711 ui::DomKey::Constant<'6'>::Character},
1712 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_NONE, ui::DomKey::F6}},
1713 {ui::ET_KEY_PRESSED,
1714 {ui::VKEY_7, ui::DomCode::DIGIT7, ui::EF_COMMAND_DOWN,
1715 ui::DomKey::Constant<'7'>::Character},
1716 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_NONE, ui::DomKey::F7}},
1717 {ui::ET_KEY_PRESSED,
1718 {ui::VKEY_8, ui::DomCode::DIGIT8, ui::EF_COMMAND_DOWN,
1719 ui::DomKey::Constant<'8'>::Character},
1720 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_NONE, ui::DomKey::F8}},
1721 {ui::ET_KEY_PRESSED,
1722 {ui::VKEY_9, ui::DomCode::DIGIT9, ui::EF_COMMAND_DOWN,
1723 ui::DomKey::Constant<'9'>::Character},
1724 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_NONE, ui::DomKey::F9}},
1725 {ui::ET_KEY_PRESSED,
1726 {ui::VKEY_0, ui::DomCode::DIGIT0, ui::EF_COMMAND_DOWN,
1727 ui::DomKey::Constant<'0'>::Character},
1728 {ui::VKEY_F10, ui::DomCode::F10, ui::EF_NONE, ui::DomKey::F10}},
1729 {ui::ET_KEY_PRESSED,
1730 {ui::VKEY_OEM_MINUS, ui::DomCode::MINUS, ui::EF_COMMAND_DOWN,
1731 ui::DomKey::Constant<'-'>::Character},
1732 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_NONE, ui::DomKey::F11}},
1733 {ui::ET_KEY_PRESSED,
1734 {ui::VKEY_OEM_PLUS, ui::DomCode::EQUAL, ui::EF_COMMAND_DOWN,
1735 ui::DomKey::Constant<'='>::Character},
1736 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_NONE, ui::DomKey::F12}},
1738 // The function keys should not be rewritten with Search key pressed.
1739 {ui::ET_KEY_PRESSED,
1740 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_COMMAND_DOWN, ui::DomKey::F1},
1741 {ui::VKEY_F1, ui::DomCode::F1, ui::EF_NONE, ui::DomKey::F1}},
1742 {ui::ET_KEY_PRESSED,
1743 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_COMMAND_DOWN, ui::DomKey::F2},
1744 {ui::VKEY_F2, ui::DomCode::F2, ui::EF_NONE, ui::DomKey::F2}},
1745 {ui::ET_KEY_PRESSED,
1746 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_COMMAND_DOWN, ui::DomKey::F3},
1747 {ui::VKEY_F3, ui::DomCode::F3, ui::EF_NONE, ui::DomKey::F3}},
1748 {ui::ET_KEY_PRESSED,
1749 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_COMMAND_DOWN, ui::DomKey::F4},
1750 {ui::VKEY_F4, ui::DomCode::F4, ui::EF_NONE, ui::DomKey::F4}},
1751 {ui::ET_KEY_PRESSED,
1752 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_COMMAND_DOWN, ui::DomKey::F5},
1753 {ui::VKEY_F5, ui::DomCode::F5, ui::EF_NONE, ui::DomKey::F5}},
1754 {ui::ET_KEY_PRESSED,
1755 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_COMMAND_DOWN, ui::DomKey::F6},
1756 {ui::VKEY_F6, ui::DomCode::F6, ui::EF_NONE, ui::DomKey::F6}},
1757 {ui::ET_KEY_PRESSED,
1758 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_COMMAND_DOWN, ui::DomKey::F7},
1759 {ui::VKEY_F7, ui::DomCode::F7, ui::EF_NONE, ui::DomKey::F7}},
1760 {ui::ET_KEY_PRESSED,
1761 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_COMMAND_DOWN, ui::DomKey::F8},
1762 {ui::VKEY_F8, ui::DomCode::F8, ui::EF_NONE, ui::DomKey::F8}},
1763 {ui::ET_KEY_PRESSED,
1764 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_COMMAND_DOWN, ui::DomKey::F9},
1765 {ui::VKEY_F9, ui::DomCode::F9, ui::EF_NONE, ui::DomKey::F9}},
1766 {ui::ET_KEY_PRESSED,
1767 {ui::VKEY_F10, ui::DomCode::F10, ui::EF_COMMAND_DOWN, ui::DomKey::F10},
1768 {ui::VKEY_F10, ui::DomCode::F10, ui::EF_NONE, ui::DomKey::F10}},
1769 {ui::ET_KEY_PRESSED,
1770 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_COMMAND_DOWN, ui::DomKey::F11},
1771 {ui::VKEY_F11, ui::DomCode::F11, ui::EF_NONE, ui::DomKey::F11}},
1772 {ui::ET_KEY_PRESSED,
1773 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_COMMAND_DOWN, ui::DomKey::F12},
1774 {ui::VKEY_F12, ui::DomCode::F12, ui::EF_NONE, ui::DomKey::F12}}};
1776 for (const auto& test : tests) {
1777 CheckKeyTestCase(&rewriter, test);
1781 TEST_F(EventRewriterTest, TestRewriteExtendedKeysWithSearchRemapped) {
1782 // Remap Search to Control.
1783 TestingPrefServiceSyncable prefs;
1784 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1785 IntegerPrefMember search;
1786 search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
1787 search.SetValue(chromeos::input_method::kControlKey);
1789 EventRewriter rewriter(NULL);
1790 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1791 rewriter.set_pref_service_for_testing(&prefs);
1793 KeyTestCase tests[] = {
1794 // Alt+Search+Down -> End
1795 {ui::ET_KEY_PRESSED,
1796 {ui::VKEY_DOWN, ui::DomCode::ARROW_DOWN,
1797 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::DomKey::ARROW_DOWN},
1798 {ui::VKEY_END, ui::DomCode::END, ui::EF_NONE, ui::DomKey::END}},
1800 // Shift+Alt+Search+Down -> Shift+End
1801 {ui::ET_KEY_PRESSED,
1802 {ui::VKEY_DOWN, ui::DomCode::ARROW_DOWN,
1803 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN,
1804 ui::DomKey::ARROW_DOWN},
1805 {ui::VKEY_END, ui::DomCode::END, ui::EF_SHIFT_DOWN, ui::DomKey::END}},
1808 for (const auto& test : tests) {
1809 CheckKeyTestCase(&rewriter, test);
1813 TEST_F(EventRewriterTest, TestRewriteKeyEventSentByXSendEvent) {
1814 // Remap Control to Alt.
1815 TestingPrefServiceSyncable prefs;
1816 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1817 IntegerPrefMember control;
1818 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
1819 control.SetValue(chromeos::input_method::kAltKey);
1821 EventRewriter rewriter(NULL);
1822 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1823 rewriter.set_pref_service_for_testing(&prefs);
1825 // Send left control press.
1827 ui::KeyEvent keyevent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL,
1828 ui::DomCode::CONTROL_LEFT, ui::EF_FINAL,
1829 ui::DomKey::CONTROL, ui::EventTimeForNow());
1830 scoped_ptr<ui::Event> new_event;
1831 // Control should NOT be remapped to Alt if EF_FINAL is set.
1832 EXPECT_EQ(ui::EVENT_REWRITE_CONTINUE,
1833 rewriter.RewriteEvent(keyevent, &new_event));
1834 EXPECT_FALSE(new_event);
1836 #if defined(USE_X11)
1837 // Send left control press, using XI2 native events.
1839 ui::ScopedXI2Event xev;
1840 xev.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, 0);
1841 XEvent* xevent = xev;
1842 xevent->xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), XK_Control_L);
1843 xevent->xkey.send_event = True; // XSendEvent() always does this.
1844 ui::KeyEvent keyevent(xev);
1845 scoped_ptr<ui::Event> new_event;
1846 // Control should NOT be remapped to Alt if send_event
1847 // flag in the event is True.
1848 EXPECT_EQ(ui::EVENT_REWRITE_CONTINUE,
1849 rewriter.RewriteEvent(keyevent, &new_event));
1850 EXPECT_FALSE(new_event);
1852 #endif
1855 TEST_F(EventRewriterTest, TestRewriteNonNativeEvent) {
1856 // Remap Control to Alt.
1857 TestingPrefServiceSyncable prefs;
1858 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1859 IntegerPrefMember control;
1860 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
1861 control.SetValue(chromeos::input_method::kAltKey);
1863 EventRewriter rewriter(NULL);
1864 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1865 rewriter.set_pref_service_for_testing(&prefs);
1867 const int kTouchId = 2;
1868 gfx::Point location(0, 0);
1869 ui::TouchEvent press(ui::ET_TOUCH_PRESSED, location, kTouchId,
1870 base::TimeDelta());
1871 press.set_flags(ui::EF_CONTROL_DOWN);
1872 #if defined(USE_X11)
1873 ui::UpdateX11EventForFlags(&press);
1874 #endif
1876 scoped_ptr<ui::Event> new_event;
1877 rewriter.RewriteEvent(press, &new_event);
1878 EXPECT_TRUE(new_event);
1879 // Control should be remapped to Alt.
1880 EXPECT_EQ(ui::EF_ALT_DOWN,
1881 new_event->flags() & (ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN));
1884 // Keeps a buffer of handled events.
1885 class EventBuffer : public ui::test::TestEventProcessor {
1886 public:
1887 EventBuffer() {}
1888 ~EventBuffer() override {}
1890 void PopEvents(ScopedVector<ui::Event>* events) {
1891 events->clear();
1892 events->swap(events_);
1895 private:
1896 // ui::EventProcessor overrides:
1897 ui::EventDispatchDetails OnEventFromSource(ui::Event* event) override {
1898 if (event->IsKeyEvent()) {
1899 events_.push_back(new ui::KeyEvent(*static_cast<ui::KeyEvent*>(event)));
1900 } else if (event->IsMouseWheelEvent()) {
1901 events_.push_back(
1902 new ui::MouseWheelEvent(*static_cast<ui::MouseWheelEvent*>(event)));
1903 } else if (event->IsMouseEvent()) {
1904 events_.push_back(
1905 new ui::MouseEvent(*static_cast<ui::MouseEvent*>(event)));
1907 return ui::EventDispatchDetails();
1910 ScopedVector<ui::Event> events_;
1912 DISALLOW_COPY_AND_ASSIGN(EventBuffer);
1915 // Trivial EventSource that does nothing but send events.
1916 class TestEventSource : public ui::EventSource {
1917 public:
1918 explicit TestEventSource(ui::EventProcessor* processor)
1919 : processor_(processor) {}
1920 ui::EventProcessor* GetEventProcessor() override { return processor_; }
1921 ui::EventDispatchDetails Send(ui::Event* event) {
1922 return SendEventToProcessor(event);
1925 private:
1926 ui::EventProcessor* processor_;
1929 // Tests of event rewriting that depend on the Ash window manager.
1930 class EventRewriterAshTest : public ash::test::AshTestBase {
1931 public:
1932 EventRewriterAshTest()
1933 : source_(&buffer_),
1934 fake_user_manager_(new user_manager::FakeUserManager),
1935 user_manager_enabler_(fake_user_manager_) {}
1936 ~EventRewriterAshTest() override {}
1938 bool RewriteFunctionKeys(const ui::Event& event,
1939 scoped_ptr<ui::Event>* rewritten_event) {
1940 return rewriter_->RewriteEvent(event, rewritten_event);
1943 ui::EventDispatchDetails Send(ui::Event* event) {
1944 return source_.Send(event);
1947 void SendKeyEvent(ui::EventType type,
1948 ui::KeyboardCode key_code,
1949 ui::DomCode code,
1950 ui::DomKey key) {
1951 ui::KeyEvent press(type, key_code, code, ui::EF_NONE, key,
1952 ui::EventTimeForNow());
1953 ui::EventDispatchDetails details = Send(&press);
1954 CHECK(!details.dispatcher_destroyed);
1957 void SendActivateStickyKeyPattern(ui::KeyboardCode key_code,
1958 ui::DomCode code,
1959 ui::DomKey key) {
1960 SendKeyEvent(ui::ET_KEY_PRESSED, key_code, code, key);
1961 SendKeyEvent(ui::ET_KEY_RELEASED, key_code, code, key);
1964 protected:
1965 TestingPrefServiceSyncable* prefs() { return &prefs_; }
1967 void PopEvents(ScopedVector<ui::Event>* events) { buffer_.PopEvents(events); }
1969 void SetUp() override {
1970 AshTestBase::SetUp();
1971 sticky_keys_controller_ =
1972 ash::Shell::GetInstance()->sticky_keys_controller();
1973 rewriter_.reset(new EventRewriter(sticky_keys_controller_));
1974 chromeos::Preferences::RegisterProfilePrefs(prefs_.registry());
1975 rewriter_->set_pref_service_for_testing(&prefs_);
1976 #if defined(USE_X11)
1977 ui::SetUpTouchPadForTest(kTouchPadDeviceId);
1978 #endif
1979 source_.AddEventRewriter(rewriter_.get());
1980 sticky_keys_controller_->Enable(true);
1983 void TearDown() override {
1984 rewriter_.reset();
1985 AshTestBase::TearDown();
1988 protected:
1989 ash::StickyKeysController* sticky_keys_controller_;
1991 private:
1992 scoped_ptr<EventRewriter> rewriter_;
1994 EventBuffer buffer_;
1995 TestEventSource source_;
1997 user_manager::FakeUserManager* fake_user_manager_; // Not owned.
1998 chromeos::ScopedUserManagerEnabler user_manager_enabler_;
1999 TestingPrefServiceSyncable prefs_;
2001 DISALLOW_COPY_AND_ASSIGN(EventRewriterAshTest);
2004 TEST_F(EventRewriterAshTest, TopRowKeysAreFunctionKeys) {
2005 scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(1));
2006 ash::wm::WindowState* window_state = ash::wm::GetWindowState(window.get());
2007 window_state->Activate();
2008 ScopedVector<ui::Event> events;
2010 // Create a simulated keypress of F1 targetted at the window.
2011 ui::KeyEvent press_f1(ui::ET_KEY_PRESSED, ui::VKEY_F1, ui::DomCode::F1,
2012 ui::EF_NONE, ui::DomKey::F1, ui::EventTimeForNow());
2014 // Simulate an apps v2 window that has requested top row keys as function
2015 // keys. The event should not be rewritten.
2016 window_state->set_top_row_keys_are_function_keys(true);
2017 ui::EventDispatchDetails details = Send(&press_f1);
2018 ASSERT_FALSE(details.dispatcher_destroyed);
2019 PopEvents(&events);
2020 EXPECT_EQ(1u, events.size());
2021 EXPECT_EQ(
2022 GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_F1,
2023 ui::DomCode::F1, ui::EF_NONE, ui::DomKey::F1),
2024 GetKeyEventAsString(*static_cast<ui::KeyEvent*>(events[0])));
2026 // The event should also not be rewritten if the send-function-keys pref is
2027 // additionally set, for both apps v2 and regular windows.
2028 BooleanPrefMember send_function_keys_pref;
2029 send_function_keys_pref.Init(prefs::kLanguageSendFunctionKeys, prefs());
2030 send_function_keys_pref.SetValue(true);
2031 window_state->set_top_row_keys_are_function_keys(false);
2032 details = Send(&press_f1);
2033 ASSERT_FALSE(details.dispatcher_destroyed);
2034 PopEvents(&events);
2035 EXPECT_EQ(1u, events.size());
2036 EXPECT_EQ(
2037 GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_F1,
2038 ui::DomCode::F1, ui::EF_NONE, ui::DomKey::F1),
2039 GetKeyEventAsString(*static_cast<ui::KeyEvent*>(events[0])));
2041 // If the pref isn't set when an event is sent to a regular window, F1 is
2042 // rewritten to the back key.
2043 send_function_keys_pref.SetValue(false);
2044 details = Send(&press_f1);
2045 ASSERT_FALSE(details.dispatcher_destroyed);
2046 PopEvents(&events);
2047 EXPECT_EQ(1u, events.size());
2048 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_PRESSED, ui::VKEY_BROWSER_BACK,
2049 ui::DomCode::BROWSER_BACK, ui::EF_NONE,
2050 ui::DomKey::BROWSER_BACK),
2051 GetKeyEventAsString(*static_cast<ui::KeyEvent*>(events[0])));
2054 TEST_F(EventRewriterTest, TestRewrittenModifierClick) {
2055 #if defined(USE_X11)
2056 std::vector<int> device_list;
2057 device_list.push_back(10);
2058 ui::TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
2060 // Remap Control to Alt.
2061 TestingPrefServiceSyncable prefs;
2062 chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
2063 IntegerPrefMember control;
2064 control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
2065 control.SetValue(chromeos::input_method::kAltKey);
2067 EventRewriter rewriter(NULL);
2068 rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
2069 rewriter.set_pref_service_for_testing(&prefs);
2071 // Check that Control + Left Button is converted (via Alt + Left Button)
2072 // to Right Button.
2073 ui::ScopedXI2Event xev;
2074 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_PRESSED, gfx::Point(),
2075 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_CONTROL_DOWN);
2076 ui::MouseEvent press(xev);
2077 // Sanity check.
2078 EXPECT_EQ(ui::ET_MOUSE_PRESSED, press.type());
2079 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON | ui::EF_CONTROL_DOWN, press.flags());
2080 scoped_ptr<ui::Event> new_event;
2081 const ui::MouseEvent* result =
2082 RewriteMouseButtonEvent(&rewriter, press, &new_event);
2083 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2084 EXPECT_FALSE(ui::EF_LEFT_MOUSE_BUTTON & result->flags());
2085 EXPECT_FALSE(ui::EF_CONTROL_DOWN & result->flags());
2086 EXPECT_FALSE(ui::EF_ALT_DOWN & result->flags());
2087 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2088 #endif
2091 TEST_F(EventRewriterTest, DontRewriteIfNotRewritten) {
2092 // TODO(kpschoedel): pending changes for crbug.com/360377
2093 // to |chromeos::EventRewriter::RewriteLocatedEvent()
2094 #if defined(USE_X11)
2095 std::vector<int> device_list;
2096 device_list.push_back(10);
2097 device_list.push_back(11);
2098 ui::TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
2099 #endif
2100 TestingPrefServiceSyncable prefs;
2101 EventRewriter rewriter(NULL);
2102 rewriter.set_pref_service_for_testing(&prefs);
2103 const int kLeftAndAltFlag = ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN;
2105 // Test Alt + Left click.
2107 ui::MouseEvent press(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
2108 ui::EventTimeForNow(), kLeftAndAltFlag,
2109 ui::EF_LEFT_MOUSE_BUTTON);
2110 ui::EventTestApi test_press(&press);
2111 test_press.set_source_device_id(10);
2112 // Sanity check.
2113 EXPECT_EQ(ui::ET_MOUSE_PRESSED, press.type());
2114 EXPECT_EQ(kLeftAndAltFlag, press.flags());
2115 scoped_ptr<ui::Event> new_event;
2116 const ui::MouseEvent* result =
2117 RewriteMouseButtonEvent(&rewriter, press, &new_event);
2118 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2119 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2120 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2123 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
2124 ui::EventTimeForNow(), kLeftAndAltFlag,
2125 ui::EF_LEFT_MOUSE_BUTTON);
2126 ui::EventTestApi test_release(&release);
2127 test_release.set_source_device_id(10);
2128 scoped_ptr<ui::Event> new_event;
2129 const ui::MouseEvent* result =
2130 RewriteMouseButtonEvent(&rewriter, release, &new_event);
2131 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2132 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2133 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2135 #if defined(USE_X11)
2136 // Test Alt + Left click, using XI2 native events.
2138 ui::ScopedXI2Event xev;
2139 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_PRESSED, gfx::Point(),
2140 kLeftAndAltFlag);
2141 ui::MouseEvent press(xev);
2142 // Sanity check.
2143 EXPECT_EQ(ui::ET_MOUSE_PRESSED, press.type());
2144 EXPECT_EQ(kLeftAndAltFlag, press.flags());
2145 scoped_ptr<ui::Event> new_event;
2146 const ui::MouseEvent* result =
2147 RewriteMouseButtonEvent(&rewriter, press, &new_event);
2148 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2149 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2150 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2153 ui::ScopedXI2Event xev;
2154 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_RELEASED, gfx::Point(),
2155 kLeftAndAltFlag);
2156 ui::MouseEvent release(xev);
2157 scoped_ptr<ui::Event> new_event;
2158 const ui::MouseEvent* result =
2159 RewriteMouseButtonEvent(&rewriter, release, &new_event);
2160 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2161 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2162 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2164 #endif
2166 // No ALT in frst click.
2168 ui::MouseEvent press(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
2169 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2170 ui::EF_LEFT_MOUSE_BUTTON);
2171 ui::EventTestApi test_press(&press);
2172 test_press.set_source_device_id(10);
2173 scoped_ptr<ui::Event> new_event;
2174 const ui::MouseEvent* result =
2175 RewriteMouseButtonEvent(&rewriter, press, &new_event);
2176 EXPECT_TRUE(ui::EF_LEFT_MOUSE_BUTTON & result->flags());
2177 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
2180 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
2181 ui::EventTimeForNow(), kLeftAndAltFlag,
2182 ui::EF_LEFT_MOUSE_BUTTON);
2183 ui::EventTestApi test_release(&release);
2184 test_release.set_source_device_id(10);
2185 scoped_ptr<ui::Event> new_event;
2186 const ui::MouseEvent* result =
2187 RewriteMouseButtonEvent(&rewriter, release, &new_event);
2188 EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & result->flags());
2189 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
2191 #if defined(USE_X11)
2192 // No ALT in frst click, using XI2 native events.
2194 ui::ScopedXI2Event xev;
2195 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_PRESSED, gfx::Point(),
2196 ui::EF_LEFT_MOUSE_BUTTON);
2197 ui::MouseEvent press(xev);
2198 scoped_ptr<ui::Event> new_event;
2199 const ui::MouseEvent* result =
2200 RewriteMouseButtonEvent(&rewriter, press, &new_event);
2201 EXPECT_TRUE(ui::EF_LEFT_MOUSE_BUTTON & result->flags());
2202 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
2205 ui::ScopedXI2Event xev;
2206 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_RELEASED, gfx::Point(),
2207 kLeftAndAltFlag);
2208 ui::MouseEvent release(xev);
2209 scoped_ptr<ui::Event> new_event;
2210 const ui::MouseEvent* result =
2211 RewriteMouseButtonEvent(&rewriter, release, &new_event);
2212 EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & result->flags());
2213 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
2215 #endif
2217 // ALT on different device.
2219 ui::MouseEvent press(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
2220 ui::EventTimeForNow(), kLeftAndAltFlag,
2221 ui::EF_LEFT_MOUSE_BUTTON);
2222 ui::EventTestApi test_press(&press);
2223 test_press.set_source_device_id(11);
2224 scoped_ptr<ui::Event> new_event;
2225 const ui::MouseEvent* result =
2226 RewriteMouseButtonEvent(&rewriter, press, &new_event);
2227 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2228 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2229 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2232 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
2233 ui::EventTimeForNow(), kLeftAndAltFlag,
2234 ui::EF_LEFT_MOUSE_BUTTON);
2235 ui::EventTestApi test_release(&release);
2236 test_release.set_source_device_id(10);
2237 scoped_ptr<ui::Event> new_event;
2238 const ui::MouseEvent* result =
2239 RewriteMouseButtonEvent(&rewriter, release, &new_event);
2240 EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & result->flags());
2241 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
2244 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
2245 ui::EventTimeForNow(), kLeftAndAltFlag,
2246 ui::EF_LEFT_MOUSE_BUTTON);
2247 ui::EventTestApi test_release(&release);
2248 test_release.set_source_device_id(11);
2249 scoped_ptr<ui::Event> new_event;
2250 const ui::MouseEvent* result =
2251 RewriteMouseButtonEvent(&rewriter, release, &new_event);
2252 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2253 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2254 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2256 #if defined(USE_X11)
2257 // ALT on different device, using XI2 native events.
2259 ui::ScopedXI2Event xev;
2260 xev.InitGenericButtonEvent(11, ui::ET_MOUSE_PRESSED, gfx::Point(),
2261 kLeftAndAltFlag);
2262 ui::MouseEvent press(xev);
2263 scoped_ptr<ui::Event> new_event;
2264 const ui::MouseEvent* result =
2265 RewriteMouseButtonEvent(&rewriter, press, &new_event);
2266 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2267 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2268 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2271 ui::ScopedXI2Event xev;
2272 xev.InitGenericButtonEvent(10, ui::ET_MOUSE_RELEASED, gfx::Point(),
2273 kLeftAndAltFlag);
2274 ui::MouseEvent release(xev);
2275 scoped_ptr<ui::Event> new_event;
2276 const ui::MouseEvent* result =
2277 RewriteMouseButtonEvent(&rewriter, release, &new_event);
2278 EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & result->flags());
2279 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
2282 ui::ScopedXI2Event xev;
2283 xev.InitGenericButtonEvent(11, ui::ET_MOUSE_RELEASED, gfx::Point(),
2284 kLeftAndAltFlag);
2285 ui::MouseEvent release(xev);
2286 scoped_ptr<ui::Event> new_event;
2287 const ui::MouseEvent* result =
2288 RewriteMouseButtonEvent(&rewriter, release, &new_event);
2289 EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2290 EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2291 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2293 #endif
2296 TEST_F(EventRewriterAshTest, StickyKeyEventDispatchImpl) {
2297 // Test the actual key event dispatch implementation.
2298 ScopedVector<ui::Event> events;
2300 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
2301 ui::DomKey::CONTROL);
2302 PopEvents(&events);
2303 EXPECT_EQ(1u, events.size());
2304 EXPECT_EQ(ui::ET_KEY_PRESSED, events[0]->type());
2305 EXPECT_EQ(ui::VKEY_CONTROL,
2306 static_cast<ui::KeyEvent*>(events[0])->key_code());
2308 // Test key press event is correctly modified and modifier release
2309 // event is sent.
2310 ui::KeyEvent press(ui::ET_KEY_PRESSED, ui::VKEY_C, ui::DomCode::KEY_C,
2311 ui::EF_NONE, ui::DomKey::Constant<'c'>::Character,
2312 ui::EventTimeForNow());
2313 ui::EventDispatchDetails details = Send(&press);
2314 PopEvents(&events);
2315 EXPECT_EQ(2u, events.size());
2316 EXPECT_EQ(ui::ET_KEY_PRESSED, events[0]->type());
2317 EXPECT_EQ(ui::VKEY_C, static_cast<ui::KeyEvent*>(events[0])->key_code());
2318 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
2319 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
2320 EXPECT_EQ(ui::VKEY_CONTROL,
2321 static_cast<ui::KeyEvent*>(events[1])->key_code());
2323 // Test key release event is not modified.
2324 ui::KeyEvent release(ui::ET_KEY_RELEASED, ui::VKEY_C, ui::DomCode::KEY_C,
2325 ui::EF_NONE, ui::DomKey::Constant<'c'>::Character,
2326 ui::EventTimeForNow());
2327 details = Send(&release);
2328 ASSERT_FALSE(details.dispatcher_destroyed);
2329 PopEvents(&events);
2330 EXPECT_EQ(1u, events.size());
2331 EXPECT_EQ(ui::ET_KEY_RELEASED, events[0]->type());
2332 EXPECT_EQ(ui::VKEY_C, static_cast<ui::KeyEvent*>(events[0])->key_code());
2333 EXPECT_FALSE(events[0]->flags() & ui::EF_CONTROL_DOWN);
2336 TEST_F(EventRewriterAshTest, MouseEventDispatchImpl) {
2337 ScopedVector<ui::Event> events;
2339 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
2340 ui::DomKey::CONTROL);
2341 PopEvents(&events);
2343 // Test mouse press event is correctly modified.
2344 gfx::Point location(0, 0);
2345 ui::MouseEvent press(ui::ET_MOUSE_PRESSED, location, location,
2346 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2347 ui::EF_LEFT_MOUSE_BUTTON);
2348 ui::EventDispatchDetails details = Send(&press);
2349 ASSERT_FALSE(details.dispatcher_destroyed);
2350 PopEvents(&events);
2351 EXPECT_EQ(1u, events.size());
2352 EXPECT_EQ(ui::ET_MOUSE_PRESSED, events[0]->type());
2353 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
2355 // Test mouse release event is correctly modified and modifier release
2356 // event is sent. The mouse event should have the correct DIP location.
2357 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, location, location,
2358 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2359 ui::EF_LEFT_MOUSE_BUTTON);
2360 details = Send(&release);
2361 ASSERT_FALSE(details.dispatcher_destroyed);
2362 PopEvents(&events);
2363 EXPECT_EQ(2u, events.size());
2364 EXPECT_EQ(ui::ET_MOUSE_RELEASED, events[0]->type());
2365 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
2366 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
2367 EXPECT_EQ(ui::VKEY_CONTROL,
2368 static_cast<ui::KeyEvent*>(events[1])->key_code());
2371 TEST_F(EventRewriterAshTest, MouseWheelEventDispatchImpl) {
2372 ScopedVector<ui::Event> events;
2374 // Test positive mouse wheel event is correctly modified and modifier release
2375 // event is sent.
2376 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
2377 ui::DomKey::CONTROL);
2378 PopEvents(&events);
2379 gfx::Point location(0, 0);
2380 ui::MouseEvent mev(ui::ET_MOUSEWHEEL, location, location,
2381 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2382 ui::EF_LEFT_MOUSE_BUTTON);
2383 ui::MouseWheelEvent positive(mev, 0, ui::MouseWheelEvent::kWheelDelta);
2384 ui::EventDispatchDetails details = Send(&positive);
2385 ASSERT_FALSE(details.dispatcher_destroyed);
2386 PopEvents(&events);
2387 EXPECT_EQ(2u, events.size());
2388 EXPECT_TRUE(events[0]->IsMouseWheelEvent());
2389 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
2390 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
2391 EXPECT_EQ(ui::VKEY_CONTROL,
2392 static_cast<ui::KeyEvent*>(events[1])->key_code());
2394 // Test negative mouse wheel event is correctly modified and modifier release
2395 // event is sent.
2396 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
2397 ui::DomKey::CONTROL);
2398 PopEvents(&events);
2399 ui::MouseWheelEvent negative(mev, 0, -ui::MouseWheelEvent::kWheelDelta);
2400 details = Send(&negative);
2401 ASSERT_FALSE(details.dispatcher_destroyed);
2402 PopEvents(&events);
2403 EXPECT_EQ(2u, events.size());
2404 EXPECT_TRUE(events[0]->IsMouseWheelEvent());
2405 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
2406 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
2407 EXPECT_EQ(ui::VKEY_CONTROL,
2408 static_cast<ui::KeyEvent*>(events[1])->key_code());
2411 class StickyKeysOverlayTest : public EventRewriterAshTest {
2412 public:
2413 StickyKeysOverlayTest() : overlay_(NULL) {}
2415 ~StickyKeysOverlayTest() override {}
2417 void SetUp() override {
2418 EventRewriterAshTest::SetUp();
2419 overlay_ = sticky_keys_controller_->GetOverlayForTest();
2420 ASSERT_TRUE(overlay_);
2423 ash::StickyKeysOverlay* overlay_;
2426 TEST_F(StickyKeysOverlayTest, OneModifierEnabled) {
2427 EXPECT_FALSE(overlay_->is_visible());
2428 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2429 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2431 // Pressing modifier key should show overlay.
2432 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
2433 ui::DomKey::CONTROL);
2434 EXPECT_TRUE(overlay_->is_visible());
2435 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
2436 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2438 // Pressing a normal key should hide overlay.
2439 SendActivateStickyKeyPattern(ui::VKEY_T, ui::DomCode::KEY_T,
2440 ui::DomKey::Constant<'t'>::Character);
2441 EXPECT_FALSE(overlay_->is_visible());
2442 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2443 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2446 TEST_F(StickyKeysOverlayTest, TwoModifiersEnabled) {
2447 EXPECT_FALSE(overlay_->is_visible());
2448 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2449 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2450 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2451 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2453 // Pressing two modifiers should show overlay.
2454 SendActivateStickyKeyPattern(ui::VKEY_SHIFT, ui::DomCode::SHIFT_LEFT,
2455 ui::DomKey::SHIFT);
2456 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
2457 ui::DomKey::CONTROL);
2458 EXPECT_TRUE(overlay_->is_visible());
2459 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
2460 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2461 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
2462 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2464 // Pressing a normal key should hide overlay.
2465 SendActivateStickyKeyPattern(ui::VKEY_N, ui::DomCode::KEY_N,
2466 ui::DomKey::Constant<'n'>::Character);
2467 EXPECT_FALSE(overlay_->is_visible());
2468 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2469 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2470 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2471 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2474 TEST_F(StickyKeysOverlayTest, LockedModifier) {
2475 EXPECT_FALSE(overlay_->is_visible());
2476 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2477 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
2479 // Pressing a modifier key twice should lock modifier and show overlay.
2480 SendActivateStickyKeyPattern(ui::VKEY_LMENU, ui::DomCode::ALT_LEFT,
2481 ui::DomKey::ALT);
2482 SendActivateStickyKeyPattern(ui::VKEY_LMENU, ui::DomCode::ALT_LEFT,
2483 ui::DomKey::ALT);
2484 EXPECT_TRUE(overlay_->is_visible());
2485 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
2486 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
2488 // Pressing a normal key should not hide overlay.
2489 SendActivateStickyKeyPattern(ui::VKEY_D, ui::DomCode::KEY_D,
2490 ui::DomKey::Constant<'d'>::Character);
2491 EXPECT_TRUE(overlay_->is_visible());
2492 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
2493 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
2496 TEST_F(StickyKeysOverlayTest, LockedAndNormalModifier) {
2497 EXPECT_FALSE(overlay_->is_visible());
2498 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2499 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2500 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2501 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2503 // Pressing a modifier key twice should lock modifier and show overlay.
2504 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
2505 ui::DomKey::CONTROL);
2506 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
2507 ui::DomKey::CONTROL);
2508 EXPECT_TRUE(overlay_->is_visible());
2509 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
2510 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2512 // Pressing another modifier key should still show overlay.
2513 SendActivateStickyKeyPattern(ui::VKEY_SHIFT, ui::DomCode::SHIFT_LEFT,
2514 ui::DomKey::SHIFT);
2515 EXPECT_TRUE(overlay_->is_visible());
2516 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
2517 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2518 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
2519 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2521 // Pressing a normal key should not hide overlay but disable normal modifier.
2522 SendActivateStickyKeyPattern(ui::VKEY_D, ui::DomCode::KEY_D,
2523 ui::DomKey::Constant<'d'>::Character);
2524 EXPECT_TRUE(overlay_->is_visible());
2525 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
2526 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2527 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2528 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2531 TEST_F(StickyKeysOverlayTest, ModifiersDisabled) {
2532 EXPECT_FALSE(overlay_->is_visible());
2533 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2534 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2535 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2536 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2537 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2538 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
2539 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2540 overlay_->GetModifierKeyState(ui::EF_COMMAND_DOWN));
2542 // Enable modifiers.
2543 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
2544 ui::DomKey::CONTROL);
2545 SendActivateStickyKeyPattern(ui::VKEY_SHIFT, ui::DomCode::SHIFT_LEFT,
2546 ui::DomKey::SHIFT);
2547 SendActivateStickyKeyPattern(ui::VKEY_SHIFT, ui::DomCode::SHIFT_LEFT,
2548 ui::DomKey::SHIFT);
2549 SendActivateStickyKeyPattern(ui::VKEY_LMENU, ui::DomCode::ALT_LEFT,
2550 ui::DomKey::ALT);
2551 SendActivateStickyKeyPattern(ui::VKEY_COMMAND, ui::DomCode::OS_LEFT,
2552 ui::DomKey::OS);
2553 SendActivateStickyKeyPattern(ui::VKEY_COMMAND, ui::DomCode::OS_LEFT,
2554 ui::DomKey::OS);
2556 EXPECT_TRUE(overlay_->is_visible());
2557 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
2558 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2559 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
2560 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2561 EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
2562 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
2563 EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
2564 overlay_->GetModifierKeyState(ui::EF_COMMAND_DOWN));
2566 // Disable modifiers and overlay should be hidden.
2567 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
2568 ui::DomKey::CONTROL);
2569 SendActivateStickyKeyPattern(ui::VKEY_CONTROL, ui::DomCode::CONTROL_LEFT,
2570 ui::DomKey::CONTROL);
2571 SendActivateStickyKeyPattern(ui::VKEY_SHIFT, ui::DomCode::SHIFT_LEFT,
2572 ui::DomKey::SHIFT);
2573 SendActivateStickyKeyPattern(ui::VKEY_LMENU, ui::DomCode::ALT_LEFT,
2574 ui::DomKey::ALT);
2575 SendActivateStickyKeyPattern(ui::VKEY_LMENU, ui::DomCode::ALT_LEFT,
2576 ui::DomKey::ALT);
2577 SendActivateStickyKeyPattern(ui::VKEY_COMMAND, ui::DomCode::OS_LEFT,
2578 ui::DomKey::OS);
2580 EXPECT_FALSE(overlay_->is_visible());
2581 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2582 overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2583 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2584 overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2585 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2586 overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
2587 EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2588 overlay_->GetModifierKeyState(ui::EF_COMMAND_DOWN));
2591 TEST_F(StickyKeysOverlayTest, ModifierVisibility) {
2592 // All but AltGr and Mod3 should initially be visible.
2593 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_CONTROL_DOWN));
2594 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_SHIFT_DOWN));
2595 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALT_DOWN));
2596 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_COMMAND_DOWN));
2597 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
2598 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
2600 // Turn all modifiers on.
2601 sticky_keys_controller_->SetModifiersEnabled(true, true);
2602 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_CONTROL_DOWN));
2603 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_SHIFT_DOWN));
2604 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALT_DOWN));
2605 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_COMMAND_DOWN));
2606 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
2607 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
2609 // Turn off Mod3.
2610 sticky_keys_controller_->SetModifiersEnabled(false, true);
2611 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
2612 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
2614 // Turn off AltGr.
2615 sticky_keys_controller_->SetModifiersEnabled(true, false);
2616 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
2617 EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
2619 // Turn off AltGr and Mod3.
2620 sticky_keys_controller_->SetModifiersEnabled(false, false);
2621 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
2622 EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
2625 } // namespace chromeos