| // 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_UI_ASH_EVENT_REWRITER_H_ |
| #define CHROME_BROWSER_UI_ASH_EVENT_REWRITER_H_ |
| |
| #include <map> |
| #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 "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; |
| |
| namespace aura { |
| class RootWindow; |
| } |
| |
| #if defined(OS_CHROMEOS) |
| namespace chromeos { |
| |
| class KeyboardDrivenEventRewriter; |
| |
| namespace input_method { |
| class XKeyboard; |
| } |
| } |
| #endif |
| |
| class EventRewriter : public ash::EventRewriterDelegate, |
| public aura::RootWindowObserver |
| #if defined(OS_CHROMEOS) |
| , public chromeos::DeviceHierarchyObserver |
| #endif |
| { |
| public: |
| enum DeviceType { |
| kDeviceUnknown = 0, |
| kDeviceAppleKeyboard, |
| }; |
| |
| EventRewriter(); |
| virtual ~EventRewriter(); |
| |
| // Calls DeviceAddedInternal. |
| DeviceType DeviceAddedForTesting(int device_id, |
| const std::string& device_name); |
| // Calls Rewrite. |
| void RewriteForTesting(ui::KeyEvent* event); |
| |
| const std::map<int, DeviceType>& device_id_to_type_for_testing() const { |
| return device_id_to_type_; |
| } |
| void set_last_device_id_for_testing(int device_id) { |
| last_device_id_ = device_id; |
| } |
| void set_pref_service_for_testing(const PrefService* pref_service) { |
| pref_service_for_testing_ = pref_service; |
| } |
| #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); |
| |
| private: |
| friend class EventRewriterAshTest; |
| |
| // 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; |
| |
| #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; |
| virtual void DeviceKeyPressedOrReleased(int device_id) OVERRIDE; |
| |
| // We don't want to include Xlib.h here since it has polluting macros, so |
| // define these locally. |
| typedef unsigned long KeySym; |
| typedef unsigned char KeyCode; |
| |
| // Updates |*_xkeycode_| in response to a keyboard map change. |
| void RefreshKeycodes(); |
| // Converts an X key symbol like XK_Control_L to a key code. |
| unsigned char NativeKeySymToNativeKeycode(KeySym keysym); |
| |
| 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; |
| }; |
| |
| // Returns true if the target for |event| would prefer to receive raw function |
| // 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(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 |
| // remapping was found and remapped values were updated. |
| bool RewriteWithKeyboardRemappingsByKeySym( |
| const KeyboardRemapping* remappings, |
| size_t num_remappings, |
| KeySym keysym, |
| unsigned int native_mods, |
| unsigned int mods, |
| KeySym* remapped_native_keysym, |
| 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 |
| // the KeySym in the KeyboardRemapping struct into the KeyCode before matching |
| // to allow any KeyCode on the same physical key as the given KeySym to match. |
| // Returns true if a remapping was found and remapped values were updated. |
| bool RewriteWithKeyboardRemappingsByKeyCode( |
| const KeyboardRemapping* remappings, |
| size_t num_remappings, |
| KeyCode keycode, |
| unsigned int native_mods, |
| unsigned int mods, |
| KeySym* remapped_native_keysym, |
| 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(ui::KeyEvent* event); |
| |
| // Rewrites a modifier key press/release following the current user |
| // preferences. |
| 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(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(ui::KeyEvent* event); |
| |
| // Rewrites Backspace and Arrow keys following the Chrome OS keyboard spec. |
| // * Alt+Backspace -> Delete |
| // * Alt+Up -> Prior (aka PageUp) |
| // * Alt+Down -> Next (aka PageDown) |
| // * Ctrl+Alt+Up -> Home |
| // * Ctrl+Alt+Down -> End |
| // When the Search key acts as a function key, it instead maps: |
| // * Search+Backspace -> Delete |
| // * Search+Up -> Prior (aka PageUp) |
| // * Search+Down -> Next (aka PageDown) |
| // * Search+Left -> Home |
| // * Search+Right -> End |
| // * Search+. -> Insert |
| // Returns true when the |event| is rewritten. |
| 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(ui::KeyEvent* event); |
| |
| // Rewrites the located |event|. |
| void RewriteLocatedEvent(ui::LocatedEvent* event); |
| |
| // Overwrites |event| with the keycodes and flags. |
| void OverwriteEvent(ui::KeyEvent* event, |
| unsigned int new_native_keycode, |
| 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_|. |
| DeviceType DeviceAddedInternal(int device_id, const std::string& device_name); |
| |
| // Returns true if |last_device_id_| is Apple's. |
| bool IsAppleKeyboard() const; |
| |
| // 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_; |
| |
| chromeos::input_method::XKeyboard* xkeyboard_for_testing_; |
| |
| scoped_ptr<chromeos::KeyboardDrivenEventRewriter> |
| keyboard_driven_event_rewriter_; |
| #endif |
| |
| const PrefService* pref_service_for_testing_; |
| |
| DISALLOW_COPY_AND_ASSIGN(EventRewriter); |
| }; |
| |
| #endif // CHROME_BROWSER_UI_ASH_EVENT_REWRITER_H_ |