1 // Copyright (c) 2012 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.
5 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
7 #define XK_3270 // for XK_3270_BackTab
8 #include <X11/keysym.h>
10 #include <X11/Xutil.h>
11 #include <X11/XF86keysym.h>
13 #include "base/basictypes.h"
14 #include "base/logging.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "ui/events/keycodes/dom4/keycode_converter.h"
21 // Get an ui::KeyboardCode from an X keyevent
22 KeyboardCode KeyboardCodeFromXKeyEvent(XEvent* xev) {
23 // XLookupKeysym does not take into consideration the state of the lock/shift
24 // etc. keys. So it is necessary to use XLookupString instead.
26 XLookupString(&xev->xkey, NULL, 0, &keysym, NULL);
27 KeyboardCode keycode = KeyboardCodeFromXKeysym(keysym);
28 if (keycode == VKEY_UNKNOWN) {
29 keysym = DefaultXKeysymFromHardwareKeycode(xev->xkey.keycode);
30 keycode = KeyboardCodeFromXKeysym(keysym);
36 KeyboardCode KeyboardCodeFromXKeysym(unsigned int keysym) {
37 // TODO(sad): Have |keysym| go through the X map list?
56 case XK_KP_Begin: // NumPad 5 without Num Lock, for crosbug.com/29169.
68 case XK_KP_Page_Up: // aka XK_KP_Prior
71 case XK_KP_Page_Down: // aka XK_KP_Next
99 return VKEY_NONCONVERT;
100 case XK_Zenkaku_Hankaku:
101 return VKEY_DBE_DBCSCHAR;
191 return static_cast<KeyboardCode>(VKEY_0 + (keysym - XK_0));
224 return static_cast<KeyboardCode>(VKEY_NUMPAD0 + (keysym - XK_KP_0));
228 return VKEY_MULTIPLY;
231 case XK_KP_Separator:
232 return VKEY_SEPARATOR;
234 return VKEY_SUBTRACT;
242 return VKEY_OEM_PLUS;
245 return VKEY_OEM_COMMA;
248 return VKEY_OEM_MINUS;
251 return VKEY_OEM_PERIOD;
267 case XK_bracketright:
273 case XK_ISO_Level5_Shift:
286 case XK_ISO_Level3_Shift:
339 return static_cast<KeyboardCode>(VKEY_F1 + (keysym - XK_F1));
344 return static_cast<KeyboardCode>(VKEY_F1 + (keysym - XK_KP_F1));
346 case XK_guillemotleft:
347 case XK_guillemotright:
349 // In the case of canadian multilingual keyboard layout, VKEY_OEM_102 is
350 // assigned to ugrave key.
354 return VKEY_OEM_102; // international backslash key in 102 keyboard.
356 // When evdev is in use, /usr/share/X11/xkb/symbols/inet maps F13-18 keys
357 // to the special XF86XK symbols to support Microsoft Ergonomic keyboards:
358 // https://bugs.freedesktop.org/show_bug.cgi?id=5783
359 // In Chrome, we map these X key symbols back to F13-18 since we don't have
360 // VKEYs for these XF86XK symbols.
374 // For supporting multimedia buttons on a USB keyboard.
376 return VKEY_BROWSER_BACK;
378 return VKEY_BROWSER_FORWARD;
380 return VKEY_BROWSER_REFRESH;
382 return VKEY_BROWSER_STOP;
384 return VKEY_BROWSER_SEARCH;
385 case XF86XK_Favorites:
386 return VKEY_BROWSER_FAVORITES;
387 case XF86XK_HomePage:
388 return VKEY_BROWSER_HOME;
389 case XF86XK_AudioMute:
390 return VKEY_VOLUME_MUTE;
391 case XF86XK_AudioLowerVolume:
392 return VKEY_VOLUME_DOWN;
393 case XF86XK_AudioRaiseVolume:
394 return VKEY_VOLUME_UP;
395 case XF86XK_AudioNext:
396 return VKEY_MEDIA_NEXT_TRACK;
397 case XF86XK_AudioPrev:
398 return VKEY_MEDIA_PREV_TRACK;
399 case XF86XK_AudioStop:
400 return VKEY_MEDIA_STOP;
401 case XF86XK_AudioPlay:
402 return VKEY_MEDIA_PLAY_PAUSE;
404 return VKEY_MEDIA_LAUNCH_MAIL;
405 case XF86XK_LaunchA: // F3 on an Apple keyboard.
406 return VKEY_MEDIA_LAUNCH_APP1;
407 case XF86XK_LaunchB: // F4 on an Apple keyboard.
408 case XF86XK_Calculator:
409 return VKEY_MEDIA_LAUNCH_APP2;
412 case XF86XK_PowerOff:
414 case XF86XK_MonBrightnessDown:
415 return VKEY_BRIGHTNESS_DOWN;
416 case XF86XK_MonBrightnessUp:
417 return VKEY_BRIGHTNESS_UP;
418 case XF86XK_KbdBrightnessDown:
419 return VKEY_KBD_BRIGHTNESS_DOWN;
420 case XF86XK_KbdBrightnessUp:
421 return VKEY_KBD_BRIGHTNESS_UP;
423 // TODO(sad): some keycodes are still missing.
425 DLOG(WARNING) << "Unknown keysym: " << base::StringPrintf("0x%x", keysym);
429 const char* CodeFromXEvent(XEvent* xev) {
430 return KeycodeConverter::GetInstance()->NativeKeycodeToCode(
434 uint16 GetCharacterFromXEvent(XEvent* xev) {
436 int bytes_written = XLookupString(&xev->xkey, buf, 6, NULL, NULL);
437 DCHECK_LE(bytes_written, 6);
439 base::string16 result;
440 return (bytes_written > 0 && base::UTF8ToUTF16(buf, bytes_written, &result) &&
441 result.length() == 1) ? result[0] : 0;
444 unsigned int DefaultXKeysymFromHardwareKeycode(unsigned int hardware_code) {
445 static const unsigned int kHardwareKeycodeMap[] = {
455 XK_Escape, // 0x09: XK_Escape
466 XK_minus, // 0x14: XK_minus
467 XK_equal, // 0x15: XK_equal
468 XK_BackSpace, // 0x16: XK_BackSpace
469 XK_Tab, // 0x17: XK_Tab
480 XK_bracketleft, // 0x22: XK_bracketleft
481 XK_bracketright, // 0x23: XK_bracketright
482 XK_Return, // 0x24: XK_Return
483 XK_Control_L, // 0x25: XK_Control_L
493 XK_semicolon, // 0x2F: XK_semicolon
494 XK_apostrophe, // 0x30: XK_apostrophe
495 XK_grave, // 0x31: XK_grave
496 XK_Shift_L, // 0x32: XK_Shift_L
497 XK_backslash, // 0x33: XK_backslash
505 XK_comma, // 0x3B: XK_comma
506 XK_period, // 0x3C: XK_period
507 XK_slash, // 0x3D: XK_slash
508 XK_Shift_R, // 0x3E: XK_Shift_R
509 0, // 0x3F: XK_KP_Multiply
510 XK_Alt_L, // 0x40: XK_Alt_L
511 XK_space, // 0x41: XK_space
512 XK_Caps_Lock, // 0x42: XK_Caps_Lock
513 XK_F1, // 0x43: XK_F1
514 XK_F2, // 0x44: XK_F2
515 XK_F3, // 0x45: XK_F3
516 XK_F4, // 0x46: XK_F4
517 XK_F5, // 0x47: XK_F5
518 XK_F6, // 0x48: XK_F6
519 XK_F7, // 0x49: XK_F7
520 XK_F8, // 0x4A: XK_F8
521 XK_F9, // 0x4B: XK_F9
522 XK_F10, // 0x4C: XK_F10
523 XK_Num_Lock, // 0x4D: XK_Num_Lock
524 XK_Scroll_Lock, // 0x4E: XK_Scroll_Lock
527 if (hardware_code >= arraysize(kHardwareKeycodeMap)) {
528 // Checks for arrow keys.
529 switch (hardware_code) {
541 return kHardwareKeycodeMap[hardware_code];
544 // TODO(jcampan): this method might be incomplete.
545 int XKeysymForWindowsKeyCode(KeyboardCode keycode, bool shift) {
568 return XK_KP_Multiply;
572 return XK_KP_Subtract;
574 return XK_KP_Decimal;
581 return shift ? XK_ISO_Left_Tab : XK_Tab;
595 return XK_ISO_Level3_Shift;
606 return XK_Hangul_Hanja;
609 case VKEY_NONCONVERT:
611 case VKEY_DBE_SBCSCHAR:
612 return XK_Zenkaku_Hankaku;
613 case VKEY_DBE_DBCSCHAR:
614 return XK_Zenkaku_Hankaku;
648 return shift ? XK_parenright : XK_0;
650 return shift ? XK_exclam : XK_1;
652 return shift ? XK_at : XK_2;
654 return shift ? XK_numbersign : XK_3;
656 return shift ? XK_dollar : XK_4;
658 return shift ? XK_percent : XK_5;
660 return shift ? XK_asciicircum : XK_6;
662 return shift ? XK_ampersand : XK_7;
664 return shift ? XK_asterisk : XK_8;
666 return shift ? XK_parenleft : XK_9;
694 return (shift ? XK_A : XK_a) + (keycode - VKEY_A);
705 return XK_Scroll_Lock;
708 return shift ? XK_colon : XK_semicolon;
710 return shift ? XK_plus : XK_equal;
712 return shift ? XK_less : XK_comma;
714 return shift ? XK_underscore : XK_minus;
715 case VKEY_OEM_PERIOD:
716 return shift ? XK_greater : XK_period;
718 return shift ? XK_question : XK_slash;
720 return shift ? XK_asciitilde : XK_quoteleft;
722 return shift ? XK_braceleft : XK_bracketleft;
724 return shift ? XK_bar : XK_backslash;
726 return shift ? XK_braceright : XK_bracketright;
728 return shift ? XK_quotedbl : XK_quoteright;
730 return XK_ISO_Level5_Shift;
732 return shift ? XK_guillemotleft : XK_guillemotright;
758 return XK_F1 + (keycode - VKEY_F1);
760 case VKEY_BROWSER_BACK:
762 case VKEY_BROWSER_FORWARD:
763 return XF86XK_Forward;
764 case VKEY_BROWSER_REFRESH:
765 return XF86XK_Reload;
766 case VKEY_BROWSER_STOP:
768 case VKEY_BROWSER_SEARCH:
769 return XF86XK_Search;
770 case VKEY_BROWSER_FAVORITES:
771 return XF86XK_Favorites;
772 case VKEY_BROWSER_HOME:
773 return XF86XK_HomePage;
774 case VKEY_VOLUME_MUTE:
775 return XF86XK_AudioMute;
776 case VKEY_VOLUME_DOWN:
777 return XF86XK_AudioLowerVolume;
779 return XF86XK_AudioRaiseVolume;
780 case VKEY_MEDIA_NEXT_TRACK:
781 return XF86XK_AudioNext;
782 case VKEY_MEDIA_PREV_TRACK:
783 return XF86XK_AudioPrev;
784 case VKEY_MEDIA_STOP:
785 return XF86XK_AudioStop;
786 case VKEY_MEDIA_PLAY_PAUSE:
787 return XF86XK_AudioPlay;
788 case VKEY_MEDIA_LAUNCH_MAIL:
790 case VKEY_MEDIA_LAUNCH_APP1:
791 return XF86XK_LaunchA;
792 case VKEY_MEDIA_LAUNCH_APP2:
793 return XF86XK_LaunchB;
797 return XF86XK_PowerOff;
798 case VKEY_BRIGHTNESS_DOWN:
799 return XF86XK_MonBrightnessDown;
800 case VKEY_BRIGHTNESS_UP:
801 return XF86XK_MonBrightnessUp;
802 case VKEY_KBD_BRIGHTNESS_DOWN:
803 return XF86XK_KbdBrightnessDown;
804 case VKEY_KBD_BRIGHTNESS_UP:
805 return XF86XK_KbdBrightnessUp;
808 LOG(WARNING) << "Unknown keycode:" << keycode;