Upstream version 11.39.250.0
[platform/framework/web/crosswalk.git] / src / ozone / wayland / input / keyboard_engine_xkb.cc
1 // Copyright 2013 Intel Corporation. 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 "ozone/wayland/input/keyboard_engine_xkb.h"
6
7 #include <sys/mman.h>
8
9 #include "ozone/ui/events/keyboard_codes_ozone.h"
10 #include "ui/events/event.h"
11
12 namespace ozonewayland {
13
14 KeyboardEngineXKB::KeyboardEngineXKB() : keyboard_modifiers_(0),
15     mods_depressed_(0),
16     mods_latched_(0),
17     mods_locked_(0),
18     group_(0),
19     last_key_(-1),
20     last_modifiers_(0),
21     cached_sym_(XKB_KEY_NoSymbol),
22     keymap_(NULL),
23     state_(NULL),
24     context_(NULL) {
25 }
26
27 KeyboardEngineXKB::~KeyboardEngineXKB() {
28   FiniXKB();
29 }
30
31 void KeyboardEngineXKB::OnKeyboardKeymap(int fd, uint32_t size) {
32   char *map_str =
33       reinterpret_cast<char*>(mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0));
34   if (map_str == MAP_FAILED)
35     return;
36
37   InitXKB();
38   keymap_ = xkb_map_new_from_string(context_,
39                                     map_str,
40                                     XKB_KEYMAP_FORMAT_TEXT_V1,
41                                     (xkb_map_compile_flags)0);
42   munmap(map_str, size);
43   if (!keymap_)
44     return;
45
46   state_ = xkb_state_new(keymap_);
47   if (state_) {
48     xkb_map_unref(keymap_);
49     keymap_ = NULL;
50   }
51 }
52
53 void KeyboardEngineXKB::OnKeyModifiers(uint32_t mods_depressed,
54                                         uint32_t mods_latched,
55                                         uint32_t mods_locked,
56                                         uint32_t group) {
57   if (!state_)
58     return;
59
60   if ((mods_depressed_ == mods_depressed) && (mods_locked_ == mods_locked)
61       && (mods_latched_ == mods_latched) && (group_ == group)) {
62     return;
63   }
64
65   mods_depressed_ = mods_depressed;
66   mods_locked_ = mods_locked;
67   mods_latched_ = mods_latched;
68   group_ = group;
69   xkb_state_update_mask(state_,
70                         mods_depressed_,
71                         mods_latched_,
72                         mods_locked_,
73                         0,
74                         0,
75                         group_);
76
77   keyboard_modifiers_ = 0;
78   if (xkb_state_mod_name_is_active(
79       state_, XKB_MOD_NAME_SHIFT, XKB_STATE_MODS_EFFECTIVE))
80     keyboard_modifiers_ |= ui::EF_SHIFT_DOWN;
81
82   if (xkb_state_mod_name_is_active(
83       state_, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE))
84     keyboard_modifiers_ |= ui::EF_CONTROL_DOWN;
85
86   if (xkb_state_mod_name_is_active(
87       state_, XKB_MOD_NAME_ALT, XKB_STATE_MODS_EFFECTIVE))
88     keyboard_modifiers_ |= ui::EF_ALT_DOWN;
89
90   if (xkb_state_mod_name_is_active(
91       state_, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_EFFECTIVE))
92     keyboard_modifiers_ |= ui::EF_CAPS_LOCK_DOWN;
93 }
94
95 unsigned KeyboardEngineXKB::ConvertKeyCodeFromEvdev(unsigned hardwarecode) {
96   if (hardwarecode == last_key_ && last_modifiers_ ==  keyboard_modifiers_)
97     return cached_sym_;
98
99   const xkb_keysym_t *syms;
100   xkb_keysym_t sym;
101   uint32_t code = hardwarecode + 8;
102   uint32_t num_syms = xkb_key_get_syms(state_, code, &syms);
103   if (num_syms == 1)
104     sym = syms[0];
105   else
106     sym = XKB_KEY_NoSymbol;
107
108   last_key_ = hardwarecode;
109   last_modifiers_ =  keyboard_modifiers_;
110   cached_sym_ = sym;
111   NormalizeKey();
112
113   return cached_sym_;
114 }
115
116 bool KeyboardEngineXKB::IgnoreKeyNotify(
117          unsigned hardwarecode, bool pressed) {
118   // If the key is pressed or it's a special modifier key i.e altgr, we cannot
119   // ignore it.
120   // TODO(kalyan): Handle all needed cases here.
121   if (pressed || IsSpecialModifier(hardwarecode))
122     return false;
123
124   // No modifiers set, we don't have to deal with any special cases. Ignore the
125   // release events.
126   if (!keyboard_modifiers_ || IsOnlyCapsLocked())
127     return true;
128
129   return false;
130 }
131
132 void KeyboardEngineXKB::InitXKB() {
133   if (context_)
134     return;
135
136   context_ = xkb_context_new((xkb_context_flags)0);
137 }
138
139 void KeyboardEngineXKB::FiniXKB() {
140   if (state_) {
141     xkb_state_unref(state_);
142     state_ = NULL;
143   }
144
145   if (keymap_) {
146     xkb_map_unref(keymap_);
147     keymap_ = NULL;
148   }
149
150   if (context_) {
151     xkb_context_unref(context_);
152     context_ = NULL;
153   }
154 }
155
156 bool KeyboardEngineXKB::IsSpecialModifier(unsigned hardwarecode) {
157     switch (ConvertKeyCodeFromEvdev(hardwarecode)) {
158     case XKB_KEY_ISO_Level3_Shift:  // altgr
159       return true;
160     break;
161     default:
162     return false;
163   }
164 }
165
166 bool KeyboardEngineXKB::IsOnlyCapsLocked() const {
167   if ((keyboard_modifiers_ & ui::EF_CONTROL_DOWN) != 0)
168     return false;
169
170   if ((keyboard_modifiers_ & ui::EF_ALT_DOWN) != 0)
171     return false;
172
173   if ((keyboard_modifiers_ & ui::EF_SHIFT_DOWN) != 0)
174     return false;
175
176   return true;
177 }
178
179 void KeyboardEngineXKB::NormalizeKey() {
180   if ((cached_sym_ >= XKB_KEY_A && cached_sym_ <= XKB_KEY_Z) ||
181        (cached_sym_ >= XKB_KEY_a && cached_sym_ <= XKB_KEY_z) ||
182          (cached_sym_ >= XKB_KEY_0 && cached_sym_ <= XKB_KEY_9))
183     return;
184
185   if (cached_sym_ >= XKB_KEY_KP_0 && cached_sym_ <= XKB_KEY_KP_9) {
186     // Numpad Number-keys can be represented by a keysym value of 0-9 nos.
187     cached_sym_ = XKB_KEY_0 + (cached_sym_ - XKB_KEY_KP_0);
188   } else if (cached_sym_ > 0x01000100 && cached_sym_ < 0x01ffffff) {
189     // Any UCS character in this range will simply be the character's
190     // Unicode number plus 0x01000000.
191     cached_sym_ = cached_sym_ - 0x001000000;
192   } else if (cached_sym_ >= XKB_KEY_F1 && cached_sym_ <= XKB_KEY_F24) {
193     cached_sym_ = ui::OZONEACTIONKEY_F1 + (cached_sym_ - XKB_KEY_F1);
194   } else if (cached_sym_ >= XKB_KEY_KP_F1 && cached_sym_ <= XKB_KEY_KP_F4) {
195       cached_sym_ = ui::OZONEACTIONKEY_F1 + (cached_sym_ - XKB_KEY_KP_F1);
196   } else {
197       switch (cached_sym_) {
198         case XKB_KEY_dead_circumflex:
199           cached_sym_ = ui::OZONECHARCODE_CARET_CIRCUMFLEX;
200           break;
201         case XKB_KEY_dead_diaeresis:
202           cached_sym_ = ui::OZONECHARCODE_SPACING_DIAERESIS;
203           break;
204         case XKB_KEY_dead_perispomeni:
205           cached_sym_ = ui::OZONECHARCODE_TILDE;
206           break;
207         case XKB_KEY_dead_acute:
208           cached_sym_ = ui::OZONECHARCODE_SPACING_ACUTE;
209           break;
210         case XKB_KEY_dead_grave:
211           cached_sym_ = ui::OZONECHARCODE_GRAVE_ASSCENT;
212           break;
213         case XKB_KEY_endash:
214           cached_sym_ = ui::OZONECHARCODE_ENDASH;
215           break;
216         case XKB_KEY_singlelowquotemark:
217           cached_sym_ = ui::OZONECHARCODE_SINGLE_LOW_QUOTATION_MARK;
218           break;
219         case XKB_KEY_dead_cedilla:
220           cached_sym_ = ui::OZONECHARCODE_SPACING_CEDILLA;
221           break;
222         case XKB_KEY_KP_Equal:
223           cached_sym_ = ui::OZONECHARCODE_EQUAL;
224           break;
225         case XKB_KEY_KP_Multiply:
226           cached_sym_ = ui::OZONECHARCODE_MULTIPLY;
227           break;
228         case XKB_KEY_KP_Add:
229           cached_sym_ = ui::OZONECHARCODE_PLUS;
230           break;
231         case XKB_KEY_KP_Separator:
232           cached_sym_ = ui::OZONECHARCODE_COMMA;
233           break;
234         case XKB_KEY_KP_Subtract:
235           cached_sym_ = ui::OZONECHARCODE_MINUS;
236           break;
237         case XKB_KEY_KP_Decimal:
238           cached_sym_ = ui::OZONECHARCODE_PERIOD;
239           break;
240         case XKB_KEY_KP_Divide:
241           cached_sym_ = ui::OZONECHARCODE_DIVISION;
242           break;
243         case XKB_KEY_Delete:
244         case XKB_KEY_KP_Delete:
245           cached_sym_ = ui::OZONEACTIONKEY_DELETE;
246           break;
247         case XKB_KEY_KP_Tab:
248         case XKB_KEY_ISO_Left_Tab:
249         case XKB_KEY_Tab:
250         case XKB_KEY_3270_BackTab:
251           cached_sym_ = ui::OZONEACTIONKEY_TAB;
252           break;
253         case XKB_KEY_Sys_Req:
254         case XKB_KEY_Escape:
255           cached_sym_ = ui::OZONEACTIONKEY_ESCAPE;
256           break;
257         case XKB_KEY_Linefeed:
258           cached_sym_ = ui::OZONECHARCODE_LINEFEED;
259           break;
260         case XKB_KEY_Return:
261         case XKB_KEY_KP_Enter:
262         case XKB_KEY_ISO_Enter:
263           cached_sym_ = ui::OZONEACTIONKEY_RETURN;
264           break;
265         case XKB_KEY_KP_Space:
266         case XKB_KEY_space:
267           cached_sym_ = ui::OZONEACTIONKEY_SPACE;
268           break;
269         case XKB_KEY_dead_caron:
270           cached_sym_ = ui::OZONECHARCODE_CARON;
271           break;
272         case XKB_KEY_BackSpace:
273           cached_sym_ = ui::OZONEACTIONKEY_BACK;
274           break;
275         case XKB_KEY_dead_doubleacute:
276           cached_sym_ = ui::OZONECHARCODE_DOUBLE_ACUTE_ACCENT;
277           break;
278         case XKB_KEY_dead_horn:
279           cached_sym_ = ui::OZONECHARCODE_COMBINING_HORN;
280           break;
281         case XKB_KEY_oe:
282           cached_sym_ = ui::OZONECHARCODE_LSMALL_OE;
283           break;
284         case XKB_KEY_OE:
285           cached_sym_ = ui::OZONECHARCODE_LOE;
286           break;
287         case XKB_KEY_idotless:
288           cached_sym_ = ui::OZONECHARCODE_LSMALL_DOT_LESS_I;
289           break;
290         case XKB_KEY_kra:
291           cached_sym_ = ui::OZONECHARCODE_LSMALL_KRA;
292           break;
293         case XKB_KEY_dead_stroke:
294           cached_sym_ = ui::OZONECHARCODE_MINUS;
295           break;
296         case XKB_KEY_eng:
297           cached_sym_ = ui::OZONECHARCODE_LSMALL_ENG;
298           break;
299         case XKB_KEY_ENG:
300           cached_sym_ = ui::OZONECHARCODE_LENG;
301           break;
302         case XKB_KEY_leftsinglequotemark:
303           cached_sym_ = ui::OZONECHARCODE_LEFT_SINGLE_QUOTATION_MARK;
304           break;
305         case XKB_KEY_rightsinglequotemark:
306           cached_sym_ = ui::OZONECHARCODE_RIGHT_SINGLE_QUOTATION_MARK;
307           break;
308         case XKB_KEY_dead_belowdot:
309           cached_sym_ = ui::OZONECHARCODE_COMBINING_DOT_BELOW;
310           break;
311         case XKB_KEY_dead_belowdiaeresis:
312           cached_sym_ = ui::OZONECHARCODE_COMBINING_DIAERESIS_BELOW;
313           break;
314         case XKB_KEY_Clear:
315         case XKB_KEY_KP_Begin:
316           cached_sym_ = ui::OZONEACTIONKEY_CLEAR;
317           break;
318         case XKB_KEY_Home:
319         case XKB_KEY_KP_Home:
320           cached_sym_ = ui::OZONEACTIONKEY_HOME;
321           break;
322         case XKB_KEY_End:
323         case XKB_KEY_KP_End:
324           cached_sym_ = ui::OZONEACTIONKEY_END;
325           break;
326         case XKB_KEY_Page_Up:
327         case XKB_KEY_KP_Page_Up:  // aka XKB_KEY_KP_Prior
328           cached_sym_ = ui::OZONEACTIONKEY_PRIOR;
329           break;
330         case XKB_KEY_Page_Down:
331         case XKB_KEY_KP_Page_Down:  // aka XKB_KEY_KP_Next
332           cached_sym_ = ui::OZONEACTIONKEY_NEXT;
333           break;
334         case XKB_KEY_Left:
335         case XKB_KEY_KP_Left:
336           cached_sym_ = ui::OZONEACTIONKEY_LEFT;
337           break;
338         case XKB_KEY_Right:
339         case XKB_KEY_KP_Right:
340           cached_sym_ = ui::OZONEACTIONKEY_RIGHT;
341           break;
342         case XKB_KEY_Down:
343         case XKB_KEY_KP_Down:
344           cached_sym_ = ui::OZONEACTIONKEY_DOWN;
345           break;
346         case XKB_KEY_Up:
347         case XKB_KEY_KP_Up:
348           cached_sym_ = ui::OZONEACTIONKEY_UP;
349           break;
350         case XKB_KEY_Kana_Lock:
351         case XKB_KEY_Kana_Shift:
352           cached_sym_ = ui::OZONEACTIONKEY_KANA;
353           break;
354         case XKB_KEY_Hangul:
355           cached_sym_ = ui::OZONEACTIONKEY_HANGUL;
356           break;
357         case XKB_KEY_Hangul_Hanja:
358           cached_sym_ = ui::OZONEACTIONKEY_HANJA;
359           break;
360         case XKB_KEY_Kanji:
361           cached_sym_ = ui::OZONEACTIONKEY_KANJI;
362           break;
363         case XKB_KEY_Henkan:
364           cached_sym_ = ui::OZONEACTIONKEY_CONVERT;
365           break;
366         case XKB_KEY_Muhenkan:
367           cached_sym_ = ui::OZONEACTIONKEY_NONCONVERT;
368           break;
369         case XKB_KEY_Zenkaku_Hankaku:
370           cached_sym_ = ui::OZONEACTIONKEY_DBE_DBCSCHAR;
371           break;
372         case XKB_KEY_ISO_Level5_Shift:
373           cached_sym_ = ui::OZONEACTIONKEY_OEM_8;
374           break;
375         case XKB_KEY_Shift_L:
376         case XKB_KEY_Shift_R:
377           cached_sym_ = ui::OZONEACTIONKEY_SHIFT;
378           break;
379         case XKB_KEY_Control_L:
380         case XKB_KEY_Control_R:
381           cached_sym_ = ui::OZONEACTIONKEY_CONTROL;
382           break;
383         case XKB_KEY_Meta_L:
384         case XKB_KEY_Meta_R:
385         case XKB_KEY_Alt_L:
386         case XKB_KEY_Alt_R:
387           cached_sym_ = ui::OZONEACTIONKEY_MENU;
388           break;
389         case XKB_KEY_ISO_Level3_Shift:
390           cached_sym_ = ui::OZONEACTIONKEY_ALTGR;
391           break;
392         case XKB_KEY_Multi_key:
393           cached_sym_ = 0xE6;
394           break;
395         case XKB_KEY_Pause:
396           cached_sym_ = ui::OZONEACTIONKEY_PAUSE;
397           break;
398         case XKB_KEY_Caps_Lock:
399           cached_sym_ = ui::OZONEACTIONKEY_CAPITAL;
400           break;
401         case XKB_KEY_Num_Lock:
402           cached_sym_ = ui::OZONEACTIONKEY_NUMLOCK;
403           break;
404         case XKB_KEY_Scroll_Lock:
405           cached_sym_ = ui::OZONEACTIONKEY_SCROLL;
406           break;
407         case XKB_KEY_Select:
408           cached_sym_ = ui::OZONEACTIONKEY_SELECT;
409           break;
410         case XKB_KEY_Print:
411           cached_sym_ = ui::OZONEACTIONKEY_PRINT;
412           break;
413         case XKB_KEY_Execute:
414           cached_sym_ = ui::OZONEACTIONKEY_EXECUTE;
415           break;
416         case XKB_KEY_Insert:
417         case XKB_KEY_KP_Insert:
418           cached_sym_ = ui::OZONEACTIONKEY_INSERT;
419           break;
420         case XKB_KEY_Help:
421           cached_sym_ = ui::OZONEACTIONKEY_HELP;
422           break;
423         case XKB_KEY_Super_L:
424           cached_sym_ = ui::OZONEACTIONKEY_LWIN;
425           break;
426         case XKB_KEY_Super_R:
427           cached_sym_ = ui::OZONEACTIONKEY_RWIN;
428           break;
429         case XKB_KEY_Menu:
430           cached_sym_ = ui::OZONEACTIONKEY_APPS;
431           break;
432         case XKB_KEY_XF86Tools:
433           cached_sym_ = ui::OZONEACTIONKEY_F13;
434           break;
435         case XKB_KEY_XF86Launch5:
436           cached_sym_ = ui::OZONEACTIONKEY_F14;
437           break;
438         case XKB_KEY_XF86Launch6:
439           cached_sym_ = ui::OZONEACTIONKEY_F15;
440           break;
441         case XKB_KEY_XF86Launch7:
442           cached_sym_ = ui::OZONEACTIONKEY_F16;
443           break;
444         case XKB_KEY_XF86Launch8:
445           cached_sym_ = ui::OZONEACTIONKEY_F17;
446           break;
447         case XKB_KEY_XF86Launch9:
448           cached_sym_ = ui::OZONEACTIONKEY_F18;
449           break;
450
451         // For supporting multimedia buttons on a USB keyboard.
452         case XKB_KEY_XF86Back:
453           cached_sym_ = ui::OZONEACTIONKEY_BROWSER_BACK;
454           break;
455         case XKB_KEY_XF86Forward:
456           cached_sym_ = ui::OZONEACTIONKEY_BROWSER_FORWARD;
457           break;
458         case XKB_KEY_XF86Reload:
459           cached_sym_ = ui::OZONEACTIONKEY_BROWSER_REFRESH;
460           break;
461         case XKB_KEY_XF86Stop:
462           cached_sym_ = ui::OZONEACTIONKEY_BROWSER_STOP;
463           break;
464         case XKB_KEY_XF86Search:
465           cached_sym_ = ui::OZONEACTIONKEY_BROWSER_SEARCH;
466           break;
467         case XKB_KEY_XF86Favorites:
468           cached_sym_ = ui::OZONEACTIONKEY_BROWSER_FAVORITES;
469           break;
470         case XKB_KEY_XF86HomePage:
471           cached_sym_ = ui::OZONEACTIONKEY_BROWSER_HOME;
472           break;
473         case XKB_KEY_XF86AudioMute:
474           cached_sym_ = ui::OZONEACTIONKEY_VOLUME_MUTE;
475           break;
476         case XKB_KEY_XF86AudioLowerVolume:
477           cached_sym_ = ui::OZONEACTIONKEY_VOLUME_DOWN;
478           break;
479         case XKB_KEY_XF86AudioRaiseVolume:
480           cached_sym_ = ui::OZONEACTIONKEY_VOLUME_UP;
481           break;
482         case XKB_KEY_XF86AudioNext:
483           cached_sym_ = ui::OZONEACTIONKEY_MEDIA_NEXT_TRACK;
484           break;
485         case XKB_KEY_XF86AudioPrev:
486           cached_sym_ = ui::OZONEACTIONKEY_MEDIA_PREV_TRACK;
487           break;
488         case XKB_KEY_XF86AudioStop:
489           cached_sym_ = ui::OZONEACTIONKEY_MEDIA_STOP;
490           break;
491         case XKB_KEY_XF86AudioPlay:
492           cached_sym_ = ui::OZONEACTIONKEY_MEDIA_PLAY_PAUSE;
493           break;
494         case XKB_KEY_XF86Mail:
495           cached_sym_ = ui::OZONEACTIONKEY_MEDIA_LAUNCH_MAIL;
496           break;
497         case XKB_KEY_XF86LaunchA:
498           cached_sym_ = ui::OZONEACTIONKEY_MEDIA_LAUNCH_APP1;
499           break;
500         case XKB_KEY_XF86LaunchB:
501         case XKB_KEY_XF86Calculator:
502           cached_sym_ = ui::OZONEACTIONKEY_MEDIA_LAUNCH_APP2;
503           break;
504         case XKB_KEY_XF86WLAN:
505           cached_sym_ = ui::OZONEACTIONKEY_WLAN;
506           break;
507         case XKB_KEY_XF86PowerOff:
508           cached_sym_ = ui::OZONEACTIONKEY_POWER;
509           break;
510         case XKB_KEY_XF86MonBrightnessDown:
511           cached_sym_ = ui::OZONEACTIONKEY_BRIGHTNESS_DOWN;
512           break;
513         case XKB_KEY_XF86MonBrightnessUp:
514           cached_sym_ = ui::OZONEACTIONKEY_BRIGHTNESS_UP;
515           break;
516         case XKB_KEY_XF86KbdBrightnessDown:
517           cached_sym_ = ui::OZONEACTIONKEY_KBD_BRIGHTNESS_DOWN;
518           break;
519         case XKB_KEY_XF86KbdBrightnessUp:
520           cached_sym_ = ui::OZONEACTIONKEY_KBD_BRIGHTNESS_UP;
521           break;
522         case XKB_KEY_emptyset:
523         case XKB_KEY_NoSymbol:
524           cached_sym_ = ui::OZONECHARCODE_NULL;
525           break;
526         default:
527           break;
528     }
529   }
530 }
531
532 }  // namespace ozonewayland