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

Side by Side Diff: chrome/browser/ui/views/ash/key_rewriter.cc

Issue 10756003: Apply Ash's key rewriter to an aura::MouseEvent so that Modifler+Click is handled correctly (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address comments Created 8 years, 5 months 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
« no previous file with comments | « chrome/browser/ui/views/ash/key_rewriter.h ('k') | ui/aura/dispatcher_linux.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/views/ash/key_rewriter.h" 5 #include "chrome/browser/ui/views/ash/key_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 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 172
173 return kDeviceUnknown; 173 return kDeviceUnknown;
174 } 174 }
175 175
176 void KeyRewriter::RewriteForTesting(aura::KeyEvent* event) { 176 void KeyRewriter::RewriteForTesting(aura::KeyEvent* event) {
177 Rewrite(event); 177 Rewrite(event);
178 } 178 }
179 179
180 ash::KeyRewriterDelegate::Action KeyRewriter::RewriteOrFilterKeyEvent( 180 ash::KeyRewriterDelegate::Action KeyRewriter::RewriteOrFilterKeyEvent(
181 aura::KeyEvent* event) { 181 aura::KeyEvent* event) {
182 const ash::KeyRewriterDelegate::Action kActionRewrite = 182 if (event->HasNativeEvent())
183 ash::KeyRewriterDelegate::ACTION_REWRITE_EVENT; 183 Rewrite(event);
184 if (!event->HasNativeEvent()) { 184 return ash::KeyRewriterDelegate::ACTION_REWRITE_EVENT;
185 // Do not handle a fabricated event generated by tests. 185 }
186 return kActionRewrite; 186
187 } 187 ash::KeyRewriterDelegate::Action KeyRewriter::RewriteOrFilterLocatedEvent(
188 Rewrite(event); 188 aura::LocatedEvent* event) {
189 return kActionRewrite; // Do not drop the event. 189 if (event->HasNativeEvent())
190 RewriteLocatedEvent(event);
191 return ash::KeyRewriterDelegate::ACTION_REWRITE_EVENT;
190 } 192 }
191 193
192 void KeyRewriter::OnKeyboardMappingChanged(const aura::RootWindow* root) { 194 void KeyRewriter::OnKeyboardMappingChanged(const aura::RootWindow* root) {
193 #if defined(OS_CHROMEOS) 195 #if defined(OS_CHROMEOS)
194 RefreshKeycodes(); 196 RefreshKeycodes();
195 #endif 197 #endif
196 } 198 }
197 199
198 #if defined(OS_CHROMEOS) 200 #if defined(OS_CHROMEOS)
199 void KeyRewriter::DeviceAdded(int device_id) { 201 void KeyRewriter::DeviceAdded(int device_id) {
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 device_id_to_type_.find(last_device_id_); 348 device_id_to_type_.find(last_device_id_);
347 if (iter == device_id_to_type_.end()) { 349 if (iter == device_id_to_type_.end()) {
348 LOG(ERROR) << "Device ID " << last_device_id_ << " is unknown."; 350 LOG(ERROR) << "Device ID " << last_device_id_ << " is unknown.";
349 return false; 351 return false;
350 } 352 }
351 353
352 const DeviceType type = iter->second; 354 const DeviceType type = iter->second;
353 return type == kDeviceAppleKeyboard; 355 return type == kDeviceAppleKeyboard;
354 } 356 }
355 357
358 void KeyRewriter::GetRemappedModifierMasks(
359 int original_flags,
360 unsigned int original_native_modifiers,
361 int* remapped_flags,
362 unsigned int* remapped_native_modifiers) const {
363 #if defined(OS_CHROMEOS)
364 // TODO(glotov): remove the following condition when we do not restart chrome
365 // when user logs in as guest. See Rewrite() for details.
366 if (chromeos::UserManager::Get()->IsLoggedInAsGuest() &&
367 chromeos::BaseLoginDisplayHost::default_host()) {
368 return;
369 }
370
371 const PrefService* pref_service =
372 pref_service_ ? pref_service_ : GetPrefService();
373 if (!pref_service)
374 return;
375
376 for (size_t i = 0; i < arraysize(kModifierFlagToPrefName); ++i) {
377 if (original_native_modifiers &
378 kModifierFlagToPrefName[i].native_modifier) {
379 const ModifierRemapping* remapped_key =
380 GetRemappedKey(kModifierFlagToPrefName[i].pref_name, *pref_service);
381 // Rewrite Command-L/R key presses on an Apple keyboard to Control-L/R.
382 if (IsAppleKeyboard() &&
383 (kModifierFlagToPrefName[i].native_modifier == Mod4Mask)) {
384 remapped_key = kModifierRemappingCtrl;
385 }
386 if (remapped_key) {
387 *remapped_flags |= remapped_key->flag;
388 *remapped_native_modifiers |= remapped_key->native_modifier;
389 } else {
390 *remapped_flags |= kModifierFlagToPrefName[i].flag;
391 *remapped_native_modifiers |=
392 kModifierFlagToPrefName[i].native_modifier;
393 }
394 }
395 }
396
397 *remapped_flags =
398 (original_flags & ~(ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)) |
399 *remapped_flags;
400 *remapped_native_modifiers =
401 (original_native_modifiers & ~(Mod4Mask | ControlMask | Mod1Mask)) |
402 *remapped_native_modifiers;
403 #endif
404 }
405
356 bool KeyRewriter::RewriteModifiers(aura::KeyEvent* event) { 406 bool KeyRewriter::RewriteModifiers(aura::KeyEvent* event) {
357 // Do nothing if we have just logged in as guest but have not restarted chrome 407 // Do nothing if we have just logged in as guest but have not restarted chrome
358 // process yet (so we are still on the login screen). In this situations we 408 // process yet (so we are still on the login screen). In this situations we
359 // have no user profile so can not do anything useful. 409 // have no user profile so can not do anything useful.
360 // Note that currently, unlike other accounts, when user logs in as guest, we 410 // Note that currently, unlike other accounts, when user logs in as guest, we
361 // restart chrome process. In future this is to be changed. 411 // restart chrome process. In future this is to be changed.
362 // TODO(glotov): remove the following condition when we do not restart chrome 412 // TODO(glotov): remove the following condition when we do not restart chrome
363 // when user logs in as guest. 413 // when user logs in as guest.
364 #if defined(OS_CHROMEOS) 414 #if defined(OS_CHROMEOS)
365 if (chromeos::UserManager::Get()->IsLoggedInAsGuest() && 415 if (chromeos::UserManager::Get()->IsLoggedInAsGuest() &&
366 chromeos::BaseLoginDisplayHost::default_host()) 416 chromeos::BaseLoginDisplayHost::default_host())
367 return false; 417 return false;
368 #endif // defined(OS_CHROMEOS) 418 #endif // defined(OS_CHROMEOS)
369 const PrefService* pref_service = 419 const PrefService* pref_service =
370 pref_service_ ? pref_service_ : GetPrefService(); 420 pref_service_ ? pref_service_ : GetPrefService();
371 if (!pref_service) 421 if (!pref_service)
372 return false; 422 return false;
373 423
374 #if defined(OS_CHROMEOS) 424 #if defined(OS_CHROMEOS)
375 DCHECK_EQ(chromeos::input_method::kControlKey, 425 DCHECK_EQ(chromeos::input_method::kControlKey,
376 kModifierRemappingCtrl->remap_to); 426 kModifierRemappingCtrl->remap_to);
377 427
378 XEvent* xev = event->native_event(); 428 XEvent* xev = event->native_event();
379 XKeyEvent* xkey = &(xev->xkey); 429 XKeyEvent* xkey = &(xev->xkey);
380 KeySym keysym = XLookupKeysym(xkey, 0); 430 KeySym keysym = XLookupKeysym(xkey, 0);
381 431
382 ui::KeyboardCode remapped_keycode = event->key_code(); 432 ui::KeyboardCode remapped_keycode = event->key_code();
383 KeyCode remapped_native_keycode = xkey->keycode; 433 KeyCode remapped_native_keycode = xkey->keycode;
384 int remapped_flags = 0;
385 unsigned int remapped_native_modifiers = 0U;
386 434
387 // First, remap |keysym|. 435 // First, remap |keysym|.
388 const char* pref_name = NULL; 436 const char* pref_name = NULL;
389 switch (keysym) { 437 switch (keysym) {
390 case XK_Super_L: 438 case XK_Super_L:
391 case XK_Super_R: 439 case XK_Super_R:
392 pref_name = prefs::kLanguageXkbRemapSearchKeyTo; 440 pref_name = prefs::kLanguageXkbRemapSearchKeyTo;
393 break; 441 break;
394 case XK_Control_L: 442 case XK_Control_L:
395 case XK_Control_R: 443 case XK_Control_R:
(...skipping 17 matching lines...) Expand all
413 if (remapped_key) { 461 if (remapped_key) {
414 remapped_keycode = remapped_key->keycode; 462 remapped_keycode = remapped_key->keycode;
415 const size_t level = (event->IsShiftDown() ? (1 << 1) : 0) + 463 const size_t level = (event->IsShiftDown() ? (1 << 1) : 0) +
416 (IsRight(keysym) ? (1 << 0) : 0); 464 (IsRight(keysym) ? (1 << 0) : 0);
417 const KeySym native_keysym = remapped_key->native_keysyms[level]; 465 const KeySym native_keysym = remapped_key->native_keysyms[level];
418 remapped_native_keycode = NativeKeySymToNativeKeycode(native_keysym); 466 remapped_native_keycode = NativeKeySymToNativeKeycode(native_keysym);
419 } 467 }
420 } 468 }
421 469
422 // Next, remap modifier bits. 470 // Next, remap modifier bits.
423 for (size_t i = 0; i < arraysize(kModifierFlagToPrefName); ++i) { 471 int remapped_flags = 0;
424 if (xkey->state & kModifierFlagToPrefName[i].native_modifier) { 472 unsigned int remapped_native_modifiers = 0U;
425 const ModifierRemapping* remapped_key = 473 GetRemappedModifierMasks(event->flags(), xkey->state,
426 GetRemappedKey(kModifierFlagToPrefName[i].pref_name, *pref_service); 474 &remapped_flags, &remapped_native_modifiers);
427 // Rewrite Command-L/R key presses on an Apple keyboard to Control-L/R.
428 if (IsAppleKeyboard() &&
429 (kModifierFlagToPrefName[i].native_modifier == Mod4Mask)) {
430 remapped_key = kModifierRemappingCtrl;
431 }
432 if (remapped_key) {
433 remapped_flags |= remapped_key->flag;
434 remapped_native_modifiers |= remapped_key->native_modifier;
435 } else {
436 remapped_flags |= kModifierFlagToPrefName[i].flag;
437 remapped_native_modifiers |= kModifierFlagToPrefName[i].native_modifier;
438 }
439 }
440 }
441
442 remapped_flags = (event->flags() & ~(ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)) |
443 remapped_flags;
444 remapped_native_modifiers =
445 (xkey->state & ~(Mod4Mask | ControlMask | Mod1Mask)) |
446 remapped_native_modifiers;
447 475
448 // Toggle Caps Lock if the remapped key is ui::VKEY_CAPITAL, but do nothing if 476 // Toggle Caps Lock if the remapped key is ui::VKEY_CAPITAL, but do nothing if
449 // the original key is ui::VKEY_CAPITAL (i.e. a Caps Lock key on an external 477 // the original key is ui::VKEY_CAPITAL (i.e. a Caps Lock key on an external
450 // keyboard is pressed) since X can handle that case. 478 // keyboard is pressed) since X can handle that case.
451 if ((event->type() == ui::ET_KEY_PRESSED) && 479 if ((event->type() == ui::ET_KEY_PRESSED) &&
452 (event->key_code() != ui::VKEY_CAPITAL) && 480 (event->key_code() != ui::VKEY_CAPITAL) &&
453 (remapped_keycode == ui::VKEY_CAPITAL)) { 481 (remapped_keycode == ui::VKEY_CAPITAL)) {
454 chromeos::input_method::XKeyboard* xkeyboard = xkeyboard_ ? 482 chromeos::input_method::XKeyboard* xkeyboard = xkeyboard_ ?
455 xkeyboard_ : InputMethodManager::GetInstance()->GetXKeyboard(); 483 xkeyboard_ : InputMethodManager::GetInstance()->GetXKeyboard();
456 xkeyboard->SetCapsLockEnabled(!xkeyboard->CapsLockIsEnabled()); 484 xkeyboard->SetCapsLockEnabled(!xkeyboard->CapsLockIsEnabled());
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 OverwriteEvent(event, next_xkeycode_, xkey->state & ~Mod1Mask, 616 OverwriteEvent(event, next_xkeycode_, xkey->state & ~Mod1Mask,
589 ui::VKEY_NEXT, event->flags() & ~ui::EF_ALT_DOWN); 617 ui::VKEY_NEXT, event->flags() & ~ui::EF_ALT_DOWN);
590 rewritten = true; 618 rewritten = true;
591 } 619 }
592 #else 620 #else
593 // TODO(yusukes): Support Ash on other platforms if needed. 621 // TODO(yusukes): Support Ash on other platforms if needed.
594 #endif 622 #endif
595 return rewritten; 623 return rewritten;
596 } 624 }
597 625
626 void KeyRewriter::RewriteLocatedEvent(aura::LocatedEvent* event) {
627 #if defined(OS_CHROMEOS)
628 XEvent* xevent = event->native_event();
629 if (!xevent || xevent->type != GenericEvent)
630 return;
631
632 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
633 if (xievent->evtype != XI_ButtonPress && xievent->evtype != XI_ButtonRelease)
634 return;
635
636 // First, remap modifier masks.
637 int remapped_flags = 0;
638 unsigned int remapped_native_modifiers = 0U;
639 GetRemappedModifierMasks(event->flags(), xievent->mods.effective,
640 &remapped_flags, &remapped_native_modifiers);
641 xievent->mods.effective = remapped_native_modifiers;
642
643 // Then, remap Alt+Button1 to Button3.
644 if ((xievent->mods.effective & Mod1Mask) && xievent->detail == 1) {
645 xievent->mods.effective &= ~Mod1Mask;
646 xievent->detail = 3;
647 if (xievent->evtype == XI_ButtonRelease) {
648 // On the release clear the left button from the existing state and the
649 // mods, and set the right button.
650 XISetMask(xievent->buttons.mask, 3);
651 XIClearMask(xievent->buttons.mask, 1);
652 xievent->mods.effective &= ~Button1Mask;
653 }
654 }
655
656 event->set_flags(ui::EventFlagsFromNative(xevent));
657 #else
658 // TODO(yusukes): Support Ash on other platforms if needed.
659 #endif
660 }
661
598 void KeyRewriter::OverwriteEvent(aura::KeyEvent* event, 662 void KeyRewriter::OverwriteEvent(aura::KeyEvent* event,
599 unsigned int new_native_keycode, 663 unsigned int new_native_keycode,
600 unsigned int new_native_state, 664 unsigned int new_native_state,
601 ui::KeyboardCode new_keycode, 665 ui::KeyboardCode new_keycode,
602 int new_flags) { 666 int new_flags) {
603 #if defined(OS_CHROMEOS) 667 #if defined(OS_CHROMEOS)
604 XEvent* xev = event->native_event(); 668 XEvent* xev = event->native_event();
605 XKeyEvent* xkey = &(xev->xkey); 669 XKeyEvent* xkey = &(xev->xkey);
606 xkey->keycode = new_native_keycode; 670 xkey->keycode = new_native_keycode;
607 xkey->state = new_native_state; 671 xkey->state = new_native_state;
(...skipping 12 matching lines...) Expand all
620 const DeviceType type = KeyRewriter::GetDeviceType(device_name); 684 const DeviceType type = KeyRewriter::GetDeviceType(device_name);
621 if (type == kDeviceAppleKeyboard) { 685 if (type == kDeviceAppleKeyboard) {
622 VLOG(1) << "Apple keyboard '" << device_name << "' connected: " 686 VLOG(1) << "Apple keyboard '" << device_name << "' connected: "
623 << "id=" << device_id; 687 << "id=" << device_id;
624 } 688 }
625 // Always overwrite the existing device_id since the X server may reuse a 689 // Always overwrite the existing device_id since the X server may reuse a
626 // device id for an unattached device. 690 // device id for an unattached device.
627 device_id_to_type_[device_id] = type; 691 device_id_to_type_[device_id] = type;
628 return type; 692 return type;
629 } 693 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/ash/key_rewriter.h ('k') | ui/aura/dispatcher_linux.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698