Home | History | Annotate | Download | only in chromeos
      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