1 // Copyright 2013 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. 4 5 #include "base/basictypes.h" 6 #include "base/compiler_specific.h" 7 #include "base/strings/stringprintf.h" 8 #include "chrome/browser/chromeos/keyboard_driven_event_rewriter.h" 9 #include "testing/gtest/include/gtest/gtest.h" 10 #include "ui/base/events/event.h" 11 #include "ui/base/x/x11_util.h" 12 13 #include <X11/keysym.h> 14 #include <X11/XF86keysym.h> 15 #include <X11/Xlib.h> 16 17 namespace chromeos { 18 19 // Creates an XKeyEvent to initialize a ui::KeyEvent that is passed to 20 // KeyboardDrivenEventRewriter for processing. 21 void InitXKeyEvent(ui::KeyboardCode ui_keycode, 22 int ui_flags, 23 ui::EventType ui_type, 24 KeyCode x_keycode, 25 unsigned int x_state, 26 XEvent* event) { 27 ui::InitXKeyEventForTesting(ui_type, 28 ui_keycode, 29 ui_flags, 30 event); 31 event->xkey.keycode = x_keycode; 32 event->xkey.state = x_state; 33 } 34 35 class KeyboardDrivenEventRewriterTest : public testing::Test { 36 public: 37 KeyboardDrivenEventRewriterTest() 38 : display_(ui::GetXDisplay()), 39 keycode_a_(XKeysymToKeycode(display_, XK_a)), 40 keycode_up_(XKeysymToKeycode(display_, XK_Up)), 41 keycode_down_(XKeysymToKeycode(display_, XK_Down)), 42 keycode_left_(XKeysymToKeycode(display_, XK_Left)), 43 keycode_right_(XKeysymToKeycode(display_, XK_Right)), 44 keycode_return_(XKeysymToKeycode(display_, XK_Return)) { 45 } 46 47 virtual ~KeyboardDrivenEventRewriterTest() {} 48 49 protected: 50 std::string GetRewrittenEventAsString(ui::KeyboardCode ui_keycode, 51 int ui_flags, 52 ui::EventType ui_type, 53 KeyCode x_keycode, 54 unsigned int x_state) { 55 XEvent xev; 56 InitXKeyEvent(ui_keycode, ui_flags, ui_type, x_keycode, x_state, &xev); 57 ui::KeyEvent keyevent(&xev, false /* is_char */); 58 rewriter_.RewriteForTesting(&keyevent); 59 return base::StringPrintf( 60 "ui_flags=%d x_state=%u", keyevent.flags(), xev.xkey.state); 61 } 62 63 std::string GetExpectedResultAsString(int ui_flags, unsigned int x_state) { 64 return base::StringPrintf("ui_flags=%d x_state=%u", ui_flags, x_state); 65 } 66 67 Display* display_; 68 const KeyCode keycode_a_; 69 const KeyCode keycode_up_; 70 const KeyCode keycode_down_; 71 const KeyCode keycode_left_; 72 const KeyCode keycode_right_; 73 const KeyCode keycode_return_; 74 75 KeyboardDrivenEventRewriter rewriter_; 76 77 private: 78 DISALLOW_COPY_AND_ASSIGN(KeyboardDrivenEventRewriterTest); 79 }; 80 81 TEST_F(KeyboardDrivenEventRewriterTest, PassThrough) { 82 struct { 83 ui::KeyboardCode ui_keycode; 84 int ui_flags; 85 KeyCode x_keycode; 86 unsigned int x_state; 87 } kTests[] = { 88 { ui::VKEY_A, ui::EF_NONE, keycode_a_, 0 }, 89 { ui::VKEY_A, ui::EF_CONTROL_DOWN, keycode_a_, ControlMask }, 90 { ui::VKEY_A, ui::EF_ALT_DOWN, keycode_a_, Mod1Mask }, 91 { ui::VKEY_A, ui::EF_SHIFT_DOWN, keycode_a_, ShiftMask }, 92 { ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, 93 keycode_a_, ControlMask | Mod1Mask }, 94 { ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN, 95 keycode_a_, ControlMask | Mod1Mask | ShiftMask }, 96 97 { ui::VKEY_LEFT, ui::EF_NONE, keycode_left_, 0 }, 98 { ui::VKEY_LEFT, ui::EF_CONTROL_DOWN, keycode_left_, ControlMask }, 99 { ui::VKEY_LEFT, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, 100 keycode_left_, ControlMask | Mod1Mask }, 101 102 { ui::VKEY_RIGHT, ui::EF_NONE, keycode_right_, 0 }, 103 { ui::VKEY_RIGHT, ui::EF_CONTROL_DOWN, keycode_right_, ControlMask }, 104 { ui::VKEY_RIGHT, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, 105 keycode_right_, ControlMask | Mod1Mask }, 106 107 { ui::VKEY_UP, ui::EF_NONE, keycode_up_, 0 }, 108 { ui::VKEY_UP, ui::EF_CONTROL_DOWN, keycode_up_, ControlMask }, 109 { ui::VKEY_UP, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, 110 keycode_up_, ControlMask | Mod1Mask }, 111 112 { ui::VKEY_DOWN, ui::EF_NONE, keycode_down_, 0 }, 113 { ui::VKEY_DOWN, ui::EF_CONTROL_DOWN, keycode_down_, ControlMask }, 114 { ui::VKEY_DOWN, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, 115 keycode_down_, ControlMask | Mod1Mask }, 116 117 { ui::VKEY_RETURN, ui::EF_NONE, keycode_return_, 0 }, 118 { ui::VKEY_RETURN, ui::EF_CONTROL_DOWN, keycode_return_, ControlMask }, 119 { ui::VKEY_RETURN, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, 120 keycode_return_, ControlMask | Mod1Mask }, 121 }; 122 123 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) { 124 EXPECT_EQ(GetExpectedResultAsString(kTests[i].ui_flags, 125 kTests[i].x_state), 126 GetRewrittenEventAsString(kTests[i].ui_keycode, 127 kTests[i].ui_flags, 128 ui::ET_KEY_PRESSED, 129 kTests[i].x_keycode, 130 kTests[i].x_state)) 131 << "Test case " << i; 132 } 133 } 134 135 TEST_F(KeyboardDrivenEventRewriterTest, Rewrite) { 136 const int kModifierMask = ui::EF_SHIFT_DOWN; 137 const unsigned int kXState = ShiftMask; 138 139 struct { 140 ui::KeyboardCode ui_keycode; 141 int ui_flags; 142 KeyCode x_keycode; 143 unsigned int x_state; 144 } kTests[] = { 145 { ui::VKEY_LEFT, kModifierMask, keycode_left_, kXState }, 146 { ui::VKEY_RIGHT, kModifierMask, keycode_right_, kXState }, 147 { ui::VKEY_UP, kModifierMask, keycode_up_, kXState }, 148 { ui::VKEY_DOWN, kModifierMask, keycode_down_, kXState }, 149 { ui::VKEY_RETURN, kModifierMask, keycode_return_, kXState }, 150 }; 151 152 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) { 153 EXPECT_EQ(GetExpectedResultAsString(ui::EF_NONE, 0), 154 GetRewrittenEventAsString(kTests[i].ui_keycode, 155 kTests[i].ui_flags, 156 ui::ET_KEY_PRESSED, 157 kTests[i].x_keycode, 158 kTests[i].x_state)) 159 << "Test case " << i; 160 } 161 } 162 163 } // namespace chromeos 164