22constexpr size_t kCharacterCacheSize = 8;
24constexpr SHORT kStateMaskToggled = 0x01;
25constexpr SHORT kStateMaskPressed = 0x80;
27const char* empty_character =
"";
33char _GetBit(
char32_t ch,
size_t start,
size_t end) {
40 FML_DCHECK(0 <= ch && ch <= 0x10FFFF) <<
"Character out of range";
43 }
else if (ch <= 0x07FF) {
44 result.push_back(0b11000000 + _GetBit(ch, 11, 6));
45 result.push_back(0b10000000 + _GetBit(ch, 6, 0));
46 }
else if (ch <= 0xFFFF) {
47 result.push_back(0b11100000 + _GetBit(ch, 16, 12));
48 result.push_back(0b10000000 + _GetBit(ch, 12, 6));
49 result.push_back(0b10000000 + _GetBit(ch, 6, 0));
51 result.push_back(0b11110000 + _GetBit(ch, 21, 18));
52 result.push_back(0b10000000 + _GetBit(ch, 18, 12));
53 result.push_back(0b10000000 + _GetBit(ch, 12, 6));
54 result.push_back(0b10000000 + _GetBit(ch, 6, 0));
63 : perform_send_event_(send_event),
64 get_key_state_(get_key_state),
66 InitCriticalKeys(map_virtual_key_to_scan_code);
72 return (codeUnit <= 0x7f && codeUnit >= 0x20) ||
73 (codeUnit <= 0xff && codeUnit >= 0x80);
81 constexpr uint64_t lower_a = 0x61;
82 constexpr uint64_t upper_a = 0x41;
83 constexpr uint64_t upper_z = 0x5a;
85 constexpr uint64_t lower_a_grave = 0xe0;
86 constexpr uint64_t upper_a_grave = 0xc0;
87 constexpr uint64_t upper_thorn = 0xde;
88 constexpr uint64_t division = 0xf7;
91 if (n >= upper_a && n <= upper_z) {
92 return n - upper_a + lower_a;
96 if (n >= upper_a_grave && n <= upper_thorn && n != division) {
97 return n - upper_a_grave + lower_a_grave;
107 return (windowsScanCode & 0xff) | (
extended ? 0xe000 : 0);
110uint64_t KeyboardKeyEmbedderHandler::ApplyPlaneToId(uint64_t
id,
112 return (
id & valueMask) | plane;
115uint64_t KeyboardKeyEmbedderHandler::GetPhysicalKey(
int scancode,
118 auto resultIt = windowsToPhysicalMap_.find(chromiumScancode);
119 if (resultIt != windowsToPhysicalMap_.end())
120 return resultIt->second;
121 return ApplyPlaneToId(
scancode, windowsPlane);
124uint64_t KeyboardKeyEmbedderHandler::GetLogicalKey(
int key,
127 if (
key == VK_PROCESSKEY) {
128 return VK_PROCESSKEY;
136 if (numpadIter != scanCodeToLogicalMap_.cend())
137 return numpadIter->second;
140 auto logicalIt = windowsToLogicalMap_.find(
key);
141 if (logicalIt != windowsToLogicalMap_.cend())
142 return logicalIt->second;
146 return ApplyPlaneToId(
toLower(
key), unicodePlane);
149 return ApplyPlaneToId(
toLower(
key), windowsPlane);
152void KeyboardKeyEmbedderHandler::KeyboardHookImpl(
159 std::function<
void(
bool)>
callback) {
165 auto last_logical_record_iter = pressingRecords_.find(physical_key);
166 bool had_record = last_logical_record_iter != pressingRecords_.end();
167 uint64_t last_logical_record =
168 had_record ? last_logical_record_iter->second : 0;
174 uint64_t sequence_logical_key =
175 had_record ? last_logical_record : logical_key;
177 if (sequence_logical_key == VK_PROCESSKEY) {
186 const bool is_event_down =
action == WM_KEYDOWN ||
action == WM_SYSKEYDOWN;
188 bool event_key_can_be_repeat =
true;
189 UpdateLastSeenCriticalKey(
key, physical_key, sequence_logical_key);
201 SynchronizeCriticalToggledStates(
key, is_event_down,
202 &event_key_can_be_repeat);
209 SynchronizeCriticalPressedStates(
key, physical_key, is_event_down,
210 event_key_can_be_repeat);
214 last_logical_record_iter = pressingRecords_.find(physical_key);
215 had_record = last_logical_record_iter != pressingRecords_.end();
216 last_logical_record = had_record ? last_logical_record_iter->second : 0;
221 char character_bytes[kCharacterCacheSize];
224 uint64_t eventual_logical_record;
225 uint64_t result_logical_key;
233 SendSynthesizeUpEvent(physical_key, last_logical_record);
234 last_logical_record_iter = pressingRecords_.find(physical_key);
235 had_record = last_logical_record_iter != pressingRecords_.end();
236 last_logical_record = had_record ? last_logical_record_iter->second : 0;
243 ConvertUtf32ToUtf8_(character_bytes,
character);
244 eventual_logical_record = last_logical_record;
245 result_logical_key = last_logical_record;
250 ConvertUtf32ToUtf8_(character_bytes,
character);
251 eventual_logical_record = logical_key;
252 result_logical_key = logical_key;
255 if (last_logical_record == 0) {
266 character_bytes[0] =
'\0';
267 eventual_logical_record = 0;
268 result_logical_key = last_logical_record;
272 if (eventual_logical_record != 0) {
273 pressingRecords_[physical_key] = eventual_logical_record;
275 auto record_iter = pressingRecords_.find(physical_key);
279 if (record_iter != pressingRecords_.end()) {
280 pressingRecords_.erase(record_iter);
288 .timestamp =
static_cast<double>(
289 std::chrono::duration_cast<std::chrono::microseconds>(
290 std::chrono::high_resolution_clock::now().time_since_epoch())
293 .physical = physical_key,
294 .logical = result_logical_key,
296 .synthesized =
false,
300 uint64_t response_id = response_id_;
301 PendingResponse pending{
304 uint64_t response_id) {
305 auto found = pending_responses_.find(response_id);
306 if (found != pending_responses_.end()) {
307 pending_responses_.erase(found);
311 .response_id = response_id,
313 auto pending_ptr = std::make_unique<PendingResponse>(std::move(pending));
314 pending_responses_[response_id] = std::move(pending_ptr);
315 SendEvent(key_data, KeyboardKeyEmbedderHandler::HandleResponse,
316 reinterpret_cast<void*
>(pending_responses_[response_id].get()));
323 SynchronizeCriticalPressedStates(
key, physical_key, is_event_down,
324 event_key_can_be_repeat);
334 std::function<
void(
bool)>
callback) {
335 sent_any_events =
false;
338 if (!sent_any_events) {
341 .timestamp =
static_cast<double>(
342 std::chrono::duration_cast<std::chrono::microseconds>(
343 std::chrono::high_resolution_clock::now().time_since_epoch())
349 .synthesized =
false,
351 SendEvent(empty_event,
nullptr,
nullptr);
356 return pressingRecords_;
359void KeyboardKeyEmbedderHandler::UpdateLastSeenCriticalKey(
361 uint64_t physical_key,
362 uint64_t logical_key) {
363 auto found = critical_keys_.find(virtual_key);
364 if (found != critical_keys_.end()) {
365 found->second.physical_key = physical_key;
366 found->second.logical_key = logical_key;
370void KeyboardKeyEmbedderHandler::SynchronizeCriticalToggledStates(
371 int event_virtual_key,
373 bool* event_key_can_be_repeat) {
376 for (
auto& kv : critical_keys_) {
377 UINT virtual_key = kv.first;
378 CriticalKey& key_info = kv.second;
379 if (key_info.physical_key == 0) {
386 if (key_info.check_toggled) {
387 const bool target_is_pressed =
388 pressingRecords_.find(key_info.physical_key) !=
389 pressingRecords_.end();
396 const bool true_toggled = get_key_state_(virtual_key) & kStateMaskToggled;
397 bool pre_event_toggled = true_toggled;
400 if (virtual_key == event_virtual_key && !target_is_pressed &&
402 pre_event_toggled = !pre_event_toggled;
404 if (key_info.toggled_on != pre_event_toggled) {
406 if (target_is_pressed) {
407 SendEvent(SynthesizeSimpleEvent(
409 key_info.logical_key, empty_character),
413 pressingRecords_[key_info.physical_key] = key_info.logical_key;
415 key_info.physical_key,
416 key_info.logical_key, empty_character),
418 *event_key_can_be_repeat =
false;
420 key_info.toggled_on = true_toggled;
425void KeyboardKeyEmbedderHandler::SynchronizeCriticalPressedStates(
426 int event_virtual_key,
427 int event_physical_key,
429 bool event_key_can_be_repeat) {
441 for (
auto& kv : critical_keys_) {
442 UINT virtual_key = kv.first;
443 CriticalKey& key_info = kv.second;
444 if (key_info.physical_key == 0) {
449 if (key_info.check_pressed) {
450 SHORT true_pressed = get_key_state_(virtual_key) & kStateMaskPressed;
451 auto pressing_record_iter = pressingRecords_.find(key_info.physical_key);
452 bool now_pressed = pressing_record_iter != pressingRecords_.end();
453 bool pre_event_pressed = true_pressed;
465 if (virtual_key == event_virtual_key) {
466 if (event_key_can_be_repeat) {
469 pre_event_pressed =
false;
481 if (event_physical_key == key_info.physical_key) {
485 if (now_pressed != pre_event_pressed) {
487 pressingRecords_.erase(pressing_record_iter);
489 pressingRecords_[key_info.physical_key] = key_info.logical_key;
491 const char* empty_character =
"";
493 SynthesizeSimpleEvent(
495 key_info.physical_key, key_info.logical_key, empty_character),
504 const uint64_t physical_shift_left =
506 const uint64_t physical_shift_right =
508 const uint64_t logical_shift_left =
510 const uint64_t physical_control_left =
512 const uint64_t physical_control_right =
514 const uint64_t logical_control_left =
517 bool shift_pressed = (modifiers_state &
kShift) != 0;
518 SynthesizeIfNeeded(physical_shift_left, physical_shift_right,
519 logical_shift_left, shift_pressed);
520 bool control_pressed = (modifiers_state &
kControl) != 0;
521 SynthesizeIfNeeded(physical_control_left, physical_control_right,
522 logical_control_left, control_pressed);
525void KeyboardKeyEmbedderHandler::SynthesizeIfNeeded(uint64_t physical_left,
526 uint64_t physical_right,
527 uint64_t logical_left,
529 auto pressing_record_iter_left = pressingRecords_.find(physical_left);
530 bool left_pressed = pressing_record_iter_left != pressingRecords_.end();
531 auto pressing_record_iter_right = pressingRecords_.find(physical_right);
532 bool right_pressed = pressing_record_iter_right != pressingRecords_.end();
533 bool already_pressed = left_pressed || right_pressed;
534 bool synthesize_down = is_pressed && !already_pressed;
535 bool synthesize_up = !is_pressed && already_pressed;
537 if (synthesize_down) {
538 SendSynthesizeDownEvent(physical_left, logical_left);
541 if (synthesize_up && left_pressed) {
542 uint64_t known_logical = pressing_record_iter_left->second;
543 SendSynthesizeUpEvent(physical_left, known_logical);
546 if (synthesize_up && right_pressed) {
547 uint64_t known_logical = pressing_record_iter_right->second;
548 SendSynthesizeUpEvent(physical_right, known_logical);
552void KeyboardKeyEmbedderHandler::SendSynthesizeDownEvent(uint64_t physical,
557 pressingRecords_[physical] = logical;
560void KeyboardKeyEmbedderHandler::SendSynthesizeUpEvent(uint64_t physical,
565 pressingRecords_.erase(physical);
568void KeyboardKeyEmbedderHandler::HandleResponse(
bool handled,
void*
user_data) {
569 PendingResponse* pending =
reinterpret_cast<PendingResponse*
>(
user_data);
570 auto callback = std::move(pending->callback);
571 callback(handled, pending->response_id);
574void KeyboardKeyEmbedderHandler::InitCriticalKeys(
575 MapVirtualKeyToScanCode map_virtual_key_to_scan_code) {
576 auto createCheckedKey = [
this, &map_virtual_key_to_scan_code](
579 bool check_toggled) -> CriticalKey {
580 UINT scan_code = map_virtual_key_to_scan_code(virtual_key,
extended);
582 .physical_key = GetPhysicalKey(scan_code,
extended),
583 .logical_key = GetLogicalKey(virtual_key,
extended, scan_code),
584 .check_pressed = check_pressed || check_toggled,
585 .check_toggled = check_toggled,
586 .toggled_on = check_toggled
587 ? !!(get_key_state_(virtual_key) & kStateMaskToggled)
592 critical_keys_.emplace(VK_LSHIFT,
593 createCheckedKey(VK_LSHIFT,
false,
true,
false));
594 critical_keys_.emplace(VK_RSHIFT,
595 createCheckedKey(VK_RSHIFT,
false,
true,
false));
596 critical_keys_.emplace(VK_LCONTROL,
597 createCheckedKey(VK_LCONTROL,
false,
true,
false));
598 critical_keys_.emplace(VK_RCONTROL,
599 createCheckedKey(VK_RCONTROL,
true,
true,
false));
600 critical_keys_.emplace(VK_LMENU,
601 createCheckedKey(VK_LMENU,
false,
true,
false));
602 critical_keys_.emplace(VK_RMENU,
603 createCheckedKey(VK_RMENU,
true,
true,
false));
604 critical_keys_.emplace(VK_LWIN, createCheckedKey(VK_LWIN,
true,
true,
false));
605 critical_keys_.emplace(VK_RWIN, createCheckedKey(VK_RWIN,
true,
true,
false));
606 critical_keys_.emplace(VK_CAPITAL,
607 createCheckedKey(VK_CAPITAL,
false,
true,
true));
608 critical_keys_.emplace(VK_SCROLL,
609 createCheckedKey(VK_SCROLL,
false,
true,
true));
610 critical_keys_.emplace(VK_NUMLOCK,
611 createCheckedKey(VK_NUMLOCK,
true,
true,
true));
614void KeyboardKeyEmbedderHandler::ConvertUtf32ToUtf8_(
char* out,
char32_t ch) {
620 strcpy_s(out, kCharacterCacheSize, result.c_str());
630 .timestamp =
static_cast<double>(
631 std::chrono::duration_cast<std::chrono::microseconds>(
632 std::chrono::high_resolution_clock::now().time_since_epoch())
635 .physical = physical,
642void KeyboardKeyEmbedderHandler::SendEvent(
const FlutterKeyEvent& event,
645 sent_any_events =
true;
std::function< void(const FlutterKeyEvent &, FlutterKeyEventCallback, void *)> SendEventHandler
virtual ~KeyboardKeyEmbedderHandler()
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)
std::function< SHORT(int)> GetKeyStateHandler
void(* FlutterKeyEventCallback)(bool, void *)
@ kFlutterKeyEventTypeDown
@ kFlutterKeyEventTypeRepeat
FlutterDesktopBinaryReply callback
#define FML_DCHECK(condition)
constexpr int kKeyCodeShiftLeft
constexpr int kScanCodeShiftRight
constexpr int kScanCodeShiftLeft
constexpr int kScanCodeControlRight
std::string ConvertChar32ToUtf8(char32_t ch)
static uint16_t normalizeScancode(int windowsScanCode, bool extended)
static uint64_t toLower(uint64_t n)
static bool isEasciiPrintable(int codeUnit)
constexpr int kScanCodeControlLeft
constexpr int kKeyCodeControlLeft
uint32_t UndeadChar(uint32_t ch)
size_t struct_size
The size of this struct. Must be sizeof(FlutterKeyEvent).