Chromium Code Reviews| Index: chrome/browser/ui/ash/event_rewriter.cc |
| diff --git a/chrome/browser/ui/ash/event_rewriter.cc b/chrome/browser/ui/ash/event_rewriter.cc |
| index 42b1b8e6d928b410dc41ab1c72bb1c6bf1488542..69b3e0adde280c691c9e6b91c1b24d94d3d8a212 100644 |
| --- a/chrome/browser/ui/ash/event_rewriter.cc |
| +++ b/chrome/browser/ui/ash/event_rewriter.cc |
| @@ -121,12 +121,6 @@ bool HasChromeOSKeyboard() { |
| switches::kHasChromeOSKeyboard); |
| } |
| -bool EventSourceIsChromebookKeyboard(ui::KeyEvent* /* event */) { |
| - // TODO(danakj): Determine if the event came from a Chromebook internal |
| - // keyboard. |
| - return true; |
| -} |
| - |
| bool IsMod3UsedByCurrentInputMethod() { |
| // Since both German Neo2 XKB layout and Caps Lock depend on Mod3Mask, |
| // it's not possible to make both features work. For now, we don't remap |
| @@ -149,6 +143,7 @@ const PrefService* GetPrefService() { |
| EventRewriter::EventRewriter() |
| : last_device_id_(kBadDeviceId), |
| #if defined(OS_CHROMEOS) |
| + force_external_keyboard_for_testing_(false), |
| xkeyboard_(NULL), |
| #endif |
| pref_service_(NULL) { |
| @@ -200,6 +195,11 @@ EventRewriter::DeviceType EventRewriter::GetDeviceType( |
| return kDeviceAppleKeyboard; |
| } |
| + // TODO(danakj): This could also impact laptops other than Chromebooks, and |
| + // might belong behind a command-line flag to be used only on Chromebooks. |
| + if (LowerCaseEqualsASCII(device_name, "at translated set 2 keyboard")) |
|
Yusuke Sato
2012/11/28 20:39:17
can you also support Chrome USB keyboard for Stump
|
| + return kDeviceChromebookKeyboard; |
| + |
| return kDeviceUnknown; |
| } |
| @@ -301,6 +301,42 @@ void EventRewriter::RefreshKeycodes() { |
| kp_8_xkeycode_ = XKeysymToKeycode(display, XK_KP_8); |
| kp_9_xkeycode_ = XKeysymToKeycode(display, XK_KP_9); |
| kp_decimal_xkeycode_ = XKeysymToKeycode(display, XK_KP_Decimal); |
| + f1_xkeycode_ = XKeysymToKeycode(display, XK_F1); |
| + f2_xkeycode_ = XKeysymToKeycode(display, XK_F2); |
| + f3_xkeycode_ = XKeysymToKeycode(display, XK_F3); |
| + f4_xkeycode_ = XKeysymToKeycode(display, XK_F4); |
| + f5_xkeycode_ = XKeysymToKeycode(display, XK_F5); |
| + f6_xkeycode_ = XKeysymToKeycode(display, XK_F6); |
| + f7_xkeycode_ = XKeysymToKeycode(display, XK_F7); |
| + f8_xkeycode_ = XKeysymToKeycode(display, XK_F8); |
| + f9_xkeycode_ = XKeysymToKeycode(display, XK_F9); |
| + f10_xkeycode_ = XKeysymToKeycode(display, XK_F10); |
| + f11_xkeycode_ = XKeysymToKeycode(display, XK_F11); |
| + f12_xkeycode_ = XKeysymToKeycode(display, XK_F12); |
| + number1_xkeycode_ = XKeysymToKeycode(display, XK_1); |
| + number2_xkeycode_ = XKeysymToKeycode(display, XK_2); |
| + number3_xkeycode_ = XKeysymToKeycode(display, XK_3); |
| + number4_xkeycode_ = XKeysymToKeycode(display, XK_4); |
| + number5_xkeycode_ = XKeysymToKeycode(display, XK_5); |
| + number6_xkeycode_ = XKeysymToKeycode(display, XK_6); |
| + number7_xkeycode_ = XKeysymToKeycode(display, XK_7); |
| + number8_xkeycode_ = XKeysymToKeycode(display, XK_8); |
| + number9_xkeycode_ = XKeysymToKeycode(display, XK_9); |
| + number0_xkeycode_ = XKeysymToKeycode(display, XK_0); |
| + minus_xkeycode_ = XKeysymToKeycode(display, XK_minus); |
| + equal_xkeycode_ = XKeysymToKeycode(display, XK_equal); |
| + browser_back_xkeycode_ = XKeysymToKeycode(display, XF86XK_Back); |
| + browser_forward_xkeycode_ = XKeysymToKeycode(display, XF86XK_Forward); |
| + browser_refresh_xkeycode_ = XKeysymToKeycode(display, XF86XK_Reload); |
| + media_launch_app1_xkeycode_ = XKeysymToKeycode(display, XF86XK_LaunchA); |
| + media_launch_app2_xkeycode_ = XKeysymToKeycode(display, XF86XK_LaunchB); |
| + brightness_down_xkeycode_ = |
| + XKeysymToKeycode(display, XF86XK_MonBrightnessDown); |
| + brightness_up_xkeycode_ = XKeysymToKeycode(display, XF86XK_MonBrightnessUp); |
| + volume_mute_xkeycode_ = XKeysymToKeycode(display, XF86XK_AudioMute); |
| + volume_down_xkeycode_ = XKeysymToKeycode(display, XF86XK_AudioLowerVolume); |
| + volume_up_xkeycode_ = XKeysymToKeycode(display, XF86XK_AudioRaiseVolume); |
| + power_xkeycode_ = XKeysymToKeycode(display, XF86XK_PowerOff); |
| } |
| KeyCode EventRewriter::NativeKeySymToNativeKeycode(KeySym keysym) { |
| @@ -360,6 +396,25 @@ KeyCode EventRewriter::NativeKeySymToNativeKeycode(KeySym keysym) { |
| } |
| return 0U; |
| } |
| + |
| +bool EventRewriter::EventSourceIsChromebookKeyboard(ui::KeyEvent* /* event */) { |
| + if (force_external_keyboard_for_testing_) |
| + return false; |
| + |
| + if (last_device_id_ == kBadDeviceId) |
| + return false; |
| + |
| + // Check which device generated |event|. |
| + std::map<int, DeviceType>::const_iterator iter = |
| + device_id_to_type_.find(last_device_id_); |
| + if (iter == device_id_to_type_.end()) { |
| + LOG(ERROR) << "Device ID " << last_device_id_ << " is unknown."; |
| + return false; |
| + } |
| + |
| + const DeviceType type = iter->second; |
| + return type == kDeviceChromebookKeyboard; |
| +} |
| #endif |
| void EventRewriter::Rewrite(ui::KeyEvent* event) { |
| @@ -372,7 +427,7 @@ void EventRewriter::Rewrite(ui::KeyEvent* event) { |
| RewriteModifiers(event); |
| RewriteNumPadKeys(event); |
| RewriteBackspaceAndArrowKeys(event); |
| - // TODO(yusukes): Implement crosbug.com/27167 (allow sending function keys). |
| + RewriteFunctionKeys(event); |
| } |
| bool EventRewriter::IsAppleKeyboard() const { |
| @@ -731,6 +786,175 @@ bool EventRewriter::RewriteBackspaceAndArrowKeys(ui::KeyEvent* event) { |
| return rewritten; |
| } |
| +bool EventRewriter::RewriteFunctionKeys(ui::KeyEvent* event) { |
| +#if defined(OS_CHROMEOS) |
| + XEvent* xev = event->native_event(); |
| + XKeyEvent* xkey = &(xev->xkey); |
| + const KeySym keysym = XLookupKeysym(xkey, 0); |
| + |
| + KeyCode remapped_native_keycode = 0; |
| + ui::KeyboardCode remapped_keycode = ui::VKEY_UNKNOWN; |
| + unsigned int remapped_native_state = xkey->state; |
| + int remapped_flags = event->flags(); |
| + |
| + // On a Chromebook keyboard, F<number> keys have special purposes. On other |
| + // keyboards, they should act as usual. |
| + if (!EventSourceIsChromebookKeyboard(event)) |
| + return false; |
| + |
| + // Rewrite the actual F1-F12 keys on a Chromebook keyboard to special keys. |
| + switch (keysym) { |
| + case XK_F1: |
| + // Remap F1 to BROWSER_BACK |
| + remapped_native_keycode = browser_back_xkeycode_; |
| + remapped_keycode = ui::VKEY_BROWSER_BACK; |
| + break; |
| + case XK_F2: |
| + // Remap F2 to BROWSER_FORWARD |
| + remapped_native_keycode = browser_forward_xkeycode_; |
| + remapped_keycode = ui::VKEY_BROWSER_FORWARD; |
| + break; |
| + case XK_F3: |
| + // Remap F3 to BROWSER_REFRESH |
| + remapped_native_keycode = browser_refresh_xkeycode_; |
| + remapped_keycode = ui::VKEY_BROWSER_REFRESH; |
| + break; |
| + case XK_F4: |
| + // Remap F4 to MEDIA_LAUNCH_APP2 |
| + remapped_native_keycode = media_launch_app2_xkeycode_; |
| + remapped_keycode = ui::VKEY_MEDIA_LAUNCH_APP2; |
| + break; |
| + case XK_F5: |
| + // Remap F5 to MEDIA_LAUNCH_APP1 |
| + remapped_native_keycode = media_launch_app1_xkeycode_; |
| + remapped_keycode = ui::VKEY_MEDIA_LAUNCH_APP1; |
| + break; |
| + case XK_F6: |
| + // Remap F6 to BRIGHTNESS_DOWN |
| + remapped_native_keycode = brightness_down_xkeycode_; |
| + remapped_keycode = ui::VKEY_BRIGHTNESS_DOWN; |
| + break; |
| + case XK_F7: |
| + // Remap F7 to BRIGHTNESS_UP |
| + remapped_native_keycode = brightness_up_xkeycode_; |
| + remapped_keycode = ui::VKEY_BRIGHTNESS_UP; |
| + break; |
| + case XK_F8: |
| + // Remap F8 to VOLUME_MUTE |
| + remapped_native_keycode = volume_mute_xkeycode_; |
| + remapped_keycode = ui::VKEY_VOLUME_MUTE; |
| + break; |
| + case XK_F9: |
| + // Remap F9 to VOLUME_DOWN |
| + remapped_native_keycode = volume_down_xkeycode_; |
| + remapped_keycode = ui::VKEY_VOLUME_DOWN; |
| + break; |
| + case XK_F10: |
| + // Remap F10 to VOLUME_UP |
| + remapped_native_keycode = volume_up_xkeycode_; |
| + remapped_keycode = ui::VKEY_VOLUME_UP; |
| + break; |
| + case XK_F11: |
| + // Remap F11 to POWER |
| + remapped_native_keycode = power_xkeycode_; |
| + remapped_keycode = ui::VKEY_POWER; |
| + break; |
| + default: |
| + break; |
| + } |
| + |
| + const PrefService* pref_service = |
| + pref_service_ ? pref_service_ : GetPrefService(); |
| + bool chromebook_function_key = CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kEnableChromebookFunctionKey); |
| + |
| + bool search_as_function_key = chromebook_function_key && pref_service && |
| + pref_service->GetBoolean(prefs::kLanguageSearchKeyActsAsFunctionKey); |
| + |
| + // When using Search as a Function key, remap Search+<number> to F<number>. |
| + if (search_as_function_key && xkey->state & Mod4Mask) { |
| + // We check the keycode here instead of the keysym, as these keys have |
| + // different keysyms when modifiers are pressed, such as shift. |
| + |
| + // TODO(danakj): On some i18n keyboards, these choices will be bad and we |
| + // should make layout-specific choices here. For eg. on a french keyboard |
| + // "-" and "6" are the same key, so F11 will not be accessible. |
| + KeyCode xkeycode = xkey->keycode; |
| + if (xkeycode == number1_xkeycode_) { |
| + // Remap Search+1 to F1. |
| + remapped_native_keycode = f1_xkeycode_; |
| + remapped_keycode = ui::VKEY_F1; |
| + remapped_native_state &= ~Mod4Mask; |
| + } else if (xkeycode == number2_xkeycode_) { |
| + // Remap Search+2 to F2. |
| + remapped_native_keycode = f2_xkeycode_; |
| + remapped_keycode = ui::VKEY_F2; |
| + remapped_native_state &= ~Mod4Mask; |
| + } else if (xkeycode == number3_xkeycode_) { |
| + // Remap Search+3 to F3. |
| + remapped_native_keycode = f3_xkeycode_; |
| + remapped_keycode = ui::VKEY_F3; |
| + remapped_native_state &= ~Mod4Mask; |
| + } else if (xkeycode == number4_xkeycode_) { |
| + // Remap Search+4 to F4. |
| + remapped_native_keycode = f4_xkeycode_; |
| + remapped_keycode = ui::VKEY_F4; |
| + remapped_native_state &= ~Mod4Mask; |
| + } else if (xkeycode == number5_xkeycode_) { |
| + // Remap Search+5 to F5. |
| + remapped_native_keycode = f5_xkeycode_; |
| + remapped_keycode = ui::VKEY_F5; |
| + remapped_native_state &= ~Mod4Mask; |
| + } else if (xkeycode == number6_xkeycode_) { |
| + // Remap Search+6 to F6. |
| + remapped_native_keycode = f6_xkeycode_; |
| + remapped_keycode = ui::VKEY_F6; |
| + remapped_native_state &= ~Mod4Mask; |
| + } else if (xkeycode == number7_xkeycode_) { |
| + // Remap Search+7 to F7. |
| + remapped_native_keycode = f7_xkeycode_; |
| + remapped_keycode = ui::VKEY_F7; |
| + remapped_native_state &= ~Mod4Mask; |
| + } else if (xkeycode == number8_xkeycode_) { |
| + // Remap Search+8 to F8. |
| + remapped_native_keycode = f8_xkeycode_; |
| + remapped_keycode = ui::VKEY_F8; |
| + remapped_native_state &= ~Mod4Mask; |
| + } else if (xkeycode == number9_xkeycode_) { |
| + // Remap Search+9 to F9. |
| + remapped_native_keycode = f9_xkeycode_; |
| + remapped_keycode = ui::VKEY_F9; |
| + remapped_native_state &= ~Mod4Mask; |
| + } else if (xkeycode == number0_xkeycode_) { |
| + // Remap Search+0 to F10. |
| + remapped_native_keycode = f10_xkeycode_; |
| + remapped_keycode = ui::VKEY_F10; |
| + remapped_native_state &= ~Mod4Mask; |
| + } else if (xkeycode == minus_xkeycode_) { |
| + // Remap Search+- to F11. |
| + remapped_native_keycode = f11_xkeycode_; |
| + remapped_keycode = ui::VKEY_F11; |
| + remapped_native_state &= ~Mod4Mask; |
| + } else if (xkeycode == equal_xkeycode_) { |
| + // Remap Search+= to F12. |
| + remapped_native_keycode = f12_xkeycode_; |
| + remapped_keycode = ui::VKEY_F12; |
| + remapped_native_state &= ~Mod4Mask; |
| + } |
| + } |
| + |
| + if (!remapped_native_keycode || remapped_keycode == ui::VKEY_UNKNOWN) |
| + return false; |
| + |
| + OverwriteEvent(event, remapped_native_keycode, remapped_native_state, |
| + remapped_keycode, remapped_flags); |
| + return true; |
| +#else |
| + // TODO(danakj): Support Ash on other platforms if needed. |
| + return false; |
| +#endif |
| +} |
| + |
| void EventRewriter::RewriteLocatedEvent(ui::LocatedEvent* event) { |
| #if defined(OS_CHROMEOS) |
| if (event->flags() & ui::EF_IS_SYNTHESIZED) |
| @@ -800,6 +1024,9 @@ EventRewriter::DeviceType EventRewriter::DeviceAddedInternal( |
| if (type == kDeviceAppleKeyboard) { |
| VLOG(1) << "Apple keyboard '" << device_name << "' connected: " |
| << "id=" << device_id; |
| + } else if (type == kDeviceChromebookKeyboard) { |
| + VLOG(1) << "Chromebook keyboard '" << device_name << "' connected: " |
| + << "id=" << device_id; |
| } |
| // Always overwrite the existing device_id since the X server may reuse a |
| // device id for an unattached device. |