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"
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"
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"
50 // The device id of the test touchpad device.
52 const int kTouchPadDeviceId
= 1;
54 const int kKeyboardDeviceId
= 2;
56 std::string
GetExpectedResultAsString(ui::EventType ui_type
,
57 ui::KeyboardCode ui_keycode
,
59 int ui_flags
, // ui::EventFlags
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
,
77 int ui_flags
, // ui::EventFlags
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
);
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.
93 ui::KeyboardCode key_code
;
95 int flags
; // ui::EventFlags
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
));
120 class EventRewriterTest
: public ash::test::AshTestBase
{
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();
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())
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
,
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.
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.
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.
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.
326 {ui::VKEY_INSERT
, ui::DomCode::NUMPAD0
, ui::EF_ALT_DOWN
,
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.
333 {ui::VKEY_DELETE
, ui::DomCode::NUMPAD_DECIMAL
, ui::EF_ALT_DOWN
,
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.
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.
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.
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.
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.
367 {ui::VKEY_CLEAR
, ui::DomCode::NUMPAD5
, ui::EF_ALT_DOWN
,
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
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
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
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
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
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".
513 {ui::VKEY_END
, ui::DomCode::NUMPAD1
, ui::EF_COMMAND_DOWN
,
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
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.
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
,
560 // Press left Control. Confirm the event is not rewritten.
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.
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.
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
,
580 // Press right Alt. Confirm the event is not rewritten.
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
,
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.
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.
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
,
623 {ui::VKEY_LWIN
, ui::DomCode::OS_LEFT
, ui::EF_CAPS_LOCK_DOWN
,
626 // Press Shift+Ctrl+Alt+Search+A. Confirm the event is not rewritten.
628 {ui::VKEY_B
, ui::DomCode::KEY_B
,
629 ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
| ui::EF_ALT_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
|
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.
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.
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.
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.
683 {ui::VKEY_LWIN
, ui::DomCode::OS_LEFT
, ui::EF_CONTROL_DOWN
,
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
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
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.
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.
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.
751 {ui::VKEY_LWIN
, ui::DomCode::OS_LEFT
, ui::EF_COMMAND_DOWN
,
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.
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.
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.
782 {ui::VKEY_LWIN
, ui::DomCode::OS_LEFT
,
783 ui::EF_CONTROL_DOWN
| ui::EF_ALT_DOWN
| ui::EF_COMMAND_DOWN
,
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.
791 {ui::VKEY_LWIN
, ui::DomCode::OS_LEFT
,
792 ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
| ui::EF_ALT_DOWN
|
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.
801 {ui::VKEY_B
, ui::DomCode::KEY_B
,
802 ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
| ui::EF_ALT_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.
829 {ui::VKEY_LWIN
, ui::DomCode::OS_LEFT
, ui::EF_COMMAND_DOWN
,
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.
854 {ui::VKEY_LWIN
, ui::DomCode::OS_LEFT
, ui::EF_COMMAND_DOWN
,
856 {ui::VKEY_MENU
, ui::DomCode::ALT_LEFT
, ui::EF_ALT_DOWN
,
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.
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 '<>'.
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.
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.
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
,
908 // Then, press all of the three, Control+Alt+Search.
910 {ui::VKEY_LWIN
, ui::DomCode::OS_LEFT
,
911 ui::EF_CONTROL_DOWN
| ui::EF_ALT_DOWN
| ui::EF_COMMAND_DOWN
,
913 {ui::VKEY_MENU
, ui::DomCode::ALT_LEFT
,
914 ui::EF_CONTROL_DOWN
| ui::EF_ALT_DOWN
| ui::EF_COMMAND_DOWN
,
917 // Press Shift+Control+Alt+Search.
919 {ui::VKEY_LWIN
, ui::DomCode::OS_LEFT
,
920 ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
| ui::EF_ALT_DOWN
|
923 {ui::VKEY_MENU
, ui::DomCode::ALT_LEFT
,
924 ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
| ui::EF_ALT_DOWN
|
928 // Press Shift+Control+Alt+Search+B
930 {ui::VKEY_B
, ui::DomCode::KEY_B
,
931 ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
| ui::EF_ALT_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
|
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_
);
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_
);
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_
);
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_
);
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_
);
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_
);
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
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
));
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
));
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
,
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
));
1203 EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED
, ui::VKEY_MENU
,
1204 ui::DomCode::ALT_LEFT
, ui::EF_NONE
,
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
,
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
));
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
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
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
,
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
}},
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
}},
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
}},
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
,
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
[] = {
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
}},
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
}},
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
}},
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
}},
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
}},
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
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
);
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
,
1871 press
.set_flags(ui::EF_CONTROL_DOWN
);
1872 #if defined(USE_X11)
1873 ui::UpdateX11EventForFlags(&press
);
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
{
1888 ~EventBuffer() override
{}
1890 void PopEvents(ScopedVector
<ui::Event
>* events
) {
1892 events
->swap(events_
);
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()) {
1902 new ui::MouseWheelEvent(*static_cast<ui::MouseWheelEvent
*>(event
)));
1903 } else if (event
->IsMouseEvent()) {
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
{
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
);
1926 ui::EventProcessor
* processor_
;
1929 // Tests of event rewriting that depend on the Ash window manager.
1930 class EventRewriterAshTest
: public ash::test::AshTestBase
{
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
,
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
,
1960 SendKeyEvent(ui::ET_KEY_PRESSED
, key_code
, code
, key
);
1961 SendKeyEvent(ui::ET_KEY_RELEASED
, key_code
, code
, key
);
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
);
1979 source_
.AddEventRewriter(rewriter_
.get());
1980 sticky_keys_controller_
->Enable(true);
1983 void TearDown() override
{
1985 AshTestBase::TearDown();
1989 ash::StickyKeysController
* sticky_keys_controller_
;
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
);
2020 EXPECT_EQ(1u, events
.size());
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
);
2035 EXPECT_EQ(1u, events
.size());
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
);
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)
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
);
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());
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
);
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);
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(),
2141 ui::MouseEvent
press(xev
);
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(),
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());
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(),
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());
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(),
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(),
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(),
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());
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
);
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
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
);
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
);
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
);
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
);
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
);
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
2376 SendActivateStickyKeyPattern(ui::VKEY_CONTROL
, ui::DomCode::CONTROL_LEFT
,
2377 ui::DomKey::CONTROL
);
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
);
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
2396 SendActivateStickyKeyPattern(ui::VKEY_CONTROL
, ui::DomCode::CONTROL_LEFT
,
2397 ui::DomKey::CONTROL
);
2399 ui::MouseWheelEvent
negative(mev
, 0, -ui::MouseWheelEvent::kWheelDelta
);
2400 details
= Send(&negative
);
2401 ASSERT_FALSE(details
.dispatcher_destroyed
);
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
{
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
,
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
,
2482 SendActivateStickyKeyPattern(ui::VKEY_LMENU
, ui::DomCode::ALT_LEFT
,
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
,
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
,
2547 SendActivateStickyKeyPattern(ui::VKEY_SHIFT
, ui::DomCode::SHIFT_LEFT
,
2549 SendActivateStickyKeyPattern(ui::VKEY_LMENU
, ui::DomCode::ALT_LEFT
,
2551 SendActivateStickyKeyPattern(ui::VKEY_COMMAND
, ui::DomCode::OS_LEFT
,
2553 SendActivateStickyKeyPattern(ui::VKEY_COMMAND
, ui::DomCode::OS_LEFT
,
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
,
2573 SendActivateStickyKeyPattern(ui::VKEY_LMENU
, ui::DomCode::ALT_LEFT
,
2575 SendActivateStickyKeyPattern(ui::VKEY_LMENU
, ui::DomCode::ALT_LEFT
,
2577 SendActivateStickyKeyPattern(ui::VKEY_COMMAND
, ui::DomCode::OS_LEFT
,
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
));
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
));
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