| 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 |