| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/events/ozone/evdev/keyboard_evdev.h" |
| |
| #include "ui/events/event.h" |
| #include "ui/events/keycodes/dom4/keycode_converter.h" |
| #include "ui/events/ozone/evdev/event_modifiers_evdev.h" |
| |
| namespace ui { |
| |
| namespace { |
| |
| const int kXkbKeycodeOffset = 8; |
| |
| ui::KeyboardCode KeyboardCodeFromEvdevKey(unsigned int code) { |
| static const ui::KeyboardCode kLinuxBaseKeyMap[] = { |
| ui::VKEY_UNKNOWN, // KEY_RESERVED |
| ui::VKEY_ESCAPE, // KEY_ESC |
| ui::VKEY_1, // KEY_1 |
| ui::VKEY_2, // KEY_2 |
| ui::VKEY_3, // KEY_3 |
| ui::VKEY_4, // KEY_4 |
| ui::VKEY_5, // KEY_5 |
| ui::VKEY_6, // KEY_6 |
| ui::VKEY_7, // KEY_7 |
| ui::VKEY_8, // KEY_8 |
| ui::VKEY_9, // KEY_9 |
| ui::VKEY_0, // KEY_0 |
| ui::VKEY_OEM_MINUS, // KEY_MINUS |
| ui::VKEY_OEM_PLUS, // KEY_EQUAL |
| ui::VKEY_BACK, // KEY_BACKSPACE |
| ui::VKEY_TAB, // KEY_TAB |
| ui::VKEY_Q, // KEY_Q |
| ui::VKEY_W, // KEY_W |
| ui::VKEY_E, // KEY_E |
| ui::VKEY_R, // KEY_R |
| ui::VKEY_T, // KEY_T |
| ui::VKEY_Y, // KEY_Y |
| ui::VKEY_U, // KEY_U |
| ui::VKEY_I, // KEY_I |
| ui::VKEY_O, // KEY_O |
| ui::VKEY_P, // KEY_P |
| ui::VKEY_OEM_4, // KEY_LEFTBRACE |
| ui::VKEY_OEM_6, // KEY_RIGHTBRACE |
| ui::VKEY_RETURN, // KEY_ENTER |
| ui::VKEY_CONTROL, // KEY_LEFTCTRL |
| ui::VKEY_A, // KEY_A |
| ui::VKEY_S, // KEY_S |
| ui::VKEY_D, // KEY_D |
| ui::VKEY_F, // KEY_F |
| ui::VKEY_G, // KEY_G |
| ui::VKEY_H, // KEY_H |
| ui::VKEY_J, // KEY_J |
| ui::VKEY_K, // KEY_K |
| ui::VKEY_L, // KEY_L |
| ui::VKEY_OEM_1, // KEY_SEMICOLON |
| ui::VKEY_OEM_7, // KEY_APOSTROPHE |
| ui::VKEY_OEM_3, // KEY_GRAVE |
| ui::VKEY_SHIFT, // KEY_LEFTSHIFT |
| ui::VKEY_OEM_5, // KEY_BACKSLASH |
| ui::VKEY_Z, // KEY_Z |
| ui::VKEY_X, // KEY_X |
| ui::VKEY_C, // KEY_C |
| ui::VKEY_V, // KEY_V |
| ui::VKEY_B, // KEY_B |
| ui::VKEY_N, // KEY_N |
| ui::VKEY_M, // KEY_M |
| ui::VKEY_OEM_COMMA, // KEY_COMMA |
| ui::VKEY_OEM_PERIOD, // KEY_DOT |
| ui::VKEY_OEM_2, // KEY_SLASH |
| ui::VKEY_SHIFT, // KEY_RIGHTSHIFT |
| ui::VKEY_MULTIPLY, // KEY_KPASTERISK |
| ui::VKEY_MENU, // KEY_LEFTALT |
| ui::VKEY_SPACE, // KEY_SPACE |
| ui::VKEY_CAPITAL, // KEY_CAPSLOCK |
| ui::VKEY_F1, // KEY_F1 |
| ui::VKEY_F2, // KEY_F2 |
| ui::VKEY_F3, // KEY_F3 |
| ui::VKEY_F4, // KEY_F4 |
| ui::VKEY_F5, // KEY_F5 |
| ui::VKEY_F6, // KEY_F6 |
| ui::VKEY_F7, // KEY_F7 |
| ui::VKEY_F8, // KEY_F8 |
| ui::VKEY_F9, // KEY_F9 |
| ui::VKEY_F10, // KEY_F10 |
| ui::VKEY_NUMLOCK, // KEY_NUMLOCK |
| ui::VKEY_SCROLL, // KEY_SCROLLLOCK |
| ui::VKEY_NUMPAD7, // KEY_KP7 |
| ui::VKEY_NUMPAD8, // KEY_KP8 |
| ui::VKEY_NUMPAD9, // KEY_KP9 |
| ui::VKEY_SUBTRACT, // KEY_KPMINUS |
| ui::VKEY_NUMPAD4, // KEY_KP4 |
| ui::VKEY_NUMPAD5, // KEY_KP5 |
| ui::VKEY_NUMPAD6, // KEY_KP6 |
| ui::VKEY_ADD, // KEY_KPPLUS |
| ui::VKEY_NUMPAD1, // KEY_KP1 |
| ui::VKEY_NUMPAD2, // KEY_KP2 |
| ui::VKEY_NUMPAD3, // KEY_KP3 |
| ui::VKEY_NUMPAD0, // KEY_KP0 |
| ui::VKEY_DECIMAL, // KEY_KPDOT |
| ui::VKEY_UNKNOWN, // (unassigned) |
| ui::VKEY_DBE_DBCSCHAR, // KEY_ZENKAKUHANKAKU |
| ui::VKEY_OEM_102, // KEY_102ND |
| ui::VKEY_F11, // KEY_F11 |
| ui::VKEY_F12, // KEY_F12 |
| ui::VKEY_UNKNOWN, // KEY_RO |
| ui::VKEY_UNKNOWN, // KEY_KATAKANA |
| ui::VKEY_UNKNOWN, // KEY_HIRAGANA |
| ui::VKEY_CONVERT, // KEY_HENKAN |
| ui::VKEY_UNKNOWN, // KEY_KATAKANAHIRAGANA |
| ui::VKEY_NONCONVERT, // KEY_MUHENKAN |
| ui::VKEY_UNKNOWN, // KEY_KPJPCOMMA |
| ui::VKEY_RETURN, // KEY_KPENTER |
| ui::VKEY_CONTROL, // KEY_RIGHTCTRL |
| ui::VKEY_DIVIDE, // KEY_KPSLASH |
| ui::VKEY_PRINT, // KEY_SYSRQ |
| ui::VKEY_MENU, // KEY_RIGHTALT |
| ui::VKEY_RETURN, // KEY_LINEFEED |
| ui::VKEY_HOME, // KEY_HOME |
| ui::VKEY_UP, // KEY_UP |
| ui::VKEY_PRIOR, // KEY_PAGEUP |
| ui::VKEY_LEFT, // KEY_LEFT |
| ui::VKEY_RIGHT, // KEY_RIGHT |
| ui::VKEY_END, // KEY_END |
| ui::VKEY_DOWN, // KEY_DOWN |
| ui::VKEY_NEXT, // KEY_PAGEDOWN |
| ui::VKEY_INSERT, // KEY_INSERT |
| ui::VKEY_DELETE, // KEY_DELETE |
| ui::VKEY_UNKNOWN, // KEY_MACRO |
| ui::VKEY_VOLUME_MUTE, // KEY_MUTE |
| ui::VKEY_VOLUME_DOWN, // KEY_VOLUMEDOWN |
| ui::VKEY_VOLUME_UP, // KEY_VOLUMEUP |
| ui::VKEY_POWER, // KEY_POWER |
| ui::VKEY_OEM_PLUS, // KEY_KPEQUAL |
| ui::VKEY_UNKNOWN, // KEY_KPPLUSMINUS |
| ui::VKEY_PAUSE, // KEY_PAUSE |
| ui::VKEY_MEDIA_LAUNCH_APP1, // KEY_SCALE |
| ui::VKEY_DECIMAL, // KEY_KPCOMMA |
| ui::VKEY_HANGUL, // KEY_HANGEUL |
| ui::VKEY_HANJA, // KEY_HANJA |
| ui::VKEY_UNKNOWN, // KEY_YEN |
| ui::VKEY_LWIN, // KEY_LEFTMETA |
| ui::VKEY_RWIN, // KEY_RIGHTMETA |
| ui::VKEY_APPS, // KEY_COMPOSE |
| }; |
| |
| if (code < arraysize(kLinuxBaseKeyMap)) |
| return kLinuxBaseKeyMap[code]; |
| |
| LOG(ERROR) << "Unknown key code: " << code; |
| return ui::VKEY_UNKNOWN; |
| } |
| |
| int ModifierFromEvdevKey(unsigned int code) { |
| switch (code) { |
| case KEY_CAPSLOCK: |
| return EVDEV_MODIFIER_CAPS_LOCK; |
| case KEY_LEFTSHIFT: |
| case KEY_RIGHTSHIFT: |
| return EVDEV_MODIFIER_SHIFT; |
| case KEY_LEFTCTRL: |
| case KEY_RIGHTCTRL: |
| return EVDEV_MODIFIER_CONTROL; |
| case KEY_LEFTALT: |
| case KEY_RIGHTALT: |
| return EVDEV_MODIFIER_ALT; |
| case BTN_LEFT: |
| return EVDEV_MODIFIER_LEFT_MOUSE_BUTTON; |
| case BTN_MIDDLE: |
| return EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON; |
| case BTN_RIGHT: |
| return EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON; |
| case KEY_LEFTMETA: |
| case KEY_RIGHTMETA: |
| return EVDEV_MODIFIER_COMMAND; |
| default: |
| return EVDEV_MODIFIER_NONE; |
| } |
| } |
| |
| bool IsModifierLockKeyFromEvdevKey(unsigned int code) { |
| return code == KEY_CAPSLOCK; |
| } |
| |
| } // namespace |
| |
| KeyboardEvdev::KeyboardEvdev(EventModifiersEvdev* modifiers, |
| const EventDispatchCallback& callback) |
| : callback_(callback), modifiers_(modifiers) { |
| } |
| |
| KeyboardEvdev::~KeyboardEvdev() { |
| } |
| |
| void KeyboardEvdev::OnKeyChange(unsigned int key, bool down) { |
| if (key > KEY_MAX) |
| return; |
| |
| if (down != key_state_.test(key)) { |
| // State transition: !(down) -> (down) |
| if (down) |
| key_state_.set(key); |
| else |
| key_state_.reset(key); |
| |
| UpdateModifier(key, down); |
| } |
| |
| DispatchKey(key, down); |
| } |
| |
| void KeyboardEvdev::UpdateModifier(unsigned int key, bool down) { |
| int modifier = ModifierFromEvdevKey(key); |
| int locking = IsModifierLockKeyFromEvdevKey(key); |
| |
| if (modifier == EVDEV_MODIFIER_NONE) |
| return; |
| |
| if (locking) |
| modifiers_->UpdateModifierLock(modifier, down); |
| else |
| modifiers_->UpdateModifier(modifier, down); |
| } |
| |
| void KeyboardEvdev::DispatchKey(unsigned int key, bool down) { |
| ui::KeyboardCode code = KeyboardCodeFromEvdevKey(key); |
| int flags = modifiers_->GetModifierFlags(); |
| |
| if (code == VKEY_UNKNOWN) |
| return; |
| |
| callback_.Run(make_scoped_ptr(new KeyEvent( |
| down ? ET_KEY_PRESSED : ET_KEY_RELEASED, |
| code, |
| KeycodeConverter::NativeKeycodeToCode(key + kXkbKeycodeOffset), |
| flags))); |
| } |
| |
| } // namespace ui |