Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(596)

Side by Side Diff: chrome/browser/ui/ash/event_rewriter.cc

Issue 11417144: Use rewriting to make ChromeOS keyboard F<number> keys produce extended keycodes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "chrome/browser/ui/ash/event_rewriter.h" 5 #include "chrome/browser/ui/ash/event_rewriter.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "ash/shell.h" 9 #include "ash/shell.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 break; 114 break;
115 } 115 }
116 return false; 116 return false;
117 } 117 }
118 118
119 bool HasChromeOSKeyboard() { 119 bool HasChromeOSKeyboard() {
120 return CommandLine::ForCurrentProcess()->HasSwitch( 120 return CommandLine::ForCurrentProcess()->HasSwitch(
121 switches::kHasChromeOSKeyboard); 121 switches::kHasChromeOSKeyboard);
122 } 122 }
123 123
124 bool EventSourceIsChromebookKeyboard(ui::KeyEvent* /* event */) {
125 // TODO(danakj): Determine if the event came from a Chromebook internal
126 // keyboard.
127 return true;
128 }
129
130 bool IsMod3UsedByCurrentInputMethod() { 124 bool IsMod3UsedByCurrentInputMethod() {
131 // Since both German Neo2 XKB layout and Caps Lock depend on Mod3Mask, 125 // Since both German Neo2 XKB layout and Caps Lock depend on Mod3Mask,
132 // it's not possible to make both features work. For now, we don't remap 126 // it's not possible to make both features work. For now, we don't remap
133 // Mod3Mask when Neo2 is in use. 127 // Mod3Mask when Neo2 is in use.
134 // TODO(yusukes): Remove the restriction. 128 // TODO(yusukes): Remove the restriction.
135 return InputMethodManager::GetInstance()->GetCurrentInputMethod().id() == 129 return InputMethodManager::GetInstance()->GetCurrentInputMethod().id() ==
136 kNeo2LayoutId; 130 kNeo2LayoutId;
137 } 131 }
138 #endif 132 #endif
139 133
140 const PrefService* GetPrefService() { 134 const PrefService* GetPrefService() {
141 Profile* profile = ProfileManager::GetDefaultProfile(); 135 Profile* profile = ProfileManager::GetDefaultProfile();
142 if (profile) 136 if (profile)
143 return profile->GetPrefs(); 137 return profile->GetPrefs();
144 return NULL; 138 return NULL;
145 } 139 }
146 140
147 } // namespace 141 } // namespace
148 142
149 EventRewriter::EventRewriter() 143 EventRewriter::EventRewriter()
150 : last_device_id_(kBadDeviceId), 144 : last_device_id_(kBadDeviceId),
151 #if defined(OS_CHROMEOS) 145 #if defined(OS_CHROMEOS)
146 force_external_keyboard_for_testing_(false),
152 xkeyboard_(NULL), 147 xkeyboard_(NULL),
153 #endif 148 #endif
154 pref_service_(NULL) { 149 pref_service_(NULL) {
155 // The ash shell isn't instantiated for our unit tests. 150 // The ash shell isn't instantiated for our unit tests.
156 if (ash::Shell::HasInstance()) 151 if (ash::Shell::HasInstance())
157 ash::Shell::GetPrimaryRootWindow()->AddRootWindowObserver(this); 152 ash::Shell::GetPrimaryRootWindow()->AddRootWindowObserver(this);
158 #if defined(OS_CHROMEOS) 153 #if defined(OS_CHROMEOS)
159 if (base::chromeos::IsRunningOnChromeOS()) { 154 if (base::chromeos::IsRunningOnChromeOS()) {
160 chromeos::XInputHierarchyChangedEventListener::GetInstance() 155 chromeos::XInputHierarchyChangedEventListener::GetInstance()
161 ->AddObserver(this); 156 ->AddObserver(this);
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 kp_1_xkeycode_ = XKeysymToKeycode(display, XK_KP_1); 289 kp_1_xkeycode_ = XKeysymToKeycode(display, XK_KP_1);
295 kp_2_xkeycode_ = XKeysymToKeycode(display, XK_KP_2); 290 kp_2_xkeycode_ = XKeysymToKeycode(display, XK_KP_2);
296 kp_3_xkeycode_ = XKeysymToKeycode(display, XK_KP_3); 291 kp_3_xkeycode_ = XKeysymToKeycode(display, XK_KP_3);
297 kp_4_xkeycode_ = XKeysymToKeycode(display, XK_KP_4); 292 kp_4_xkeycode_ = XKeysymToKeycode(display, XK_KP_4);
298 kp_5_xkeycode_ = XKeysymToKeycode(display, XK_KP_5); 293 kp_5_xkeycode_ = XKeysymToKeycode(display, XK_KP_5);
299 kp_6_xkeycode_ = XKeysymToKeycode(display, XK_KP_6); 294 kp_6_xkeycode_ = XKeysymToKeycode(display, XK_KP_6);
300 kp_7_xkeycode_ = XKeysymToKeycode(display, XK_KP_7); 295 kp_7_xkeycode_ = XKeysymToKeycode(display, XK_KP_7);
301 kp_8_xkeycode_ = XKeysymToKeycode(display, XK_KP_8); 296 kp_8_xkeycode_ = XKeysymToKeycode(display, XK_KP_8);
302 kp_9_xkeycode_ = XKeysymToKeycode(display, XK_KP_9); 297 kp_9_xkeycode_ = XKeysymToKeycode(display, XK_KP_9);
303 kp_decimal_xkeycode_ = XKeysymToKeycode(display, XK_KP_Decimal); 298 kp_decimal_xkeycode_ = XKeysymToKeycode(display, XK_KP_Decimal);
299 f1_xkeycode_ = XKeysymToKeycode(display, XK_F1);
300 f2_xkeycode_ = XKeysymToKeycode(display, XK_F2);
301 f3_xkeycode_ = XKeysymToKeycode(display, XK_F3);
302 f4_xkeycode_ = XKeysymToKeycode(display, XK_F4);
303 f5_xkeycode_ = XKeysymToKeycode(display, XK_F5);
304 f6_xkeycode_ = XKeysymToKeycode(display, XK_F6);
305 f7_xkeycode_ = XKeysymToKeycode(display, XK_F7);
306 f8_xkeycode_ = XKeysymToKeycode(display, XK_F8);
307 f9_xkeycode_ = XKeysymToKeycode(display, XK_F9);
308 f10_xkeycode_ = XKeysymToKeycode(display, XK_F10);
309 f11_xkeycode_ = XKeysymToKeycode(display, XK_F11);
310 f12_xkeycode_ = XKeysymToKeycode(display, XK_F12);
311 number1_xkeycode_ = XKeysymToKeycode(display, XK_1);
312 number2_xkeycode_ = XKeysymToKeycode(display, XK_2);
313 number3_xkeycode_ = XKeysymToKeycode(display, XK_3);
314 number4_xkeycode_ = XKeysymToKeycode(display, XK_4);
315 number5_xkeycode_ = XKeysymToKeycode(display, XK_5);
316 number6_xkeycode_ = XKeysymToKeycode(display, XK_6);
317 number7_xkeycode_ = XKeysymToKeycode(display, XK_7);
318 number8_xkeycode_ = XKeysymToKeycode(display, XK_8);
319 number9_xkeycode_ = XKeysymToKeycode(display, XK_9);
320 number0_xkeycode_ = XKeysymToKeycode(display, XK_0);
321 minus_xkeycode_ = XKeysymToKeycode(display, XK_minus);
322 equal_xkeycode_ = XKeysymToKeycode(display, XK_equal);
323 browser_back_xkeycode_ = XKeysymToKeycode(display, XF86XK_Back);
324 browser_forward_xkeycode_ = XKeysymToKeycode(display, XF86XK_Forward);
325 browser_refresh_xkeycode_ = XKeysymToKeycode(display, XF86XK_Reload);
326 media_launch_app1_xkeycode_ = XKeysymToKeycode(display, XF86XK_LaunchA);
327 media_launch_app2_xkeycode_ = XKeysymToKeycode(display, XF86XK_LaunchB);
328 brightness_down_xkeycode_ =
329 XKeysymToKeycode(display, XF86XK_MonBrightnessDown);
330 brightness_up_xkeycode_ = XKeysymToKeycode(display, XF86XK_MonBrightnessUp);
331 volume_mute_xkeycode_ = XKeysymToKeycode(display, XF86XK_AudioMute);
332 volume_down_xkeycode_ = XKeysymToKeycode(display, XF86XK_AudioLowerVolume);
333 volume_up_xkeycode_ = XKeysymToKeycode(display, XF86XK_AudioRaiseVolume);
334 power_xkeycode_ = XKeysymToKeycode(display, XF86XK_PowerOff);
304 } 335 }
305 336
306 KeyCode EventRewriter::NativeKeySymToNativeKeycode(KeySym keysym) { 337 KeyCode EventRewriter::NativeKeySymToNativeKeycode(KeySym keysym) {
307 switch (keysym) { 338 switch (keysym) {
308 case XK_Control_L: 339 case XK_Control_L:
309 return control_l_xkeycode_; 340 return control_l_xkeycode_;
310 case XK_Control_R: 341 case XK_Control_R:
311 return control_r_xkeycode_; 342 return control_r_xkeycode_;
312 case XK_Alt_L: 343 case XK_Alt_L:
313 return alt_l_xkeycode_; 344 return alt_l_xkeycode_;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 return kp_8_xkeycode_; 384 return kp_8_xkeycode_;
354 case XK_KP_9: 385 case XK_KP_9:
355 return kp_9_xkeycode_; 386 return kp_9_xkeycode_;
356 case XK_KP_Decimal: 387 case XK_KP_Decimal:
357 return kp_decimal_xkeycode_; 388 return kp_decimal_xkeycode_;
358 default: 389 default:
359 break; 390 break;
360 } 391 }
361 return 0U; 392 return 0U;
362 } 393 }
394
395 bool EventRewriter::EventSourceIsChromebookKeyboard(ui::KeyEvent* /* event */) {
396 // TODO(danakj): Determine if the event came from a Chromebook internal
397 // keyboard.
398 if (force_external_keyboard_for_testing_)
399 return false;
400 return true;
401 }
363 #endif 402 #endif
364 403
365 void EventRewriter::Rewrite(ui::KeyEvent* event) { 404 void EventRewriter::Rewrite(ui::KeyEvent* event) {
366 #if defined(OS_CHROMEOS) 405 #if defined(OS_CHROMEOS)
367 // Do not rewrite an event sent by ui_controls::SendKeyPress(). See 406 // Do not rewrite an event sent by ui_controls::SendKeyPress(). See
368 // crbug.com/136465. 407 // crbug.com/136465.
369 if (event->native_event()->xkey.send_event) 408 if (event->native_event()->xkey.send_event)
370 return; 409 return;
371 #endif 410 #endif
372 RewriteModifiers(event); 411 RewriteModifiers(event);
373 RewriteNumPadKeys(event); 412 RewriteNumPadKeys(event);
374 RewriteBackspaceAndArrowKeys(event); 413 RewriteBackspaceAndArrowKeys(event);
375 // TODO(yusukes): Implement crosbug.com/27167 (allow sending function keys). 414 RewriteFunctionKeys(event);
376 } 415 }
377 416
378 bool EventRewriter::IsAppleKeyboard() const { 417 bool EventRewriter::IsAppleKeyboard() const {
379 if (last_device_id_ == kBadDeviceId) 418 if (last_device_id_ == kBadDeviceId)
380 return false; 419 return false;
381 420
382 // Check which device generated |event|. 421 // Check which device generated |event|.
383 std::map<int, DeviceType>::const_iterator iter = 422 std::map<int, DeviceType>::const_iterator iter =
384 device_id_to_type_.find(last_device_id_); 423 device_id_to_type_.find(last_device_id_);
385 if (iter == device_id_to_type_.end()) { 424 if (iter == device_id_to_type_.end()) {
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 ui::VKEY_NEXT, event->flags()); 763 ui::VKEY_NEXT, event->flags());
725 rewritten = true; 764 rewritten = true;
726 } 765 }
727 } 766 }
728 #else 767 #else
729 // TODO(yusukes): Support Ash on other platforms if needed. 768 // TODO(yusukes): Support Ash on other platforms if needed.
730 #endif 769 #endif
731 return rewritten; 770 return rewritten;
732 } 771 }
733 772
773 bool EventRewriter::RewriteFunctionKeys(ui::KeyEvent* event) {
774 #if defined(OS_CHROMEOS)
775 XEvent* xev = event->native_event();
776 XKeyEvent* xkey = &(xev->xkey);
777 const KeySym keysym = XLookupKeysym(xkey, 0);
778
779 KeyCode remapped_native_keycode = 0;
780 ui::KeyboardCode remapped_keycode = ui::VKEY_UNKNOWN;
781 unsigned int remapped_native_state = xkey->state;
782 int remapped_flags = event->flags();
783
784 // On a Chromebook keyboard, F<number> keys have special purposes. On other
785 // keyboards, they should act as usual.
786 if (!EventSourceIsChromebookKeyboard(event))
787 return false;
788
789 // Rewrite the actual F1-F12 keys on a Chromebook keyboard to special keys.
790 switch (keysym) {
791 case XK_F1:
792 // Remap F1 to BROWSER_BACK
793 remapped_native_keycode = browser_back_xkeycode_;
794 remapped_keycode = ui::VKEY_BROWSER_BACK;
795 break;
796 case XK_F2:
797 // Remap F2 to BROWSER_FORWARD
798 remapped_native_keycode = browser_forward_xkeycode_;
799 remapped_keycode = ui::VKEY_BROWSER_FORWARD;
800 break;
801 case XK_F3:
802 // Remap F3 to BROWSER_REFRESH
803 remapped_native_keycode = browser_refresh_xkeycode_;
804 remapped_keycode = ui::VKEY_BROWSER_REFRESH;
805 break;
806 case XK_F4:
807 // Remap F4 to MEDIA_LAUNCH_APP2
808 remapped_native_keycode = media_launch_app2_xkeycode_;
809 remapped_keycode = ui::VKEY_MEDIA_LAUNCH_APP2;
810 break;
811 case XK_F5:
812 // Remap F5 to MEDIA_LAUNCH_APP1
813 remapped_native_keycode = media_launch_app1_xkeycode_;
814 remapped_keycode = ui::VKEY_MEDIA_LAUNCH_APP1;
815 break;
816 case XK_F6:
817 // Remap F6 to BRIGHTNESS_DOWN
818 remapped_native_keycode = brightness_down_xkeycode_;
819 remapped_keycode = ui::VKEY_BRIGHTNESS_DOWN;
820 break;
821 case XK_F7:
822 // Remap F7 to BRIGHTNESS_UP
823 remapped_native_keycode = brightness_up_xkeycode_;
824 remapped_keycode = ui::VKEY_BRIGHTNESS_UP;
825 break;
826 case XK_F8:
827 // Remap F8 to VOLUME_MUTE
828 remapped_native_keycode = volume_mute_xkeycode_;
829 remapped_keycode = ui::VKEY_VOLUME_MUTE;
830 break;
831 case XK_F9:
832 // Remap F9 to VOLUME_DOWN
833 remapped_native_keycode = volume_down_xkeycode_;
834 remapped_keycode = ui::VKEY_VOLUME_DOWN;
835 break;
836 case XK_F10:
837 // Remap F10 to VOLUME_UP
838 remapped_native_keycode = volume_up_xkeycode_;
839 remapped_keycode = ui::VKEY_VOLUME_UP;
840 break;
841 case XK_F11:
842 // Remap F11 to POWER
843 remapped_native_keycode = power_xkeycode_;
844 remapped_keycode = ui::VKEY_POWER;
845 break;
846 default:
847 break;
848 }
849
850 const PrefService* pref_service =
851 pref_service_ ? pref_service_ : GetPrefService();
852 bool chromebook_function_key = CommandLine::ForCurrentProcess()->HasSwitch(
853 switches::kEnableChromebookFunctionKey);
854
855 bool search_as_function_key = chromebook_function_key && pref_service &&
856 pref_service->GetBoolean(prefs::kLanguageSearchKeyActsAsFunctionKey);
857
858 // When using Search as a Function key, remap Search+<number> to F<number>.
859 if (search_as_function_key && xkey->state & Mod4Mask) {
860 // We check the keycode here instead of the keysym, as these keys have
861 // different keysyms when modifiers are pressed, such as shift.
862 KeyCode xkeycode = xkey->keycode;
863 if (xkeycode == number1_xkeycode_) {
864 // Remap Search+1 to F1.
865 remapped_native_keycode = f1_xkeycode_;
866 remapped_keycode = ui::VKEY_F1;
867 remapped_native_state &= ~Mod4Mask;
868 } else if (xkeycode == number2_xkeycode_) {
869 // Remap Search+2 to F2.
870 remapped_native_keycode = f2_xkeycode_;
871 remapped_keycode = ui::VKEY_F2;
872 remapped_native_state &= ~Mod4Mask;
873 } else if (xkeycode == number3_xkeycode_) {
874 // Remap Search+3 to F3.
875 remapped_native_keycode = f3_xkeycode_;
876 remapped_keycode = ui::VKEY_F3;
877 remapped_native_state &= ~Mod4Mask;
878 } else if (xkeycode == number4_xkeycode_) {
879 // Remap Search+4 to F4.
880 remapped_native_keycode = f4_xkeycode_;
881 remapped_keycode = ui::VKEY_F4;
882 remapped_native_state &= ~Mod4Mask;
883 } else if (xkeycode == number5_xkeycode_) {
884 // Remap Search+5 to F5.
885 remapped_native_keycode = f5_xkeycode_;
886 remapped_keycode = ui::VKEY_F5;
887 remapped_native_state &= ~Mod4Mask;
888 } else if (xkeycode == number6_xkeycode_) {
889 // Remap Search+6 to F6.
890 remapped_native_keycode = f6_xkeycode_;
891 remapped_keycode = ui::VKEY_F6;
892 remapped_native_state &= ~Mod4Mask;
893 } else if (xkeycode == number7_xkeycode_) {
894 // Remap Search+7 to F7.
895 remapped_native_keycode = f7_xkeycode_;
896 remapped_keycode = ui::VKEY_F7;
897 remapped_native_state &= ~Mod4Mask;
898 } else if (xkeycode == number8_xkeycode_) {
899 // Remap Search+8 to F8.
900 remapped_native_keycode = f8_xkeycode_;
901 remapped_keycode = ui::VKEY_F8;
902 remapped_native_state &= ~Mod4Mask;
903 } else if (xkeycode == number9_xkeycode_) {
904 // Remap Search+9 to F9.
905 remapped_native_keycode = f9_xkeycode_;
906 remapped_keycode = ui::VKEY_F9;
907 remapped_native_state &= ~Mod4Mask;
908 } else if (xkeycode == number0_xkeycode_) {
909 // Remap Search+0 to F10.
910 remapped_native_keycode = f10_xkeycode_;
911 remapped_keycode = ui::VKEY_F10;
912 remapped_native_state &= ~Mod4Mask;
913 } else if (xkeycode == minus_xkeycode_) {
Yusuke Sato 2012/11/27 01:56:54 Could you add a TODO comment to explain the i18n k
danakj 2012/11/27 03:14:26 Yep!
914 // Remap Search+- to F11.
915 remapped_native_keycode = f11_xkeycode_;
916 remapped_keycode = ui::VKEY_F11;
917 remapped_native_state &= ~Mod4Mask;
918 } else if (xkeycode == equal_xkeycode_) {
919 // Remap Search+= to F12.
920 remapped_native_keycode = f12_xkeycode_;
921 remapped_keycode = ui::VKEY_F12;
922 remapped_native_state &= ~Mod4Mask;
923 }
924 }
925
926 if (!remapped_native_keycode || remapped_keycode == ui::VKEY_UNKNOWN)
927 return false;
928
929 OverwriteEvent(event, remapped_native_keycode, remapped_native_state,
930 remapped_keycode, remapped_flags);
931 return true;
932 #else
933 // TODO(danakj): Support Ash on other platforms if needed.
934 #endif
935
936 return false;
Yusuke Sato 2012/11/27 01:56:54 nit: move this line to line 933?
danakj 2012/11/27 03:14:26 Done.
937 }
938
734 void EventRewriter::RewriteLocatedEvent(ui::LocatedEvent* event) { 939 void EventRewriter::RewriteLocatedEvent(ui::LocatedEvent* event) {
735 #if defined(OS_CHROMEOS) 940 #if defined(OS_CHROMEOS)
736 if (event->flags() & ui::EF_IS_SYNTHESIZED) 941 if (event->flags() & ui::EF_IS_SYNTHESIZED)
737 return; 942 return;
738 943
739 XEvent* xevent = event->native_event(); 944 XEvent* xevent = event->native_event();
740 if (!xevent || xevent->type != GenericEvent) 945 if (!xevent || xevent->type != GenericEvent)
741 return; 946 return;
742 947
743 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data); 948 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
799 const DeviceType type = EventRewriter::GetDeviceType(device_name); 1004 const DeviceType type = EventRewriter::GetDeviceType(device_name);
800 if (type == kDeviceAppleKeyboard) { 1005 if (type == kDeviceAppleKeyboard) {
801 VLOG(1) << "Apple keyboard '" << device_name << "' connected: " 1006 VLOG(1) << "Apple keyboard '" << device_name << "' connected: "
802 << "id=" << device_id; 1007 << "id=" << device_id;
803 } 1008 }
804 // Always overwrite the existing device_id since the X server may reuse a 1009 // Always overwrite the existing device_id since the X server may reuse a
805 // device id for an unattached device. 1010 // device id for an unattached device.
806 device_id_to_type_[device_id] = type; 1011 device_id_to_type_[device_id] = type;
807 return type; 1012 return type;
808 } 1013 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698