blob: c25d7b9ae884b1647e2efdeb44658f59367e7394 [file] [log] [blame]
// Copyright 2014 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_EVENTS_EVENT_REWRITER_H_
#define CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_
#include <map>
#include <set>
#include <string>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/containers/hash_tables.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/chromeos/device_hierarchy_observer.h"
#include "chromeos/ime/ime_keyboard.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/events/platform/platform_event_observer.h"
class PrefService;
typedef union _XEvent XEvent;
namespace chromeos {
namespace input_method {
class ImeKeyboard;
}
class EventRewriter : public DeviceHierarchyObserver,
public ui::PlatformEventObserver {
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(XEvent* 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;
}
void set_keyboard_for_testing(input_method::ImeKeyboard* keyboard) {
keyboard_for_testing_ = keyboard;
}
// Gets DeviceType from the |device_name|.
static DeviceType GetDeviceType(const std::string& device_name);
private:
friend class EventRewriterAshTest;
friend class EventRewriterTest;
void DeviceKeyPressedOrReleased(int device_id);
// ui::PlatformEventObserver:
virtual void WillProcessEvent(const ui::PlatformEvent& event) OVERRIDE;
virtual void DidProcessEvent(const ui::PlatformEvent& event) OVERRIDE;
// DeviceHierarchyObserver:
virtual void DeviceHierarchyChanged() OVERRIDE;
virtual void DeviceAdded(int device_id) OVERRIDE;
virtual void DeviceRemoved(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_native_mods;
KeySym output_keysym;
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(XEvent* 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,
KeySym* remapped_native_keysym,
unsigned int* remapped_native_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,
KeySym* remapped_native_keysym,
unsigned int* remapped_native_mods);
// 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);
// Rewrites a modifier key press/release following the current user
// preferences.
bool RewriteModifiers(XEvent* 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);
// 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);
// 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(XEvent* 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);
// Rewrites the located |event|.
void RewriteLocatedEvent(XEvent* event);
// Overwrites |event| with the keycodes and flags.
void OverwriteEvent(XEvent* event,
unsigned int new_native_keycode,
unsigned int new_native_state);
// 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_native_modifiers| to |remapped_native_modifiers| following
// the current user prefs.
void GetRemappedModifierMasks(unsigned int original_native_modifiers,
unsigned int* remapped_native_modifiers) const;
std::map<int, DeviceType> device_id_to_type_;
int last_device_id_;
// 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::ImeKeyboard* keyboard_for_testing_;
const PrefService* pref_service_for_testing_;
DISALLOW_COPY_AND_ASSIGN(EventRewriter);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_