Flutter Engine
The Flutter Engine
keyboard_key_channel_handler.cc
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#include "flutter/shell/platform/windows/keyboard_key_channel_handler.h"
6
7#include <windows.h>
8
9#include "flutter/fml/logging.h"
10#include "flutter/shell/platform/common/json_message_codec.h"
11#include "flutter/shell/platform/windows/keyboard_utils.h"
12
13namespace flutter {
14
15namespace {
16
17static constexpr char kChannelName[] = "flutter/keyevent";
18
19static constexpr char kKeyCodeKey[] = "keyCode";
20static constexpr char kScanCodeKey[] = "scanCode";
21static constexpr char kCharacterCodePointKey[] = "characterCodePoint";
22static constexpr char kModifiersKey[] = "modifiers";
23static constexpr char kKeyMapKey[] = "keymap";
24static constexpr char kTypeKey[] = "type";
25static constexpr char kHandledKey[] = "handled";
26
27static constexpr char kWindowsKeyMap[] = "windows";
28static constexpr char kKeyUp[] = "keyup";
29static constexpr char kKeyDown[] = "keydown";
30
31// The maximum number of pending events to keep before
32// emitting a warning on the console about unhandled events.
33static constexpr int kMaxPendingEvents = 1000;
34
35// The bit for a scancode indicating the key is extended.
36//
37// Win32 defines some keys to be "extended", such as ShiftRight, which shares
38// the same scancode as its non-extended counterpart, such as ShiftLeft. In
39// Chromium's scancode table, from which Flutter's physical key list is
40// derived, these keys are marked with this bit. See
41// https://chromium.googlesource.com/codesearch/chromium/src/+/refs/heads/main/ui/events/keycodes/dom/dom_code_data.inc
42static constexpr int kScancodeExtended = 0xe000;
43
44// Re-definition of the modifiers for compatibility with the Flutter framework.
45// These have to be in sync with the framework's RawKeyEventDataWindows
46// modifiers definition.
47// https://github.com/flutter/flutter/blob/19ff596979e407c484a32f4071420fca4f4c885f/packages/flutter/lib/src/services/raw_keyboard_windows.dart#L203
48static constexpr int kShift = 1 << 0;
49static constexpr int kShiftLeft = 1 << 1;
50static constexpr int kShiftRight = 1 << 2;
51static constexpr int kControl = 1 << 3;
52static constexpr int kControlLeft = 1 << 4;
53static constexpr int kControlRight = 1 << 5;
54static constexpr int kAlt = 1 << 6;
55static constexpr int kAltLeft = 1 << 7;
56static constexpr int kAltRight = 1 << 8;
57static constexpr int kWinLeft = 1 << 9;
58static constexpr int kWinRight = 1 << 10;
59static constexpr int kCapsLock = 1 << 11;
60static constexpr int kNumLock = 1 << 12;
61static constexpr int kScrollLock = 1 << 13;
62
63/// Calls GetKeyState() an all modifier keys and packs the result in an int,
64/// with the re-defined values declared above for compatibility with the Flutter
65/// framework.
66int GetModsForKeyState() {
67 int mods = 0;
68
69 if (GetKeyState(VK_SHIFT) < 0)
70 mods |= kShift;
71 if (GetKeyState(VK_LSHIFT) < 0)
72 mods |= kShiftLeft;
73 if (GetKeyState(VK_RSHIFT) < 0)
74 mods |= kShiftRight;
75 if (GetKeyState(VK_CONTROL) < 0)
76 mods |= kControl;
77 if (GetKeyState(VK_LCONTROL) < 0)
78 mods |= kControlLeft;
79 if (GetKeyState(VK_RCONTROL) < 0)
80 mods |= kControlRight;
81 if (GetKeyState(VK_MENU) < 0)
82 mods |= kAlt;
83 if (GetKeyState(VK_LMENU) < 0)
84 mods |= kAltLeft;
85 if (GetKeyState(VK_RMENU) < 0)
86 mods |= kAltRight;
87 if (GetKeyState(VK_LWIN) < 0)
88 mods |= kWinLeft;
89 if (GetKeyState(VK_RWIN) < 0)
90 mods |= kWinRight;
91 if (GetKeyState(VK_CAPITAL) < 0)
92 mods |= kCapsLock;
93 if (GetKeyState(VK_NUMLOCK) < 0)
94 mods |= kNumLock;
95 if (GetKeyState(VK_SCROLL) < 0)
96 mods |= kScrollLock;
97 return mods;
98}
99
100} // namespace
101
103 flutter::BinaryMessenger* messenger)
104 : channel_(
105 std::make_unique<flutter::BasicMessageChannel<rapidjson::Document>>(
106 messenger,
108 &flutter::JsonMessageCodec::GetInstance())) {}
109
111
113 // Do nothing.
114}
115
116std::map<uint64_t, uint64_t> KeyboardKeyChannelHandler::GetPressedState() {
117 // Returns an empty state because it will never be called.
118 // KeyboardKeyEmbedderHandler is the only KeyboardKeyHandlerDelegate to handle
119 // GetPressedState() calls.
120 std::map<uint64_t, uint64_t> empty_state;
121 return empty_state;
122}
123
125 int key,
126 int scancode,
127 int action,
128 char32_t character,
129 bool extended,
130 bool was_down,
131 std::function<void(bool)> callback) {
132 // TODO: Translate to a cross-platform key code system rather than passing
133 // the native key code.
134 rapidjson::Document event(rapidjson::kObjectType);
135 auto& allocator = event.GetAllocator();
136 event.AddMember(kKeyCodeKey, key, allocator);
137 event.AddMember(kScanCodeKey, scancode | (extended ? kScancodeExtended : 0),
138 allocator);
139 event.AddMember(kCharacterCodePointKey, UndeadChar(character), allocator);
140 event.AddMember(kKeyMapKey, kWindowsKeyMap, allocator);
141 event.AddMember(kModifiersKey, GetModsForKeyState(), allocator);
142
143 switch (action) {
144 case WM_SYSKEYDOWN:
145 case WM_KEYDOWN:
146 event.AddMember(kTypeKey, kKeyDown, allocator);
147 break;
148 case WM_SYSKEYUP:
149 case WM_KEYUP:
150 event.AddMember(kTypeKey, kKeyUp, allocator);
151 break;
152 default:
153 FML_LOG(WARNING) << "Unknown key event action: " << action;
154 callback(false);
155 return;
156 }
157 channel_->Send(event, [callback = std::move(callback)](const uint8_t* reply,
158 size_t reply_size) {
160 reply, reply_size);
161 bool handled = decoded ? (*decoded)[kHandledKey].GetBool() : false;
162 callback(handled);
163 });
164}
165
166} // namespace flutter
static NSString *const kChannelName
static const JsonMessageCodec & GetInstance()
void KeyboardHook(int key, int scancode, int action, char32_t character, bool extended, bool was_down, std::function< void(bool)> callback)
KeyboardKeyChannelHandler(flutter::BinaryMessenger *messenger)
std::map< uint64_t, uint64_t > GetPressedState()
std::unique_ptr< T > DecodeMessage(const uint8_t *binary_message, const size_t message_size) const
Definition: message_codec.h:29
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
FlKeyEvent * event
#define FML_LOG(severity)
Definition: logging.h:82
Dart_NativeFunction function
Definition: fuchsia.cc:51
static constexpr char kScanCodeKey[]
static constexpr char kKeyMapKey[]
static constexpr char kKeyDown[]
static constexpr char kKeyUp[]
static constexpr char kModifiersKey[]
static constexpr char kKeyCodeKey[]
constexpr int kShift
constexpr char kTypeKey[]
Definition: shell.cc:50
constexpr int kControl
uint32_t UndeadChar(uint32_t ch)
Definition: ref_ptr.h:256