OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/events/keycodes/keyboard_code_conversion_x.h" | 5 #include "ui/events/keycodes/keyboard_code_conversion_x.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #define XK_3270 // for XK_3270_BackTab | 9 #define XK_3270 // for XK_3270_BackTab |
10 #include <X11/keysym.h> | 10 #include <X11/XF86keysym.h> |
11 #include <X11/Xlib.h> | 11 #include <X11/Xlib.h> |
12 #include <X11/Xutil.h> | 12 #include <X11/Xutil.h> |
13 #include <X11/XF86keysym.h> | 13 #include <X11/extensions/XInput2.h> |
| 14 #include <X11/keysym.h> |
14 | 15 |
15 #include "base/basictypes.h" | 16 #include "base/basictypes.h" |
16 #include "base/logging.h" | 17 #include "base/logging.h" |
17 #include "base/strings/stringprintf.h" | 18 #include "base/strings/stringprintf.h" |
18 #include "base/strings/sys_string_conversions.h" | 19 #include "base/strings/sys_string_conversions.h" |
19 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
20 #include "ui/events/keycodes/dom4/keycode_converter.h" | 21 #include "ui/events/keycodes/dom4/keycode_converter.h" |
21 | 22 |
22 #define VKEY_UNSUPPORTED VKEY_UNKNOWN | 23 #define VKEY_UNSUPPORTED VKEY_UNKNOWN |
23 | 24 |
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 T_MAP comp = {0}; | 454 T_MAP comp = {0}; |
454 const T_MAP* p = std::lower_bound(map, map + size, key, comp); | 455 const T_MAP* p = std::lower_bound(map, map + size, key, comp); |
455 if (p != map + size && !comp(*p, key) && !comp(key, *p)) | 456 if (p != map + size && !comp(*p, key) && !comp(key, *p)) |
456 return static_cast<KeyboardCode>(p->vk); | 457 return static_cast<KeyboardCode>(p->vk); |
457 return VKEY_UNKNOWN; | 458 return VKEY_UNKNOWN; |
458 } | 459 } |
459 | 460 |
460 } // namespace | 461 } // namespace |
461 | 462 |
462 // Get an ui::KeyboardCode from an X keyevent | 463 // Get an ui::KeyboardCode from an X keyevent |
463 KeyboardCode KeyboardCodeFromXKeyEvent(XEvent* xev) { | 464 KeyboardCode KeyboardCodeFromXKeyEvent(const XEvent* xev) { |
464 // Gets correct VKEY code from XEvent is performed as the following steps: | 465 // Gets correct VKEY code from XEvent is performed as the following steps: |
465 // 1. Gets the keysym without modifier states. | 466 // 1. Gets the keysym without modifier states. |
466 // 2. For [a-z] & [0-9] cases, returns the VKEY code accordingly. | 467 // 2. For [a-z] & [0-9] cases, returns the VKEY code accordingly. |
467 // 3. Find keysym in map0. | 468 // 3. Find keysym in map0. |
468 // 4. If not found, fallback to find keysym + hardware_code in map1. | 469 // 4. If not found, fallback to find keysym + hardware_code in map1. |
469 // 5. If not found, fallback to find keysym + keysym_shift + hardware_code | 470 // 5. If not found, fallback to find keysym + keysym_shift + hardware_code |
470 // in map2. | 471 // in map2. |
471 // 6. If not found, fallback to find keysym + keysym_shift + keysym_altgr + | 472 // 6. If not found, fallback to find keysym + keysym_shift + keysym_altgr + |
472 // hardware_code in map3. | 473 // hardware_code in map3. |
473 // 7. If not found, fallback to find in KeyboardCodeFromXKeysym(), which | 474 // 7. If not found, fallback to find in KeyboardCodeFromXKeysym(), which |
474 // mainly for non-letter keys. | 475 // mainly for non-letter keys. |
475 // 8. If not found, fallback to find with the hardware code in US layout. | 476 // 8. If not found, fallback to find with the hardware code in US layout. |
476 | 477 |
477 KeySym keysym = NoSymbol; | 478 KeySym keysym = NoSymbol; |
478 XKeyEvent xkey = xev->xkey; | 479 XEvent xkeyevent; |
479 xkey.state &= (~0xFF | Mod2Mask); // Clears the xkey's state except numlock. | 480 if (xev->type == GenericEvent) { |
| 481 // Convert the XI2 key event into a core key event so that we can |
| 482 // continue to use XLookupString() until crbug.com/367732 is complete. |
| 483 InitXKeyEventFromXIDeviceEvent(*xev, &xkeyevent); |
| 484 } else { |
| 485 xkeyevent.xkey = xev->xkey; |
| 486 } |
| 487 XKeyEvent* xkey = &xkeyevent.xkey; |
| 488 xkey->state &= (~0xFF | Mod2Mask); // Clears the xkey's state except numlock. |
480 // XLookupKeysym does not take into consideration the state of the lock/shift | 489 // XLookupKeysym does not take into consideration the state of the lock/shift |
481 // etc. keys. So it is necessary to use XLookupString instead. | 490 // etc. keys. So it is necessary to use XLookupString instead. |
482 XLookupString(&xkey, NULL, 0, &keysym, NULL); | 491 XLookupString(xkey, NULL, 0, &keysym, NULL); |
483 | 492 |
484 // [a-z] cases. | 493 // [a-z] cases. |
485 if (keysym >= XK_a && keysym <= XK_z) | 494 if (keysym >= XK_a && keysym <= XK_z) |
486 return static_cast<KeyboardCode>(VKEY_A + keysym - XK_a); | 495 return static_cast<KeyboardCode>(VKEY_A + keysym - XK_a); |
487 | 496 |
488 // [0-9] cases. | 497 // [0-9] cases. |
489 if (keysym >= XK_0 && keysym <= XK_9) | 498 if (keysym >= XK_0 && keysym <= XK_9) |
490 return static_cast<KeyboardCode>(VKEY_0 + keysym - XK_0); | 499 return static_cast<KeyboardCode>(VKEY_0 + keysym - XK_0); |
491 | 500 |
492 KeyboardCode keycode = VKEY_UNKNOWN; | 501 KeyboardCode keycode = VKEY_UNKNOWN; |
493 | 502 |
494 if (!IsKeypadKey(keysym) && !IsPrivateKeypadKey(keysym) && | 503 if (!IsKeypadKey(keysym) && !IsPrivateKeypadKey(keysym) && |
495 !IsCursorKey(keysym) && !IsPFKey(keysym) && !IsFunctionKey(keysym) && | 504 !IsCursorKey(keysym) && !IsPFKey(keysym) && !IsFunctionKey(keysym) && |
496 !IsModifierKey(keysym)) { | 505 !IsModifierKey(keysym)) { |
497 MAP0 key0 = {keysym & 0xFFFF, 0}; | 506 MAP0 key0 = {keysym & 0xFFFF, 0}; |
498 keycode = FindVK(key0, map0, arraysize(map0)); | 507 keycode = FindVK(key0, map0, arraysize(map0)); |
499 if (keycode != VKEY_UNKNOWN) | 508 if (keycode != VKEY_UNKNOWN) |
500 return keycode; | 509 return keycode; |
501 | 510 |
502 MAP1 key1 = {keysym & 0xFFFF, xkey.keycode, 0}; | 511 MAP1 key1 = {keysym & 0xFFFF, xkey->keycode, 0}; |
503 keycode = FindVK(key1, map1, arraysize(map1)); | 512 keycode = FindVK(key1, map1, arraysize(map1)); |
504 if (keycode != VKEY_UNKNOWN) | 513 if (keycode != VKEY_UNKNOWN) |
505 return keycode; | 514 return keycode; |
506 | 515 |
507 KeySym keysym_shift = NoSymbol; | 516 KeySym keysym_shift = NoSymbol; |
508 xkey.state |= ShiftMask; | 517 xkey->state |= ShiftMask; |
509 XLookupString(&xkey, NULL, 0, &keysym_shift, NULL); | 518 XLookupString(xkey, NULL, 0, &keysym_shift, NULL); |
510 MAP2 key2 = {keysym & 0xFFFF, xkey.keycode, keysym_shift & 0xFFFF, 0}; | 519 MAP2 key2 = {keysym & 0xFFFF, xkey->keycode, keysym_shift & 0xFFFF, 0}; |
511 keycode = FindVK(key2, map2, arraysize(map2)); | 520 keycode = FindVK(key2, map2, arraysize(map2)); |
512 if (keycode != VKEY_UNKNOWN) | 521 if (keycode != VKEY_UNKNOWN) |
513 return keycode; | 522 return keycode; |
514 | 523 |
515 KeySym keysym_altgr = NoSymbol; | 524 KeySym keysym_altgr = NoSymbol; |
516 xkey.state &= ~ShiftMask; | 525 xkey->state &= ~ShiftMask; |
517 xkey.state |= Mod1Mask; | 526 xkey->state |= Mod1Mask; |
518 XLookupString(&xkey, NULL, 0, &keysym_altgr, NULL); | 527 XLookupString(xkey, NULL, 0, &keysym_altgr, NULL); |
519 MAP3 key3 = {keysym & 0xFFFF, xkey.keycode, keysym_shift & 0xFFFF, | 528 MAP3 key3 = {keysym & 0xFFFF, xkey->keycode, keysym_shift & 0xFFFF, |
520 keysym_altgr & 0xFFFF, 0}; | 529 keysym_altgr & 0xFFFF, 0}; |
521 keycode = FindVK(key3, map3, arraysize(map3)); | 530 keycode = FindVK(key3, map3, arraysize(map3)); |
522 if (keycode != VKEY_UNKNOWN) | 531 if (keycode != VKEY_UNKNOWN) |
523 return keycode; | 532 return keycode; |
524 | 533 |
525 // On Linux some keys has AltGr char but not on Windows. | 534 // On Linux some keys has AltGr char but not on Windows. |
526 // So if cannot find VKEY with (ch0+sc+ch1+ch2) in map3, tries to fallback | 535 // So if cannot find VKEY with (ch0+sc+ch1+ch2) in map3, tries to fallback |
527 // to just find VKEY with (ch0+sc+ch1). This is the best we could do. | 536 // to just find VKEY with (ch0+sc+ch1). This is the best we could do. |
528 MAP3 key4 = {keysym & 0xFFFF, xkey.keycode, keysym_shift & 0xFFFF, 0xFFFF, | 537 MAP3 key4 = {keysym & 0xFFFF, xkey->keycode, keysym_shift & 0xFFFF, 0xFFFF, |
529 0}; | 538 0}; |
530 const MAP3* p = | 539 const MAP3* p = |
531 std::lower_bound(map3, map3 + arraysize(map3), key4, MAP3()); | 540 std::lower_bound(map3, map3 + arraysize(map3), key4, MAP3()); |
532 if (p != map3 + arraysize(map3) && p->ch0 == key4.ch0 && p->sc == key4.sc && | 541 if (p != map3 + arraysize(map3) && p->ch0 == key4.ch0 && p->sc == key4.sc && |
533 p->ch1 == key4.ch1) | 542 p->ch1 == key4.ch1) |
534 return static_cast<KeyboardCode>(p->vk); | 543 return static_cast<KeyboardCode>(p->vk); |
535 } | 544 } |
536 | 545 |
537 keycode = KeyboardCodeFromXKeysym(keysym); | 546 keycode = KeyboardCodeFromXKeysym(keysym); |
538 if (keycode == VKEY_UNKNOWN) | 547 if (keycode == VKEY_UNKNOWN) |
539 keycode = DefaultKeyboardCodeFromHardwareKeycode(xkey.keycode); | 548 keycode = DefaultKeyboardCodeFromHardwareKeycode(xkey->keycode); |
540 | 549 |
541 return keycode; | 550 return keycode; |
542 } | 551 } |
543 | 552 |
544 KeyboardCode KeyboardCodeFromXKeysym(unsigned int keysym) { | 553 KeyboardCode KeyboardCodeFromXKeysym(unsigned int keysym) { |
545 // TODO(sad): Have |keysym| go through the X map list? | 554 // TODO(sad): Have |keysym| go through the X map list? |
546 | 555 |
547 switch (keysym) { | 556 switch (keysym) { |
548 case XK_BackSpace: | 557 case XK_BackSpace: |
549 return VKEY_BACK; | 558 return VKEY_BACK; |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 return VKEY_KBD_BRIGHTNESS_DOWN; | 825 return VKEY_KBD_BRIGHTNESS_DOWN; |
817 case XF86XK_KbdBrightnessUp: | 826 case XF86XK_KbdBrightnessUp: |
818 return VKEY_KBD_BRIGHTNESS_UP; | 827 return VKEY_KBD_BRIGHTNESS_UP; |
819 | 828 |
820 // TODO(sad): some keycodes are still missing. | 829 // TODO(sad): some keycodes are still missing. |
821 } | 830 } |
822 DLOG(WARNING) << "Unknown keysym: " << base::StringPrintf("0x%x", keysym); | 831 DLOG(WARNING) << "Unknown keysym: " << base::StringPrintf("0x%x", keysym); |
823 return VKEY_UNKNOWN; | 832 return VKEY_UNKNOWN; |
824 } | 833 } |
825 | 834 |
826 const char* CodeFromXEvent(XEvent* xev) { | 835 const char* CodeFromXEvent(const XEvent* xev) { |
827 return KeycodeConverter::GetInstance()->NativeKeycodeToCode( | 836 int keycode = (xev->type == GenericEvent) |
828 xev->xkey.keycode); | 837 ? static_cast<XIDeviceEvent*>(xev->xcookie.data)->detail |
| 838 : xev->xkey.keycode; |
| 839 return KeycodeConverter::GetInstance()->NativeKeycodeToCode(keycode); |
829 } | 840 } |
830 | 841 |
831 uint16 GetCharacterFromXEvent(XEvent* xev) { | 842 uint16 GetCharacterFromXEvent(const XEvent* xev) { |
| 843 XEvent xkeyevent; |
| 844 const XKeyEvent* xkey = NULL; |
832 char buf[6]; | 845 char buf[6]; |
833 int bytes_written = XLookupString(&xev->xkey, buf, 6, NULL, NULL); | 846 if (xev->type == GenericEvent) { |
| 847 // Convert the XI2 key event into a core key event so that we can |
| 848 // continue to use XLookupString() until crbug.com/367732 is complete. |
| 849 InitXKeyEventFromXIDeviceEvent(*xev, &xkeyevent); |
| 850 xkey = &xkeyevent.xkey; |
| 851 } else { |
| 852 xkey = &xev->xkey; |
| 853 } |
| 854 int bytes_written = |
| 855 XLookupString(const_cast<XKeyEvent*>(xkey), buf, 6, NULL, NULL); |
834 DCHECK_LE(bytes_written, 6); | 856 DCHECK_LE(bytes_written, 6); |
835 | 857 |
836 if (bytes_written <= 0) | 858 if (bytes_written <= 0) |
837 return 0; | 859 return 0; |
838 const base::string16& result = base::WideToUTF16( | 860 const base::string16& result = base::WideToUTF16( |
839 base::SysNativeMBToWide(base::StringPiece(buf, bytes_written))); | 861 base::SysNativeMBToWide(base::StringPiece(buf, bytes_written))); |
840 return result.length() == 1 ? result[0] : 0; | 862 return result.length() == 1 ? result[0] : 0; |
841 } | 863 } |
842 | 864 |
843 KeyboardCode DefaultKeyboardCodeFromHardwareKeycode( | 865 KeyboardCode DefaultKeyboardCodeFromHardwareKeycode( |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1269 return XF86XK_KbdBrightnessDown; | 1291 return XF86XK_KbdBrightnessDown; |
1270 case VKEY_KBD_BRIGHTNESS_UP: | 1292 case VKEY_KBD_BRIGHTNESS_UP: |
1271 return XF86XK_KbdBrightnessUp; | 1293 return XF86XK_KbdBrightnessUp; |
1272 | 1294 |
1273 default: | 1295 default: |
1274 LOG(WARNING) << "Unknown keycode:" << keycode; | 1296 LOG(WARNING) << "Unknown keycode:" << keycode; |
1275 return 0; | 1297 return 0; |
1276 } | 1298 } |
1277 } | 1299 } |
1278 | 1300 |
| 1301 void InitXKeyEventFromXIDeviceEvent(const XEvent& src, XEvent* xkeyevent) { |
| 1302 DCHECK(src.type == GenericEvent); |
| 1303 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(src.xcookie.data); |
| 1304 switch (xievent->evtype) { |
| 1305 case XI_KeyPress: |
| 1306 xkeyevent->type = KeyPress; |
| 1307 break; |
| 1308 case XI_KeyRelease: |
| 1309 xkeyevent->type = KeyRelease; |
| 1310 break; |
| 1311 default: |
| 1312 NOTREACHED(); |
| 1313 } |
| 1314 xkeyevent->xkey.serial = xievent->serial; |
| 1315 xkeyevent->xkey.send_event = xievent->send_event; |
| 1316 xkeyevent->xkey.display = xievent->display; |
| 1317 xkeyevent->xkey.window = xievent->event; |
| 1318 xkeyevent->xkey.root = xievent->root; |
| 1319 xkeyevent->xkey.subwindow = xievent->child; |
| 1320 xkeyevent->xkey.time = xievent->time; |
| 1321 xkeyevent->xkey.x = xievent->event_x; |
| 1322 xkeyevent->xkey.y = xievent->event_y; |
| 1323 xkeyevent->xkey.x_root = xievent->root_x; |
| 1324 xkeyevent->xkey.y_root = xievent->root_y; |
| 1325 xkeyevent->xkey.state = xievent->mods.effective; |
| 1326 xkeyevent->xkey.keycode = xievent->detail; |
| 1327 xkeyevent->xkey.same_screen = 1; |
| 1328 } |
| 1329 |
1279 } // namespace ui | 1330 } // namespace ui |
OLD | NEW |