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.
5 #include "ozone/wayland/input/keyboard_engine_xkb.h"
9 #include "ozone/ui/events/keyboard_codes_ozone.h"
10 #include "ui/events/event.h"
12 namespace ozonewayland {
14 KeyboardEngineXKB::KeyboardEngineXKB() : keyboard_modifiers_(0),
21 cached_sym_(XKB_KEY_NoSymbol),
27 KeyboardEngineXKB::~KeyboardEngineXKB() {
31 void KeyboardEngineXKB::OnKeyboardKeymap(int fd, uint32_t size) {
33 reinterpret_cast<char*>(mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0));
34 if (map_str == MAP_FAILED)
38 keymap_ = xkb_map_new_from_string(context_,
40 XKB_KEYMAP_FORMAT_TEXT_V1,
41 (xkb_map_compile_flags)0);
42 munmap(map_str, size);
46 state_ = xkb_state_new(keymap_);
48 xkb_map_unref(keymap_);
53 void KeyboardEngineXKB::OnKeyModifiers(uint32_t mods_depressed,
54 uint32_t mods_latched,
60 if ((mods_depressed_ == mods_depressed) && (mods_locked_ == mods_locked)
61 && (mods_latched_ == mods_latched) && (group_ == group)) {
65 mods_depressed_ = mods_depressed;
66 mods_locked_ = mods_locked;
67 mods_latched_ = mods_latched;
69 xkb_state_update_mask(state_,
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;
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;
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;
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;
95 unsigned KeyboardEngineXKB::ConvertKeyCodeFromEvdev(unsigned hardwarecode) {
96 if (hardwarecode == last_key_ && last_modifiers_ == keyboard_modifiers_)
99 const xkb_keysym_t *syms;
101 uint32_t code = hardwarecode + 8;
102 uint32_t num_syms = xkb_key_get_syms(state_, code, &syms);
106 sym = XKB_KEY_NoSymbol;
108 last_key_ = hardwarecode;
109 last_modifiers_ = keyboard_modifiers_;
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
120 // TODO(kalyan): Handle all needed cases here.
121 if (pressed || IsSpecialModifier(hardwarecode))
124 // No modifiers set, we don't have to deal with any special cases. Ignore the
126 if (!keyboard_modifiers_ || IsOnlyCapsLocked())
132 void KeyboardEngineXKB::InitXKB() {
136 context_ = xkb_context_new((xkb_context_flags)0);
139 void KeyboardEngineXKB::FiniXKB() {
141 xkb_state_unref(state_);
146 xkb_map_unref(keymap_);
151 xkb_context_unref(context_);
156 bool KeyboardEngineXKB::IsSpecialModifier(unsigned hardwarecode) {
157 switch (ConvertKeyCodeFromEvdev(hardwarecode)) {
158 case XKB_KEY_ISO_Level3_Shift: // altgr
166 bool KeyboardEngineXKB::IsOnlyCapsLocked() const {
167 if ((keyboard_modifiers_ & ui::EF_CONTROL_DOWN) != 0)
170 if ((keyboard_modifiers_ & ui::EF_ALT_DOWN) != 0)
173 if ((keyboard_modifiers_ & ui::EF_SHIFT_DOWN) != 0)
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))
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);
197 switch (cached_sym_) {
198 case XKB_KEY_dead_circumflex:
199 cached_sym_ = ui::OZONECHARCODE_CARET_CIRCUMFLEX;
201 case XKB_KEY_dead_diaeresis:
202 cached_sym_ = ui::OZONECHARCODE_SPACING_DIAERESIS;
204 case XKB_KEY_dead_perispomeni:
205 cached_sym_ = ui::OZONECHARCODE_TILDE;
207 case XKB_KEY_dead_acute:
208 cached_sym_ = ui::OZONECHARCODE_SPACING_ACUTE;
210 case XKB_KEY_dead_grave:
211 cached_sym_ = ui::OZONECHARCODE_GRAVE_ASSCENT;
214 cached_sym_ = ui::OZONECHARCODE_ENDASH;
216 case XKB_KEY_singlelowquotemark:
217 cached_sym_ = ui::OZONECHARCODE_SINGLE_LOW_QUOTATION_MARK;
219 case XKB_KEY_dead_cedilla:
220 cached_sym_ = ui::OZONECHARCODE_SPACING_CEDILLA;
222 case XKB_KEY_KP_Equal:
223 cached_sym_ = ui::OZONECHARCODE_EQUAL;
225 case XKB_KEY_KP_Multiply:
226 cached_sym_ = ui::OZONECHARCODE_MULTIPLY;
229 cached_sym_ = ui::OZONECHARCODE_PLUS;
231 case XKB_KEY_KP_Separator:
232 cached_sym_ = ui::OZONECHARCODE_COMMA;
234 case XKB_KEY_KP_Subtract:
235 cached_sym_ = ui::OZONECHARCODE_MINUS;
237 case XKB_KEY_KP_Decimal:
238 cached_sym_ = ui::OZONECHARCODE_PERIOD;
240 case XKB_KEY_KP_Divide:
241 cached_sym_ = ui::OZONECHARCODE_DIVISION;
244 case XKB_KEY_KP_Delete:
245 cached_sym_ = ui::OZONEACTIONKEY_DELETE;
248 case XKB_KEY_ISO_Left_Tab:
250 case XKB_KEY_3270_BackTab:
251 cached_sym_ = ui::OZONEACTIONKEY_TAB;
253 case XKB_KEY_Sys_Req:
255 cached_sym_ = ui::OZONEACTIONKEY_ESCAPE;
257 case XKB_KEY_Linefeed:
258 cached_sym_ = ui::OZONECHARCODE_LINEFEED;
261 case XKB_KEY_KP_Enter:
262 case XKB_KEY_ISO_Enter:
263 cached_sym_ = ui::OZONEACTIONKEY_RETURN;
265 case XKB_KEY_KP_Space:
267 cached_sym_ = ui::OZONEACTIONKEY_SPACE;
269 case XKB_KEY_dead_caron:
270 cached_sym_ = ui::OZONECHARCODE_CARON;
272 case XKB_KEY_BackSpace:
273 cached_sym_ = ui::OZONEACTIONKEY_BACK;
275 case XKB_KEY_dead_doubleacute:
276 cached_sym_ = ui::OZONECHARCODE_DOUBLE_ACUTE_ACCENT;
278 case XKB_KEY_dead_horn:
279 cached_sym_ = ui::OZONECHARCODE_COMBINING_HORN;
282 cached_sym_ = ui::OZONECHARCODE_LSMALL_OE;
285 cached_sym_ = ui::OZONECHARCODE_LOE;
287 case XKB_KEY_idotless:
288 cached_sym_ = ui::OZONECHARCODE_LSMALL_DOT_LESS_I;
291 cached_sym_ = ui::OZONECHARCODE_LSMALL_KRA;
293 case XKB_KEY_dead_stroke:
294 cached_sym_ = ui::OZONECHARCODE_MINUS;
297 cached_sym_ = ui::OZONECHARCODE_LSMALL_ENG;
300 cached_sym_ = ui::OZONECHARCODE_LENG;
302 case XKB_KEY_leftsinglequotemark:
303 cached_sym_ = ui::OZONECHARCODE_LEFT_SINGLE_QUOTATION_MARK;
305 case XKB_KEY_rightsinglequotemark:
306 cached_sym_ = ui::OZONECHARCODE_RIGHT_SINGLE_QUOTATION_MARK;
308 case XKB_KEY_dead_belowdot:
309 cached_sym_ = ui::OZONECHARCODE_COMBINING_DOT_BELOW;
311 case XKB_KEY_dead_belowdiaeresis:
312 cached_sym_ = ui::OZONECHARCODE_COMBINING_DIAERESIS_BELOW;
315 case XKB_KEY_KP_Begin:
316 cached_sym_ = ui::OZONEACTIONKEY_CLEAR;
319 case XKB_KEY_KP_Home:
320 cached_sym_ = ui::OZONEACTIONKEY_HOME;
324 cached_sym_ = ui::OZONEACTIONKEY_END;
326 case XKB_KEY_Page_Up:
327 case XKB_KEY_KP_Page_Up: // aka XKB_KEY_KP_Prior
328 cached_sym_ = ui::OZONEACTIONKEY_PRIOR;
330 case XKB_KEY_Page_Down:
331 case XKB_KEY_KP_Page_Down: // aka XKB_KEY_KP_Next
332 cached_sym_ = ui::OZONEACTIONKEY_NEXT;
335 case XKB_KEY_KP_Left:
336 cached_sym_ = ui::OZONEACTIONKEY_LEFT;
339 case XKB_KEY_KP_Right:
340 cached_sym_ = ui::OZONEACTIONKEY_RIGHT;
343 case XKB_KEY_KP_Down:
344 cached_sym_ = ui::OZONEACTIONKEY_DOWN;
348 cached_sym_ = ui::OZONEACTIONKEY_UP;
350 case XKB_KEY_Kana_Lock:
351 case XKB_KEY_Kana_Shift:
352 cached_sym_ = ui::OZONEACTIONKEY_KANA;
355 cached_sym_ = ui::OZONEACTIONKEY_HANGUL;
357 case XKB_KEY_Hangul_Hanja:
358 cached_sym_ = ui::OZONEACTIONKEY_HANJA;
361 cached_sym_ = ui::OZONEACTIONKEY_KANJI;
364 cached_sym_ = ui::OZONEACTIONKEY_CONVERT;
366 case XKB_KEY_Muhenkan:
367 cached_sym_ = ui::OZONEACTIONKEY_NONCONVERT;
369 case XKB_KEY_Zenkaku_Hankaku:
370 cached_sym_ = ui::OZONEACTIONKEY_DBE_DBCSCHAR;
372 case XKB_KEY_ISO_Level5_Shift:
373 cached_sym_ = ui::OZONEACTIONKEY_OEM_8;
375 case XKB_KEY_Shift_L:
376 case XKB_KEY_Shift_R:
377 cached_sym_ = ui::OZONEACTIONKEY_SHIFT;
379 case XKB_KEY_Control_L:
380 case XKB_KEY_Control_R:
381 cached_sym_ = ui::OZONEACTIONKEY_CONTROL;
387 cached_sym_ = ui::OZONEACTIONKEY_MENU;
389 case XKB_KEY_ISO_Level3_Shift:
390 cached_sym_ = ui::OZONEACTIONKEY_ALTGR;
392 case XKB_KEY_Multi_key:
396 cached_sym_ = ui::OZONEACTIONKEY_PAUSE;
398 case XKB_KEY_Caps_Lock:
399 cached_sym_ = ui::OZONEACTIONKEY_CAPITAL;
401 case XKB_KEY_Num_Lock:
402 cached_sym_ = ui::OZONEACTIONKEY_NUMLOCK;
404 case XKB_KEY_Scroll_Lock:
405 cached_sym_ = ui::OZONEACTIONKEY_SCROLL;
408 cached_sym_ = ui::OZONEACTIONKEY_SELECT;
411 cached_sym_ = ui::OZONEACTIONKEY_PRINT;
413 case XKB_KEY_Execute:
414 cached_sym_ = ui::OZONEACTIONKEY_EXECUTE;
417 case XKB_KEY_KP_Insert:
418 cached_sym_ = ui::OZONEACTIONKEY_INSERT;
421 cached_sym_ = ui::OZONEACTIONKEY_HELP;
423 case XKB_KEY_Super_L:
424 cached_sym_ = ui::OZONEACTIONKEY_LWIN;
426 case XKB_KEY_Super_R:
427 cached_sym_ = ui::OZONEACTIONKEY_RWIN;
430 cached_sym_ = ui::OZONEACTIONKEY_APPS;
432 case XKB_KEY_XF86Tools:
433 cached_sym_ = ui::OZONEACTIONKEY_F13;
435 case XKB_KEY_XF86Launch5:
436 cached_sym_ = ui::OZONEACTIONKEY_F14;
438 case XKB_KEY_XF86Launch6:
439 cached_sym_ = ui::OZONEACTIONKEY_F15;
441 case XKB_KEY_XF86Launch7:
442 cached_sym_ = ui::OZONEACTIONKEY_F16;
444 case XKB_KEY_XF86Launch8:
445 cached_sym_ = ui::OZONEACTIONKEY_F17;
447 case XKB_KEY_XF86Launch9:
448 cached_sym_ = ui::OZONEACTIONKEY_F18;
451 // For supporting multimedia buttons on a USB keyboard.
452 case XKB_KEY_XF86Back:
453 cached_sym_ = ui::OZONEACTIONKEY_BROWSER_BACK;
455 case XKB_KEY_XF86Forward:
456 cached_sym_ = ui::OZONEACTIONKEY_BROWSER_FORWARD;
458 case XKB_KEY_XF86Reload:
459 cached_sym_ = ui::OZONEACTIONKEY_BROWSER_REFRESH;
461 case XKB_KEY_XF86Stop:
462 cached_sym_ = ui::OZONEACTIONKEY_BROWSER_STOP;
464 case XKB_KEY_XF86Search:
465 cached_sym_ = ui::OZONEACTIONKEY_BROWSER_SEARCH;
467 case XKB_KEY_XF86Favorites:
468 cached_sym_ = ui::OZONEACTIONKEY_BROWSER_FAVORITES;
470 case XKB_KEY_XF86HomePage:
471 cached_sym_ = ui::OZONEACTIONKEY_BROWSER_HOME;
473 case XKB_KEY_XF86AudioMute:
474 cached_sym_ = ui::OZONEACTIONKEY_VOLUME_MUTE;
476 case XKB_KEY_XF86AudioLowerVolume:
477 cached_sym_ = ui::OZONEACTIONKEY_VOLUME_DOWN;
479 case XKB_KEY_XF86AudioRaiseVolume:
480 cached_sym_ = ui::OZONEACTIONKEY_VOLUME_UP;
482 case XKB_KEY_XF86AudioNext:
483 cached_sym_ = ui::OZONEACTIONKEY_MEDIA_NEXT_TRACK;
485 case XKB_KEY_XF86AudioPrev:
486 cached_sym_ = ui::OZONEACTIONKEY_MEDIA_PREV_TRACK;
488 case XKB_KEY_XF86AudioStop:
489 cached_sym_ = ui::OZONEACTIONKEY_MEDIA_STOP;
491 case XKB_KEY_XF86AudioPlay:
492 cached_sym_ = ui::OZONEACTIONKEY_MEDIA_PLAY_PAUSE;
494 case XKB_KEY_XF86Mail:
495 cached_sym_ = ui::OZONEACTIONKEY_MEDIA_LAUNCH_MAIL;
497 case XKB_KEY_XF86LaunchA:
498 cached_sym_ = ui::OZONEACTIONKEY_MEDIA_LAUNCH_APP1;
500 case XKB_KEY_XF86LaunchB:
501 case XKB_KEY_XF86Calculator:
502 cached_sym_ = ui::OZONEACTIONKEY_MEDIA_LAUNCH_APP2;
504 case XKB_KEY_XF86WLAN:
505 cached_sym_ = ui::OZONEACTIONKEY_WLAN;
507 case XKB_KEY_XF86PowerOff:
508 cached_sym_ = ui::OZONEACTIONKEY_POWER;
510 case XKB_KEY_XF86MonBrightnessDown:
511 cached_sym_ = ui::OZONEACTIONKEY_BRIGHTNESS_DOWN;
513 case XKB_KEY_XF86MonBrightnessUp:
514 cached_sym_ = ui::OZONEACTIONKEY_BRIGHTNESS_UP;
516 case XKB_KEY_XF86KbdBrightnessDown:
517 cached_sym_ = ui::OZONEACTIONKEY_KBD_BRIGHTNESS_DOWN;
519 case XKB_KEY_XF86KbdBrightnessUp:
520 cached_sym_ = ui::OZONEACTIONKEY_KBD_BRIGHTNESS_UP;
522 case XKB_KEY_emptyset:
523 case XKB_KEY_NoSymbol:
524 cached_sym_ = ui::OZONECHARCODE_NULL;
532 } // namespace ozonewayland