| 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"
15 #include "flutter/shell/platform/windows/keyboard_key_handler.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.)
34 class KeyboardKeyEmbedderHandler
35 : public KeyboardKeyHandler::KeyboardKeyHandlerDelegate {
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 */)>;
42 using MapVirtualKeyToScanCode =
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
63 virtual ~KeyboardKeyEmbedderHandler();
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_
flutter::KeyboardKeyEmbedderHandler
Definition: keyboard_key_embedder_handler.h:35
flutter::KeyboardKeyEmbedderHandler::SendEventHandler
std::function< void(const FlutterKeyEvent &, FlutterKeyEventCallback, void *)> SendEventHandler
Definition: keyboard_key_embedder_handler.h:40
flutter::KeyboardKeyEmbedderHandler::~KeyboardKeyEmbedderHandler
virtual ~KeyboardKeyEmbedderHandler()
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
flutter::KeyboardKeyEmbedderHandler::MapVirtualKeyToScanCode
std::function< SHORT(UINT, bool)> MapVirtualKeyToScanCode
Definition: keyboard_key_embedder_handler.h:43
flutter::KeyboardKeyEmbedderHandler::GetPressedState
std::map< uint64_t, uint64_t > GetPressedState() override
Definition: keyboard_key_embedder_handler.cc:353
flutter::KeyboardKeyEmbedderHandler::SyncModifiersIfNeeded
void SyncModifiersIfNeeded(int modifiers_state) override
Definition: keyboard_key_embedder_handler.cc:500
flutter::KeyboardKeyEmbedderHandler::KeyboardKeyEmbedderHandler
KeyboardKeyEmbedderHandler(SendEventHandler send_event, GetKeyStateHandler get_key_state, MapVirtualKeyToScanCode map_vk_to_scan)
Definition: keyboard_key_embedder_handler.cc:59
flutter::KeyboardKeyEmbedderHandler::GetKeyStateHandler
std::function< SHORT(int)> GetKeyStateHandler
Definition: keyboard_key_embedder_handler.h:41
flutter::KeyboardKeyHandler::KeyboardKeyHandlerDelegate
Definition: keyboard_key_handler.h:39
user_data
void * user_data
Definition: flutter_windows_view_unittests.cc:53
callback
FlutterDesktopBinaryReply callback
Definition: flutter_windows_view_unittests.cc:52
keyboard_key_handler.h
extended
bool extended
Definition: keyboard_key_handler_unittests.cc:118
key
int key
Definition: keyboard_key_handler_unittests.cc:114
character
char32_t character
Definition: keyboard_key_handler_unittests.cc:117
action
int action
Definition: keyboard_key_handler_unittests.cc:116
scancode
int scancode
Definition: keyboard_key_handler_unittests.cc:115
was_down
bool was_down
Definition: keyboard_key_handler_unittests.cc:119
type
enum flutter::testing::@93::KeyboardChange::Type type
toggled_on
bool toggled_on
Definition: keyboard_unittests.cc:127
flutter
Definition: accessibility_bridge_windows.cc:11
flutter::ConvertChar32ToUtf8
std::string ConvertChar32ToUtf8(char32_t ch)
Definition: keyboard_key_embedder_handler.cc:38