Chromium Code Reviews| Index: chrome/browser/ui/views/ash/key_rewriter_unittest.cc |
| diff --git a/chrome/browser/ui/views/ash/key_rewriter_unittest.cc b/chrome/browser/ui/views/ash/key_rewriter_unittest.cc |
| index f32e785fc52de9976a2318160be328c38803e623..94f185735c24f8a83536c87b68267625d1d0bbc4 100644 |
| --- a/chrome/browser/ui/views/ash/key_rewriter_unittest.cc |
| +++ b/chrome/browser/ui/views/ash/key_rewriter_unittest.cc |
| @@ -3,7 +3,10 @@ |
| // found in the LICENSE file. |
| #include "base/basictypes.h" |
| +#include "chrome/browser/prefs/pref_member.h" |
| #include "chrome/browser/ui/views/ash/key_rewriter.h" |
| +#include "chrome/common/pref_names.h" |
| +#include "chrome/test/base/testing_pref_service.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/aura/event.h" |
| @@ -11,6 +14,8 @@ |
| #include <X11/keysym.h> |
| #include <X11/Xlib.h> |
| +#include "chrome/browser/chromeos/input_method/mock_xkeyboard.h" |
| +#include "chrome/browser/chromeos/preferences.h" |
| #include "ui/base/x/x11_util.h" |
| namespace { |
| @@ -99,9 +104,11 @@ TEST(KeyRewriterTest, TestRewriteCommandToControl) { |
| XKeysymToKeycode(ui::GetXDisplay(), XK_Control_R); |
| // First, test with a PC keyboard. |
| + TestingPrefService prefs; |
| KeyRewriter rewriter; |
| rewriter.DeviceAddedForTesting(0, "PC Keyboard"); |
| rewriter.set_last_device_id_for_testing(0); |
| + rewriter.set_pref_service_for_testing(&prefs); |
| { |
| // XK_a, Alt modifier. |
| InitXKeyEvent(ui::VKEY_A, ui::EF_ALT_DOWN, kKeycodeA, Mod1Mask, &xev); |
| @@ -258,7 +265,9 @@ TEST(KeyRewriterTest, TestRewriteNumPadKeys) { |
| const unsigned int kKeycodeNumPadPrior = |
| XKeysymToKeycode(display, XK_KP_Prior); |
| + TestingPrefService prefs; |
| KeyRewriter rewriter; |
| + rewriter.set_pref_service_for_testing(&prefs); |
| { |
| // XK_KP_Insert (= NumPad 0 without Num Lock), no modifier. |
| InitXKeyEvent(ui::VKEY_INSERT, 0, kKeycodeNumPadInsert, 0, &xev); |
| @@ -534,9 +543,11 @@ TEST(KeyRewriterTest, TestRewriteNumPadKeysOnAppleKeyboard) { |
| const unsigned int kKeycodeNumPadEnd = XKeysymToKeycode(display, XK_KP_End); |
| const unsigned int kKeycodeNumPad1 = XKeysymToKeycode(display, XK_KP_1); |
| + TestingPrefService prefs; |
| KeyRewriter rewriter; |
| rewriter.DeviceAddedForTesting(0, "Apple Keyboard"); |
| rewriter.set_last_device_id_for_testing(0); |
| + rewriter.set_pref_service_for_testing(&prefs); |
| { |
| // XK_KP_End (= NumPad 1 without Num Lock), Win modifier. |
| InitXKeyEvent(ui::VKEY_END, 0, kKeycodeNumPadEnd, Mod4Mask, &xev); |
| @@ -563,4 +574,656 @@ TEST(KeyRewriterTest, TestRewriteNumPadKeysOnAppleKeyboard) { |
| } |
| } |
| +TEST(KeyRewriterTest, TestRewriteModifiersNoRemap) { |
| + XEvent xev; |
| + Display* display = ui::GetXDisplay(); |
| + |
| + const unsigned int kKeycodeSuperL = XKeysymToKeycode(display, XK_Super_L); |
|
Daniel Erat
2012/05/23 16:37:32
nit: KeyCode instead of unsigned int for all of th
Yusuke Sato
2012/05/24 08:24:42
Done.
|
| + const unsigned int kKeycodeControlL = XKeysymToKeycode(display, XK_Control_L); |
| + const unsigned int kKeycodeControlR = XKeysymToKeycode(display, XK_Control_R); |
| + const unsigned int kKeycodeAltL = XKeysymToKeycode(display, XK_Alt_L); |
| + const unsigned int kKeycodeAltR = XKeysymToKeycode(display, XK_Alt_R); |
| + CHECK(kKeycodeAltR); |
| + |
| + TestingPrefService prefs; |
| + KeyRewriter rewriter; |
| + rewriter.set_pref_service_for_testing(&prefs); |
| + { |
| + // Press Search. |
| + InitXKeyEvent(ui::VKEY_LWIN, 0, kKeycodeSuperL, 0U, &xev); |
|
Daniel Erat
2012/05/23 16:37:32
there's a bunch of duplicate code in this file. d
Yusuke Sato
2012/05/24 08:24:42
Thanks for the suggestion! Done.
|
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is not rewritten. |
| + EXPECT_EQ(ui::VKEY_LWIN, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + EXPECT_EQ(ui::ET_KEY_PRESSED, keyevent.type()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeSuperL, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + EXPECT_EQ(KeyPress, xkey.type); |
| + } |
| + { |
| + // Press left Control. |
| + InitXKeyEvent(ui::VKEY_CONTROL, 0, kKeycodeControlL, 0U, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is not rewritten. |
| + EXPECT_EQ(ui::VKEY_CONTROL, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeControlL, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + } |
| + { |
| + // Press right Control. |
| + InitXKeyEvent(ui::VKEY_CONTROL, 0, kKeycodeControlR, 0U, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is not rewritten. |
| + EXPECT_EQ(ui::VKEY_CONTROL, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeControlR, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + } |
| + { |
| + // Press left Alt. |
| + InitXKeyEvent(ui::VKEY_MENU, 0, kKeycodeAltL, 0U, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is not rewritten. |
| + EXPECT_EQ(ui::VKEY_MENU, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeAltL, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + } |
| + { |
| + // Press right Alt. |
| + InitXKeyEvent(ui::VKEY_MENU, 0, kKeycodeAltR, 0U, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is not rewritten. |
| + EXPECT_EQ(ui::VKEY_MENU, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeAltR, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + } |
| + |
| + // Test KeyRelease event, just in case. |
| + { |
| + // Release Search. |
| + InitXKeyEvent(ui::VKEY_LWIN, 0, kKeycodeSuperL, Mod4Mask, &xev); |
| + xev.type = KeyRelease; |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the release event is not rewritten. |
| + EXPECT_EQ(ui::VKEY_LWIN, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + EXPECT_EQ(ui::ET_KEY_RELEASED, keyevent.type()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeSuperL, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(Mod4Mask), xkey.state); |
| + EXPECT_EQ(KeyRelease, xkey.type); |
| + } |
| +} |
| + |
| +TEST(KeyRewriterTest, TestRewriteModifiersNoRemapMultipleKeys) { |
| + XEvent xev; |
| + Display* display = ui::GetXDisplay(); |
| + |
| + const unsigned int kKeycodeSuperL = XKeysymToKeycode(display, XK_Super_L); |
| + const unsigned int kKeycodeMetaL = XKeysymToKeycode(display, XK_Meta_L); |
| + const unsigned int kKeycodeMetaR = XKeysymToKeycode(display, XK_Meta_R); |
| + const unsigned int kKeycodeA = XKeysymToKeycode(display, XK_A); |
| + |
| + TestingPrefService prefs; |
| + KeyRewriter rewriter; |
| + rewriter.set_pref_service_for_testing(&prefs); |
| + { |
| + // Press left Alt with Shift. |
| + InitXKeyEvent(ui::VKEY_MENU, ui::EF_SHIFT_DOWN, |
| + kKeycodeMetaL, ShiftMask, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is not rewritten. |
| + EXPECT_EQ(ui::VKEY_MENU, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_SHIFT_DOWN, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeMetaL, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(ShiftMask), xkey.state); |
| + } |
| + { |
| + // Press right Alt with Shift. |
| + InitXKeyEvent(ui::VKEY_MENU, ui::EF_SHIFT_DOWN, |
| + kKeycodeMetaR, ShiftMask, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is not rewritten. |
| + EXPECT_EQ(ui::VKEY_MENU, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_SHIFT_DOWN, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeMetaR, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(ShiftMask), xkey.state); |
| + } |
| + { |
| + // Press Search with Caps Lock mask. |
| + InitXKeyEvent(ui::VKEY_LWIN, ui::EF_CAPS_LOCK_DOWN, |
| + kKeycodeSuperL, LockMask, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is not rewritten. |
| + EXPECT_EQ(ui::VKEY_LWIN, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_CAPS_LOCK_DOWN, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeSuperL, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(LockMask), xkey.state); |
| + } |
| + { |
| + // Release Search with Caps Lock mask. |
| + InitXKeyEvent(ui::VKEY_LWIN, ui::EF_CAPS_LOCK_DOWN, |
| + kKeycodeSuperL, LockMask | Mod4Mask, &xev); |
| + xev.type = KeyRelease; |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is not rewritten. |
| + EXPECT_EQ(ui::VKEY_LWIN, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_CAPS_LOCK_DOWN, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeSuperL, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(LockMask | Mod4Mask), xkey.state); |
| + } |
| + { |
| + // Press Shift+Ctrl+Alt+Search+A |
| + InitXKeyEvent(ui::VKEY_A, |
| + ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, |
| + kKeycodeA, |
| + ShiftMask | ControlMask | Mod1Mask | Mod4Mask, |
| + &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is not rewritten. |
| + EXPECT_EQ(ui::VKEY_A, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, |
| + keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeA, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>( |
| + ShiftMask | ControlMask | Mod1Mask | Mod4Mask), xkey.state); |
| + } |
| +} |
| + |
| +TEST(KeyRewriterTest, TestRewriteModifiersDisableSome) { |
| + XEvent xev; |
| + Display* display = ui::GetXDisplay(); |
| + |
| + const unsigned int kKeycodeSuperL = XKeysymToKeycode(display, XK_Super_L); |
|
Daniel Erat
2012/05/23 16:37:32
nit: KeyCode (also for other unsigned ints in this
Yusuke Sato
2012/05/24 08:24:42
Done.
|
| + const unsigned int kKeycodeControlL = XKeysymToKeycode(display, XK_Control_L); |
| + const unsigned int kKeycodeMetaL = XKeysymToKeycode(display, XK_Meta_L); |
| + const unsigned int kKeycodeVoidSymbol = |
| + XKeysymToKeycode(display, XK_VoidSymbol); |
| + const unsigned int kKeycodeA = XKeysymToKeycode(display, XK_a); |
| + |
| + // Disable Search and Control keys. |
| + TestingPrefService prefs; |
| + chromeos::Preferences::RegisterUserPrefs(&prefs); |
| + IntegerPrefMember search; |
| + search.Init(prefs::kLanguageXkbRemapSearchKeyTo, &prefs, NULL); |
| + search.SetValue(chromeos::input_method::kVoidKey); |
| + IntegerPrefMember control; |
| + control.Init(prefs::kLanguageXkbRemapControlKeyTo, &prefs, NULL); |
| + control.SetValue(chromeos::input_method::kVoidKey); |
| + |
| + KeyRewriter rewriter; |
| + rewriter.set_pref_service_for_testing(&prefs); |
| + { |
| + // Press left Alt with Shift. This key press shouldn't be affected by the |
| + // pref. |
| + InitXKeyEvent(ui::VKEY_MENU, ui::EF_SHIFT_DOWN, |
| + kKeycodeMetaL, ShiftMask, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is not rewritten. |
| + EXPECT_EQ(ui::VKEY_MENU, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_SHIFT_DOWN, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeMetaL, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(ShiftMask), xkey.state); |
| + } |
| + { |
| + // Press Search. |
| + InitXKeyEvent(ui::VKEY_LWIN, 0, kKeycodeSuperL, 0U, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now VKEY_UNKNOWN + XK_VoidSymbol. |
| + EXPECT_EQ(ui::VKEY_UNKNOWN, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeVoidSymbol, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + } |
| + { |
| + // Press Control. |
| + InitXKeyEvent(ui::VKEY_CONTROL, 0, kKeycodeControlL, 0U, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now VKEY_UNKNOWN + XK_VoidSymbol. |
| + EXPECT_EQ(ui::VKEY_UNKNOWN, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeVoidSymbol, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + } |
| + { |
| + // Press Control+Search. |
| + InitXKeyEvent(ui::VKEY_LWIN, ui::EF_CONTROL_DOWN, |
| + kKeycodeSuperL, ControlMask, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now VKEY_UNKNOWN + XK_VoidSymbol without any |
| + // modifiers. |
| + EXPECT_EQ(ui::VKEY_UNKNOWN, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeVoidSymbol, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + } |
| + { |
| + // Press Control+Search+a. |
| + InitXKeyEvent(ui::VKEY_A, ui::EF_CONTROL_DOWN, |
| + kKeycodeA, ControlMask | Mod4Mask, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now VKEY_A without any modifiers. |
| + EXPECT_EQ(ui::VKEY_A, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeA, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + } |
| + { |
| + // Press Control+Search+Alt+a. |
| + InitXKeyEvent(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, |
| + kKeycodeA, ControlMask | Mod1Mask | Mod4Mask, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now VKEY_A only with the Alt modifier. |
| + EXPECT_EQ(ui::VKEY_A, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_ALT_DOWN, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeA, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(Mod1Mask), xkey.state); |
| + } |
| + |
| + |
| + const unsigned int kKeycodeAltL = XKeysymToKeycode(display, XK_Alt_L); |
| + const unsigned int kKeycodeB = XKeysymToKeycode(display, XK_b); |
| + |
| + // Remap Alt to Control. |
| + IntegerPrefMember alt; |
| + alt.Init(prefs::kLanguageXkbRemapAltKeyTo, &prefs, NULL); |
| + alt.SetValue(chromeos::input_method::kControlKey); |
| + { |
| + // Press left Alt. |
| + InitXKeyEvent(ui::VKEY_MENU, 0, kKeycodeAltL, 0U, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now VKEY_CONTROL + XK_Control_L even though the |
| + // Control key itself is disabled. |
| + EXPECT_EQ(ui::VKEY_CONTROL, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeControlL, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + } |
| + { |
| + // Press Alt+b. |
| + InitXKeyEvent(ui::VKEY_B, ui::EF_ALT_DOWN, kKeycodeB, Mod1Mask, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now Control+b even though the Control key itself is |
| + // disabled. |
| + EXPECT_EQ(ui::VKEY_B, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_CONTROL_DOWN, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeB, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(ControlMask), xkey.state); |
| + } |
| +} |
| + |
| +TEST(KeyRewriterTest, TestRewriteModifiersRemapToControl) { |
| + XEvent xev; |
| + Display* display = ui::GetXDisplay(); |
| + |
| + const unsigned int kKeycodeSuperL = XKeysymToKeycode(display, XK_Super_L); |
| + const unsigned int kKeycodeControlL = XKeysymToKeycode(display, XK_Control_L); |
| + const unsigned int kKeycodeControlR = XKeysymToKeycode(display, XK_Control_R); |
| + const unsigned int kKeycodeAltL = XKeysymToKeycode(display, XK_Alt_L); |
| + const unsigned int kKeycodeAltR = XKeysymToKeycode(display, XK_Alt_R); |
| + const unsigned int kKeycodeA = XKeysymToKeycode(display, XK_A); |
| + |
| + // Remap Search to Control. |
| + TestingPrefService prefs; |
| + chromeos::Preferences::RegisterUserPrefs(&prefs); |
| + IntegerPrefMember search; |
| + search.Init(prefs::kLanguageXkbRemapSearchKeyTo, &prefs, NULL); |
| + search.SetValue(chromeos::input_method::kControlKey); |
| + |
| + KeyRewriter rewriter; |
| + rewriter.set_pref_service_for_testing(&prefs); |
| + { |
| + // Press Search. |
| + InitXKeyEvent(ui::VKEY_LWIN, 0, kKeycodeSuperL, 0U, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now VKEY_CONTROL + XK_Control_L. |
| + EXPECT_EQ(ui::VKEY_CONTROL, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeControlL, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + } |
| + |
| + // Remap Alt to Control too. |
| + IntegerPrefMember alt; |
| + alt.Init(prefs::kLanguageXkbRemapAltKeyTo, &prefs, NULL); |
| + alt.SetValue(chromeos::input_method::kControlKey); |
| + { |
| + // Press left Alt. |
| + InitXKeyEvent(ui::VKEY_MENU, 0, kKeycodeAltL, 0U, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now VKEY_CONTROL + XK_Control_L. |
| + EXPECT_EQ(ui::VKEY_CONTROL, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeControlL, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + } |
| + { |
| + // Press right Alt. |
| + InitXKeyEvent(ui::VKEY_MENU, 0, kKeycodeAltR, 0U, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now VKEY_CONTROL + XK_Control_R. |
| + EXPECT_EQ(ui::VKEY_CONTROL, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeControlR, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + } |
| + { |
| + // Press Alt+Search. |
| + InitXKeyEvent(ui::VKEY_LWIN, ui::EF_ALT_DOWN, |
| + kKeycodeSuperL, Mod1Mask, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now VKEY_CONTROL + XK_Control_L. |
| + EXPECT_EQ(ui::VKEY_CONTROL, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_CONTROL_DOWN, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeControlL, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(ControlMask), xkey.state); |
| + } |
| + { |
| + // Press Control+Alt+Search. |
| + InitXKeyEvent(ui::VKEY_LWIN, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, |
| + kKeycodeSuperL, ControlMask | Mod1Mask, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now VKEY_CONTROL + XK_Control_L. |
| + EXPECT_EQ(ui::VKEY_CONTROL, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_CONTROL_DOWN, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeControlL, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(ControlMask), xkey.state); |
| + } |
| + { |
| + // Press Shift+Control+Alt+Search. |
| + InitXKeyEvent(ui::VKEY_LWIN, |
| + ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, |
| + kKeycodeSuperL, ShiftMask | ControlMask | Mod1Mask, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now Control with Shift and Control modifiers. |
| + EXPECT_EQ(ui::VKEY_CONTROL, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeControlL, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(ShiftMask | ControlMask), xkey.state); |
| + } |
| + { |
| + // Press Shift+Control+Alt+Search+A |
| + InitXKeyEvent(ui::VKEY_A, |
| + ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, |
| + kKeycodeA, ShiftMask | ControlMask | Mod1Mask, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now A with Shift and Control modifiers. |
| + EXPECT_EQ(ui::VKEY_A, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeA, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(ShiftMask | ControlMask), xkey.state); |
| + } |
| +} |
| + |
| +TEST(KeyRewriterTest, TestRewriteModifiersRemapMany) { |
| + XEvent xev; |
| + Display* display = ui::GetXDisplay(); |
| + |
| + const unsigned int kKeycodeSuperL = XKeysymToKeycode(display, XK_Super_L); |
| + const unsigned int kKeycodeControlL = XKeysymToKeycode(display, XK_Control_L); |
| + const unsigned int kKeycodeAltL = XKeysymToKeycode(display, XK_Alt_L); |
| + const unsigned int kKeycodeMetaL = XKeysymToKeycode(display, XK_Meta_L); |
| + const unsigned int kKeycodeA = XKeysymToKeycode(display, XK_A); |
| + |
| + // Remap Search to Alt. |
| + TestingPrefService prefs; |
| + chromeos::Preferences::RegisterUserPrefs(&prefs); |
| + IntegerPrefMember search; |
| + search.Init(prefs::kLanguageXkbRemapSearchKeyTo, &prefs, NULL); |
| + search.SetValue(chromeos::input_method::kAltKey); |
| + |
| + KeyRewriter rewriter; |
| + rewriter.set_pref_service_for_testing(&prefs); |
| + { |
| + // Press Search. |
| + InitXKeyEvent(ui::VKEY_LWIN, 0, kKeycodeSuperL, 0U, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now VKEY_MENU + XK_Alt_L. |
| + EXPECT_EQ(ui::VKEY_MENU, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeAltL, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + } |
| + |
| + // Remap Alt to Control. |
| + IntegerPrefMember alt; |
| + alt.Init(prefs::kLanguageXkbRemapAltKeyTo, &prefs, NULL); |
| + alt.SetValue(chromeos::input_method::kControlKey); |
| + { |
| + // Press left Alt. |
| + InitXKeyEvent(ui::VKEY_MENU, 0, kKeycodeAltL, 0U, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now VKEY_CONTROL + XK_Control_L. |
| + EXPECT_EQ(ui::VKEY_CONTROL, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeControlL, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + } |
| + |
| + // Remap Control to Search. |
| + IntegerPrefMember control; |
| + control.Init(prefs::kLanguageXkbRemapControlKeyTo, &prefs, NULL); |
| + control.SetValue(chromeos::input_method::kSearchKey); |
| + { |
| + // Press left Control. |
| + InitXKeyEvent(ui::VKEY_CONTROL, 0, kKeycodeControlL, 0U, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is now VKEY_LWIN. |
| + EXPECT_EQ(ui::VKEY_LWIN, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeSuperL, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + } |
| + |
| + // Then, press all of the three. |
| + { |
| + // Press Control+Alt+Search. |
| + InitXKeyEvent(ui::VKEY_LWIN, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, |
| + kKeycodeSuperL, ControlMask | Mod1Mask, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + // Confirm the event is unchanged. |
| + EXPECT_EQ(ui::VKEY_MENU, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_CONTROL_DOWN, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeAltL, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(ControlMask | Mod4Mask), xkey.state); |
| + } |
| + { |
| + // Press Shift+Control+Alt+Search. |
| + InitXKeyEvent(ui::VKEY_LWIN, |
| + ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, |
| + kKeycodeSuperL, ShiftMask | ControlMask | Mod1Mask, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + EXPECT_EQ(ui::VKEY_MENU, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeMetaL, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(ShiftMask | ControlMask | Mod4Mask), |
| + xkey.state); |
| + } |
| + { |
| + // Press Shift+Control+Alt+Search+A |
| + InitXKeyEvent(ui::VKEY_A, |
| + ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, |
| + kKeycodeA, ShiftMask | ControlMask | Mod1Mask | Mod4Mask, |
| + &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + EXPECT_EQ(ui::VKEY_A, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, |
| + keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeA, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>( |
| + ShiftMask | ControlMask | Mod1Mask | Mod4Mask), xkey.state); |
| + } |
| +} |
| + |
| +TEST(KeyRewriterTest, TestRewriteModifiersRemapToCapsLock) { |
| + XEvent xev; |
| + Display* display = ui::GetXDisplay(); |
| + |
| + const unsigned int kKeycodeSuperL = XKeysymToKeycode(display, XK_Super_L); |
| + const unsigned int kKeycodeCapsLock = XKeysymToKeycode(display, XK_Caps_Lock); |
| + |
| + // Remap Search to Caps Lock. |
| + TestingPrefService prefs; |
| + chromeos::Preferences::RegisterUserPrefs(&prefs); |
| + IntegerPrefMember search; |
| + search.Init(prefs::kLanguageXkbRemapSearchKeyTo, &prefs, NULL); |
| + search.SetValue(chromeos::input_method::kCapsLockKey); |
| + |
| + chromeos::input_method::MockXKeyboard xkeyboard; |
| + KeyRewriter rewriter; |
| + rewriter.set_pref_service_for_testing(&prefs); |
| + rewriter.set_xkeyboard_for_testing(&xkeyboard); |
| + EXPECT_FALSE(xkeyboard.caps_lock_is_enabled_); |
| + { |
| + // Press Search. |
| + InitXKeyEvent(ui::VKEY_LWIN, 0, kKeycodeSuperL, 0U, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + EXPECT_EQ(ui::VKEY_CAPITAL, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeCapsLock, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + // Confirm that the Caps Lock status is changed. |
| + EXPECT_TRUE(xkeyboard.caps_lock_is_enabled_); |
| + } |
| + { |
| + // Release Search. |
| + InitXKeyEvent(ui::VKEY_LWIN, ui::EF_CAPS_LOCK_DOWN, |
| + kKeycodeSuperL, Mod4Mask | LockMask, &xev); |
| + xev.type = KeyRelease; |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + EXPECT_EQ(ui::VKEY_CAPITAL, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_CAPS_LOCK_DOWN, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeCapsLock, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(LockMask), xkey.state); |
| + // Confirm that the Caps Lock status is not changed. |
| + EXPECT_TRUE(xkeyboard.caps_lock_is_enabled_); |
| + } |
| + { |
| + // Press Search. |
| + InitXKeyEvent(ui::VKEY_LWIN, 0, kKeycodeSuperL, 0U, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + EXPECT_EQ(ui::VKEY_CAPITAL, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeCapsLock, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + // Confirm that the Caps Lock status is changed. |
| + EXPECT_FALSE(xkeyboard.caps_lock_is_enabled_); |
| + } |
| + { |
| + // Release Search. |
| + InitXKeyEvent(ui::VKEY_LWIN, ui::EF_CAPS_LOCK_DOWN, |
| + kKeycodeSuperL, Mod4Mask | LockMask, &xev); |
| + xev.type = KeyRelease; |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + EXPECT_EQ(ui::VKEY_CAPITAL, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_CAPS_LOCK_DOWN, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeCapsLock, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(LockMask), xkey.state); |
| + // Confirm that the Caps Lock status is not changed. |
| + EXPECT_FALSE(xkeyboard.caps_lock_is_enabled_); |
| + } |
| + { |
| + // Press Caps Lock (on an external keyboard). |
| + InitXKeyEvent(ui::VKEY_CAPITAL, 0, kKeycodeCapsLock, 0U, &xev); |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + EXPECT_EQ(ui::VKEY_CAPITAL, keyevent.key_code()); |
| + EXPECT_EQ(0, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeCapsLock, xkey.keycode); |
| + EXPECT_EQ(0U, xkey.state); |
| + // Confirm that calling RewriteForTesting() does not change the state of |
| + // |xkeyboard|. In this case, X Window system itself should change the |
| + // Caps Lock state, not ash::KeyRewriter. |
| + EXPECT_FALSE(xkeyboard.caps_lock_is_enabled_); |
| + } |
| + { |
| + // Press Caps Lock (on an external keyboard). |
| + InitXKeyEvent(ui::VKEY_CAPITAL, ui::EF_CAPS_LOCK_DOWN, |
| + kKeycodeCapsLock, LockMask, &xev); |
| + xev.type = KeyRelease; |
| + aura::KeyEvent keyevent(&xev, false /* is_char */); |
| + rewriter.RewriteForTesting(&keyevent); |
| + EXPECT_EQ(ui::VKEY_CAPITAL, keyevent.key_code()); |
| + EXPECT_EQ(ui::EF_CAPS_LOCK_DOWN, keyevent.flags()); |
| + const XKeyEvent& xkey = keyevent.native_event()->xkey; |
| + EXPECT_EQ(kKeycodeCapsLock, xkey.keycode); |
| + EXPECT_EQ(static_cast<unsigned int>(LockMask), xkey.state); |
| + EXPECT_FALSE(xkeyboard.caps_lock_is_enabled_); |
| + } |
| +} |
| #endif // OS_CHROMEOS |