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 #if defined(TOOLKIT_GTK)
378 case XF86XK_AddFavorite:
382 // ui::AcceleratorGtk tries to convert the XF86XK_ keysyms on Chrome
383 // startup. It's safe to return VKEY_UNKNOWN here since ui::AcceleratorGtk
384 // also checks a Gdk keysym. http://crbug.com/109843
388 // For supporting multimedia buttons on a USB keyboard.
390 return VKEY_BROWSER_BACK;
392 return VKEY_BROWSER_FORWARD;
394 return VKEY_BROWSER_REFRESH;
396 return VKEY_BROWSER_STOP;
398 return VKEY_BROWSER_SEARCH;
399 case XF86XK_Favorites:
400 return VKEY_BROWSER_FAVORITES;
401 case XF86XK_HomePage:
402 return VKEY_BROWSER_HOME;
403 case XF86XK_AudioMute:
404 return VKEY_VOLUME_MUTE;
405 case XF86XK_AudioLowerVolume:
406 return VKEY_VOLUME_DOWN;
407 case XF86XK_AudioRaiseVolume:
408 return VKEY_VOLUME_UP;
409 case XF86XK_AudioNext:
410 return VKEY_MEDIA_NEXT_TRACK;
411 case XF86XK_AudioPrev:
412 return VKEY_MEDIA_PREV_TRACK;
413 case XF86XK_AudioStop:
414 return VKEY_MEDIA_STOP;
415 case XF86XK_AudioPlay:
416 return VKEY_MEDIA_PLAY_PAUSE;
418 return VKEY_MEDIA_LAUNCH_MAIL;
419 case XF86XK_LaunchA: // F3 on an Apple keyboard.
420 return VKEY_MEDIA_LAUNCH_APP1;
421 case XF86XK_LaunchB: // F4 on an Apple keyboard.
422 case XF86XK_Calculator:
423 return VKEY_MEDIA_LAUNCH_APP2;
426 case XF86XK_PowerOff:
428 case XF86XK_MonBrightnessDown:
429 return VKEY_BRIGHTNESS_DOWN;
430 case XF86XK_MonBrightnessUp:
431 return VKEY_BRIGHTNESS_UP;
432 case XF86XK_KbdBrightnessDown:
433 return VKEY_KBD_BRIGHTNESS_DOWN;
434 case XF86XK_KbdBrightnessUp:
435 return VKEY_KBD_BRIGHTNESS_UP;
437 // TODO(sad): some keycodes are still missing.
439 DLOG(WARNING) << "Unknown keysym: " << base::StringPrintf("0x%x", keysym);
443 const char* CodeFromXEvent(XEvent* xev) {
444 return KeycodeConverter::GetInstance()->NativeKeycodeToCode(
448 uint16 GetCharacterFromXEvent(XEvent* xev) {
450 int bytes_written = XLookupString(&xev->xkey, buf, 6, NULL, NULL);
451 DCHECK_LE(bytes_written, 6);
453 base::string16 result;
454 return (bytes_written > 0 && base::UTF8ToUTF16(buf, bytes_written, &result) &&
455 result.length() == 1) ? result[0] : 0;
458 unsigned int DefaultXKeysymFromHardwareKeycode(unsigned int hardware_code) {
459 static const unsigned int kHardwareKeycodeMap[] = {
469 XK_Escape, // 0x09: XK_Escape
480 XK_minus, // 0x14: XK_minus
481 XK_equal, // 0x15: XK_equal
482 XK_BackSpace, // 0x16: XK_BackSpace
483 XK_Tab, // 0x17: XK_Tab
494 XK_bracketleft, // 0x22: XK_bracketleft
495 XK_bracketright, // 0x23: XK_bracketright
496 XK_Return, // 0x24: XK_Return
497 XK_Control_L, // 0x25: XK_Control_L
507 XK_semicolon, // 0x2F: XK_semicolon
508 XK_apostrophe, // 0x30: XK_apostrophe
509 XK_grave, // 0x31: XK_grave
510 XK_Shift_L, // 0x32: XK_Shift_L
511 XK_backslash, // 0x33: XK_backslash
519 XK_comma, // 0x3B: XK_comma
520 XK_period, // 0x3C: XK_period
521 XK_slash, // 0x3D: XK_slash
522 XK_Shift_R, // 0x3E: XK_Shift_R
523 0, // 0x3F: XK_KP_Multiply
524 XK_Alt_L, // 0x40: XK_Alt_L
525 XK_space, // 0x41: XK_space
526 XK_Caps_Lock, // 0x42: XK_Caps_Lock
527 XK_F1, // 0x43: XK_F1
528 XK_F2, // 0x44: XK_F2
529 XK_F3, // 0x45: XK_F3
530 XK_F4, // 0x46: XK_F4
531 XK_F5, // 0x47: XK_F5
532 XK_F6, // 0x48: XK_F6
533 XK_F7, // 0x49: XK_F7
534 XK_F8, // 0x4A: XK_F8
535 XK_F9, // 0x4B: XK_F9
536 XK_F10, // 0x4C: XK_F10
537 XK_Num_Lock, // 0x4D: XK_Num_Lock
538 XK_Scroll_Lock, // 0x4E: XK_Scroll_Lock
541 if (hardware_code >= arraysize(kHardwareKeycodeMap)) {
542 // Checks for arrow keys.
543 switch (hardware_code) {
555 return kHardwareKeycodeMap[hardware_code];
558 // TODO(jcampan): this method might be incomplete.
559 int XKeysymForWindowsKeyCode(KeyboardCode keycode, bool shift) {
582 return XK_KP_Multiply;
586 return XK_KP_Subtract;
588 return XK_KP_Decimal;
595 return shift ? XK_ISO_Left_Tab : XK_Tab;
609 return XK_ISO_Level3_Shift;
620 return XK_Hangul_Hanja;
623 case VKEY_NONCONVERT:
625 case VKEY_DBE_SBCSCHAR:
626 return XK_Zenkaku_Hankaku;
627 case VKEY_DBE_DBCSCHAR:
628 return XK_Zenkaku_Hankaku;
662 return shift ? XK_parenright : XK_0;
664 return shift ? XK_exclam : XK_1;
666 return shift ? XK_at : XK_2;
668 return shift ? XK_numbersign : XK_3;
670 return shift ? XK_dollar : XK_4;
672 return shift ? XK_percent : XK_5;
674 return shift ? XK_asciicircum : XK_6;
676 return shift ? XK_ampersand : XK_7;
678 return shift ? XK_asterisk : XK_8;
680 return shift ? XK_parenleft : XK_9;
708 return (shift ? XK_A : XK_a) + (keycode - VKEY_A);
719 return XK_Scroll_Lock;
722 return shift ? XK_colon : XK_semicolon;
724 return shift ? XK_plus : XK_equal;
726 return shift ? XK_less : XK_comma;
728 return shift ? XK_underscore : XK_minus;
729 case VKEY_OEM_PERIOD:
730 return shift ? XK_greater : XK_period;
732 return shift ? XK_question : XK_slash;
734 return shift ? XK_asciitilde : XK_quoteleft;
736 return shift ? XK_braceleft : XK_bracketleft;
738 return shift ? XK_bar : XK_backslash;
740 return shift ? XK_braceright : XK_bracketright;
742 return shift ? XK_quotedbl : XK_quoteright;
744 return XK_ISO_Level5_Shift;
746 return shift ? XK_guillemotleft : XK_guillemotright;
772 return XK_F1 + (keycode - VKEY_F1);
774 case VKEY_BROWSER_BACK:
776 case VKEY_BROWSER_FORWARD:
777 return XF86XK_Forward;
778 case VKEY_BROWSER_REFRESH:
779 return XF86XK_Reload;
780 case VKEY_BROWSER_STOP:
782 case VKEY_BROWSER_SEARCH:
783 return XF86XK_Search;
784 case VKEY_BROWSER_FAVORITES:
785 return XF86XK_Favorites;
786 case VKEY_BROWSER_HOME:
787 return XF86XK_HomePage;
788 case VKEY_VOLUME_MUTE:
789 return XF86XK_AudioMute;
790 case VKEY_VOLUME_DOWN:
791 return XF86XK_AudioLowerVolume;
793 return XF86XK_AudioRaiseVolume;
794 case VKEY_MEDIA_NEXT_TRACK:
795 return XF86XK_AudioNext;
796 case VKEY_MEDIA_PREV_TRACK:
797 return XF86XK_AudioPrev;
798 case VKEY_MEDIA_STOP:
799 return XF86XK_AudioStop;
800 case VKEY_MEDIA_PLAY_PAUSE:
801 return XF86XK_AudioPlay;
802 case VKEY_MEDIA_LAUNCH_MAIL:
804 case VKEY_MEDIA_LAUNCH_APP1:
805 return XF86XK_LaunchA;
806 case VKEY_MEDIA_LAUNCH_APP2:
807 return XF86XK_LaunchB;
811 return XF86XK_PowerOff;
812 case VKEY_BRIGHTNESS_DOWN:
813 return XF86XK_MonBrightnessDown;
814 case VKEY_BRIGHTNESS_UP:
815 return XF86XK_MonBrightnessUp;
816 case VKEY_KBD_BRIGHTNESS_DOWN:
817 return XF86XK_KbdBrightnessDown;
818 case VKEY_KBD_BRIGHTNESS_UP:
819 return XF86XK_KbdBrightnessUp;
822 LOG(WARNING) << "Unknown keycode:" << keycode;