8#include "flutter/fml/logging.h"
9#include "flutter/shell/platform/windows/keyboard_manager.h"
10#include "flutter/shell/platform/windows/keyboard_utils.h"
18constexpr int kMaxPendingEvents = 1000;
43bool IsKeyDownAltRight(
int action,
int virtual_key,
bool extended) {
44 return virtual_key == VK_RMENU &&
extended &&
52 return virtual_key == VK_RMENU &&
extended &&
59bool IsKeyDownCtrlLeft(
int action,
int virtual_key) {
60 return virtual_key == VK_LCONTROL &&
65bool IsDeadKey(uint32_t ch) {
69char32_t CodePointFromSurrogatePair(
wchar_t high,
wchar_t low) {
70 return 0x10000 + ((
static_cast<char32_t>(
high) & 0x000003FF) << 10) +
78 return MapVirtualKey(
scancode, MAPVK_VSC_TO_VK_EX);
81 return extended ? VK_RMENU : VK_LMENU;
84 return extended ? VK_RCONTROL : VK_LCONTROL;
90bool IsPrintable(uint32_t c) {
91 constexpr char32_t kMinPrintable =
' ';
92 constexpr char32_t kDelete = 0x7F;
93 return c >= kMinPrintable && c !=
kDelete;
97 return action == WM_SYSKEYDOWN ||
action == WM_SYSKEYUP ||
104 : window_delegate_(delegate),
105 last_key_is_ctrl_left_down(
false),
106 should_synthesize_ctrl_left_up(
false),
107 processing_event_(
false) {}
116 pending_redispatches_.push_back(
message);
120 FML_LOG(
ERROR) <<
"Unable to synthesize event for keyboard event.";
123 if (pending_redispatches_.size() > kMaxPendingEvents) {
125 <<
"There are " << pending_redispatches_.size()
126 <<
" keyboard events that have not yet received a response from the "
127 <<
"framework. Are responses being sent?";
131bool KeyboardManager::RemoveRedispatchedMessage(
UINT const action,
134 for (
auto iter = pending_redispatches_.begin();
135 iter != pending_redispatches_.end(); ++iter) {
136 if (
action == iter->action && wparam == iter->wparam) {
137 pending_redispatches_.erase(iter);
147 if (RemoveRedispatchedMessage(
action, wparam, lparam)) {
157 current_session_.push_back(
message);
166 current_session_.size() <= 1
168 : ¤t_session_[current_session_.size() - 2];
185 if (current_session_.front().IsGeneralKeyDown()) {
186 const Win32Message first_message = current_session_.front();
187 const uint8_t
scancode = (lparam >> 16) & 0xff;
188 const uint16_t key_code = first_message.
wparam;
189 const bool extended = ((lparam >> 24) & 0x01) == 0x01;
190 const bool was_down = lparam & 0x40000000;
195 if (
action == WM_DEADCHAR ||
action == WM_SYSDEADCHAR) {
202 character = IsPrintable(code_point) ? code_point : 0;
204 auto event = std::make_unique<PendingEvent>(
PendingEvent{
207 .action =
static_cast<UINT>(
action == WM_SYSCHAR ? WM_SYSKEYDOWN
212 .session = std::move(current_session_),
215 pending_events_.push_back(std::move(
event));
220 return !IsSysAction(
action);
231 auto event = std::make_unique<PendingEvent>(
PendingEvent{
233 .character = code_point,
234 .session = std::move(current_session_),
236 pending_events_.push_back(std::move(
event));
246 if (wparam == VK_PACKET) {
250 const uint8_t
scancode = (lparam >> 16) & 0xff;
251 const bool extended = ((lparam >> 24) & 0x01) == 0x01;
254 const bool was_down = lparam & 0x40000000;
259 if (last_key_is_ctrl_left_down) {
260 should_synthesize_ctrl_left_up =
true;
263 if (IsKeyDownCtrlLeft(
action, key_code)) {
264 last_key_is_ctrl_left_down =
true;
266 should_synthesize_ctrl_left_up =
false;
268 last_key_is_ctrl_left_down =
false;
271 if (should_synthesize_ctrl_left_up) {
272 should_synthesize_ctrl_left_up =
false;
274 (1 << 0) | (ctrl_left_scancode << 16) |
275 (0 << 24) | (1 << 30) |
281 current_session_.clear();
282 current_session_.push_back(
284 const bool is_keydown_message =
292 UINT next_key_action = PeekNextMessageType(WM_KEYFIRST, WM_KEYLAST);
293 bool has_char_action =
294 (next_key_action == WM_DEADCHAR ||
295 next_key_action == WM_SYSDEADCHAR || next_key_action == WM_CHAR ||
296 next_key_action == WM_SYSCHAR);
297 if (
character > 0 && is_keydown_message && has_char_action) {
307 auto event = std::make_unique<PendingEvent>(
PendingEvent{
314 .session = std::move(current_session_),
316 pending_events_.push_back(std::move(
event));
320 return !IsSysAction(
action);
323 FML_LOG(
FATAL) <<
"No event handler for keyboard event with action "
329void KeyboardManager::ProcessNextEvent() {
330 if (processing_event_ || pending_events_.empty()) {
333 processing_event_ =
true;
334 auto pending_event = std::move(pending_events_.front());
335 pending_events_.pop_front();
336 PerformProcessEvent(std::move(pending_event), [
this] {
338 processing_event_ =
false;
343void KeyboardManager::PerformProcessEvent(std::unique_ptr<PendingEvent>
event,
347 if (
event->action == WM_CHAR) {
348 DispatchText(*
event);
356 PendingEvent* event_p =
event.release();
357 window_delegate_->
OnKey(
358 event_p->key, event_p->scancode, event_p->action, event_p->character,
359 event_p->extended, event_p->was_down,
361 HandleOnKeyResult(std::unique_ptr<PendingEvent>(event_p), handled);
366void KeyboardManager::HandleOnKeyResult(std::unique_ptr<PendingEvent>
event,
367 bool framework_handled) {
368 const UINT last_action =
event->session.back().action;
371 bool handled = framework_handled || IsSysAction(last_action);
380 if (last_action == WM_CHAR) {
381 DispatchText(*
event);
387void KeyboardManager::DispatchText(
const PendingEvent&
event) {
394 bool is_printable = IsPrintable(
event.session.back().wparam);
395 bool valid =
event.character != 0 && is_printable;
402UINT KeyboardManager::PeekNextMessageType(
UINT wMsgFilterMin,
403 UINT wMsgFilterMax) {
406 &next_message, wMsgFilterMin, wMsgFilterMax, PM_NOREMOVE);
410 return next_message.message;
virtual UINT Win32DispatchMessage(UINT Msg, WPARAM wParam, LPARAM lParam)=0
virtual void OnText(const std::u16string &text)=0
virtual BOOL Win32PeekMessage(LPMSG lpMsg, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg)=0
virtual void OnKey(int key, int scancode, int action, char32_t character, bool extended, bool was_down, KeyEventCallback callback)=0
virtual uint32_t Win32MapVkToChar(uint32_t virtual_key)=0
KeyboardManager(WindowDelegate *delegate)
bool HandleMessage(UINT const message, WPARAM const wparam, LPARAM const lparam)
virtual void RedispatchEvent(std::unique_ptr< PendingEvent > event)
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
#define FML_LOG(severity)
#define FML_DCHECK(condition)
Dart_NativeFunction function
std::u16string EncodeUtf16(char32_t character)
constexpr int kDeadKeyCharMask
bool IsHighSurrogate() const
bool IsLowSurrogate() const