diff options
20 files changed, 672 insertions, 334 deletions
diff --git a/ash/accelerators/accelerator_dispatcher.cc b/ash/accelerators/accelerator_dispatcher.cc index 6088dfe..c4c4f33 100644 --- a/ash/accelerators/accelerator_dispatcher.cc +++ b/ash/accelerators/accelerator_dispatcher.cc @@ -15,6 +15,7 @@ #include "ash/accelerators/accelerator_controller.h" #include "ash/shell.h" +#include "ash/wm/event_rewriter_event_filter.h" #include "ui/aura/env.h" #include "ui/aura/root_window.h" #include "ui/base/accelerators/accelerator.h" @@ -92,7 +93,16 @@ uint32_t AcceleratorDispatcher::Dispatch(const base::NativeEvent& event) { return POST_DISPATCH_PERFORM_DEFAULT; if (IsKeyEvent(event)) { + // Modifiers can be changed by the user preference, so we need to rewrite + // the event explicitly. ui::KeyEvent key_event(event, false); + ui::EventHandler* event_rewriter = + ash::Shell::GetInstance()->event_rewriter_filter(); + DCHECK(event_rewriter); + event_rewriter->OnKeyEvent(&key_event); + if (key_event.stopped_propagation()) + return POST_DISPATCH_NONE; + if (IsPossibleAcceleratorNotForMenu(key_event)) { if (views::MenuController* menu_controller = views::MenuController::GetActiveInstance()) { diff --git a/ash/ash.gyp b/ash/ash.gyp index f31dc06..3faf546 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -144,6 +144,7 @@ 'drag_drop/drag_drop_tracker.h', 'drag_drop/drag_image_view.cc', 'drag_drop/drag_image_view.h', + 'event_rewriter_delegate.h', 'first_run/desktop_cleaner.cc', 'first_run/desktop_cleaner.h', 'first_run/first_run_helper.cc', @@ -495,6 +496,8 @@ 'wm/drag_window_resizer.h', 'wm/event_client_impl.cc', 'wm/event_client_impl.h', + 'wm/event_rewriter_event_filter.cc', + 'wm/event_rewriter_event_filter.h', 'wm/frame_border_hit_test_controller.cc', 'wm/frame_border_hit_test_controller.h', 'wm/header_painter.cc', diff --git a/ash/event_rewriter_delegate.h b/ash/event_rewriter_delegate.h new file mode 100644 index 0000000..c54c9a3 --- /dev/null +++ b/ash/event_rewriter_delegate.h @@ -0,0 +1,34 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_EVENT_REWRITER_DELEGATE_H_ +#define ASH_EVENT_REWRITER_DELEGATE_H_ + +namespace ui { +class KeyEvent; +class LocatedEvent; +} // namespace aura + +namespace ash { + +// Delegate for rewriting or filtering an event. +class EventRewriterDelegate { + public: + enum Action { + ACTION_REWRITE_EVENT, + ACTION_DROP_EVENT, + }; + + virtual ~EventRewriterDelegate() {} + + // A derived class can do either of the following: + // 1) Just return ACTION_DROP_EVENT to drop the |event|. + // 2) Rewrite the |event| and return ACTION_REWRITE_EVENT. + virtual Action RewriteOrFilterKeyEvent(ui::KeyEvent* event) = 0; + virtual Action RewriteOrFilterLocatedEvent(ui::LocatedEvent* event) = 0; +}; + +} // namespace ash + +#endif // ASH_EVENT_REWRITER_DELEGATE_H_ diff --git a/ash/shell.cc b/ash/shell.cc index 3a49d2e..39daa14 100644 --- a/ash/shell.cc +++ b/ash/shell.cc @@ -58,6 +58,7 @@ #include "ash/wm/coordinate_conversion.h" #include "ash/wm/custom_frame_view_ash.h" #include "ash/wm/event_client_impl.h" +#include "ash/wm/event_rewriter_event_filter.h" #include "ash/wm/lock_state_controller.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/overlay_event_filter.h" @@ -622,6 +623,7 @@ Shell::~Shell() { RemovePreTargetHandler(magnifier_key_scroller_.get()); magnifier_key_scroller_.reset(); #endif + RemovePreTargetHandler(event_rewriter_filter_.get()); RemovePreTargetHandler(user_activity_detector_.get()); RemovePreTargetHandler(overlay_filter_.get()); RemovePreTargetHandler(input_method_filter_.get()); @@ -832,6 +834,8 @@ void Shell::Init() { #endif // The order in which event filters are added is significant. + event_rewriter_filter_.reset(new internal::EventRewriterEventFilter); + AddPreTargetHandler(event_rewriter_filter_.get()); #if defined(OS_CHROMEOS) // The StickyKeysController also rewrites events and must be added diff --git a/ash/shell.h b/ash/shell.h index efd3dde..07d0575 100644 --- a/ash/shell.h +++ b/ash/shell.h @@ -328,6 +328,9 @@ class ASH_EXPORT Shell views::corewm::TooltipController* tooltip_controller() { return tooltip_controller_.get(); } + internal::EventRewriterEventFilter* event_rewriter_filter() { + return event_rewriter_filter_.get(); + } internal::OverlayEventFilter* overlay_filter() { return overlay_filter_.get(); } @@ -656,6 +659,9 @@ class ASH_EXPORT Shell event_transformation_handler_; scoped_ptr<WindowTreeHostFactory> window_tree_host_factory_; + // An event filter that rewrites or drops an event. + scoped_ptr<internal::EventRewriterEventFilter> event_rewriter_filter_; + // An event filter that pre-handles key events while the partial // screenshot UI or the keyboard overlay is active. scoped_ptr<internal::OverlayEventFilter> overlay_filter_; diff --git a/ash/wm/event_rewriter_event_filter.cc b/ash/wm/event_rewriter_event_filter.cc new file mode 100644 index 0000000..dd87e2a --- /dev/null +++ b/ash/wm/event_rewriter_event_filter.cc @@ -0,0 +1,56 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/event_rewriter_event_filter.h" + +#include "ash/event_rewriter_delegate.h" +#include "base/logging.h" +#include "ui/events/event.h" + +namespace ash { +namespace internal { + +EventRewriterEventFilter::EventRewriterEventFilter() {} + +EventRewriterEventFilter::~EventRewriterEventFilter() {} + +void EventRewriterEventFilter::SetEventRewriterDelegate( + scoped_ptr<EventRewriterDelegate> delegate) { + delegate_ = delegate.Pass(); +} + +void EventRewriterEventFilter::OnKeyEvent(ui::KeyEvent* event) { + if (!delegate_) + return; + + // Do not consume a translated key event which is generated by an IME. + if (event->type() == ui::ET_TRANSLATED_KEY_PRESS || + event->type() == ui::ET_TRANSLATED_KEY_RELEASE) { + return; + } + + switch (delegate_->RewriteOrFilterKeyEvent(event)) { + case EventRewriterDelegate::ACTION_REWRITE_EVENT: + break; + case EventRewriterDelegate::ACTION_DROP_EVENT: + event->StopPropagation(); + break; + } +} + +void EventRewriterEventFilter::OnMouseEvent(ui::MouseEvent* event) { + if (!delegate_) + return; + + switch (delegate_->RewriteOrFilterLocatedEvent(event)) { + case EventRewriterDelegate::ACTION_REWRITE_EVENT: + break; + case EventRewriterDelegate::ACTION_DROP_EVENT: + event->StopPropagation(); + break; + } +} + +} // namespace internal +} // namespace ash diff --git a/ash/wm/event_rewriter_event_filter.h b/ash/wm/event_rewriter_event_filter.h new file mode 100644 index 0000000..86f7f53 --- /dev/null +++ b/ash/wm/event_rewriter_event_filter.h @@ -0,0 +1,41 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WM_EVENT_REWRITER_EVENT_FILTER_ +#define ASH_WM_EVENT_REWRITER_EVENT_FILTER_ + +#include "ash/ash_export.h" +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "ui/events/event_handler.h" + +namespace ash { + +class EventRewriterDelegate; + +namespace internal { + +// An event filter that rewrites or drops an event. +class ASH_EXPORT EventRewriterEventFilter : public ui::EventHandler { + public: + EventRewriterEventFilter(); + virtual ~EventRewriterEventFilter(); + + void SetEventRewriterDelegate(scoped_ptr<EventRewriterDelegate> delegate); + + private: + // Overridden from ui::EventHandler: + virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; + virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; + + scoped_ptr<EventRewriterDelegate> delegate_; + + DISALLOW_COPY_AND_ASSIGN(EventRewriterEventFilter); +}; + +} // namespace internal +} // namespace ash + +#endif // ASH_WM_EVENT_REWRITER_EVENT_FILTER_ diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc index 064699b..9274012 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc +++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc @@ -12,6 +12,7 @@ #include "ash/shell.h" #include "ash/sticky_keys/sticky_keys_controller.h" #include "ash/system/tray/system_tray_notifier.h" +#include "ash/wm/event_rewriter_event_filter.h" #include "base/memory/scoped_ptr.h" #include "base/memory/singleton.h" #include "base/metrics/histogram.h" diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index 63fea22..d1f76ce 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc @@ -32,7 +32,6 @@ #include "chrome/browser/chromeos/boot_times_loader.h" #include "chrome/browser/chromeos/contacts/contact_manager.h" #include "chrome/browser/chromeos/dbus/cros_dbus_service.h" -#include "chrome/browser/chromeos/event_rewriter.h" #include "chrome/browser/chromeos/extensions/default_app_order.h" #include "chrome/browser/chromeos/extensions/extension_system_event_observer.h" #include "chrome/browser/chromeos/external_metrics.h" @@ -703,8 +702,6 @@ void ChromeBrowserMainPartsChromeos::PreBrowserStart() { DeviceUMA::GetInstance(); #endif - event_rewriter_.reset(new EventRewriter()); - // -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun() // -- immediately after ChildProcess::WaitForDebugger(). @@ -769,7 +766,6 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() { retail_mode_power_save_blocker_.reset(); peripheral_battery_observer_.reset(); power_prefs_.reset(); - event_rewriter_.reset(); // The XInput2 event listener needs to be shut down earlier than when // Singletons are finally destroyed in AtExitManager. diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.h b/chrome/browser/chromeos/chrome_browser_main_chromeos.h index 462d319..4a6038c 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.h +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.h @@ -21,7 +21,6 @@ class PowerSaveBlocker; namespace chromeos { class DataPromoNotification; -class EventRewriter; class ExtensionSystemEventObserver; class IdleActionWarningObserver; class MagnificationManager; @@ -72,7 +71,6 @@ class ChromeBrowserMainPartsChromeos : public ChromeBrowserMainPartsLinux { scoped_ptr<DataPromoNotification> data_promo_notification_; scoped_ptr<internal::DBusServices> dbus_services_; - scoped_ptr<EventRewriter> event_rewriter_; VersionLoader cros_version_loader_; base::CancelableTaskTracker tracker_; diff --git a/chrome/browser/chromeos/keyboard_driven_event_rewriter.cc b/chrome/browser/chromeos/keyboard_driven_event_rewriter.cc index 9f9ef78..389757f 100644 --- a/chrome/browser/chromeos/keyboard_driven_event_rewriter.cc +++ b/chrome/browser/chromeos/keyboard_driven_event_rewriter.cc @@ -8,7 +8,7 @@ #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/system/input_device_settings.h" -#include "ui/events/event_utils.h" +#include "ui/events/event.h" namespace chromeos { @@ -35,34 +35,35 @@ KeyboardDrivenEventRewriter::KeyboardDrivenEventRewriter() {} KeyboardDrivenEventRewriter::~KeyboardDrivenEventRewriter() {} bool KeyboardDrivenEventRewriter::RewriteIfKeyboardDrivenOnLoginScreen( - XEvent* event) { + ui::KeyEvent* event) { if (!ShouldStripModifiersForArrowKeysAndEnter()) return false; return RewriteEvent(event); } -bool KeyboardDrivenEventRewriter::RewriteForTesting(XEvent* event) { +bool KeyboardDrivenEventRewriter::RewriteForTesting(ui::KeyEvent* event) { return RewriteEvent(event); } -bool KeyboardDrivenEventRewriter::RewriteEvent(XEvent* event) { - int flags = ui::EventFlagsFromNative(event); - if ((flags & kModifierMask) != kModifierMask) +bool KeyboardDrivenEventRewriter::RewriteEvent(ui::KeyEvent* event) { + if ((event->flags() & kModifierMask) != kModifierMask) return false; - ui::KeyboardCode key_code = ui::KeyboardCodeFromNative(event); - - if (key_code != ui::VKEY_LEFT && - key_code != ui::VKEY_RIGHT && - key_code != ui::VKEY_UP && - key_code != ui::VKEY_DOWN && - key_code != ui::VKEY_RETURN && - key_code != ui::VKEY_F6) { + + if (event->key_code() != ui::VKEY_LEFT && + event->key_code() != ui::VKEY_RIGHT && + event->key_code() != ui::VKEY_UP && + event->key_code() != ui::VKEY_DOWN && + event->key_code() != ui::VKEY_RETURN && + event->key_code() != ui::VKEY_F6) { return false; } - XKeyEvent* xkey = &(event->xkey); + XEvent* xev = event->native_event(); + XKeyEvent* xkey = &(xev->xkey); xkey->state &= ~(ControlMask | Mod1Mask | ShiftMask); + event->set_flags(event->flags() & ~kModifierMask); + event->NormalizeFlags(); return true; } diff --git a/chrome/browser/chromeos/keyboard_driven_event_rewriter.h b/chrome/browser/chromeos/keyboard_driven_event_rewriter.h index 96e053d..d55aeab 100644 --- a/chrome/browser/chromeos/keyboard_driven_event_rewriter.h +++ b/chrome/browser/chromeos/keyboard_driven_event_rewriter.h @@ -7,7 +7,9 @@ #include "base/basictypes.h" -typedef union _XEvent XEvent; +namespace ui { +class KeyEvent; +} namespace chromeos { @@ -22,13 +24,13 @@ class KeyboardDrivenEventRewriter { // Calls RewriteEvent to modify |event| if it is on login screen and the // keyboard driven flag is enabled. Returns true if the event is changed // and no further changes should happen. - bool RewriteIfKeyboardDrivenOnLoginScreen(XEvent* event); + bool RewriteIfKeyboardDrivenOnLoginScreen(ui::KeyEvent* event); // Calls RewriteEvent for testing. - bool RewriteForTesting(XEvent* event); + bool RewriteForTesting(ui::KeyEvent* event); private: - bool RewriteEvent(XEvent* event); + bool RewriteEvent(ui::KeyEvent* event); DISALLOW_COPY_AND_ASSIGN(KeyboardDrivenEventRewriter); }; diff --git a/chrome/browser/chromeos/keyboard_driven_event_rewriter_unittest.cc b/chrome/browser/chromeos/keyboard_driven_event_rewriter_unittest.cc index dc807ef..151bbab 100644 --- a/chrome/browser/chromeos/keyboard_driven_event_rewriter_unittest.cc +++ b/chrome/browser/chromeos/keyboard_driven_event_rewriter_unittest.cc @@ -42,8 +42,8 @@ class KeyboardDrivenEventRewriterTest : public testing::Test { XEvent* xevent = xev; xevent->xkey.keycode = x_keycode; xevent->xkey.state = x_state; - bool changed = rewriter_.RewriteForTesting(xevent); ui::KeyEvent keyevent(xev, false /* is_char */); + bool changed = rewriter_.RewriteForTesting(&keyevent); return base::StringPrintf("ui_flags=%d x_state=%u changed=%d", keyevent.flags(), xevent->xkey.state, diff --git a/chrome/browser/ui/ash/ash_init.cc b/chrome/browser/ui/ash/ash_init.cc index 4ba1425..8551ef4 100644 --- a/chrome/browser/ui/ash/ash_init.cc +++ b/chrome/browser/ui/ash/ash_init.cc @@ -10,12 +10,14 @@ #include "ash/magnifier/magnification_controller.h" #include "ash/magnifier/partial_magnification_controller.h" #include "ash/shell.h" +#include "ash/wm/event_rewriter_event_filter.h" #include "base/command_line.h" #include "chrome/browser/browser_shutdown.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/accessibility/magnification_manager.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/ui/ash/chrome_shell_delegate.h" +#include "chrome/browser/ui/ash/event_rewriter.h" #include "chrome/browser/ui/ash/screenshot_taker.h" #include "chrome/common/chrome_switches.h" #include "ui/aura/env.h" @@ -56,6 +58,8 @@ void OpenAsh() { // Shell takes ownership of ChromeShellDelegate. ash::Shell* shell = ash::Shell::CreateInstance(new ChromeShellDelegate); + shell->event_rewriter_filter()->SetEventRewriterDelegate( + scoped_ptr<ash::EventRewriterDelegate>(new EventRewriter).Pass()); shell->accelerator_controller()->SetScreenshotDelegate( scoped_ptr<ash::ScreenshotDelegate>(new ScreenshotTaker).Pass()); #if defined(OS_CHROMEOS) diff --git a/chrome/browser/chromeos/event_rewriter.cc b/chrome/browser/ui/ash/event_rewriter.cc index 5f084c5..5912b1e 100644 --- a/chrome/browser/chromeos/event_rewriter.cc +++ b/chrome/browser/ui/ash/event_rewriter.cc @@ -1,47 +1,51 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/chromeos/event_rewriter.h" +#include "chrome/browser/ui/ash/event_rewriter.h" +#include <vector> + +#include "ash/shell.h" +#include "base/logging.h" +#include "base/prefs/pref_service.h" +#include "base/strings/string_util.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "ui/aura/root_window.h" +#include "ui/events/event.h" +#include "ui/events/event_utils.h" +#include "ui/events/keycodes/keyboard_code_conversion.h" + +#if defined(OS_CHROMEOS) #include <X11/extensions/XInput2.h> #include <X11/keysym.h> #include <X11/XF86keysym.h> #include <X11/Xlib.h> -// Get rid of macros from Xlib.h that conflicts with other parts of the code. -#undef RootWindow -#undef Status -#include <vector> +// Get rid of a macro from Xlib.h that conflicts with OwnershipService class. +#undef Status -#include "ash/shell.h" #include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" #include "base/command_line.h" -#include "base/logging.h" -#include "base/prefs/pref_service.h" -#include "base/strings/string_util.h" #include "base/sys_info.h" #include "chrome/browser/chromeos/keyboard_driven_event_rewriter.h" #include "chrome/browser/chromeos/login/login_display_host_impl.h" #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.h" -#include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/pref_names.h" #include "chromeos/chromeos_switches.h" #include "chromeos/ime/input_method_manager.h" #include "chromeos/ime/xkeyboard.h" -#include "ui/aura/root_window.h" #include "ui/base/x/x11_util.h" -#include "ui/events/event.h" -#include "ui/events/event_utils.h" #include "ui/events/keycodes/keyboard_code_conversion_x.h" #include "ui/views/corewm/window_util.h" +#endif namespace { const int kBadDeviceId = -1; +#if defined(OS_CHROMEOS) const char kNeo2LayoutId[] = "xkb:de:neo:ger"; const char kCaMultixLayoutId[] = "xkb:ca:multix:fra"; @@ -132,36 +136,43 @@ bool IsMod3UsedByCurrentInputMethod() { manager->GetCurrentInputMethod().id() == kCaMultixLayoutId; } -} // namespace +#endif // defined(OS_CHROMEOS) -namespace chromeos { +} // namespace EventRewriter::EventRewriter() : last_device_id_(kBadDeviceId), +#if defined(OS_CHROMEOS) xkeyboard_for_testing_(NULL), - keyboard_driven_event_rewriter_(new KeyboardDrivenEventRewriter), + keyboard_driven_event_rewriter_( + new chromeos::KeyboardDrivenEventRewriter), +#endif pref_service_for_testing_(NULL) { // The ash shell isn't instantiated for our unit tests. if (ash::Shell::HasInstance()) { ash::Shell::GetPrimaryRootWindow()->GetDispatcher()-> AddRootWindowObserver(this); } - base::MessageLoopForUI::current()->AddObserver(this); +#if defined(OS_CHROMEOS) if (base::SysInfo::IsRunningOnChromeOS()) { - XInputHierarchyChangedEventListener::GetInstance()->AddObserver(this); + chromeos::XInputHierarchyChangedEventListener::GetInstance() + ->AddObserver(this); } RefreshKeycodes(); +#endif } EventRewriter::~EventRewriter() { - base::MessageLoopForUI::current()->RemoveObserver(this); if (ash::Shell::HasInstance()) { ash::Shell::GetPrimaryRootWindow()->GetDispatcher()-> RemoveRootWindowObserver(this); } +#if defined(OS_CHROMEOS) if (base::SysInfo::IsRunningOnChromeOS()) { - XInputHierarchyChangedEventListener::GetInstance()->RemoveObserver(this); + chromeos::XInputHierarchyChangedEventListener::GetInstance() + ->RemoveObserver(this); } +#endif } EventRewriter::DeviceType EventRewriter::DeviceAddedForTesting( @@ -192,27 +203,31 @@ EventRewriter::DeviceType EventRewriter::GetDeviceType( return kDeviceUnknown; } -void EventRewriter::RewriteForTesting(XEvent* event) { +void EventRewriter::RewriteForTesting(ui::KeyEvent* event) { Rewrite(event); } -void EventRewriter::OnKeyboardMappingChanged(const aura::RootWindow* root) { - RefreshKeycodes(); +ash::EventRewriterDelegate::Action EventRewriter::RewriteOrFilterKeyEvent( + ui::KeyEvent* event) { + if (event->HasNativeEvent()) + Rewrite(event); + return ash::EventRewriterDelegate::ACTION_REWRITE_EVENT; } -base::EventStatus EventRewriter::WillProcessEvent( - const base::NativeEvent& event) { - XEvent* xevent = event; - if (xevent->type == KeyPress || xevent->type == KeyRelease) - Rewrite(xevent); - else if (xevent->type == GenericEvent) - RewriteLocatedEvent(xevent); - return base::EVENT_CONTINUE; +ash::EventRewriterDelegate::Action EventRewriter::RewriteOrFilterLocatedEvent( + ui::LocatedEvent* event) { + if (event->HasNativeEvent()) + RewriteLocatedEvent(event); + return ash::EventRewriterDelegate::ACTION_REWRITE_EVENT; } -void EventRewriter::DidProcessEvent(const base::NativeEvent& event) { +void EventRewriter::OnKeyboardMappingChanged(const aura::RootWindow* root) { +#if defined(OS_CHROMEOS) + RefreshKeycodes(); +#endif } +#if defined(OS_CHROMEOS) void EventRewriter::DeviceAdded(int device_id) { DCHECK_NE(XIAllDevices, device_id); DCHECK_NE(XIAllMasterDevices, device_id); @@ -273,15 +288,19 @@ KeyCode EventRewriter::NativeKeySymToNativeKeycode(KeySym keysym) { return keycode; } -bool EventRewriter::TopRowKeysAreFunctionKeys(XEvent* event) const { +bool EventRewriter::TopRowKeysAreFunctionKeys(ui::KeyEvent* event) const { const PrefService* prefs = GetPrefService(); if (prefs && prefs->FindPreference(prefs::kLanguageSendFunctionKeys) && prefs->GetBoolean(prefs::kLanguageSendFunctionKeys)) return true; - ash::wm::WindowState* state = ash::wm::GetActiveWindowState(); - return state ? state->top_row_keys_are_function_keys() : false; + aura::Window* target = static_cast<aura::Window*>(event->target()); + if (!target) + return false; + aura::Window* top_level = views::corewm::GetToplevelWindow(target); + return top_level && + ash::wm::GetWindowState(top_level)->top_row_keys_are_function_keys(); } bool EventRewriter::RewriteWithKeyboardRemappingsByKeySym( @@ -289,8 +308,11 @@ bool EventRewriter::RewriteWithKeyboardRemappingsByKeySym( size_t num_remappings, KeySym keysym, unsigned int native_mods, + unsigned int mods, KeySym* remapped_native_keysym, - unsigned int* remapped_native_mods) { + unsigned int* remapped_native_mods, + ui::KeyboardCode* remapped_keycode, + unsigned int* remapped_mods) { for (size_t i = 0; i < num_remappings; ++i) { const KeyboardRemapping& map = remappings[i]; @@ -301,8 +323,10 @@ bool EventRewriter::RewriteWithKeyboardRemappingsByKeySym( continue; *remapped_native_keysym = map.output_keysym; + *remapped_keycode = map.output_keycode; *remapped_native_mods = (native_mods & ~map.input_native_mods) | map.output_native_mods; + *remapped_mods = (mods & ~map.input_mods) | map.output_mods; return true; } @@ -314,8 +338,11 @@ bool EventRewriter::RewriteWithKeyboardRemappingsByKeyCode( size_t num_remappings, KeyCode keycode, unsigned int native_mods, + unsigned int mods, KeySym* remapped_native_keysym, - unsigned int* remapped_native_mods) { + unsigned int* remapped_native_mods, + ui::KeyboardCode* remapped_keycode, + unsigned int* remapped_mods) { for (size_t i = 0; i < num_remappings; ++i) { const KeyboardRemapping& map = remappings[i]; @@ -327,13 +354,16 @@ bool EventRewriter::RewriteWithKeyboardRemappingsByKeyCode( continue; *remapped_native_keysym = map.output_keysym; + *remapped_keycode = map.output_keycode; *remapped_native_mods = (native_mods & ~map.input_native_mods) | map.output_native_mods; + *remapped_mods = (mods & ~map.input_mods) | map.output_mods; return true; } return false; } +#endif // defined(OS_CHROMEOS) const PrefService* EventRewriter::GetPrefService() const { if (pref_service_for_testing_) @@ -342,10 +372,11 @@ const PrefService* EventRewriter::GetPrefService() const { return profile ? profile->GetPrefs() : NULL; } -void EventRewriter::Rewrite(XEvent* event) { +void EventRewriter::Rewrite(ui::KeyEvent* event) { +#if defined(OS_CHROMEOS) // Do not rewrite an event sent by ui_controls::SendKeyPress(). See // crbug.com/136465. - if (event->xkey.send_event) + if (event->native_event()->xkey.send_event) return; // Keyboard driven rewriting happen first. Skip further processing if event is @@ -354,7 +385,7 @@ void EventRewriter::Rewrite(XEvent* event) { event)) { return; } - +#endif RewriteModifiers(event); RewriteNumPadKeys(event); RewriteExtendedKeys(event); @@ -378,12 +409,15 @@ bool EventRewriter::IsAppleKeyboard() const { } void EventRewriter::GetRemappedModifierMasks( + int original_flags, unsigned int original_native_modifiers, + int* remapped_flags, unsigned int* remapped_native_modifiers) const { +#if defined(OS_CHROMEOS) // TODO(glotov): remove the following condition when we do not restart chrome // when user logs in as guest. See Rewrite() for details. - if (UserManager::Get()->IsLoggedInAsGuest() && - LoginDisplayHostImpl::default_host()) { + if (chromeos::UserManager::Get()->IsLoggedInAsGuest() && + chromeos::LoginDisplayHostImpl::default_host()) { return; } @@ -414,14 +448,20 @@ void EventRewriter::GetRemappedModifierMasks( remapped_key = kModifierRemappingCtrl; } if (remapped_key) { + *remapped_flags |= remapped_key->flag; *remapped_native_modifiers |= remapped_key->native_modifier; } else { + *remapped_flags |= kModifierFlagToPrefName[i].flag; *remapped_native_modifiers |= kModifierFlagToPrefName[i].native_modifier; } } } + *remapped_flags = + (original_flags & ~(ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)) | + *remapped_flags; + unsigned int native_mask = Mod4Mask | ControlMask | Mod1Mask; if (!skip_mod2) native_mask |= Mod2Mask; @@ -430,10 +470,11 @@ void EventRewriter::GetRemappedModifierMasks( *remapped_native_modifiers = (original_native_modifiers & ~native_mask) | *remapped_native_modifiers; +#endif } -bool EventRewriter::RewriteModifiers(XEvent* event) { - DCHECK(event->type == KeyPress || event->type == KeyRelease); +bool EventRewriter::RewriteModifiers(ui::KeyEvent* event) { +#if defined(OS_CHROMEOS) // Do nothing if we have just logged in as guest but have not restarted chrome // process yet (so we are still on the login screen). In this situations we // have no user profile so can not do anything useful. @@ -441,20 +482,22 @@ bool EventRewriter::RewriteModifiers(XEvent* event) { // restart chrome process. In future this is to be changed. // TODO(glotov): remove the following condition when we do not restart chrome // when user logs in as guest. - if (UserManager::Get()->IsLoggedInAsGuest() && - LoginDisplayHostImpl::default_host()) + if (chromeos::UserManager::Get()->IsLoggedInAsGuest() && + chromeos::LoginDisplayHostImpl::default_host()) return false; const PrefService* pref_service = GetPrefService(); if (!pref_service) return false; - DCHECK_EQ(input_method::kControlKey, kModifierRemappingCtrl->remap_to); + DCHECK_EQ(chromeos::input_method::kControlKey, + kModifierRemappingCtrl->remap_to); - XKeyEvent* xkey = &event->xkey; + XEvent* xev = event->native_event(); + XKeyEvent* xkey = &(xev->xkey); KeySym keysym = XLookupKeysym(xkey, 0); - ui::KeyboardCode original_keycode = ui::KeyboardCodeFromNative(event); - ui::KeyboardCode remapped_keycode = original_keycode; + + ui::KeyboardCode remapped_keycode = event->key_code(); KeyCode remapped_native_keycode = xkey->keycode; // First, remap |keysym|. @@ -509,93 +552,113 @@ bool EventRewriter::RewriteModifiers(XEvent* event) { } if (remapped_key) { - int flags = ui::EventFlagsFromNative(event); remapped_keycode = remapped_key->keycode; - const size_t level = ((flags & ui::EF_SHIFT_DOWN) ? (1 << 1) : 0) + + const size_t level = (event->IsShiftDown() ? (1 << 1) : 0) + (IsRight(keysym) ? (1 << 0) : 0); const KeySym native_keysym = remapped_key->native_keysyms[level]; remapped_native_keycode = NativeKeySymToNativeKeycode(native_keysym); } // Next, remap modifier bits. + int remapped_flags = 0; unsigned int remapped_native_modifiers = 0U; - GetRemappedModifierMasks(xkey->state, &remapped_native_modifiers); + GetRemappedModifierMasks(event->flags(), xkey->state, + &remapped_flags, &remapped_native_modifiers); // Toggle Caps Lock if the remapped key is ui::VKEY_CAPITAL, but do nothing if // the original key is ui::VKEY_CAPITAL (i.e. a Caps Lock key on an external // keyboard is pressed) since X can handle that case. - if (event->type == KeyPress && - original_keycode != ui::VKEY_CAPITAL && - remapped_keycode == ui::VKEY_CAPITAL) { - input_method::XKeyboard* xkeyboard = xkeyboard_for_testing_ ? + if ((event->type() == ui::ET_KEY_PRESSED) && + (event->key_code() != ui::VKEY_CAPITAL) && + (remapped_keycode == ui::VKEY_CAPITAL)) { + chromeos::input_method::XKeyboard* xkeyboard = xkeyboard_for_testing_ ? xkeyboard_for_testing_ : - input_method::InputMethodManager::Get()->GetXKeyboard(); + chromeos::input_method::InputMethodManager::Get()->GetXKeyboard(); xkeyboard->SetCapsLockEnabled(!xkeyboard->CapsLockIsEnabled()); } - OverwriteEvent(event, remapped_native_keycode, remapped_native_modifiers); + OverwriteEvent(event, + remapped_native_keycode, remapped_native_modifiers, + remapped_keycode, remapped_flags); return true; +#else + // TODO(yusukes): Support Ash on other platforms if needed. + return false; +#endif } -bool EventRewriter::RewriteNumPadKeys(XEvent* event) { - DCHECK(event->type == KeyPress || event->type == KeyRelease); +bool EventRewriter::RewriteNumPadKeys(ui::KeyEvent* event) { bool rewritten = false; - XKeyEvent* xkey = &event->xkey; +#if defined(OS_CHROMEOS) + XEvent* xev = event->native_event(); + XKeyEvent* xkey = &(xev->xkey); + const KeySym keysym = XLookupKeysym(xkey, 0); switch (keysym) { case XK_KP_Insert: OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_0), - xkey->state | Mod2Mask); + xkey->state | Mod2Mask, + ui::VKEY_NUMPAD0, event->flags()); rewritten = true; break; case XK_KP_Delete: OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_Decimal), - xkey->state | Mod2Mask); + xkey->state | Mod2Mask, + ui::VKEY_DECIMAL, event->flags()); rewritten = true; break; case XK_KP_End: OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_1), - xkey->state | Mod2Mask); + xkey->state | Mod2Mask, + ui::VKEY_NUMPAD1, event->flags()); rewritten = true; break; case XK_KP_Down: OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_2), - xkey->state | Mod2Mask); + xkey->state | Mod2Mask, + ui::VKEY_NUMPAD2, event->flags()); rewritten = true; break; case XK_KP_Next: OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_3), - xkey->state | Mod2Mask); + xkey->state | Mod2Mask, + ui::VKEY_NUMPAD3, event->flags()); rewritten = true; break; case XK_KP_Left: OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_4), - xkey->state | Mod2Mask); + xkey->state | Mod2Mask, + ui::VKEY_NUMPAD4, event->flags()); rewritten = true; break; case XK_KP_Begin: OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_5), - xkey->state | Mod2Mask); + xkey->state | Mod2Mask, + ui::VKEY_NUMPAD5, event->flags()); rewritten = true; break; case XK_KP_Right: OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_6), - xkey->state | Mod2Mask); + xkey->state | Mod2Mask, + ui::VKEY_NUMPAD6, event->flags()); rewritten = true; break; case XK_KP_Home: OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_7), - xkey->state | Mod2Mask); + xkey->state | Mod2Mask, + ui::VKEY_NUMPAD7, event->flags()); rewritten = true; break; case XK_KP_Up: OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_8), - xkey->state | Mod2Mask); + xkey->state | Mod2Mask, + ui::VKEY_NUMPAD8, event->flags()); rewritten = true; break; case XK_KP_Prior: OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_9), - xkey->state | Mod2Mask); + xkey->state | Mod2Mask, + ui::VKEY_NUMPAD9, event->flags()); rewritten = true; break; case XK_KP_Divide: @@ -604,145 +667,199 @@ bool EventRewriter::RewriteNumPadKeys(XEvent* event) { case XK_KP_Add: case XK_KP_Enter: // Add Mod2Mask for consistency. - OverwriteEvent(event, xkey->keycode, xkey->state | Mod2Mask); + OverwriteEvent(event, xkey->keycode, xkey->state | Mod2Mask, + event->key_code(), event->flags()); rewritten = true; break; default: break; } +#else + // TODO(yusukes): Support Ash on other platforms if needed. +#endif return rewritten; } -bool EventRewriter::RewriteExtendedKeys(XEvent* event) { - DCHECK(event->type == KeyPress || event->type == KeyRelease); - XKeyEvent* xkey = &event->xkey; +bool EventRewriter::RewriteExtendedKeys(ui::KeyEvent* event) { +#if defined(OS_CHROMEOS) + XEvent* xev = event->native_event(); + XKeyEvent* xkey = &(xev->xkey); const KeySym keysym = XLookupKeysym(xkey, 0); KeySym remapped_native_keysym = 0; unsigned int remapped_native_mods = 0; - bool rewritten = false; + ui::KeyboardCode remapped_keycode = ui::VKEY_UNKNOWN; + unsigned int remapped_mods = 0; if (xkey->state & Mod4Mask) { // Allow Search to avoid rewriting extended keys. static const KeyboardRemapping kAvoidRemappings[] = { { // Alt+Backspace - XK_BackSpace, Mod1Mask | Mod4Mask, - XK_BackSpace, Mod1Mask, + XK_BackSpace, + ui::EF_ALT_DOWN, Mod1Mask | Mod4Mask, + XK_BackSpace, ui::VKEY_BACK, + ui::EF_ALT_DOWN, Mod1Mask, }, { // Control+Alt+Up - XK_Up, Mod1Mask | ControlMask | Mod4Mask, - XK_Up, Mod1Mask | ControlMask, + XK_Up, + ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, + Mod1Mask | ControlMask | Mod4Mask, + XK_Up, ui::VKEY_UP, + ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, Mod1Mask | ControlMask, }, { // Alt+Up - XK_Up, Mod1Mask | Mod4Mask, - XK_Up, Mod1Mask, + XK_Up, + ui::EF_ALT_DOWN, Mod1Mask | Mod4Mask, + XK_Up, ui::VKEY_UP, + ui::EF_ALT_DOWN, Mod1Mask, }, { // Control+Alt+Down - XK_Down, Mod1Mask | ControlMask | Mod4Mask, - XK_Down, Mod1Mask | ControlMask, + XK_Down, + ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, + Mod1Mask | ControlMask | Mod4Mask, + XK_Down, ui::VKEY_DOWN, + ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, Mod1Mask | ControlMask, }, { // Alt+Down - XK_Down, Mod1Mask | Mod4Mask, - XK_Down, Mod1Mask, + XK_Down, + ui::EF_ALT_DOWN, Mod1Mask | Mod4Mask, + XK_Down, ui::VKEY_DOWN, + ui::EF_ALT_DOWN, Mod1Mask, } }; - rewritten = RewriteWithKeyboardRemappingsByKeySym( - kAvoidRemappings, - arraysize(kAvoidRemappings), - keysym, - xkey->state, - &remapped_native_keysym, - &remapped_native_mods); + RewriteWithKeyboardRemappingsByKeySym(kAvoidRemappings, + arraysize(kAvoidRemappings), + keysym, + xkey->state, + event->flags(), + &remapped_native_keysym, + &remapped_native_mods, + &remapped_keycode, + &remapped_mods); } - if (!rewritten) { + if (remapped_keycode == ui::VKEY_UNKNOWN) { static const KeyboardRemapping kSearchRemappings[] = { { // Search+BackSpace -> Delete - XK_BackSpace, Mod4Mask, - XK_Delete, 0 + XK_BackSpace, + 0, Mod4Mask, + XK_Delete, ui::VKEY_DELETE, + 0, 0 }, { // Search+Left -> Home - XK_Left, Mod4Mask, - XK_Home, 0 + XK_Left, + 0, Mod4Mask, + XK_Home, ui::VKEY_HOME, + 0, 0 }, { // Search+Up -> Prior (aka PageUp) - XK_Up, Mod4Mask, - XK_Prior, 0 + XK_Up, + 0, Mod4Mask, + XK_Prior, ui::VKEY_PRIOR, + 0, 0 }, { // Search+Right -> End - XK_Right, Mod4Mask, - XK_End, 0 + XK_Right, + 0, Mod4Mask, + XK_End, ui::VKEY_END, + 0, 0 }, { // Search+Down -> Next (aka PageDown) - XK_Down, Mod4Mask, - XK_Next, 0 + XK_Down, + 0, Mod4Mask, + XK_Next, ui::VKEY_NEXT, + 0, 0 }, { // Search+Period -> Insert - XK_period, Mod4Mask, - XK_Insert, 0 + XK_period, + 0, Mod4Mask, + XK_Insert, ui::VKEY_INSERT, + 0, 0 } }; - rewritten = RewriteWithKeyboardRemappingsByKeySym( - kSearchRemappings, - arraysize(kSearchRemappings), - keysym, - xkey->state, - &remapped_native_keysym, - &remapped_native_mods); + RewriteWithKeyboardRemappingsByKeySym(kSearchRemappings, + arraysize(kSearchRemappings), + keysym, + xkey->state, + event->flags(), + &remapped_native_keysym, + &remapped_native_mods, + &remapped_keycode, + &remapped_mods); } - if (!rewritten) { + if (remapped_keycode == ui::VKEY_UNKNOWN) { static const KeyboardRemapping kNonSearchRemappings[] = { { // Alt+BackSpace -> Delete - XK_BackSpace, Mod1Mask, - XK_Delete, 0 + XK_BackSpace, + ui::EF_ALT_DOWN, Mod1Mask, + XK_Delete, ui::VKEY_DELETE, + 0, 0 }, { // Control+Alt+Up -> Home - XK_Up, Mod1Mask | ControlMask, - XK_Home, 0 + XK_Up, + ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, Mod1Mask | ControlMask, + XK_Home, ui::VKEY_HOME, + 0, 0 }, { // Alt+Up -> Prior (aka PageUp) - XK_Up, Mod1Mask, - XK_Prior, 0 + XK_Up, + ui::EF_ALT_DOWN, Mod1Mask, + XK_Prior, ui::VKEY_PRIOR, + 0, 0 }, { // Control+Alt+Down -> End - XK_Down, Mod1Mask | ControlMask, - XK_End, 0 + XK_Down, + ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, Mod1Mask | ControlMask, + XK_End, ui::VKEY_END, + 0, 0 }, { // Alt+Down -> Next (aka PageDown) - XK_Down, Mod1Mask, - XK_Next, 0 + XK_Down, + ui::EF_ALT_DOWN, Mod1Mask, + XK_Next, ui::VKEY_NEXT, + 0, 0 } }; - rewritten = RewriteWithKeyboardRemappingsByKeySym( - kNonSearchRemappings, - arraysize(kNonSearchRemappings), - keysym, - xkey->state, - &remapped_native_keysym, - &remapped_native_mods); + RewriteWithKeyboardRemappingsByKeySym(kNonSearchRemappings, + arraysize(kNonSearchRemappings), + keysym, + xkey->state, + event->flags(), + &remapped_native_keysym, + &remapped_native_mods, + &remapped_keycode, + &remapped_mods); } - if (!rewritten) + if (remapped_keycode == ui::VKEY_UNKNOWN) return false; OverwriteEvent(event, NativeKeySymToNativeKeycode(remapped_native_keysym), - remapped_native_mods); + remapped_native_mods, + remapped_keycode, + remapped_mods); return true; +#else + // TODO(yusukes): Support Ash on other platforms if needed. + return false; +#endif } -bool EventRewriter::RewriteFunctionKeys(XEvent* event) { - DCHECK(event->type == KeyPress || event->type == KeyRelease); - XKeyEvent* xkey = &event->xkey; +bool EventRewriter::RewriteFunctionKeys(ui::KeyEvent* event) { +#if defined(OS_CHROMEOS) + XEvent* xev = event->native_event(); + XKeyEvent* xkey = &(xev->xkey); const KeySym keysym = XLookupKeysym(xkey, 0); KeySym remapped_native_keysym = 0; unsigned int remapped_native_mods = 0; - bool rewritten = false; + ui::KeyboardCode remapped_keycode = ui::VKEY_UNKNOWN; + unsigned int remapped_mods = 0; // By default the top row (F1-F12) keys are special keys for back, forward, // brightness, volume, etc. However, windows for v2 apps can optionally @@ -752,65 +869,71 @@ bool EventRewriter::RewriteFunctionKeys(XEvent* event) { if ((xkey->state & Mod4Mask) && top_row_keys_are_special_keys) { // Allow Search to avoid rewriting F1-F12. static const KeyboardRemapping kFkeysToFkeys[] = { - { XK_F1, Mod4Mask, XK_F1, }, - { XK_F2, Mod4Mask, XK_F2, }, - { XK_F3, Mod4Mask, XK_F3, }, - { XK_F4, Mod4Mask, XK_F4, }, - { XK_F5, Mod4Mask, XK_F5, }, - { XK_F6, Mod4Mask, XK_F6, }, - { XK_F7, Mod4Mask, XK_F7, }, - { XK_F8, Mod4Mask, XK_F8, }, - { XK_F9, Mod4Mask, XK_F9, }, - { XK_F10, Mod4Mask, XK_F10, }, - { XK_F11, Mod4Mask, XK_F11, }, - { XK_F12, Mod4Mask, XK_F12, }, + { XK_F1, 0, Mod4Mask, XK_F1, ui::VKEY_F1, }, + { XK_F2, 0, Mod4Mask, XK_F2, ui::VKEY_F2, }, + { XK_F3, 0, Mod4Mask, XK_F3, ui::VKEY_F3, }, + { XK_F4, 0, Mod4Mask, XK_F4, ui::VKEY_F4, }, + { XK_F5, 0, Mod4Mask, XK_F5, ui::VKEY_F5, }, + { XK_F6, 0, Mod4Mask, XK_F6, ui::VKEY_F6, }, + { XK_F7, 0, Mod4Mask, XK_F7, ui::VKEY_F7, }, + { XK_F8, 0, Mod4Mask, XK_F8, ui::VKEY_F8, }, + { XK_F9, 0, Mod4Mask, XK_F9, ui::VKEY_F9, }, + { XK_F10, 0, Mod4Mask, XK_F10, ui::VKEY_F10, }, + { XK_F11, 0, Mod4Mask, XK_F11, ui::VKEY_F11, }, + { XK_F12, 0, Mod4Mask, XK_F12, ui::VKEY_F12, }, }; - rewritten = RewriteWithKeyboardRemappingsByKeySym( - kFkeysToFkeys, - arraysize(kFkeysToFkeys), - keysym, - xkey->state, - &remapped_native_keysym, - &remapped_native_mods); + RewriteWithKeyboardRemappingsByKeySym(kFkeysToFkeys, + arraysize(kFkeysToFkeys), + keysym, + xkey->state, + event->flags(), + &remapped_native_keysym, + &remapped_native_mods, + &remapped_keycode, + &remapped_mods); } - if (!rewritten) { + if (remapped_keycode == ui::VKEY_UNKNOWN) { static const KeyboardRemapping kFkeysToSpecialKeys[] = { - { XK_F1, 0, XF86XK_Back, 0 }, - { XK_F2, 0, XF86XK_Forward, 0 }, - { XK_F3, 0, XF86XK_Reload, 0 }, - { XK_F4, 0, XF86XK_LaunchB, 0 }, - { XK_F5, 0, XF86XK_LaunchA, 0 }, - { XK_F6, 0, XF86XK_MonBrightnessDown, 0 }, - { XK_F7, 0, XF86XK_MonBrightnessUp, 0 }, - { XK_F8, 0, XF86XK_AudioMute, 0 }, - { XK_F9, 0, XF86XK_AudioLowerVolume, 0 }, - { XK_F10, 0, XF86XK_AudioRaiseVolume, 0 }, + { XK_F1, 0, 0, XF86XK_Back, ui::VKEY_BROWSER_BACK, 0, 0 }, + { XK_F2, 0, 0, XF86XK_Forward, ui::VKEY_BROWSER_FORWARD, 0, 0 }, + { XK_F3, 0, 0, XF86XK_Reload, ui::VKEY_BROWSER_REFRESH, 0, 0 }, + { XK_F4, 0, 0, XF86XK_LaunchB, ui::VKEY_MEDIA_LAUNCH_APP2, 0, 0 }, + { XK_F5, 0, 0, XF86XK_LaunchA, ui::VKEY_MEDIA_LAUNCH_APP1, 0, 0 }, + { XK_F6, 0, 0, XF86XK_MonBrightnessDown, ui::VKEY_BRIGHTNESS_DOWN, 0, 0 }, + { XK_F7, 0, 0, XF86XK_MonBrightnessUp, ui::VKEY_BRIGHTNESS_UP, 0, 0 }, + { XK_F8, 0, 0, XF86XK_AudioMute, ui::VKEY_VOLUME_MUTE, 0, 0 }, + { XK_F9, 0, 0, XF86XK_AudioLowerVolume, ui::VKEY_VOLUME_DOWN, 0, 0 }, + { XK_F10, 0, 0, XF86XK_AudioRaiseVolume, ui::VKEY_VOLUME_UP, 0, 0 }, }; if (top_row_keys_are_special_keys) { // Rewrite the F1-F12 keys on a Chromebook keyboard to special keys. - rewritten = RewriteWithKeyboardRemappingsByKeySym( - kFkeysToSpecialKeys, - arraysize(kFkeysToSpecialKeys), - keysym, - xkey->state, - &remapped_native_keysym, - &remapped_native_mods); + RewriteWithKeyboardRemappingsByKeySym(kFkeysToSpecialKeys, + arraysize(kFkeysToSpecialKeys), + keysym, + xkey->state, + event->flags(), + &remapped_native_keysym, + &remapped_native_mods, + &remapped_keycode, + &remapped_mods); } else if (xkey->state & Mod4Mask) { // Use Search + F1-F12 for the special keys. - rewritten = RewriteWithKeyboardRemappingsByKeySym( - kFkeysToSpecialKeys, - arraysize(kFkeysToSpecialKeys), - keysym, - xkey->state & !Mod4Mask, - &remapped_native_keysym, - &remapped_native_mods); + RewriteWithKeyboardRemappingsByKeySym(kFkeysToSpecialKeys, + arraysize(kFkeysToSpecialKeys), + keysym, + xkey->state & !Mod4Mask, + event->flags(), + &remapped_native_keysym, + &remapped_native_mods, + &remapped_keycode, + &remapped_mods); } } - if (!rewritten && (xkey->state & Mod4Mask)) { + if (remapped_keycode == ui::VKEY_UNKNOWN && xkey->state & Mod4Mask) { // Remap Search+<number> to F<number>. // We check the keycode here instead of the keysym, as these keys have // different keysyms when modifiers are pressed, such as shift. @@ -819,47 +942,64 @@ bool EventRewriter::RewriteFunctionKeys(XEvent* event) { // should make layout-specific choices here. For eg. on a french keyboard // "-" and "6" are the same key, so F11 will not be accessible. static const KeyboardRemapping kNumberKeysToFkeys[] = { - { XK_1, Mod4Mask, XK_F1, 0 }, - { XK_2, Mod4Mask, XK_F2, 0 }, - { XK_3, Mod4Mask, XK_F3, 0 }, - { XK_4, Mod4Mask, XK_F4, 0 }, - { XK_5, Mod4Mask, XK_F5, 0 }, - { XK_6, Mod4Mask, XK_F6, 0 }, - { XK_7, Mod4Mask, XK_F7, 0 }, - { XK_8, Mod4Mask, XK_F8, 0 }, - { XK_9, Mod4Mask, XK_F9, 0 }, - { XK_0, Mod4Mask, XK_F10, 0 }, - { XK_minus, Mod4Mask, XK_F11, 0 }, - { XK_equal, Mod4Mask, XK_F12, 0 } + { XK_1, 0, Mod4Mask, XK_F1, ui::VKEY_F1, 0, 0 }, + { XK_2, 0, Mod4Mask, XK_F2, ui::VKEY_F2, 0, 0 }, + { XK_3, 0, Mod4Mask, XK_F3, ui::VKEY_F3, 0, 0 }, + { XK_4, 0, Mod4Mask, XK_F4, ui::VKEY_F4, 0, 0 }, + { XK_5, 0, Mod4Mask, XK_F5, ui::VKEY_F5, 0, 0 }, + { XK_6, 0, Mod4Mask, XK_F6, ui::VKEY_F6, 0, 0 }, + { XK_7, 0, Mod4Mask, XK_F7, ui::VKEY_F7, 0, 0 }, + { XK_8, 0, Mod4Mask, XK_F8, ui::VKEY_F8, 0, 0 }, + { XK_9, 0, Mod4Mask, XK_F9, ui::VKEY_F9, 0, 0 }, + { XK_0, 0, Mod4Mask, XK_F10, ui::VKEY_F10, 0, 0 }, + { XK_minus, 0, Mod4Mask, XK_F11, ui::VKEY_F11, 0, 0 }, + { XK_equal, 0, Mod4Mask, XK_F12, ui::VKEY_F12, 0, 0 } }; - rewritten = RewriteWithKeyboardRemappingsByKeyCode( - kNumberKeysToFkeys, - arraysize(kNumberKeysToFkeys), - xkey->keycode, - xkey->state, - &remapped_native_keysym, - &remapped_native_mods); + RewriteWithKeyboardRemappingsByKeyCode(kNumberKeysToFkeys, + arraysize(kNumberKeysToFkeys), + xkey->keycode, + xkey->state, + event->flags(), + &remapped_native_keysym, + &remapped_native_mods, + &remapped_keycode, + &remapped_mods); } - if (!rewritten) + if (remapped_keycode == ui::VKEY_UNKNOWN) return false; OverwriteEvent(event, NativeKeySymToNativeKeycode(remapped_native_keysym), - remapped_native_mods); + remapped_native_mods, + remapped_keycode, + remapped_mods); return true; +#else + // TODO(danakj): Support Ash on other platforms if needed. + return false; +#endif } -void EventRewriter::RewriteLocatedEvent(XEvent* event) { - DCHECK_EQ(GenericEvent, event->type); - XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event->xcookie.data); - DCHECK(xievent->evtype == XI_ButtonPress || - xievent->evtype == XI_ButtonRelease); +void EventRewriter::RewriteLocatedEvent(ui::LocatedEvent* event) { +#if defined(OS_CHROMEOS) + if (event->flags() & ui::EF_IS_SYNTHESIZED) + return; + + XEvent* xevent = event->native_event(); + if (!xevent || xevent->type != GenericEvent) + return; + + XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data); + if (xievent->evtype != XI_ButtonPress && xievent->evtype != XI_ButtonRelease) + return; // First, remap modifier masks. + int remapped_flags = 0; unsigned int remapped_native_modifiers = 0U; - GetRemappedModifierMasks(xievent->mods.effective, &remapped_native_modifiers); + GetRemappedModifierMasks(event->flags(), xievent->mods.effective, + &remapped_flags, &remapped_native_modifiers); xievent->mods.effective = remapped_native_modifiers; // Then, remap Alt+Button1 to Button3. @@ -879,15 +1019,34 @@ void EventRewriter::RewriteLocatedEvent(XEvent* event) { pressed_device_ids_.insert(xievent->sourceid); } } + + const int mouse_event_flags = event->flags() & + (ui::EF_IS_DOUBLE_CLICK | ui::EF_IS_TRIPLE_CLICK | ui::EF_IS_NON_CLIENT | + ui::EF_IS_SYNTHESIZED | ui::EF_FROM_TOUCH); + event->set_flags(mouse_event_flags | ui::EventFlagsFromNative(xevent)); +#else + // TODO(yusukes): Support Ash on other platforms if needed. +#endif } -void EventRewriter::OverwriteEvent(XEvent* event, +void EventRewriter::OverwriteEvent(ui::KeyEvent* event, unsigned int new_native_keycode, - unsigned int new_native_state) { - DCHECK(event->type == KeyPress || event->type == KeyRelease); - XKeyEvent* xkey = &event->xkey; + unsigned int new_native_state, + ui::KeyboardCode new_keycode, + int new_flags) { +#if defined(OS_CHROMEOS) + XEvent* xev = event->native_event(); + XKeyEvent* xkey = &(xev->xkey); xkey->keycode = new_native_keycode; xkey->state = new_native_state; + event->set_key_code(new_keycode); + event->set_character(ui::GetCharacterFromKeyCode(event->key_code(), + new_flags)); + event->set_flags(new_flags); + event->NormalizeFlags(); +#else + // TODO(yusukes): Support Ash on other platforms if needed. +#endif } EventRewriter::DeviceType EventRewriter::DeviceAddedInternal( @@ -903,5 +1062,3 @@ EventRewriter::DeviceType EventRewriter::DeviceAddedInternal( device_id_to_type_[device_id] = type; return type; } - -} // namespace chromeos diff --git a/chrome/browser/chromeos/event_rewriter.h b/chrome/browser/ui/ash/event_rewriter.h index 396911a..f085075 100644 --- a/chrome/browser/chromeos/event_rewriter.h +++ b/chrome/browser/ui/ash/event_rewriter.h @@ -1,39 +1,49 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_CHROMEOS_EVENT_REWRITER_H_ -#define CHROME_BROWSER_CHROMEOS_EVENT_REWRITER_H_ +#ifndef CHROME_BROWSER_UI_ASH_EVENT_REWRITER_H_ +#define CHROME_BROWSER_UI_ASH_EVENT_REWRITER_H_ #include <map> #include <set> #include <string> +#include "ash/event_rewriter_delegate.h" #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/containers/hash_tables.h" #include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_pump_observer.h" -#include "chrome/browser/chromeos/device_hierarchy_observer.h" #include "ui/aura/root_window_observer.h" #include "ui/events/keycodes/keyboard_codes.h" +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/device_hierarchy_observer.h" +#endif + class PrefService; -typedef union _XEvent XEvent; namespace aura { class RootWindow; } +#if defined(OS_CHROMEOS) namespace chromeos { + class KeyboardDrivenEventRewriter; + namespace input_method { class XKeyboard; } - -class EventRewriter : public aura::RootWindowObserver, - public DeviceHierarchyObserver, - public base::MessagePumpObserver { +} +#endif + +class EventRewriter : public ash::EventRewriterDelegate, + public aura::RootWindowObserver +#if defined(OS_CHROMEOS) + , public chromeos::DeviceHierarchyObserver +#endif +{ public: enum DeviceType { kDeviceUnknown = 0, @@ -47,7 +57,7 @@ class EventRewriter : public aura::RootWindowObserver, DeviceType DeviceAddedForTesting(int device_id, const std::string& device_name); // Calls Rewrite. - void RewriteForTesting(XEvent* event); + void RewriteForTesting(ui::KeyEvent* event); const std::map<int, DeviceType>& device_id_to_type_for_testing() const { return device_id_to_type_; @@ -58,9 +68,11 @@ class EventRewriter : public aura::RootWindowObserver, void set_pref_service_for_testing(const PrefService* pref_service) { pref_service_for_testing_ = pref_service; } - void set_xkeyboard_for_testing(input_method::XKeyboard* xkeyboard) { +#if defined(OS_CHROMEOS) + void set_xkeyboard_for_testing(chromeos::input_method::XKeyboard* xkeyboard) { xkeyboard_for_testing_ = xkeyboard; } +#endif // Gets DeviceType from the |device_name|. static DeviceType GetDeviceType(const std::string& device_name); @@ -69,15 +81,17 @@ class EventRewriter : public aura::RootWindowObserver, friend class EventRewriterAshTest; friend class EventRewriterTest; + // ash::EventRewriterDelegate overrides: + virtual ash::EventRewriterDelegate::Action RewriteOrFilterKeyEvent( + ui::KeyEvent* event) OVERRIDE; + virtual ash::EventRewriterDelegate::Action RewriteOrFilterLocatedEvent( + ui::LocatedEvent* event) OVERRIDE; + // aura::RootWindowObserver overrides: virtual void OnKeyboardMappingChanged(const aura::RootWindow* root) OVERRIDE; - // base::MessagePumpObserver overrides: - virtual base::EventStatus WillProcessEvent( - const base::NativeEvent& event) OVERRIDE; - virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE; - - // DeviceHierarchyObserver overrides: +#if defined(OS_CHROMEOS) + // chromeos::DeviceHierarchyObserver overrides: virtual void DeviceHierarchyChanged() OVERRIDE {} virtual void DeviceAdded(int device_id) OVERRIDE; virtual void DeviceRemoved(int device_id) OVERRIDE; @@ -95,8 +109,11 @@ class EventRewriter : public aura::RootWindowObserver, struct KeyboardRemapping { KeySym input_keysym; + unsigned int input_mods; unsigned int input_native_mods; KeySym output_keysym; + ui::KeyboardCode output_keycode; + unsigned int output_mods; unsigned int output_native_mods; }; @@ -104,7 +121,7 @@ class EventRewriter : public aura::RootWindowObserver, // keys instead of having them rewritten into back, forward, brightness, // volume, etc. or if the user has specified that they desire top-row keys to // be treated as function keys globally. - bool TopRowKeysAreFunctionKeys(XEvent* event) const; + bool TopRowKeysAreFunctionKeys(ui::KeyEvent* event) const; // Given a set of KeyboardRemapping structs, it finds a matching struct // if possible, and updates the remapped event values. Returns true if a @@ -114,8 +131,11 @@ class EventRewriter : public aura::RootWindowObserver, size_t num_remappings, KeySym keysym, unsigned int native_mods, + unsigned int mods, KeySym* remapped_native_keysym, - unsigned int* remapped_native_mods); + unsigned int* remapped_native_mods, + ui::KeyboardCode* remapped_keycode, + unsigned int* remapped_mods); // Given a set of KeyboardRemapping structs, it finds a matching struct // if possible, and updates the remapped event values. This function converts @@ -127,27 +147,31 @@ class EventRewriter : public aura::RootWindowObserver, size_t num_remappings, KeyCode keycode, unsigned int native_mods, + unsigned int mods, KeySym* remapped_native_keysym, - unsigned int* remapped_native_mods); + unsigned int* remapped_native_mods, + ui::KeyboardCode* remapped_keycode, + unsigned int* remapped_mods); +#endif // Returns the PrefService that should be used. const PrefService* GetPrefService() const; // Rewrites the |event| by applying all RewriteXXX functions as needed. - void Rewrite(XEvent* event); + void Rewrite(ui::KeyEvent* event); // Rewrites a modifier key press/release following the current user // preferences. - bool RewriteModifiers(XEvent* event); + bool RewriteModifiers(ui::KeyEvent* event); // Rewrites Fn key press/release to Control. In some cases, Fn key is not // intercepted by the EC, but generates a key event like "XK_F15 + Mod3Mask" // as shown in crosbug.com/p/14339. - bool RewriteFnKey(XEvent* event); + bool RewriteFnKey(ui::KeyEvent* event); // Rewrites a NumPad key press/release without Num Lock to a corresponding key // press/release with the lock. Returns true when |event| is rewritten. - bool RewriteNumPadKeys(XEvent* event); + bool RewriteNumPadKeys(ui::KeyEvent* event); // Rewrites Backspace and Arrow keys following the Chrome OS keyboard spec. // * Alt+Backspace -> Delete @@ -163,20 +187,22 @@ class EventRewriter : public aura::RootWindowObserver, // * Search+Right -> End // * Search+. -> Insert // Returns true when the |event| is rewritten. - bool RewriteExtendedKeys(XEvent* event); + bool RewriteExtendedKeys(ui::KeyEvent* event); // When the Search key acts as a function key, it remaps Search+1 // through Search+= to F1 through F12. Returns true when the |event| is // rewritten. - bool RewriteFunctionKeys(XEvent* event); + bool RewriteFunctionKeys(ui::KeyEvent* event); // Rewrites the located |event|. - void RewriteLocatedEvent(XEvent* event); + void RewriteLocatedEvent(ui::LocatedEvent* event); // Overwrites |event| with the keycodes and flags. - void OverwriteEvent(XEvent* event, + void OverwriteEvent(ui::KeyEvent* event, unsigned int new_native_keycode, - unsigned int new_native_state); + unsigned int new_native_state, + ui::KeyboardCode new_keycode, + int new_flags); // Checks the type of the |device_name|, and inserts a new entry to // |device_id_to_type_|. @@ -185,30 +211,32 @@ class EventRewriter : public aura::RootWindowObserver, // Returns true if |last_device_id_| is Apple's. bool IsAppleKeyboard() const; - // Remaps |original_native_modifiers| to |remapped_native_modifiers| following - // the current user prefs. - void GetRemappedModifierMasks(unsigned int original_native_modifiers, + // Remaps |original_flags| to |remapped_flags| and |original_native_modifiers| + // to |remapped_native_modifiers| following the current user prefs. + void GetRemappedModifierMasks(int original_flags, + unsigned int original_native_modifiers, + int* remapped_flags, unsigned int* remapped_native_modifiers) const; std::map<int, DeviceType> device_id_to_type_; int last_device_id_; +#if defined(OS_CHROMEOS) // A mapping from X11 KeySym keys to KeyCode values. base::hash_map<unsigned long, unsigned long> keysym_to_keycode_map_; // A set of device IDs whose press event has been rewritten. std::set<int> pressed_device_ids_; - input_method::XKeyboard* xkeyboard_for_testing_; + chromeos::input_method::XKeyboard* xkeyboard_for_testing_; - scoped_ptr<KeyboardDrivenEventRewriter> + scoped_ptr<chromeos::KeyboardDrivenEventRewriter> keyboard_driven_event_rewriter_; +#endif const PrefService* pref_service_for_testing_; DISALLOW_COPY_AND_ASSIGN(EventRewriter); }; -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_EVENT_REWRITER_H_ +#endif // CHROME_BROWSER_UI_ASH_EVENT_REWRITER_H_ diff --git a/chrome/browser/chromeos/event_rewriter_unittest.cc b/chrome/browser/ui/ash/event_rewriter_unittest.cc index 54d3eb6..c22d9ce 100644 --- a/chrome/browser/chromeos/event_rewriter_unittest.cc +++ b/chrome/browser/ui/ash/event_rewriter_unittest.cc @@ -1,41 +1,40 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/chromeos/event_rewriter.h" +#include "chrome/browser/ui/ash/event_rewriter.h" +#include "base/basictypes.h" +#include "base/command_line.h" +#include "base/prefs/pref_member.h" +#include "base/strings/stringprintf.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/base/testing_pref_service_syncable.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/event.h" + +#if defined(OS_CHROMEOS) #include <X11/keysym.h> #include <X11/XF86keysym.h> #include <X11/Xlib.h> -#undef Bool -#undef None -#undef RootWindow #include "ash/test/ash_test_base.h" #include "ash/wm/window_state.h" -#include "base/basictypes.h" -#include "base/command_line.h" -#include "base/prefs/pref_member.h" -#include "base/strings/stringprintf.h" #include "chrome/browser/chromeos/input_method/input_method_configuration.h" #include "chrome/browser/chromeos/input_method/mock_input_method_manager.h" #include "chrome/browser/chromeos/login/mock_user_manager.h" #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/preferences.h" -#include "chrome/common/pref_names.h" -#include "chrome/test/base/testing_pref_service_syncable.h" #include "chromeos/chromeos_switches.h" #include "chromeos/ime/fake_xkeyboard.h" -#include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/window.h" -#include "ui/events/event.h" #include "ui/events/test/events_test_utils_x11.h" #include "ui/events/x/touch_factory_x11.h" #include "ui/gfx/x/x11_types.h" namespace { -std::string GetRewrittenEventAsString(chromeos::EventRewriter* rewriter, +std::string GetRewrittenEventAsString(EventRewriter* rewriter, ui::KeyboardCode ui_keycode, int ui_flags, ui::EventType ui_type, @@ -46,8 +45,8 @@ std::string GetRewrittenEventAsString(chromeos::EventRewriter* rewriter, XEvent* xevent = xev; xevent->xkey.keycode = x_keycode; xevent->xkey.state = x_state; - rewriter->RewriteForTesting(xevent); - ui::KeyEvent keyevent(xevent, false /* is_char */); + ui::KeyEvent keyevent(xev, false /* is_char */); + rewriter->RewriteForTesting(&keyevent); return base::StringPrintf( "ui_keycode=%d ui_flags=%d ui_type=%d x_keycode=%u x_state=%u x_type=%d", keyevent.key_code(), keyevent.flags(), keyevent.type(), @@ -67,9 +66,7 @@ std::string GetExpectedResultAsString(ui::KeyboardCode ui_keycode, } // namespace -namespace chromeos { - -class EventRewriterTest : public ash::test::AshTestBase { +class EventRewriterTest : public testing::Test { public: EventRewriterTest() : display_(gfx::GetXDisplay()), @@ -175,12 +172,9 @@ class EventRewriterTest : public ash::test::AshTestBase { new chromeos::input_method::MockInputMethodManager; chromeos::input_method::InitializeForTesting( input_method_manager_mock_); // pass ownership - - AshTestBase::SetUp(); } virtual void TearDown() { - AshTestBase::TearDown(); // Shutdown() deletes the IME mock object. chromeos::input_method::Shutdown(); } @@ -189,11 +183,9 @@ class EventRewriterTest : public ash::test::AshTestBase { void TestRewriteNumPadKeys(); void TestRewriteNumPadKeysOnAppleKeyboard(); - void RewriteMouseEvent(EventRewriter* rewriter, - ui::MouseEvent* event) { - XEvent* xevent = event->native_event(); - rewriter->RewriteLocatedEvent(xevent); - *event = ui::MouseEvent(xevent); + void RewriteLocatedEvent(EventRewriter* rewriter, + ui::LocatedEvent* event) { + rewriter->RewriteLocatedEvent(event); } Display* display_; @@ -286,6 +278,14 @@ class EventRewriterTest : public ash::test::AshTestBase { chromeos::input_method::MockInputMethodManager* input_method_manager_mock_; }; +#else +class EventRewriterTest : public testing::Test { + public: + EventRewriterTest() {} + virtual ~EventRewriterTest() {} +}; +#endif + TEST_F(EventRewriterTest, TestGetDeviceType) { // This is the typical string which an Apple keyboard sends. EXPECT_EQ(EventRewriter::kDeviceAppleKeyboard, @@ -339,6 +339,7 @@ TEST_F(EventRewriterTest, TestDeviceAddedOrRemoved) { EXPECT_EQ(2U, rewriter.device_id_to_type_for_testing().size()); } +#if defined(OS_CHROMEOS) TEST_F(EventRewriterTest, TestRewriteCommandToControl) { // First, test with a PC keyboard. TestingPrefServiceSyncable prefs; @@ -2224,9 +2225,6 @@ TEST_F(EventRewriterTest, TestRewriteFunctionKeys) { }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { - // XKeysymToKeycode returns zero for unknown keys. So ignore those. - if (tests[i].output_native == 0) - continue; EXPECT_EQ(GetExpectedResultAsString(tests[i].output, tests[i].output_mods, ui::ET_KEY_PRESSED, @@ -2308,8 +2306,8 @@ TEST_F(EventRewriterTest, TestRewriteKeyEventSentByXSendEvent) { XEvent* xevent = xev; xevent->xkey.keycode = keycode_control_l_; xevent->xkey.send_event = True; // XSendEvent() always does this. - rewriter.RewriteForTesting(xevent); ui::KeyEvent keyevent(xev, false /* is_char */); + rewriter.RewriteForTesting(&keyevent); rewritten_event = base::StringPrintf( "ui_keycode=%d ui_flags=%d ui_type=%d " "x_keycode=%u x_state=%u x_type=%d", @@ -2337,7 +2335,7 @@ class EventRewriterAshTest : public ash::test::AshTestBase { } virtual ~EventRewriterAshTest() {} - bool RewriteFunctionKeys(XEvent* event) { + bool RewriteFunctionKeys(ui::KeyEvent* event) { return rewriter_.RewriteFunctionKeys(event); } @@ -2361,12 +2359,14 @@ TEST_F(EventRewriterAshTest, TopRowKeysAreFunctionKeys) { xev_f1.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_F1, 0); XEvent* xevent = xev_f1; xevent->xkey.keycode = keycode_f1; + ui::KeyEvent press_f1(xev_f1, false); + ui::Event::DispatcherApi dispatch_helper(&press_f1); + dispatch_helper.set_target(window.get()); // Simulate an apps v2 window that has requested top row keys as function // keys. The event should not be rewritten. window_state->set_top_row_keys_are_function_keys(true); - ASSERT_FALSE(RewriteFunctionKeys(xevent)); - ui::KeyEvent press_f1(xev_f1, false); + ASSERT_FALSE(RewriteFunctionKeys(&press_f1)); ASSERT_EQ(ui::VKEY_F1, press_f1.key_code()); // The event should also not be rewritten if the send-function-keys pref is @@ -2374,19 +2374,16 @@ TEST_F(EventRewriterAshTest, TopRowKeysAreFunctionKeys) { BooleanPrefMember send_function_keys_pref; send_function_keys_pref.Init(prefs::kLanguageSendFunctionKeys, &prefs_); send_function_keys_pref.SetValue(true); - ASSERT_FALSE(RewriteFunctionKeys(xevent)); - press_f1 = ui::KeyEvent(xev_f1, false); + ASSERT_FALSE(RewriteFunctionKeys(&press_f1)); ASSERT_EQ(ui::VKEY_F1, press_f1.key_code()); window_state->set_top_row_keys_are_function_keys(false); - ASSERT_FALSE(RewriteFunctionKeys(xevent)); - press_f1 = ui::KeyEvent(xev_f1, false); + ASSERT_FALSE(RewriteFunctionKeys(&press_f1)); ASSERT_EQ(ui::VKEY_F1, press_f1.key_code()); // If the pref isn't set when an event is sent to a regular window, F1 is // rewritten to the back key. send_function_keys_pref.SetValue(false); - ASSERT_TRUE(RewriteFunctionKeys(xevent)); - press_f1 = ui::KeyEvent(xev_f1, false); + ASSERT_TRUE(RewriteFunctionKeys(&press_f1)); ASSERT_EQ(ui::VKEY_BROWSER_BACK, press_f1.key_code()); } @@ -2407,7 +2404,7 @@ TEST_F(EventRewriterTest, DontRewriteIfNotRewritten) { EXPECT_EQ(ui::ET_MOUSE_PRESSED, press.type()); EXPECT_EQ(kLeftAndAltFlag, press.flags()); - RewriteMouseEvent(&rewriter, &press); + RewriteLocatedEvent(&rewriter, &press); EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & press.flags()); } @@ -2415,7 +2412,7 @@ TEST_F(EventRewriterTest, DontRewriteIfNotRewritten) { ui::ScopedXI2Event xev; xev.InitGenericButtonEvent(10, ui::ET_MOUSE_RELEASED, kLeftAndAltFlag); ui::MouseEvent release(xev); - RewriteMouseEvent(&rewriter, &release); + RewriteLocatedEvent(&rewriter, &release); EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & release.flags()); } @@ -2425,14 +2422,14 @@ TEST_F(EventRewriterTest, DontRewriteIfNotRewritten) { xev.InitGenericButtonEvent( 10, ui::ET_MOUSE_PRESSED, ui::EF_LEFT_MOUSE_BUTTON); ui::MouseEvent press(xev); - RewriteMouseEvent(&rewriter, &press); + RewriteLocatedEvent(&rewriter, &press); EXPECT_TRUE(ui::EF_LEFT_MOUSE_BUTTON & press.flags()); } { ui::ScopedXI2Event xev; xev.InitGenericButtonEvent(10, ui::ET_MOUSE_RELEASED, kLeftAndAltFlag); ui::MouseEvent release(xev); - RewriteMouseEvent(&rewriter, &release); + RewriteLocatedEvent(&rewriter, &release); EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & release.flags()); } @@ -2442,14 +2439,14 @@ TEST_F(EventRewriterTest, DontRewriteIfNotRewritten) { ui::ScopedXI2Event xev; xev.InitGenericButtonEvent(11, ui::ET_MOUSE_PRESSED, kLeftAndAltFlag); ui::MouseEvent press(xev); - RewriteMouseEvent(&rewriter, &press); + RewriteLocatedEvent(&rewriter, &press); EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & press.flags()); } { ui::ScopedXI2Event xev; xev.InitGenericButtonEvent(10, ui::ET_MOUSE_RELEASED, kLeftAndAltFlag); ui::MouseEvent release(xev); - RewriteMouseEvent(&rewriter, &release); + RewriteLocatedEvent(&rewriter, &release); EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & release.flags()); } @@ -2457,9 +2454,9 @@ TEST_F(EventRewriterTest, DontRewriteIfNotRewritten) { ui::ScopedXI2Event xev; xev.InitGenericButtonEvent(11, ui::ET_MOUSE_RELEASED, kLeftAndAltFlag); ui::MouseEvent release(xev); - RewriteMouseEvent(&rewriter, &release); + RewriteLocatedEvent(&rewriter, &release); EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & release.flags()); } } -} // namespace chromeos +#endif // OS_CHROMEOS diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi index 95a2851..ad90a0e 100644 --- a/chrome/chrome_browser_chromeos.gypi +++ b/chrome/chrome_browser_chromeos.gypi @@ -309,8 +309,6 @@ 'browser/chromeos/drive/write_on_cache_file.h', 'browser/chromeos/enrollment_dialog_view.cc', 'browser/chromeos/enrollment_dialog_view.h', - 'browser/chromeos/event_rewriter.cc', - 'browser/chromeos/event_rewriter.h', 'browser/chromeos/extensions/default_app_order.cc', 'browser/chromeos/extensions/default_app_order.h', 'browser/chromeos/extensions/device_local_account_external_policy_loader.cc', diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index 119c2aa..ec7e09e 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -287,6 +287,8 @@ 'browser/ui/ash/chrome_shell_delegate.h', 'browser/ui/ash/chrome_shell_delegate_chromeos.cc', 'browser/ui/ash/chrome_shell_delegate_views.cc', + 'browser/ui/ash/event_rewriter.cc', + 'browser/ui/ash/event_rewriter.h', 'browser/ui/ash/ime_controller_chromeos.cc', 'browser/ui/ash/ime_controller_chromeos.h', 'browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc', diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 5fde315..a7e005d 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -692,7 +692,6 @@ 'browser/chromeos/drive/test_util.cc', 'browser/chromeos/drive/test_util.h', 'browser/chromeos/drive/write_on_cache_file_unittest.cc', - 'browser/chromeos/event_rewriter_unittest.cc', 'browser/chromeos/extensions/default_app_order_unittest.cc', 'browser/chromeos/extensions/device_local_account_external_policy_loader_unittest.cc', 'browser/chromeos/extensions/external_cache_unittest.cc', @@ -1424,6 +1423,7 @@ 'browser/thumbnails/thumbnail_service_unittest.cc', 'browser/translate/translate_manager_unittest.cc', 'browser/ui/android/tab_model/tab_model_unittest.cc', + 'browser/ui/ash/event_rewriter_unittest.cc', 'browser/ui/ash/ime_controller_chromeos_unittest.cc', 'browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc', 'browser/ui/ash/launcher/launcher_context_menu_unittest.cc', |