Flutter Engine
The Flutter Engine
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
17namespace 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.
22std::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:
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).
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,
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
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_
GLenum type
std::function< void(const FlutterKeyEvent &, FlutterKeyEventCallback, void *)> SendEventHandler
void KeyboardHook(int key, int scancode, int action, char32_t character, bool extended, bool was_down, std::function< void(bool)> callback) override
std::function< SHORT(UINT, bool)> MapVirtualKeyToScanCode
std::map< uint64_t, uint64_t > GetPressedState() override
void SyncModifiersIfNeeded(int modifiers_state) override
KeyboardKeyEmbedderHandler(SendEventHandler send_event, GetKeyStateHandler get_key_state, MapVirtualKeyToScanCode map_vk_to_scan)
void(* FlutterKeyEventCallback)(bool, void *)
Definition: embedder.h:1155
FlutterKeyEventType
Definition: embedder.h:1074
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
FlKeyEvent * event
Dart_NativeFunction function
Definition: fuchsia.cc:51
bool toggled_on
std::string ConvertChar32ToUtf8(char32_t ch)
void * user_data
unsigned int UINT
Definition: windows_types.h:32
short SHORT
Definition: windows_types.h:29