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

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

Issue 11421055: Add power-user keyboard mode for ChromeOS with Search key acting as a typical Fn key. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Don't avoid remapping Alt-Up etc when a PrefService isn't around 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 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 if (profile) 136 if (profile)
137 return profile->GetPrefs(); 137 return profile->GetPrefs();
138 return NULL; 138 return NULL;
139 } 139 }
140 140
141 } // namespace 141 } // namespace
142 142
143 EventRewriter::EventRewriter() 143 EventRewriter::EventRewriter()
144 : last_device_id_(kBadDeviceId), 144 : last_device_id_(kBadDeviceId),
145 #if defined(OS_CHROMEOS) 145 #if defined(OS_CHROMEOS)
146 drop_search_key_release_(false),
146 xkeyboard_(NULL), 147 xkeyboard_(NULL),
147 #endif 148 #endif
148 pref_service_(NULL) { 149 pref_service_(NULL) {
149 // The ash shell isn't instantiated for our unit tests. 150 // The ash shell isn't instantiated for our unit tests.
150 if (ash::Shell::HasInstance()) 151 if (ash::Shell::HasInstance())
151 ash::Shell::GetPrimaryRootWindow()->AddRootWindowObserver(this); 152 ash::Shell::GetPrimaryRootWindow()->AddRootWindowObserver(this);
152 #if defined(OS_CHROMEOS) 153 #if defined(OS_CHROMEOS)
153 if (base::chromeos::IsRunningOnChromeOS()) { 154 if (base::chromeos::IsRunningOnChromeOS()) {
154 chromeos::XInputHierarchyChangedEventListener::GetInstance() 155 chromeos::XInputHierarchyChangedEventListener::GetInstance()
155 ->AddObserver(this); 156 ->AddObserver(this);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 return kDeviceUnknown; 198 return kDeviceUnknown;
198 } 199 }
199 200
200 void EventRewriter::RewriteForTesting(ui::KeyEvent* event) { 201 void EventRewriter::RewriteForTesting(ui::KeyEvent* event) {
201 Rewrite(event); 202 Rewrite(event);
202 } 203 }
203 204
204 ash::EventRewriterDelegate::Action EventRewriter::RewriteOrFilterKeyEvent( 205 ash::EventRewriterDelegate::Action EventRewriter::RewriteOrFilterKeyEvent(
205 ui::KeyEvent* event) { 206 ui::KeyEvent* event) {
206 if (event->HasNativeEvent()) 207 if (event->HasNativeEvent())
207 Rewrite(event); 208 return Rewrite(event);
208 return ash::EventRewriterDelegate::ACTION_REWRITE_EVENT; 209 return ash::EventRewriterDelegate::ACTION_REWRITE_EVENT;
209 } 210 }
210 211
211 ash::EventRewriterDelegate::Action EventRewriter::RewriteOrFilterLocatedEvent( 212 ash::EventRewriterDelegate::Action EventRewriter::RewriteOrFilterLocatedEvent(
212 ui::LocatedEvent* event) { 213 ui::LocatedEvent* event) {
213 if (event->HasNativeEvent()) 214 if (event->HasNativeEvent())
214 RewriteLocatedEvent(event); 215 RewriteLocatedEvent(event);
215 return ash::EventRewriterDelegate::ACTION_REWRITE_EVENT; 216 return ash::EventRewriterDelegate::ACTION_REWRITE_EVENT;
216 } 217 }
217 218
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 kp_1_xkeycode_ = XKeysymToKeycode(display, XK_KP_1); 289 kp_1_xkeycode_ = XKeysymToKeycode(display, XK_KP_1);
289 kp_2_xkeycode_ = XKeysymToKeycode(display, XK_KP_2); 290 kp_2_xkeycode_ = XKeysymToKeycode(display, XK_KP_2);
290 kp_3_xkeycode_ = XKeysymToKeycode(display, XK_KP_3); 291 kp_3_xkeycode_ = XKeysymToKeycode(display, XK_KP_3);
291 kp_4_xkeycode_ = XKeysymToKeycode(display, XK_KP_4); 292 kp_4_xkeycode_ = XKeysymToKeycode(display, XK_KP_4);
292 kp_5_xkeycode_ = XKeysymToKeycode(display, XK_KP_5); 293 kp_5_xkeycode_ = XKeysymToKeycode(display, XK_KP_5);
293 kp_6_xkeycode_ = XKeysymToKeycode(display, XK_KP_6); 294 kp_6_xkeycode_ = XKeysymToKeycode(display, XK_KP_6);
294 kp_7_xkeycode_ = XKeysymToKeycode(display, XK_KP_7); 295 kp_7_xkeycode_ = XKeysymToKeycode(display, XK_KP_7);
295 kp_8_xkeycode_ = XKeysymToKeycode(display, XK_KP_8); 296 kp_8_xkeycode_ = XKeysymToKeycode(display, XK_KP_8);
296 kp_9_xkeycode_ = XKeysymToKeycode(display, XK_KP_9); 297 kp_9_xkeycode_ = XKeysymToKeycode(display, XK_KP_9);
297 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);
298 } 311 }
299 312
300 KeyCode EventRewriter::NativeKeySymToNativeKeycode(KeySym keysym) { 313 KeyCode EventRewriter::NativeKeySymToNativeKeycode(KeySym keysym) {
301 switch (keysym) { 314 switch (keysym) {
302 case XK_Control_L: 315 case XK_Control_L:
303 return control_l_xkeycode_; 316 return control_l_xkeycode_;
304 case XK_Control_R: 317 case XK_Control_R:
305 return control_r_xkeycode_; 318 return control_r_xkeycode_;
306 case XK_Alt_L: 319 case XK_Alt_L:
307 return alt_l_xkeycode_; 320 return alt_l_xkeycode_;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 return kp_9_xkeycode_; 362 return kp_9_xkeycode_;
350 case XK_KP_Decimal: 363 case XK_KP_Decimal:
351 return kp_decimal_xkeycode_; 364 return kp_decimal_xkeycode_;
352 default: 365 default:
353 break; 366 break;
354 } 367 }
355 return 0U; 368 return 0U;
356 } 369 }
357 #endif 370 #endif
358 371
359 void EventRewriter::Rewrite(ui::KeyEvent* event) { 372 ash::EventRewriterDelegate::Action EventRewriter::Rewrite(ui::KeyEvent* event) {
360 #if defined(OS_CHROMEOS) 373 #if defined(OS_CHROMEOS)
361 // Do not rewrite an event sent by ui_controls::SendKeyPress(). See 374 // Do not rewrite an event sent by ui_controls::SendKeyPress(). See
362 // crbug.com/136465. 375 // crbug.com/136465.
363 if (event->native_event()->xkey.send_event) 376 if (event->native_event()->xkey.send_event)
364 return; 377 return ash::EventRewriterDelegate::ACTION_REWRITE_EVENT;
378
379 if (DropSearchKey(event))
380 return ash::EventRewriterDelegate::ACTION_DROP_EVENT;
365 #endif 381 #endif
366 RewriteModifiers(event); 382 RewriteModifiers(event);
367 RewriteNumPadKeys(event); 383 RewriteNumPadKeys(event);
368 RewriteBackspaceAndArrowKeys(event); 384 RewriteBackspaceAndArrowKeys(event);
369 // TODO(yusukes): Implement crosbug.com/27167 (allow sending function keys). 385 return ash::EventRewriterDelegate::ACTION_REWRITE_EVENT;
370 } 386 }
371 387
372 bool EventRewriter::IsAppleKeyboard() const { 388 bool EventRewriter::IsAppleKeyboard() const {
373 if (last_device_id_ == kBadDeviceId) 389 if (last_device_id_ == kBadDeviceId)
374 return false; 390 return false;
375 391
376 // Check which device generated |event|. 392 // Check which device generated |event|.
377 std::map<int, DeviceType>::const_iterator iter = 393 std::map<int, DeviceType>::const_iterator iter =
378 device_id_to_type_.find(last_device_id_); 394 device_id_to_type_.find(last_device_id_);
379 if (iter == device_id_to_type_.end()) { 395 if (iter == device_id_to_type_.end()) {
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
631 } 647 }
632 #else 648 #else
633 // TODO(yusukes): Support Ash on other platforms if needed. 649 // TODO(yusukes): Support Ash on other platforms if needed.
634 #endif 650 #endif
635 return rewritten; 651 return rewritten;
636 } 652 }
637 653
638 bool EventRewriter::RewriteBackspaceAndArrowKeys(ui::KeyEvent* event) { 654 bool EventRewriter::RewriteBackspaceAndArrowKeys(ui::KeyEvent* event) {
639 bool rewritten = false; 655 bool rewritten = false;
640 #if defined(OS_CHROMEOS) 656 #if defined(OS_CHROMEOS)
657 const PrefService* pref_service =
658 pref_service_ ? pref_service_ : GetPrefService();
659
660 const bool search_as_function_key = pref_service &&
Yusuke Sato 2012/11/26 07:58:12 please do either of the following: 1) check the co
danakj 2012/11/26 17:20:16 I'll check for ChromeOS keyboard flag here, thanks
danakj 2012/11/26 19:36:26 Okay, after the explanation of HasChromeOSKeyboard
661 pref_service->GetBoolean(prefs::kLanguageSearchKeyActsAsFunctionKey);
662
641 XEvent* xev = event->native_event(); 663 XEvent* xev = event->native_event();
642 XKeyEvent* xkey = &(xev->xkey); 664 XKeyEvent* xkey = &(xev->xkey);
665 const KeySym keysym = XLookupKeysym(xkey, 0);
643 666
644 const KeySym keysym = XLookupKeysym(xkey, 0); 667 if (!search_as_function_key &&
645 if (keysym == XK_BackSpace && (xkey->state & Mod1Mask)) { 668 keysym == XK_BackSpace && (xkey->state & Mod1Mask)) {
646 // Remap Alt+Backspace to Delete. 669 // Without Search as Function key: Remap Alt+Backspace to Delete.
647 OverwriteEvent(event, delete_xkeycode_, xkey->state & ~Mod1Mask, 670 OverwriteEvent(event, delete_xkeycode_, xkey->state & ~Mod1Mask,
648 ui::VKEY_DELETE, event->flags() & ~ui::EF_ALT_DOWN); 671 ui::VKEY_DELETE, event->flags() & ~ui::EF_ALT_DOWN);
649 rewritten = true; 672 rewritten = true;
650 } else if (keysym == XK_Up && 673 } else if (search_as_function_key &&
674 keysym == XK_BackSpace && (xkey->state & Mod4Mask)) {
675 // With Search as Function key: Remap Search+Backspace to Delete.
676 OverwriteEvent(event, delete_xkeycode_, xkey->state & ~Mod4Mask,
677 ui::VKEY_DELETE, event->flags());
678 rewritten = true;
679 } else if (!search_as_function_key && keysym == XK_Up &&
651 (xkey->state & ControlMask) && (xkey->state & Mod1Mask)) { 680 (xkey->state & ControlMask) && (xkey->state & Mod1Mask)) {
652 // Remap Ctrl+Alt+Up to Home. 681 // Without Search as Function key: Remap Ctrl+Alt+Up to Home.
653 OverwriteEvent(event, 682 OverwriteEvent(event,
654 home_xkeycode_, 683 home_xkeycode_,
655 xkey->state & ~(Mod1Mask | ControlMask), 684 xkey->state & ~(Mod1Mask | ControlMask),
656 ui::VKEY_HOME, 685 ui::VKEY_HOME,
657 event->flags() & ~(ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN)); 686 event->flags() & ~(ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN));
658 rewritten = true; 687 rewritten = true;
659 } else if (keysym == XK_Up && (xkey->state & Mod1Mask)) { 688 } else if (search_as_function_key &&
660 // Remap Alt+Up to Prior (aka PageUp). 689 keysym == XK_Left && (xkey->state & Mod4Mask)) {
690 // With Search as Function key: Remap Search+Left to Home.
691 OverwriteEvent(event, home_xkeycode_, xkey->state & ~Mod4Mask,
692 ui::VKEY_HOME, event->flags());
693 rewritten = true;
694 } else if (!search_as_function_key &&
695 keysym == XK_Up && (xkey->state & Mod1Mask)) {
696 // Without Search as Function key: Remap Alt+Up to Prior (aka PageUp).
661 OverwriteEvent(event, prior_xkeycode_, xkey->state & ~Mod1Mask, 697 OverwriteEvent(event, prior_xkeycode_, xkey->state & ~Mod1Mask,
662 ui::VKEY_PRIOR, event->flags() & ~ui::EF_ALT_DOWN); 698 ui::VKEY_PRIOR, event->flags() & ~ui::EF_ALT_DOWN);
663 rewritten = true; 699 rewritten = true;
664 } else if (keysym == XK_Down && 700 } else if (search_as_function_key &&
701 keysym == XK_Up && (xkey->state & Mod4Mask)) {
702 // With Search as Function key: Remap Search+Up to Prior (aka PageUp).
703 OverwriteEvent(event, prior_xkeycode_, xkey->state & ~Mod4Mask,
704 ui::VKEY_PRIOR, event->flags());
705 rewritten = true;
706 } else if (!search_as_function_key && keysym == XK_Down &&
665 (xkey->state & ControlMask) && (xkey->state & Mod1Mask)) { 707 (xkey->state & ControlMask) && (xkey->state & Mod1Mask)) {
666 // Remap Ctrl+Alt+Down to End. 708 // Without Search as Function key: Remap Ctrl+Alt+Down to End.
667 OverwriteEvent(event, 709 OverwriteEvent(event,
668 end_xkeycode_, 710 end_xkeycode_,
669 xkey->state & ~(Mod1Mask | ControlMask), 711 xkey->state & ~(Mod1Mask | ControlMask),
670 ui::VKEY_END, 712 ui::VKEY_END,
671 event->flags() & ~(ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN)); 713 event->flags() & ~(ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN));
672 rewritten = true; 714 rewritten = true;
673 } else if (keysym == XK_Down && (xkey->state & Mod1Mask)) { 715 } else if (search_as_function_key &&
674 // Remap Alt+Down to Next (aka PageDown). 716 keysym == XK_Right && (xkey->state & Mod4Mask)) {
717 // With Search as Function key: Remap Search+Right to End.
718 OverwriteEvent(event, end_xkeycode_, xkey->state & ~Mod4Mask,
719 ui::VKEY_END, event->flags());
720 rewritten = true;
721 } else if (!search_as_function_key &&
722 keysym == XK_Down && (xkey->state & Mod1Mask)) {
723 // Without Search as Function key: Remap Alt+Down to Next (aka PageDown).
675 OverwriteEvent(event, next_xkeycode_, xkey->state & ~Mod1Mask, 724 OverwriteEvent(event, next_xkeycode_, xkey->state & ~Mod1Mask,
676 ui::VKEY_NEXT, event->flags() & ~ui::EF_ALT_DOWN); 725 ui::VKEY_NEXT, event->flags() & ~ui::EF_ALT_DOWN);
677 rewritten = true; 726 rewritten = true;
727 } else if (search_as_function_key &&
728 keysym == XK_Down && (xkey->state & Mod4Mask)) {
729 // With Search as Function key: Remap Search+Down to Next (aka PageDown).
730 OverwriteEvent(event, next_xkeycode_, xkey->state & ~Mod4Mask,
731 ui::VKEY_NEXT, event->flags());
732 rewritten = true;
678 } 733 }
679 #else 734 #else
680 // TODO(yusukes): Support Ash on other platforms if needed. 735 // TODO(yusukes): Support Ash on other platforms if needed.
681 #endif 736 #endif
682 return rewritten; 737 return rewritten;
683 } 738 }
684 739
740 #if defined(OS_CHROMEOS)
741 bool EventRewriter::DropSearchKey(ui::KeyEvent* event) {
Yusuke Sato 2012/11/26 06:09:38 I guess we can remove this function if we stop usi
danakj 2012/11/26 17:20:16 We still have to drop the press or you get an apps
742 const PrefService* pref_service =
743 pref_service_ ? pref_service_ : GetPrefService();
744 if (!pref_service)
745 return false;
746 const bool search_as_function_key =
747 pref_service->GetBoolean(prefs::kLanguageSearchKeyActsAsFunctionKey);
748
749 if (!search_as_function_key)
750 return false;
751
752 XEvent* xev = event->native_event();
753 XKeyEvent* xkey = &(xev->xkey);
754
755 const KeySym keysym = XLookupKeysym(xkey, 0);
756
757 bool drop_key = false;
758
759 // If we the Search key acts like a modifier for another key, then drop the
Yusuke Sato 2012/11/26 06:09:38 nit: s/we//
danakj 2012/11/26 19:36:26 Done.
760 // release of the Search key when it happens.
761 if ((xkey->state & Mod4Mask) && keysym != XK_Super_L)
762 drop_search_key_release_ = true;
763
764 if (event->type() == ui::ET_KEY_PRESSED && keysym == XK_Super_L) {
765 // When Search key is acting as Function key, then drop Search key presses
766 // that don't include other modifiers.
767 drop_key = true;
768 } else if (event->type() == ui::ET_KEY_RELEASED && keysym == XK_Super_L) {
769 if (drop_search_key_release_) {
770 // If we ate the Search key press, then also drop the release if another
771 // key used Search as a modifier.
772 drop_key = true;
773 }
774 drop_search_key_release_ = false;
775 }
776
777 return drop_key;
778 }
779 #endif
780
685 void EventRewriter::RewriteLocatedEvent(ui::LocatedEvent* event) { 781 void EventRewriter::RewriteLocatedEvent(ui::LocatedEvent* event) {
686 #if defined(OS_CHROMEOS) 782 #if defined(OS_CHROMEOS)
687 if (event->flags() & ui::EF_IS_SYNTHESIZED) 783 if (event->flags() & ui::EF_IS_SYNTHESIZED)
688 return; 784 return;
689 785
690 XEvent* xevent = event->native_event(); 786 XEvent* xevent = event->native_event();
691 if (!xevent || xevent->type != GenericEvent) 787 if (!xevent || xevent->type != GenericEvent)
692 return; 788 return;
693 789
694 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data); 790 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 const DeviceType type = EventRewriter::GetDeviceType(device_name); 846 const DeviceType type = EventRewriter::GetDeviceType(device_name);
751 if (type == kDeviceAppleKeyboard) { 847 if (type == kDeviceAppleKeyboard) {
752 VLOG(1) << "Apple keyboard '" << device_name << "' connected: " 848 VLOG(1) << "Apple keyboard '" << device_name << "' connected: "
753 << "id=" << device_id; 849 << "id=" << device_id;
754 } 850 }
755 // Always overwrite the existing device_id since the X server may reuse a 851 // Always overwrite the existing device_id since the X server may reuse a
756 // device id for an unattached device. 852 // device id for an unattached device.
757 device_id_to_type_[device_id] = type; 853 device_id_to_type_[device_id] = type;
758 return type; 854 return type;
759 } 855 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698