Flutter Windows Embedder
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 
6 
7 #include <windows.h>
8 
9 #include "flutter/fml/logging.h"
12 
13 namespace flutter {
14 
15 namespace {
16 
17 static constexpr char kChannelName[] = "flutter/keyevent";
18 
19 static constexpr char kKeyCodeKey[] = "keyCode";
20 static constexpr char kScanCodeKey[] = "scanCode";
21 static constexpr char kCharacterCodePointKey[] = "characterCodePoint";
22 static constexpr char kModifiersKey[] = "modifiers";
23 static constexpr char kKeyMapKey[] = "keymap";
24 static constexpr char kTypeKey[] = "type";
25 static constexpr char kHandledKey[] = "handled";
26 
27 static constexpr char kWindowsKeyMap[] = "windows";
28 static constexpr char kKeyUp[] = "keyup";
29 static 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.
33 static 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
42 static 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
48 static constexpr int kShift = 1 << 0;
49 static constexpr int kShiftLeft = 1 << 1;
50 static constexpr int kShiftRight = 1 << 2;
51 static constexpr int kControl = 1 << 3;
52 static constexpr int kControlLeft = 1 << 4;
53 static constexpr int kControlRight = 1 << 5;
54 static constexpr int kAlt = 1 << 6;
55 static constexpr int kAltLeft = 1 << 7;
56 static constexpr int kAltRight = 1 << 8;
57 static constexpr int kWinLeft = 1 << 9;
58 static constexpr int kWinRight = 1 << 10;
59 static constexpr int kCapsLock = 1 << 11;
60 static constexpr int kNumLock = 1 << 12;
61 static 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.
66 int 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,
107  kChannelName,
108  &flutter::JsonMessageCodec::GetInstance())) {}
109 
111 
113  // Do nothing.
114 }
115 
116 std::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
flutter::KeyboardKeyChannelHandler::KeyboardHook
void KeyboardHook(int key, int scancode, int action, char32_t character, bool extended, bool was_down, std::function< void(bool)> callback)
Definition: keyboard_key_channel_handler.cc:124
flutter::JsonMessageCodec::GetInstance
static const JsonMessageCodec & GetInstance()
Definition: json_message_codec.cc:17
scancode
int scancode
Definition: keyboard_key_handler_unittests.cc:115
was_down
bool was_down
Definition: keyboard_key_handler_unittests.cc:119
extended
bool extended
Definition: keyboard_key_handler_unittests.cc:118
character
char32_t character
Definition: keyboard_key_handler_unittests.cc:117
json_message_codec.h
flutter::MessageCodec::DecodeMessage
std::unique_ptr< T > DecodeMessage(const uint8_t *binary_message, const size_t message_size) const
Definition: message_codec.h:29
flutter::KeyboardKeyChannelHandler::GetPressedState
std::map< uint64_t, uint64_t > GetPressedState()
Definition: keyboard_key_channel_handler.cc:116
flutter::UndeadChar
uint32_t UndeadChar(uint32_t ch)
Definition: keyboard_utils.h:34
flutter::BinaryMessenger
Definition: binary_messenger.h:28
keyboard_utils.h
flutter::BasicMessageChannel
Definition: basic_message_channel.h:56
flutter::KeyboardKeyChannelHandler::KeyboardKeyChannelHandler
KeyboardKeyChannelHandler(flutter::BinaryMessenger *messenger)
Definition: keyboard_key_channel_handler.cc:102
flutter
Definition: accessibility_bridge_windows.cc:11
flutter::JsonMessageCodec
Definition: json_message_codec.h:16
flutter::kShift
constexpr int kShift
Definition: keyboard_utils.h:14
kChannelName
static constexpr char kChannelName[]
Definition: cursor_handler.cc:13
flutter::KeyboardKeyChannelHandler::SyncModifiersIfNeeded
void SyncModifiersIfNeeded(int modifiers_state)
Definition: keyboard_key_channel_handler.cc:112
flutter::KeyboardKeyChannelHandler::~KeyboardKeyChannelHandler
~KeyboardKeyChannelHandler()
action
int action
Definition: keyboard_key_handler_unittests.cc:116
flutter::kControl
constexpr int kControl
Definition: keyboard_utils.h:15
key
int key
Definition: keyboard_key_handler_unittests.cc:114
keyboard_key_channel_handler.h
callback
FlutterDesktopBinaryReply callback
Definition: flutter_windows_view_unittests.cc:52