Flutter Windows Embedder
keyboard_key_embedder_handler.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter 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 FLUTTER_SHELL_PLATFORM_WINDOWS_KEYBOARD_KEY_EMBEDDER_HANDLER_H_
6 #define FLUTTER_SHELL_PLATFORM_WINDOWS_KEYBOARD_KEY_EMBEDDER_HANDLER_H_
7 
8 #include <functional>
9 #include <map>
10 #include <memory>
11 #include <string>
12 
13 #include "flutter/fml/macros.h"
14 #include "flutter/shell/platform/embedder/embedder.h"
16 
17 namespace flutter {
18 
19 // Encode a 32-bit unicode code point into a UTF-8 byte array.
20 //
21 // See https://en.wikipedia.org/wiki/UTF-8#Encoding for the algorithm.
22 std::string ConvertChar32ToUtf8(char32_t ch);
23 
24 // A delegate of |KeyboardKeyHandler| that handles events by sending
25 // converted |FlutterKeyEvent|s through the embedder API.
26 //
27 // This class communicates with the HardwareKeyboard API in the framework.
28 //
29 // Every key event must result in at least one FlutterKeyEvent, even an empty
30 // one (both logical and physical IDs are 0). This ensures that raw key
31 // messages are always preceded by key data so that the transit mode is
32 // correctly inferred. (Technically only the first key event needs so, but for
33 // simplicity.)
36  public:
37  using SendEventHandler =
38  std::function<void(const FlutterKeyEvent& /* event */,
39  FlutterKeyEventCallback /* callback */,
40  void* /* user_data */)>;
41  using GetKeyStateHandler = std::function<SHORT(int /* nVirtKey */)>;
43  std::function<SHORT(UINT /* nVirtKey */, bool /* extended */)>;
44 
45  // Build a KeyboardKeyEmbedderHandler.
46  //
47  // Use `send_event` to define how the class should dispatch converted
48  // flutter events, as well as how to receive the response, to the engine. It's
49  // typically FlutterWindowsEngine::SendKeyEvent. The 2nd and 3rd parameter
50  // of the SendEventHandler call might be nullptr.
51  //
52  // Use `get_key_state` to define how the class should get a reliable result of
53  // the state for a virtual key. It's typically Win32's GetKeyState, but can
54  // also be nullptr (for UWP).
55  //
56  // Use `map_vk_to_scan` to define how the class should get map a virtual key
57  // to a scan code. It's typically Win32's MapVirtualKey, but can also be
58  // nullptr (for UWP).
59  explicit KeyboardKeyEmbedderHandler(SendEventHandler send_event,
60  GetKeyStateHandler get_key_state,
61  MapVirtualKeyToScanCode map_vk_to_scan);
62 
64 
65  // |KeyboardHandlerBase|
66  void KeyboardHook(int key,
67  int scancode,
68  int action,
69  char32_t character,
70  bool extended,
71  bool was_down,
72  std::function<void(bool)> callback) override;
73 
74  void SyncModifiersIfNeeded(int modifiers_state) override;
75 
76  std::map<uint64_t, uint64_t> GetPressedState() override;
77 
78  private:
79  struct PendingResponse {
80  std::function<void(bool, uint64_t)> callback;
81  uint64_t response_id;
82  };
83 
84  // The information for a virtual key that's important enough that its
85  // state is checked after every event.
86  struct CriticalKey {
87  // Last seen value of physical key and logical key for the virtual key.
88  //
89  // Used to synthesize down events.
90  uint64_t physical_key;
91  uint64_t logical_key;
92 
93  // Whether to ensure the pressing state of the key (usually for modifier
94  // keys).
95  bool check_pressed;
96  // Whether to ensure the toggled state of the key (usually for lock keys).
97  //
98  // If this is true, `check_pressed` must be true.
99  bool check_toggled;
100  // Whether the lock key is currently toggled on.
101  bool toggled_on;
102  };
103 
104  // Implements the core logic of |KeyboardHook|, leaving out some state
105  // guards.
106  void KeyboardHookImpl(int key,
107  int scancode,
108  int action,
109  char32_t character,
110  bool extended,
111  bool was_down,
112  std::function<void(bool)> callback);
113 
114  // Assign |critical_keys_| with basic information.
115  void InitCriticalKeys(MapVirtualKeyToScanCode map_virtual_key_to_scan_code);
116  // Update |critical_keys_| with last seen logical and physical key.
117  void UpdateLastSeenCriticalKey(int virtual_key,
118  uint64_t physical_key,
119  uint64_t logical_key);
120  // Check each key's state from |get_key_state_| and synthesize events
121  // if their toggling states have been desynchronized.
122  void SynchronizeCriticalToggledStates(int event_virtual_key,
123  bool is_event_down,
124  bool* event_key_can_be_repeat);
125  // Check each key's state from |get_key_state_| and synthesize events
126  // if their pressing states have been desynchronized.
127  void SynchronizeCriticalPressedStates(int event_virtual_key,
128  int event_physical_key,
129  bool is_event_down,
130  bool event_key_can_be_repeat);
131 
132  // Wraps perform_send_event_ with state tracking. Use this instead of
133  // |perform_send_event_| to send events to the framework.
134  void SendEvent(const FlutterKeyEvent& event,
135  FlutterKeyEventCallback callback,
136  void* user_data);
137 
138  // Send a synthesized down event and update pressing records.
139  void SendSynthesizeDownEvent(uint64_t physical, uint64_t logical);
140 
141  // Send a synthesized up event and update pressing records.
142  void SendSynthesizeUpEvent(uint64_t physical, uint64_t logical);
143 
144  // Send a synthesized up or down event depending on the current pressing
145  // state.
146  void SynthesizeIfNeeded(uint64_t physical_left,
147  uint64_t physical_right,
148  uint64_t logical_left,
149  bool is_pressed);
150 
151  std::function<void(const FlutterKeyEvent&, FlutterKeyEventCallback, void*)>
152  perform_send_event_;
153  GetKeyStateHandler get_key_state_;
154 
155  // A map from physical keys to logical keys, each entry indicating a pressed
156  // key.
157  std::map<uint64_t, uint64_t> pressingRecords_;
158  // Information for key events that have been sent to the framework but yet
159  // to receive the response. Indexed by response IDs.
160  std::map<uint64_t, std::unique_ptr<PendingResponse>> pending_responses_;
161  // A self-incrementing integer, used as the ID for the next entry for
162  // |pending_responses_|.
163  uint64_t response_id_;
164  // Whether any events has been sent with |PerformSendEvent| during a
165  // |KeyboardHook|.
166  bool sent_any_events;
167 
168  // Important keys whose states are checked and guaranteed synchronized
169  // on every key event.
170  //
171  // The following maps map Win32 virtual key to the physical key and logical
172  // key they're last seen.
173  std::map<UINT, CriticalKey> critical_keys_;
174 
175  static uint64_t GetPhysicalKey(int scancode, bool extended);
176  static uint64_t GetLogicalKey(int key, bool extended, int scancode);
177  static void HandleResponse(bool handled, void* user_data);
178  static void ConvertUtf32ToUtf8_(char* out, char32_t ch);
179  static FlutterKeyEvent SynthesizeSimpleEvent(FlutterKeyEventType type,
180  uint64_t physical,
181  uint64_t logical,
182  const char* character);
183  static uint64_t ApplyPlaneToId(uint64_t id, uint64_t plane);
184 
185  static std::map<uint64_t, uint64_t> windowsToPhysicalMap_;
186  static std::map<uint64_t, uint64_t> windowsToLogicalMap_;
187  static std::map<uint64_t, uint64_t> scanCodeToLogicalMap_;
188 
189  // Mask for the 32-bit value portion of the key code.
190  static const uint64_t valueMask;
191 
192  // The plane value for keys which have a Unicode representation.
193  static const uint64_t unicodePlane;
194 
195  // The plane value for the private keys defined by the GTK embedding.
196  static const uint64_t windowsPlane;
197 
198  FML_DISALLOW_COPY_AND_ASSIGN(KeyboardKeyEmbedderHandler);
199 };
200 
201 } // namespace flutter
202 
203 #endif // FLUTTER_SHELL_PLATFORM_WINDOWS_KEYBOARD_KEY_EMBEDDER_HANDLER_H_
scancode
int scancode
Definition: keyboard_key_handler_unittests.cc:115
was_down
bool was_down
Definition: keyboard_key_handler_unittests.cc:119
flutter::KeyboardKeyEmbedderHandler::KeyboardHook
void KeyboardHook(int key, int scancode, int action, char32_t character, bool extended, bool was_down, std::function< void(bool)> callback) override
Definition: keyboard_key_embedder_handler.cc:325
extended
bool extended
Definition: keyboard_key_handler_unittests.cc:118
user_data
void * user_data
Definition: flutter_windows_view_unittests.cc:53
flutter::KeyboardKeyEmbedderHandler::GetKeyStateHandler
std::function< SHORT(int)> GetKeyStateHandler
Definition: keyboard_key_embedder_handler.h:41
character
char32_t character
Definition: keyboard_key_handler_unittests.cc:117
flutter::KeyboardKeyEmbedderHandler::~KeyboardKeyEmbedderHandler
virtual ~KeyboardKeyEmbedderHandler()
flutter::KeyboardKeyEmbedderHandler::SendEventHandler
std::function< void(const FlutterKeyEvent &, FlutterKeyEventCallback, void *)> SendEventHandler
Definition: keyboard_key_embedder_handler.h:40
flutter::KeyboardKeyHandler::KeyboardKeyHandlerDelegate
Definition: keyboard_key_handler.h:39
flutter::KeyboardKeyEmbedderHandler::MapVirtualKeyToScanCode
std::function< SHORT(UINT, bool)> MapVirtualKeyToScanCode
Definition: keyboard_key_embedder_handler.h:43
flutter::KeyboardKeyEmbedderHandler
Definition: keyboard_key_embedder_handler.h:34
toggled_on
bool toggled_on
Definition: keyboard_unittests.cc:127
flutter::ConvertChar32ToUtf8
std::string ConvertChar32ToUtf8(char32_t ch)
Definition: keyboard_key_embedder_handler.cc:38
flutter
Definition: accessibility_bridge_windows.cc:11
type
enum flutter::testing::@88::KeyboardChange::Type type
flutter::KeyboardKeyEmbedderHandler::KeyboardKeyEmbedderHandler
KeyboardKeyEmbedderHandler(SendEventHandler send_event, GetKeyStateHandler get_key_state, MapVirtualKeyToScanCode map_vk_to_scan)
Definition: keyboard_key_embedder_handler.cc:59
keyboard_key_handler.h
action
int action
Definition: keyboard_key_handler_unittests.cc:116
flutter::KeyboardKeyEmbedderHandler::GetPressedState
std::map< uint64_t, uint64_t > GetPressedState() override
Definition: keyboard_key_embedder_handler.cc:353
key
int key
Definition: keyboard_key_handler_unittests.cc:114
flutter::KeyboardKeyEmbedderHandler::SyncModifiersIfNeeded
void SyncModifiersIfNeeded(int modifiers_state) override
Definition: keyboard_key_embedder_handler.cc:500
callback
FlutterDesktopBinaryReply callback
Definition: flutter_windows_view_unittests.cc:52