1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_
6#define CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_
7
8#include <map>
9#include <set>
10#include <string>
11
12#include "base/compiler_specific.h"
13#include "base/containers/hash_tables.h"
14#include "base/memory/scoped_ptr.h"
15#include "ui/events/event.h"
16#include "ui/events/event_rewriter.h"
17
18#if defined(USE_X11)
19#include "chrome/browser/chromeos/device_hierarchy_observer.h"
20#include "ui/events/platform/platform_event_observer.h"
21typedef union _XEvent XEvent;
22#endif
23
24class PrefService;
25
26namespace chromeos {
27namespace input_method {
28class ImeKeyboard;
29}
30
31// EventRewriter makes various changes to keyboard-related events,
32// including KeyEvents and some other events with keyboard modifier flags:
33// - maps modifiers keys (Control, Alt, Search, Caps, Diamond) according
34//   to user preferences;
35// - maps Command to Control on Apple keyboards;
36// - converts numeric pad editing keys to their numeric forms;
37// - converts top-row function keys to special keys where necessary;
38// - handles various key combinations like Search+Backspace -> Delete
39//   and Search+number to Fnumber;
40// - handles key/pointer combinations like Alt+Button1 -> Button3.
41class EventRewriter
42    :
43#if defined(USE_X11)
44      public DeviceHierarchyObserver,
45      public ui::PlatformEventObserver,
46#endif
47      public ui::EventRewriter {
48 public:
49  enum DeviceType {
50    kDeviceUnknown = 0,
51    kDeviceAppleKeyboard,
52  };
53
54  EventRewriter();
55  virtual ~EventRewriter();
56
57  // Calls DeviceAddedInternal.
58  DeviceType DeviceAddedForTesting(int device_id,
59                                   const std::string& device_name);
60
61  // Calls RewriteLocatedEvent().
62  void RewriteLocatedEventForTesting(const ui::Event& event, int* flags);
63
64#if defined(USE_X11)
65  const std::map<int, DeviceType>& device_id_to_type_for_testing() const {
66    return device_id_to_type_;
67  }
68#endif
69
70  void set_last_device_id_for_testing(int device_id) {
71    last_device_id_ = device_id;
72  }
73  void set_pref_service_for_testing(const PrefService* pref_service) {
74    pref_service_for_testing_ = pref_service;
75  }
76  void set_ime_keyboard_for_testing(
77      chromeos::input_method::ImeKeyboard* ime_keyboard) {
78    ime_keyboard_for_testing_ = ime_keyboard;
79  }
80
81  // EventRewriter overrides:
82  virtual ui::EventRewriteStatus RewriteEvent(
83      const ui::Event& event,
84      scoped_ptr<ui::Event>* rewritten_event) OVERRIDE;
85  virtual ui::EventRewriteStatus NextDispatchEvent(
86      const ui::Event& last_event,
87      scoped_ptr<ui::Event>* new_event) OVERRIDE;
88
89#if defined(USE_X11)
90  // ui::PlatformEventObserver:
91  virtual void WillProcessEvent(const ui::PlatformEvent& event) OVERRIDE;
92  virtual void DidProcessEvent(const ui::PlatformEvent& event) OVERRIDE;
93
94  // DeviceHierarchyObserver:
95  virtual void DeviceHierarchyChanged() OVERRIDE;
96  virtual void DeviceAdded(int device_id) OVERRIDE;
97  virtual void DeviceRemoved(int device_id) OVERRIDE;
98#endif
99
100 private:
101  // Things that internal rewriter phases can change about an Event.
102  struct MutableKeyState {
103    int flags;
104    ui::KeyboardCode key_code;
105  };
106
107  // Tables of direct remappings for |RewriteWithKeyboardRemappingsByKeyCode()|.
108  struct KeyboardRemapping {
109    ui::KeyboardCode input_key_code;
110    int input_flags;
111    ui::KeyboardCode output_key_code;
112    int output_flags;
113  };
114
115#if defined(USE_X11)
116  void DeviceKeyPressedOrReleased(int device_id);
117#endif
118
119  // Returns the PrefService that should be used.
120  const PrefService* GetPrefService() const;
121
122  // Checks the type of the |device_name|, and inserts a new entry to
123  // |device_id_to_type_|.
124  DeviceType DeviceAddedInternal(int device_id, const std::string& device_name);
125
126  // Returns true if |last_device_id_| is Apple's.
127  bool IsAppleKeyboard() const;
128
129  // Returns true if the target for |event| would prefer to receive raw function
130  // keys instead of having them rewritten into back, forward, brightness,
131  // volume, etc. or if the user has specified that they desire top-row keys to
132  // be treated as function keys globally.
133  bool TopRowKeysAreFunctionKeys(const ui::KeyEvent& event) const;
134
135  // Given modifier flags |original_flags|, returns the remapped modifiers
136  // according to user preferences and/or event properties.
137  int GetRemappedModifierMasks(const PrefService& pref_service,
138                               const ui::Event& event,
139                               int original_flags) const;
140
141  // Given a set of KeyboardRemapping structs, it finds a matching struct
142  // if possible, and updates the remapped event values. Returns true if a
143  // remapping was found and remapped values were updated.
144  bool RewriteWithKeyboardRemappingsByKeyCode(
145      const KeyboardRemapping* remappings,
146      size_t num_remappings,
147      const MutableKeyState& input,
148      MutableKeyState* remapped_state);
149
150  // Rewrite a particular kind of event.
151  ui::EventRewriteStatus RewriteKeyEvent(
152      const ui::KeyEvent& key_event,
153      scoped_ptr<ui::Event>* rewritten_event);
154  ui::EventRewriteStatus RewriteMouseEvent(
155      const ui::MouseEvent& mouse_event,
156      scoped_ptr<ui::Event>* rewritten_event);
157  ui::EventRewriteStatus RewriteTouchEvent(
158      const ui::TouchEvent& touch_event,
159      scoped_ptr<ui::Event>* rewritten_event);
160
161  // Rewriter phases. These can inspect the original |event|, but operate using
162  // the current |state|, which may have been modified by previous phases.
163  void RewriteModifierKeys(const ui::KeyEvent& event, MutableKeyState* state);
164  void RewriteNumPadKeys(const ui::KeyEvent& event, MutableKeyState* state);
165  void RewriteExtendedKeys(const ui::KeyEvent& event, MutableKeyState* state);
166  void RewriteFunctionKeys(const ui::KeyEvent& event, MutableKeyState* state);
167  void RewriteLocatedEvent(const ui::Event& event, int* flags);
168
169  // A set of device IDs whose press event has been rewritten.
170  std::set<int> pressed_device_ids_;
171
172  std::map<int, DeviceType> device_id_to_type_;
173  int last_device_id_;
174
175  chromeos::input_method::ImeKeyboard* ime_keyboard_for_testing_;
176  const PrefService* pref_service_for_testing_;
177
178  DISALLOW_COPY_AND_ASSIGN(EventRewriter);
179};
180
181}  // namespace chromeos
182
183#endif  // CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_
184