Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ui / events / ozone / evdev / key_event_converter_evdev.cc
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.
4
5 #include "ui/events/ozone/evdev/key_event_converter_evdev.h"
6
7 #include <errno.h>
8 #include <linux/input.h>
9
10 #include "base/message_loop/message_loop.h"
11 #include "ui/events/event.h"
12 #include "ui/events/keycodes/keyboard_codes.h"
13 #include "ui/events/ozone/evdev/event_modifiers_evdev.h"
14 #include "ui/events/ozone/event_factory_ozone.h"
15
16 namespace ui {
17
18 namespace {
19
20 ui::KeyboardCode KeyboardCodeFromButton(unsigned int code) {
21   static const ui::KeyboardCode kLinuxBaseKeyMap[] = {
22       ui::VKEY_UNKNOWN,            // KEY_RESERVED
23       ui::VKEY_ESCAPE,             // KEY_ESC
24       ui::VKEY_1,                  // KEY_1
25       ui::VKEY_2,                  // KEY_2
26       ui::VKEY_3,                  // KEY_3
27       ui::VKEY_4,                  // KEY_4
28       ui::VKEY_5,                  // KEY_5
29       ui::VKEY_6,                  // KEY_6
30       ui::VKEY_7,                  // KEY_7
31       ui::VKEY_8,                  // KEY_8
32       ui::VKEY_9,                  // KEY_9
33       ui::VKEY_0,                  // KEY_0
34       ui::VKEY_OEM_MINUS,          // KEY_MINUS
35       ui::VKEY_OEM_PLUS,           // KEY_EQUAL
36       ui::VKEY_BACK,               // KEY_BACKSPACE
37       ui::VKEY_TAB,                // KEY_TAB
38       ui::VKEY_Q,                  // KEY_Q
39       ui::VKEY_W,                  // KEY_W
40       ui::VKEY_E,                  // KEY_E
41       ui::VKEY_R,                  // KEY_R
42       ui::VKEY_T,                  // KEY_T
43       ui::VKEY_Y,                  // KEY_Y
44       ui::VKEY_U,                  // KEY_U
45       ui::VKEY_I,                  // KEY_I
46       ui::VKEY_O,                  // KEY_O
47       ui::VKEY_P,                  // KEY_P
48       ui::VKEY_OEM_4,              // KEY_LEFTBRACE
49       ui::VKEY_OEM_6,              // KEY_RIGHTBRACE
50       ui::VKEY_RETURN,             // KEY_ENTER
51       ui::VKEY_CONTROL,            // KEY_LEFTCTRL
52       ui::VKEY_A,                  // KEY_A
53       ui::VKEY_S,                  // KEY_S
54       ui::VKEY_D,                  // KEY_D
55       ui::VKEY_F,                  // KEY_F
56       ui::VKEY_G,                  // KEY_G
57       ui::VKEY_H,                  // KEY_H
58       ui::VKEY_J,                  // KEY_J
59       ui::VKEY_K,                  // KEY_K
60       ui::VKEY_L,                  // KEY_L
61       ui::VKEY_OEM_1,              // KEY_SEMICOLON
62       ui::VKEY_OEM_7,              // KEY_APOSTROPHE
63       ui::VKEY_OEM_3,              // KEY_GRAVE
64       ui::VKEY_SHIFT,              // KEY_LEFTSHIFT
65       ui::VKEY_OEM_5,              // KEY_BACKSLASH
66       ui::VKEY_Z,                  // KEY_Z
67       ui::VKEY_X,                  // KEY_X
68       ui::VKEY_C,                  // KEY_C
69       ui::VKEY_V,                  // KEY_V
70       ui::VKEY_B,                  // KEY_B
71       ui::VKEY_N,                  // KEY_N
72       ui::VKEY_M,                  // KEY_M
73       ui::VKEY_OEM_COMMA,          // KEY_COMMA
74       ui::VKEY_OEM_PERIOD,         // KEY_DOT
75       ui::VKEY_OEM_2,              // KEY_SLASH
76       ui::VKEY_SHIFT,              // KEY_RIGHTSHIFT
77       ui::VKEY_MULTIPLY,           // KEY_KPASTERISK
78       ui::VKEY_MENU,               // KEY_LEFTALT
79       ui::VKEY_SPACE,              // KEY_SPACE
80       ui::VKEY_CAPITAL,            // KEY_CAPSLOCK
81       ui::VKEY_F1,                 // KEY_F1
82       ui::VKEY_F2,                 // KEY_F2
83       ui::VKEY_F3,                 // KEY_F3
84       ui::VKEY_F4,                 // KEY_F4
85       ui::VKEY_F5,                 // KEY_F5
86       ui::VKEY_F6,                 // KEY_F6
87       ui::VKEY_F7,                 // KEY_F7
88       ui::VKEY_F8,                 // KEY_F8
89       ui::VKEY_F9,                 // KEY_F9
90       ui::VKEY_F10,                // KEY_F10
91       ui::VKEY_NUMLOCK,            // KEY_NUMLOCK
92       ui::VKEY_SCROLL,             // KEY_SCROLLLOCK
93       ui::VKEY_NUMPAD7,            // KEY_KP7
94       ui::VKEY_NUMPAD8,            // KEY_KP8
95       ui::VKEY_NUMPAD9,            // KEY_KP9
96       ui::VKEY_SUBTRACT,           // KEY_KPMINUS
97       ui::VKEY_NUMPAD4,            // KEY_KP4
98       ui::VKEY_NUMPAD5,            // KEY_KP5
99       ui::VKEY_NUMPAD6,            // KEY_KP6
100       ui::VKEY_ADD,                // KEY_KPPLUS
101       ui::VKEY_NUMPAD1,            // KEY_KP1
102       ui::VKEY_NUMPAD2,            // KEY_KP2
103       ui::VKEY_NUMPAD3,            // KEY_KP3
104       ui::VKEY_NUMPAD0,            // KEY_KP0
105       ui::VKEY_DECIMAL,            // KEY_KPDOT
106       ui::VKEY_UNKNOWN,            // (unassigned)
107       ui::VKEY_DBE_DBCSCHAR,       // KEY_ZENKAKUHANKAKU
108       ui::VKEY_OEM_102,            // KEY_102ND
109       ui::VKEY_F11,                // KEY_F11
110       ui::VKEY_F12,                // KEY_F12
111       ui::VKEY_UNKNOWN,            // KEY_RO
112       ui::VKEY_UNKNOWN,            // KEY_KATAKANA
113       ui::VKEY_UNKNOWN,            // KEY_HIRAGANA
114       ui::VKEY_CONVERT,            // KEY_HENKAN
115       ui::VKEY_UNKNOWN,            // KEY_KATAKANAHIRAGANA
116       ui::VKEY_NONCONVERT,         // KEY_MUHENKAN
117       ui::VKEY_UNKNOWN,            // KEY_KPJPCOMMA
118       ui::VKEY_RETURN,             // KEY_KPENTER
119       ui::VKEY_CONTROL,            // KEY_RIGHTCTRL
120       ui::VKEY_DIVIDE,             // KEY_KPSLASH
121       ui::VKEY_PRINT,              // KEY_SYSRQ
122       ui::VKEY_MENU,               // KEY_RIGHTALT
123       ui::VKEY_RETURN,             // KEY_LINEFEED
124       ui::VKEY_HOME,               // KEY_HOME
125       ui::VKEY_UP,                 // KEY_UP
126       ui::VKEY_PRIOR,              // KEY_PAGEUP
127       ui::VKEY_LEFT,               // KEY_LEFT
128       ui::VKEY_RIGHT,              // KEY_RIGHT
129       ui::VKEY_END,                // KEY_END
130       ui::VKEY_DOWN,               // KEY_DOWN
131       ui::VKEY_NEXT,               // KEY_PAGEDOWN
132       ui::VKEY_INSERT,             // KEY_INSERT
133       ui::VKEY_DELETE,             // KEY_DELETE
134       ui::VKEY_UNKNOWN,            // KEY_MACRO
135       ui::VKEY_VOLUME_MUTE,        // KEY_MUTE
136       ui::VKEY_VOLUME_DOWN,        // KEY_VOLUMEDOWN
137       ui::VKEY_VOLUME_UP,          // KEY_VOLUMEUP
138       ui::VKEY_POWER,              // KEY_POWER
139       ui::VKEY_OEM_PLUS,           // KEY_KPEQUAL
140       ui::VKEY_UNKNOWN,            // KEY_KPPLUSMINUS
141       ui::VKEY_PAUSE,              // KEY_PAUSE
142       ui::VKEY_MEDIA_LAUNCH_APP1,  // KEY_SCALE
143       ui::VKEY_DECIMAL,            // KEY_KPCOMMA
144       ui::VKEY_HANGUL,             // KEY_HANGEUL
145       ui::VKEY_HANJA,              // KEY_HANJA
146       ui::VKEY_UNKNOWN,            // KEY_YEN
147       ui::VKEY_LWIN,               // KEY_LEFTMETA
148       ui::VKEY_RWIN,               // KEY_RIGHTMETA
149       ui::VKEY_APPS,               // KEY_COMPOSE
150   };
151
152   if (code < arraysize(kLinuxBaseKeyMap))
153     return kLinuxBaseKeyMap[code];
154
155   LOG(ERROR) << "Unknown key code: " << code;
156   return ui::VKEY_UNKNOWN;
157 }
158
159 int ModifierFromButton(unsigned int code) {
160   switch (code) {
161     case KEY_CAPSLOCK:
162       return EVDEV_MODIFIER_CAPS_LOCK;
163     case KEY_LEFTSHIFT:
164     case KEY_RIGHTSHIFT:
165       return EVDEV_MODIFIER_SHIFT;
166     case KEY_LEFTCTRL:
167     case KEY_RIGHTCTRL:
168       return EVDEV_MODIFIER_CONTROL;
169     case KEY_LEFTALT:
170     case KEY_RIGHTALT:
171       return EVDEV_MODIFIER_ALT;
172     case BTN_LEFT:
173       return EVDEV_MODIFIER_LEFT_MOUSE_BUTTON;
174     case BTN_MIDDLE:
175       return EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON;
176     case BTN_RIGHT:
177       return EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON;
178     case KEY_LEFTMETA:
179     case KEY_RIGHTMETA:
180       return EVDEV_MODIFIER_COMMAND;
181     default:
182       return EVDEV_MODIFIER_NONE;
183   }
184 }
185
186 bool IsLockButton(unsigned int code) { return code == KEY_CAPSLOCK; }
187
188 }  // namespace
189
190 KeyEventConverterEvdev::KeyEventConverterEvdev(
191     int fd,
192     base::FilePath path,
193     EventModifiersEvdev* modifiers,
194     const EventDispatchCallback& callback)
195     : EventConverterEvdev(callback),
196       fd_(fd),
197       path_(path),
198       modifiers_(modifiers) {
199   // TODO(spang): Initialize modifiers using EVIOCGKEY.
200 }
201
202 KeyEventConverterEvdev::~KeyEventConverterEvdev() {
203   Stop();
204   close(fd_);
205 }
206
207 void KeyEventConverterEvdev::Start() {
208   base::MessageLoopForUI::current()->WatchFileDescriptor(
209       fd_, true, base::MessagePumpLibevent::WATCH_READ, &controller_, this);
210 }
211
212 void KeyEventConverterEvdev::Stop() {
213   controller_.StopWatchingFileDescriptor();
214 }
215
216 void KeyEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) {
217   input_event inputs[4];
218   ssize_t read_size = read(fd, inputs, sizeof(inputs));
219   if (read_size < 0) {
220     if (errno == EINTR || errno == EAGAIN)
221       return;
222     if (errno != ENODEV)
223       PLOG(ERROR) << "error reading device " << path_.value();
224     Stop();
225     return;
226   }
227
228   CHECK_EQ(read_size % sizeof(*inputs), 0u);
229   ProcessEvents(inputs, read_size / sizeof(*inputs));
230 }
231
232 void KeyEventConverterEvdev::OnFileCanWriteWithoutBlocking(int fd) {
233   NOTREACHED();
234 }
235
236 void KeyEventConverterEvdev::ProcessEvents(const input_event* inputs,
237                                            int count) {
238   for (int i = 0; i < count; ++i) {
239     const input_event& input = inputs[i];
240     if (input.type == EV_KEY) {
241       ConvertKeyEvent(input.code, input.value);
242     } else if (input.type == EV_SYN) {
243       // TODO(sadrul): Handle this case appropriately.
244     }
245   }
246 }
247
248 void KeyEventConverterEvdev::ConvertKeyEvent(int key, int value) {
249   int down = (value != 0);
250   int repeat = (value == 2);
251   int modifier = ModifierFromButton(key);
252   ui::KeyboardCode code = KeyboardCodeFromButton(key);
253
254   if (!repeat && (modifier != EVDEV_MODIFIER_NONE)) {
255     if (IsLockButton(key)) {
256       // Locking modifier keys: CapsLock.
257       modifiers_->UpdateModifierLock(modifier, down);
258     } else {
259       // Regular modifier keys: Shift, Ctrl, Alt, etc.
260       modifiers_->UpdateModifier(modifier, down);
261     }
262   }
263
264   int flags = modifiers_->GetModifierFlags();
265
266   KeyEvent key_event(
267       down ? ET_KEY_PRESSED : ET_KEY_RELEASED, code, flags, true);
268   DispatchEventToCallback(&key_event);
269 }
270
271 }  // namespace ui