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

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