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

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: static const 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_chromeos_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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 bool found_keyboard = false; 188 bool found_keyboard = false;
194 for (size_t i = 0; i < tokens.size(); ++i) { 189 for (size_t i = 0; i < tokens.size(); ++i) {
195 if (!found_apple && LowerCaseEqualsASCII(tokens[i], "apple")) 190 if (!found_apple && LowerCaseEqualsASCII(tokens[i], "apple"))
196 found_apple = true; 191 found_apple = true;
197 if (!found_keyboard && LowerCaseEqualsASCII(tokens[i], "keyboard")) 192 if (!found_keyboard && LowerCaseEqualsASCII(tokens[i], "keyboard"))
198 found_keyboard = true; 193 found_keyboard = true;
199 if (found_apple && found_keyboard) 194 if (found_apple && found_keyboard)
200 return kDeviceAppleKeyboard; 195 return kDeviceAppleKeyboard;
201 } 196 }
202 197
198 if (HasChromeOSKeyboard()) {
199 // The chromebook internal keyboard's name.
200 if (LowerCaseEqualsASCII(device_name, "at translated set 2 keyboard"))
201 return kDeviceChromeOSKeyboard;
202 // The chromebox chrome-specific keyboard's name.
203 if (LowerCaseEqualsASCII(device_name, "samsung usb keyboard"))
204 return kDeviceChromeOSKeyboard;
205 }
206
203 return kDeviceUnknown; 207 return kDeviceUnknown;
204 } 208 }
205 209
206 void EventRewriter::RewriteForTesting(ui::KeyEvent* event) { 210 void EventRewriter::RewriteForTesting(ui::KeyEvent* event) {
207 Rewrite(event); 211 Rewrite(event);
208 } 212 }
209 213
210 ash::EventRewriterDelegate::Action EventRewriter::RewriteOrFilterKeyEvent( 214 ash::EventRewriterDelegate::Action EventRewriter::RewriteOrFilterKeyEvent(
211 ui::KeyEvent* event) { 215 ui::KeyEvent* event) {
212 if (event->HasNativeEvent()) 216 if (event->HasNativeEvent())
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 if (iter == device_id_to_type_.end()) { 272 if (iter == device_id_to_type_.end()) {
269 // |device_id| is unknown. This means the device was connected before 273 // |device_id| is unknown. This means the device was connected before
270 // booting the OS. Query the name of the device and add it to the map. 274 // booting the OS. Query the name of the device and add it to the map.
271 DeviceAdded(device_id); 275 DeviceAdded(device_id);
272 } 276 }
273 277
274 last_device_id_ = device_id; 278 last_device_id_ = device_id;
275 } 279 }
276 280
277 void EventRewriter::RefreshKeycodes() { 281 void EventRewriter::RefreshKeycodes() {
278 Display* display = ui::GetXDisplay(); 282 keysym_to_keycode_map_.clear();
279 control_l_xkeycode_ = XKeysymToKeycode(display, XK_Control_L);
280 control_r_xkeycode_ = XKeysymToKeycode(display, XK_Control_R);
281 alt_l_xkeycode_ = XKeysymToKeycode(display, XK_Alt_L);
282 alt_r_xkeycode_ = XKeysymToKeycode(display, XK_Alt_R);
283 meta_l_xkeycode_ = XKeysymToKeycode(display, XK_Meta_L);
284 meta_r_xkeycode_ = XKeysymToKeycode(display, XK_Meta_R);
285 windows_l_xkeycode_ = XKeysymToKeycode(display, XK_Super_L);
286 caps_lock_xkeycode_ = XKeysymToKeycode(display, XK_Caps_Lock);
287 void_symbol_xkeycode_ = XKeysymToKeycode(display, XK_VoidSymbol);
288 delete_xkeycode_ = XKeysymToKeycode(display, XK_Delete);
289 home_xkeycode_ = XKeysymToKeycode(display, XK_Home);
290 end_xkeycode_ = XKeysymToKeycode(display, XK_End);
291 prior_xkeycode_ = XKeysymToKeycode(display, XK_Prior);
292 next_xkeycode_ = XKeysymToKeycode(display, XK_Next);
293 kp_0_xkeycode_ = XKeysymToKeycode(display, XK_KP_0);
294 kp_1_xkeycode_ = XKeysymToKeycode(display, XK_KP_1);
295 kp_2_xkeycode_ = XKeysymToKeycode(display, XK_KP_2);
296 kp_3_xkeycode_ = XKeysymToKeycode(display, XK_KP_3);
297 kp_4_xkeycode_ = XKeysymToKeycode(display, XK_KP_4);
298 kp_5_xkeycode_ = XKeysymToKeycode(display, XK_KP_5);
299 kp_6_xkeycode_ = XKeysymToKeycode(display, XK_KP_6);
300 kp_7_xkeycode_ = XKeysymToKeycode(display, XK_KP_7);
301 kp_8_xkeycode_ = XKeysymToKeycode(display, XK_KP_8);
302 kp_9_xkeycode_ = XKeysymToKeycode(display, XK_KP_9);
303 kp_decimal_xkeycode_ = XKeysymToKeycode(display, XK_KP_Decimal);
304 } 283 }
305 284
306 KeyCode EventRewriter::NativeKeySymToNativeKeycode(KeySym keysym) { 285 KeyCode EventRewriter::NativeKeySymToNativeKeycode(KeySym keysym) {
307 switch (keysym) { 286 base::hash_map<KeySym, KeyCode>::iterator it;
308 case XK_Control_L: 287
309 return control_l_xkeycode_; 288 if (keysym_to_keycode_map_.count(keysym))
310 case XK_Control_R: 289 return keysym_to_keycode_map_[keysym];
311 return control_r_xkeycode_; 290
312 case XK_Alt_L: 291 Display* display = ui::GetXDisplay();
313 return alt_l_xkeycode_; 292 KeyCode keycode = XKeysymToKeycode(display, keysym);
314 case XK_Alt_R: 293 keysym_to_keycode_map_[keysym] = keycode;
315 return alt_r_xkeycode_; 294 return keycode;
316 case XK_Meta_L: 295 }
317 return meta_l_xkeycode_; 296
318 case XK_Meta_R: 297 bool EventRewriter::EventSourceIsChromeOSKeyboard() const {
319 return meta_r_xkeycode_; 298 if (force_chromeos_keyboard_for_testing_)
320 case XK_Super_L: 299 return true;
321 return windows_l_xkeycode_; 300
322 case XK_Caps_Lock: 301 if (last_device_id_ == kBadDeviceId)
323 return caps_lock_xkeycode_; 302 return false;
324 case XK_VoidSymbol: 303
325 return void_symbol_xkeycode_; 304 // Check which device generated |event|.
326 case XK_Delete: 305 std::map<int, DeviceType>::const_iterator iter =
327 return delete_xkeycode_; 306 device_id_to_type_.find(last_device_id_);
328 case XK_Home: 307 if (iter == device_id_to_type_.end()) {
329 return home_xkeycode_; 308 LOG(ERROR) << "Device ID " << last_device_id_ << " is unknown.";
330 case XK_End: 309 return false;
331 return end_xkeycode_;
332 case XK_Prior:
333 return prior_xkeycode_;
334 case XK_Next:
335 return next_xkeycode_;
336 case XK_KP_0:
337 return kp_0_xkeycode_;
338 case XK_KP_1:
339 return kp_1_xkeycode_;
340 case XK_KP_2:
341 return kp_2_xkeycode_;
342 case XK_KP_3:
343 return kp_3_xkeycode_;
344 case XK_KP_4:
345 return kp_4_xkeycode_;
346 case XK_KP_5:
347 return kp_5_xkeycode_;
348 case XK_KP_6:
349 return kp_6_xkeycode_;
350 case XK_KP_7:
351 return kp_7_xkeycode_;
352 case XK_KP_8:
353 return kp_8_xkeycode_;
354 case XK_KP_9:
355 return kp_9_xkeycode_;
356 case XK_KP_Decimal:
357 return kp_decimal_xkeycode_;
358 default:
359 break;
360 } 310 }
361 return 0U; 311
312 const DeviceType type = iter->second;
313 return type == kDeviceChromeOSKeyboard;
362 } 314 }
363 #endif 315 #endif
364 316
365 void EventRewriter::Rewrite(ui::KeyEvent* event) { 317 void EventRewriter::Rewrite(ui::KeyEvent* event) {
366 #if defined(OS_CHROMEOS) 318 #if defined(OS_CHROMEOS)
367 // Do not rewrite an event sent by ui_controls::SendKeyPress(). See 319 // Do not rewrite an event sent by ui_controls::SendKeyPress(). See
368 // crbug.com/136465. 320 // crbug.com/136465.
369 if (event->native_event()->xkey.send_event) 321 if (event->native_event()->xkey.send_event)
370 return; 322 return;
371 #endif 323 #endif
372 RewriteModifiers(event); 324 RewriteModifiers(event);
373 RewriteNumPadKeys(event); 325 RewriteNumPadKeys(event);
374 RewriteBackspaceAndArrowKeys(event); 326 RewriteBackspaceAndArrowKeys(event);
375 // TODO(yusukes): Implement crosbug.com/27167 (allow sending function keys). 327 RewriteFunctionKeys(event);
376 } 328 }
377 329
378 bool EventRewriter::IsAppleKeyboard() const { 330 bool EventRewriter::IsAppleKeyboard() const {
379 if (last_device_id_ == kBadDeviceId) 331 if (last_device_id_ == kBadDeviceId)
380 return false; 332 return false;
381 333
382 // Check which device generated |event|. 334 // Check which device generated |event|.
383 std::map<int, DeviceType>::const_iterator iter = 335 std::map<int, DeviceType>::const_iterator iter =
384 device_id_to_type_.find(last_device_id_); 336 device_id_to_type_.find(last_device_id_);
385 if (iter == device_id_to_type_.end()) { 337 if (iter == device_id_to_type_.end()) {
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 513
562 bool EventRewriter::RewriteNumPadKeys(ui::KeyEvent* event) { 514 bool EventRewriter::RewriteNumPadKeys(ui::KeyEvent* event) {
563 bool rewritten = false; 515 bool rewritten = false;
564 #if defined(OS_CHROMEOS) 516 #if defined(OS_CHROMEOS)
565 XEvent* xev = event->native_event(); 517 XEvent* xev = event->native_event();
566 XKeyEvent* xkey = &(xev->xkey); 518 XKeyEvent* xkey = &(xev->xkey);
567 519
568 const KeySym keysym = XLookupKeysym(xkey, 0); 520 const KeySym keysym = XLookupKeysym(xkey, 0);
569 switch (keysym) { 521 switch (keysym) {
570 case XK_KP_Insert: 522 case XK_KP_Insert:
571 OverwriteEvent(event, kp_0_xkeycode_, xkey->state | Mod2Mask, 523 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_0),
524 xkey->state | Mod2Mask,
572 ui::VKEY_NUMPAD0, event->flags()); 525 ui::VKEY_NUMPAD0, event->flags());
573 rewritten = true; 526 rewritten = true;
574 break; 527 break;
575 case XK_KP_Delete: 528 case XK_KP_Delete:
576 OverwriteEvent(event, kp_decimal_xkeycode_, xkey->state | Mod2Mask, 529 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_Decimal),
530 xkey->state | Mod2Mask,
577 ui::VKEY_DECIMAL, event->flags()); 531 ui::VKEY_DECIMAL, event->flags());
578 rewritten = true; 532 rewritten = true;
579 break; 533 break;
580 case XK_KP_End: 534 case XK_KP_End:
581 OverwriteEvent(event, kp_1_xkeycode_, xkey->state | Mod2Mask, 535 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_1),
536 xkey->state | Mod2Mask,
582 ui::VKEY_NUMPAD1, event->flags()); 537 ui::VKEY_NUMPAD1, event->flags());
583 rewritten = true; 538 rewritten = true;
584 break; 539 break;
585 case XK_KP_Down: 540 case XK_KP_Down:
586 OverwriteEvent(event, kp_2_xkeycode_, xkey->state | Mod2Mask, 541 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_2),
542 xkey->state | Mod2Mask,
587 ui::VKEY_NUMPAD2, event->flags()); 543 ui::VKEY_NUMPAD2, event->flags());
588 rewritten = true; 544 rewritten = true;
589 break; 545 break;
590 case XK_KP_Next: 546 case XK_KP_Next:
591 OverwriteEvent(event, kp_3_xkeycode_, xkey->state | Mod2Mask, 547 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_3),
548 xkey->state | Mod2Mask,
592 ui::VKEY_NUMPAD3, event->flags()); 549 ui::VKEY_NUMPAD3, event->flags());
593 rewritten = true; 550 rewritten = true;
594 break; 551 break;
595 case XK_KP_Left: 552 case XK_KP_Left:
596 OverwriteEvent(event, kp_4_xkeycode_, xkey->state | Mod2Mask, 553 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_4),
554 xkey->state | Mod2Mask,
597 ui::VKEY_NUMPAD4, event->flags()); 555 ui::VKEY_NUMPAD4, event->flags());
598 rewritten = true; 556 rewritten = true;
599 break; 557 break;
600 case XK_KP_Begin: 558 case XK_KP_Begin:
601 OverwriteEvent(event, kp_5_xkeycode_, xkey->state | Mod2Mask, 559 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_5),
560 xkey->state | Mod2Mask,
602 ui::VKEY_NUMPAD5, event->flags()); 561 ui::VKEY_NUMPAD5, event->flags());
603 rewritten = true; 562 rewritten = true;
604 break; 563 break;
605 case XK_KP_Right: 564 case XK_KP_Right:
606 OverwriteEvent(event, kp_6_xkeycode_, xkey->state | Mod2Mask, 565 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_6),
566 xkey->state | Mod2Mask,
607 ui::VKEY_NUMPAD6, event->flags()); 567 ui::VKEY_NUMPAD6, event->flags());
608 rewritten = true; 568 rewritten = true;
609 break; 569 break;
610 case XK_KP_Home: 570 case XK_KP_Home:
611 OverwriteEvent(event, kp_7_xkeycode_, xkey->state | Mod2Mask, 571 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_7),
572 xkey->state | Mod2Mask,
612 ui::VKEY_NUMPAD7, event->flags()); 573 ui::VKEY_NUMPAD7, event->flags());
613 rewritten = true; 574 rewritten = true;
614 break; 575 break;
615 case XK_KP_Up: 576 case XK_KP_Up:
616 OverwriteEvent(event, kp_8_xkeycode_, xkey->state | Mod2Mask, 577 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_8),
578 xkey->state | Mod2Mask,
617 ui::VKEY_NUMPAD8, event->flags()); 579 ui::VKEY_NUMPAD8, event->flags());
618 rewritten = true; 580 rewritten = true;
619 break; 581 break;
620 case XK_KP_Prior: 582 case XK_KP_Prior:
621 OverwriteEvent(event, kp_9_xkeycode_, xkey->state | Mod2Mask, 583 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_9),
584 xkey->state | Mod2Mask,
622 ui::VKEY_NUMPAD9, event->flags()); 585 ui::VKEY_NUMPAD9, event->flags());
623 rewritten = true; 586 rewritten = true;
624 break; 587 break;
625 case XK_KP_Divide: 588 case XK_KP_Divide:
626 case XK_KP_Multiply: 589 case XK_KP_Multiply:
627 case XK_KP_Subtract: 590 case XK_KP_Subtract:
628 case XK_KP_Add: 591 case XK_KP_Add:
629 case XK_KP_Enter: 592 case XK_KP_Enter:
630 // Add Mod2Mask for consistency. 593 // Add Mod2Mask for consistency.
631 OverwriteEvent(event, xkey->keycode, xkey->state | Mod2Mask, 594 OverwriteEvent(event, xkey->keycode, xkey->state | Mod2Mask,
632 event->key_code(), event->flags()); 595 event->key_code(), event->flags());
633 rewritten = true; 596 rewritten = true;
634 break; 597 break;
635 default: 598 default:
636 break; 599 break;
637 } 600 }
638 #else 601 #else
639 // TODO(yusukes): Support Ash on other platforms if needed. 602 // TODO(yusukes): Support Ash on other platforms if needed.
640 #endif 603 #endif
641 return rewritten; 604 return rewritten;
642 } 605 }
643 606
607 #if defined(OS_CHROMEOS)
608 struct KeyboardRemappingByKeySym {
609 KeySym input_keysym;
610 unsigned int input_mods;
611 unsigned int input_native_mods;
612 KeySym output_keysym;
613 ui::KeyboardCode output_keycode;
614 };
615
616 struct KeyboardRemappingByKeyCode {
617 KeyCode input_keycode;
618 unsigned int input_mods;
619 unsigned int input_native_mods;
620 KeySym output_keysym;
621 ui::KeyboardCode output_keycode;
622 };
623
624 bool RewriteWithKeyboardRemappingsByKeySym(
625 const KeyboardRemappingByKeySym* remappings,
626 size_t num_remappings,
627 KeySym keysym,
628 unsigned int native_mods,
629 unsigned int mods,
630 KeySym* remapped_native_keysym,
631 unsigned int* remapped_native_mods,
632 ui::KeyboardCode* remapped_keycode,
633 unsigned int* remapped_mods) {
634 for (size_t i = 0; i < num_remappings; ++i) {
635 const KeyboardRemappingByKeySym& map = remappings[i];
636
637 if (keysym != map.input_keysym)
638 continue;
639 unsigned int matched_mods = native_mods & map.input_native_mods;
640 if (matched_mods != map.input_native_mods)
641 continue;
642
643 *remapped_native_keysym = map.output_keysym;
644 *remapped_keycode = map.output_keycode;
645 *remapped_native_mods = native_mods & ~map.input_native_mods;
646 *remapped_mods = mods & ~map.input_mods;
647 return true;
648 }
649
650 return false;
651 }
652
653 bool RewriteWithKeyboardRemappingsByKeyCode(
654 const KeyboardRemappingByKeyCode* remappings,
655 size_t num_remappings,
656 KeyCode keycode,
657 unsigned int native_mods,
658 unsigned int mods,
659 KeySym* remapped_native_keysym,
660 unsigned int* remapped_native_mods,
661 ui::KeyboardCode* remapped_keycode,
662 unsigned int* remapped_mods) {
663 for (size_t i = 0; i < num_remappings; ++i) {
664 const KeyboardRemappingByKeyCode& map = remappings[i];
665
666 if (keycode != map.input_keycode)
667 continue;
668 unsigned int matched_mods = native_mods & map.input_native_mods;
669 if (matched_mods != map.input_native_mods)
670 continue;
671
672 *remapped_native_keysym = map.output_keysym;
673 *remapped_keycode = map.output_keycode;
674 *remapped_native_mods = native_mods & ~map.input_native_mods;
675 *remapped_mods = mods & ~map.input_mods;
676 return true;
677 }
678
679 return false;
680 }
681 #endif
682
644 bool EventRewriter::RewriteBackspaceAndArrowKeys(ui::KeyEvent* event) { 683 bool EventRewriter::RewriteBackspaceAndArrowKeys(ui::KeyEvent* event) {
645 bool rewritten = false;
646 #if defined(OS_CHROMEOS) 684 #if defined(OS_CHROMEOS)
647 // On a Chromebook keyboard, modifier keys can be used to access extended 685 // On a ChromeOS keyboard, modifier keys can be used to access extended
648 // keyboard shortcuts. On other keyboards, keys such as delete and page up are 686 // keyboard shortcuts. On other keyboards, keys such as delete and page up are
649 // already available, so we do not need to rewrite anything here. 687 // already available, so we do not need to rewrite anything here.
650 if (!EventSourceIsChromebookKeyboard(event)) 688 if (!EventSourceIsChromeOSKeyboard())
651 return rewritten; 689 return false;
652 690
653 const PrefService* pref_service = 691 const PrefService* pref_service =
654 pref_service_ ? pref_service_ : GetPrefService(); 692 pref_service_ ? pref_service_ : GetPrefService();
655 bool chromebook_function_key = CommandLine::ForCurrentProcess()->HasSwitch( 693 bool chromebook_function_key = CommandLine::ForCurrentProcess()->HasSwitch(
656 switches::kEnableChromebookFunctionKey); 694 switches::kEnableChromebookFunctionKey);
657 695
658 bool search_as_function_key = chromebook_function_key && pref_service && 696 bool search_as_function_key = chromebook_function_key && pref_service &&
659 pref_service->GetBoolean(prefs::kLanguageSearchKeyActsAsFunctionKey); 697 pref_service->GetBoolean(prefs::kLanguageSearchKeyActsAsFunctionKey);
698 if (search_as_function_key)
699 DCHECK(HasChromeOSKeyboard());
660 700
661 XEvent* xev = event->native_event(); 701 XEvent* xev = event->native_event();
662 XKeyEvent* xkey = &(xev->xkey); 702 XKeyEvent* xkey = &(xev->xkey);
663 const KeySym keysym = XLookupKeysym(xkey, 0); 703 const KeySym keysym = XLookupKeysym(xkey, 0);
664 704
705 KeySym remapped_native_keysym = 0;
706 unsigned int remapped_native_mods = 0;
707 ui::KeyboardCode remapped_keycode = ui::VKEY_UNKNOWN;
708 unsigned int remapped_mods = 0;
709
665 if (!search_as_function_key) { 710 if (!search_as_function_key) {
666 if (keysym == XK_BackSpace && (xkey->state & Mod1Mask)) { 711 static const KeyboardRemappingByKeySym remappings[] = {
667 // Without Search as Function key: Remap Alt+Backspace to Delete. 712 { // Alt+BackSpace -> Delete
668 OverwriteEvent(event, delete_xkeycode_, xkey->state & ~Mod1Mask, 713 XK_BackSpace,
669 ui::VKEY_DELETE, event->flags() & ~ui::EF_ALT_DOWN); 714 ui::EF_ALT_DOWN, Mod1Mask,
670 rewritten = true; 715 XK_Delete, ui::VKEY_DELETE,
671 } else if (keysym == XK_Up && 716 },
672 (xkey->state & ControlMask) && (xkey->state & Mod1Mask)) { 717 { // Control+Alt+Up -> Home
673 // Without Search as Function key: Remap Ctrl+Alt+Up to Home. 718 XK_Up,
674 OverwriteEvent(event, 719 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, Mod1Mask | ControlMask,
675 home_xkeycode_, 720 XK_Home, ui::VKEY_HOME,
676 xkey->state & ~(Mod1Mask | ControlMask), 721 },
677 ui::VKEY_HOME, 722 { // Alt+Up -> Prior (aka PageUp)
678 event->flags() & ~(ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN)); 723 XK_Up,
679 rewritten = true; 724 ui::EF_ALT_DOWN, Mod1Mask,
680 } else if (keysym == XK_Up && (xkey->state & Mod1Mask)) { 725 XK_Prior, ui::VKEY_PRIOR,
681 // Without Search as Function key: Remap Alt+Up to Prior (aka PageUp). 726 },
682 OverwriteEvent(event, prior_xkeycode_, xkey->state & ~Mod1Mask, 727 { // Control+Alt+Down -> End
683 ui::VKEY_PRIOR, event->flags() & ~ui::EF_ALT_DOWN); 728 XK_Down,
684 rewritten = true; 729 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, Mod1Mask | ControlMask,
685 } else if (keysym == XK_Down && 730 XK_End, ui::VKEY_END,
686 (xkey->state & ControlMask) && (xkey->state & Mod1Mask)) { 731 },
687 // Without Search as Function key: Remap Ctrl+Alt+Down to End. 732 { // Alt+Down -> Next (aka PageDown)
688 OverwriteEvent(event, 733 XK_Down,
689 end_xkeycode_, 734 ui::EF_ALT_DOWN, Mod1Mask,
690 xkey->state & ~(Mod1Mask | ControlMask), 735 XK_Next, ui::VKEY_NEXT,
691 ui::VKEY_END, 736 }
692 event->flags() & ~(ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN)); 737 };
693 rewritten = true; 738
694 } else if (keysym == XK_Down && (xkey->state & Mod1Mask)) { 739 RewriteWithKeyboardRemappingsByKeySym(remappings,
695 // Without Search as Function key: Remap Alt+Down to Next (aka PageDown). 740 arraysize(remappings),
696 OverwriteEvent(event, next_xkeycode_, xkey->state & ~Mod1Mask, 741 keysym,
697 ui::VKEY_NEXT, event->flags() & ~ui::EF_ALT_DOWN); 742 xkey->state,
698 rewritten = true; 743 event->flags(),
699 } 744 &remapped_native_keysym,
745 &remapped_native_mods,
746 &remapped_keycode,
747 &remapped_mods);
700 } else { 748 } else {
701 if (keysym == XK_BackSpace && (xkey->state & Mod4Mask)) { 749 static const KeyboardRemappingByKeySym remappings[] = {
702 // With Search as Function key: Remap Search+Backspace to Delete. 750 { // Search+BackSpace -> Delete
703 OverwriteEvent(event, delete_xkeycode_, xkey->state & ~Mod4Mask, 751 XK_BackSpace,
704 ui::VKEY_DELETE, event->flags()); 752 0, Mod4Mask,
705 rewritten = true; 753 XK_Delete, ui::VKEY_DELETE,
706 } else if (keysym == XK_Left && (xkey->state & Mod4Mask)) { 754 },
707 // With Search as Function key: Remap Search+Left to Home. 755 { // Search+Left -> Home
708 OverwriteEvent(event, home_xkeycode_, xkey->state & ~Mod4Mask, 756 XK_Left,
709 ui::VKEY_HOME, event->flags()); 757 0, Mod4Mask,
710 rewritten = true; 758 XK_Home, ui::VKEY_HOME,
711 } else if (keysym == XK_Up && (xkey->state & Mod4Mask)) { 759 },
712 // With Search as Function key: Remap Search+Up to Prior (aka PageUp). 760 { // Search+Up -> Prior (aka PageUp)
713 OverwriteEvent(event, prior_xkeycode_, xkey->state & ~Mod4Mask, 761 XK_Up,
714 ui::VKEY_PRIOR, event->flags()); 762 0, Mod4Mask,
715 rewritten = true; 763 XK_Prior, ui::VKEY_PRIOR,
716 } else if (keysym == XK_Right && (xkey->state & Mod4Mask)) { 764 },
717 // With Search as Function key: Remap Search+Right to End. 765 { // Search+Right -> End
718 OverwriteEvent(event, end_xkeycode_, xkey->state & ~Mod4Mask, 766 XK_Right,
719 ui::VKEY_END, event->flags()); 767 0, Mod4Mask,
720 rewritten = true; 768 XK_End, ui::VKEY_END,
721 } else if (keysym == XK_Down && (xkey->state & Mod4Mask)) { 769 },
722 // With Search as Function key: Remap Search+Down to Next (aka PageDown). 770 { // Search+Down -> Next (aka PageDown)
723 OverwriteEvent(event, next_xkeycode_, xkey->state & ~Mod4Mask, 771 XK_Down,
724 ui::VKEY_NEXT, event->flags()); 772 0, Mod4Mask,
725 rewritten = true; 773 XK_Next, ui::VKEY_NEXT,
774 }
775 };
776
777 RewriteWithKeyboardRemappingsByKeySym(remappings,
778 arraysize(remappings),
779 keysym,
780 xkey->state,
781 event->flags(),
782 &remapped_native_keysym,
783 &remapped_native_mods,
784 &remapped_keycode,
785 &remapped_mods);
786 }
787
788 if (!remapped_native_keysym || remapped_keycode == ui::VKEY_UNKNOWN)
789 return false;
790
791 OverwriteEvent(event,
792 NativeKeySymToNativeKeycode(remapped_native_keysym),
793 remapped_native_mods,
794 remapped_keycode,
795 remapped_mods);
796 return true;
797 #else
798 // TODO(yusukes): Support Ash on other platforms if needed.
799 return false;
800 #endif
801 }
802
803 bool EventRewriter::RewriteFunctionKeys(ui::KeyEvent* event) {
804 #if defined(OS_CHROMEOS)
805 XEvent* xev = event->native_event();
806 XKeyEvent* xkey = &(xev->xkey);
807 const KeySym keysym = XLookupKeysym(xkey, 0);
808
809 KeySym remapped_native_keysym = 0;
810 unsigned int remapped_native_mods = 0;
811 ui::KeyboardCode remapped_keycode = ui::VKEY_UNKNOWN;
812 unsigned int remapped_mods = 0;
813
814 // On a ChromeOS keyboard, F<number> keys have special purposes. On other
815 // keyboards, they should act as usual.
816 if (!EventSourceIsChromeOSKeyboard())
817 return false;
818
819 // Rewrite the actual F1-F12 keys on a Chromebook keyboard to special keys.
820 static const KeyboardRemappingByKeySym fkeys_to_special_keys[] = {
821 { XK_F1, 0, 0, XF86XK_Back, ui::VKEY_BROWSER_BACK, },
822 { XK_F2, 0, 0, XF86XK_Forward, ui::VKEY_BROWSER_FORWARD, },
823 { XK_F3, 0, 0, XF86XK_Reload, ui::VKEY_BROWSER_REFRESH, },
824 { XK_F4, 0, 0, XF86XK_LaunchB, ui::VKEY_MEDIA_LAUNCH_APP2, },
825 { XK_F5, 0, 0, XF86XK_LaunchA, ui::VKEY_MEDIA_LAUNCH_APP1, },
826 { XK_F6, 0, 0, XF86XK_MonBrightnessDown, ui::VKEY_BRIGHTNESS_DOWN, },
827 { XK_F7, 0, 0, XF86XK_MonBrightnessUp, ui::VKEY_BRIGHTNESS_UP, },
828 { XK_F8, 0, 0, XF86XK_AudioMute, ui::VKEY_VOLUME_MUTE, },
829 { XK_F9, 0, 0, XF86XK_AudioLowerVolume, ui::VKEY_VOLUME_DOWN, },
830 { XK_F10, 0, 0, XF86XK_AudioRaiseVolume, ui::VKEY_VOLUME_UP, },
831 { XK_F11, 0, 0, XF86XK_PowerOff, ui::VKEY_POWER, }
832 };
833
834 bool remapped =
835 RewriteWithKeyboardRemappingsByKeySym(fkeys_to_special_keys,
836 arraysize(fkeys_to_special_keys),
837 keysym,
838 xkey->state,
839 event->flags(),
840 &remapped_native_keysym,
841 &remapped_native_mods,
842 &remapped_keycode,
843 &remapped_mods);
844
845 if (!remapped) {
846 const PrefService* pref_service =
847 pref_service_ ? pref_service_ : GetPrefService();
848 bool chromebook_function_key = CommandLine::ForCurrentProcess()->HasSwitch(
849 switches::kEnableChromebookFunctionKey);
850
851 bool search_as_function_key = chromebook_function_key && pref_service &&
852 pref_service->GetBoolean(prefs::kLanguageSearchKeyActsAsFunctionKey);
853 if (search_as_function_key)
854 DCHECK(HasChromeOSKeyboard());
855
856 // When using Search as a Function key, remap Search+<number> to F<number>.
857 if (search_as_function_key && xkey->state & Mod4Mask) {
858 // We check the keycode here instead of the keysym, as these keys have
859 // different keysyms when modifiers are pressed, such as shift.
860
861 // TODO(danakj): On some i18n keyboards, these choices will be bad and we
862 // should make layout-specific choices here. For eg. on a french keyboard
863 // "-" and "6" are the same key, so F11 will not be accessible.
864 static const KeyboardRemappingByKeyCode number_keys_to_fkeys[] = {
865 { NativeKeySymToNativeKeycode(XK_1), 0, Mod4Mask,
Daniel Erat 2012/11/29 04:12:27 the keysym-to-keycode mappings can change (and hen
danakj 2012/11/29 04:34:15 Ahhh. Yes, good point. Thank you for catching that
866 XK_F1, ui::VKEY_F1, },
867 { NativeKeySymToNativeKeycode(XK_2), 0, Mod4Mask,
868 XK_F2, ui::VKEY_F2, },
869 { NativeKeySymToNativeKeycode(XK_3), 0, Mod4Mask,
870 XK_F3, ui::VKEY_F3, },
871 { NativeKeySymToNativeKeycode(XK_4), 0, Mod4Mask,
872 XK_F4, ui::VKEY_F4, },
873 { NativeKeySymToNativeKeycode(XK_5), 0, Mod4Mask,
874 XK_F5, ui::VKEY_F5, },
875 { NativeKeySymToNativeKeycode(XK_6), 0, Mod4Mask,
876 XK_F6, ui::VKEY_F6, },
877 { NativeKeySymToNativeKeycode(XK_7), 0, Mod4Mask,
878 XK_F7, ui::VKEY_F7, },
879 { NativeKeySymToNativeKeycode(XK_8), 0, Mod4Mask,
880 XK_F8, ui::VKEY_F8, },
881 { NativeKeySymToNativeKeycode(XK_9), 0, Mod4Mask,
882 XK_F9, ui::VKEY_F9, },
883 { NativeKeySymToNativeKeycode(XK_0), 0, Mod4Mask,
884 XK_F10, ui::VKEY_F10, },
885 { NativeKeySymToNativeKeycode(XK_minus), 0, Mod4Mask,
886 XK_F11, ui::VKEY_F11, },
887 { NativeKeySymToNativeKeycode(XK_equal), 0, Mod4Mask,
888 XK_F12, ui::VKEY_F12, }
889 };
890
891 RewriteWithKeyboardRemappingsByKeyCode(number_keys_to_fkeys,
892 arraysize(number_keys_to_fkeys),
893 xkey->keycode,
894 xkey->state,
895 event->flags(),
896 &remapped_native_keysym,
897 &remapped_native_mods,
898 &remapped_keycode,
899 &remapped_mods);
726 } 900 }
727 } 901 }
902
903 if (!remapped_native_keysym || remapped_keycode == ui::VKEY_UNKNOWN)
904 return false;
905
906 OverwriteEvent(event,
907 NativeKeySymToNativeKeycode(remapped_native_keysym),
908 remapped_native_mods,
909 remapped_keycode,
910 remapped_mods);
911 return true;
728 #else 912 #else
729 // TODO(yusukes): Support Ash on other platforms if needed. 913 // TODO(danakj): Support Ash on other platforms if needed.
914 return false;
730 #endif 915 #endif
731 return rewritten;
732 } 916 }
733 917
734 void EventRewriter::RewriteLocatedEvent(ui::LocatedEvent* event) { 918 void EventRewriter::RewriteLocatedEvent(ui::LocatedEvent* event) {
735 #if defined(OS_CHROMEOS) 919 #if defined(OS_CHROMEOS)
736 if (event->flags() & ui::EF_IS_SYNTHESIZED) 920 if (event->flags() & ui::EF_IS_SYNTHESIZED)
737 return; 921 return;
738 922
739 XEvent* xevent = event->native_event(); 923 XEvent* xevent = event->native_event();
740 if (!xevent || xevent->type != GenericEvent) 924 if (!xevent || xevent->type != GenericEvent)
741 return; 925 return;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
793 #endif 977 #endif
794 } 978 }
795 979
796 EventRewriter::DeviceType EventRewriter::DeviceAddedInternal( 980 EventRewriter::DeviceType EventRewriter::DeviceAddedInternal(
797 int device_id, 981 int device_id,
798 const std::string& device_name) { 982 const std::string& device_name) {
799 const DeviceType type = EventRewriter::GetDeviceType(device_name); 983 const DeviceType type = EventRewriter::GetDeviceType(device_name);
800 if (type == kDeviceAppleKeyboard) { 984 if (type == kDeviceAppleKeyboard) {
801 VLOG(1) << "Apple keyboard '" << device_name << "' connected: " 985 VLOG(1) << "Apple keyboard '" << device_name << "' connected: "
802 << "id=" << device_id; 986 << "id=" << device_id;
987 } else if (type == kDeviceChromeOSKeyboard) {
988 VLOG(1) << "ChromeOS keyboard '" << device_name << "' connected: "
989 << "id=" << device_id;
803 } 990 }
804 // Always overwrite the existing device_id since the X server may reuse a 991 // Always overwrite the existing device_id since the X server may reuse a
805 // device id for an unattached device. 992 // device id for an unattached device.
806 device_id_to_type_[device_id] = type; 993 device_id_to_type_[device_id] = type;
807 return type; 994 return type;
808 } 995 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/ash/event_rewriter.h ('k') | chrome/browser/ui/ash/event_rewriter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698