8 #include "flutter/fml/logging.h"
18 static constexpr
int kMaxPendingEvents = 1000;
43 static bool IsKeyDownAltRight(
int action,
int virtual_key,
bool extended) {
44 return virtual_key == VK_RMENU &&
extended &&
51 static bool IsKeyUpAltRight(
int action,
int virtual_key,
bool extended) {
52 return virtual_key == VK_RMENU &&
extended &&
59 static bool IsKeyDownCtrlLeft(
int action,
int virtual_key) {
60 return virtual_key == VK_LCONTROL &&
65 static bool IsDeadKey(uint32_t ch) {
69 static char32_t CodePointFromSurrogatePair(
wchar_t high,
wchar_t low) {
70 return 0x10000 + ((
static_cast<char32_t
>(high) & 0x000003FF) << 10) +
74 static uint16_t ResolveKeyCode(uint16_t original,
80 return MapVirtualKey(
scancode, MAPVK_VSC_TO_VK_EX);
83 return extended ? VK_RMENU : VK_LMENU;
86 return extended ? VK_RCONTROL : VK_LCONTROL;
92 static bool IsPrintable(uint32_t c) {
93 constexpr char32_t kMinPrintable =
' ';
94 constexpr char32_t kDelete = 0x7F;
95 return c >= kMinPrintable && c != kDelete;
98 static bool IsSysAction(UINT
action) {
99 return action == WM_SYSKEYDOWN ||
action == WM_SYSKEYUP ||
106 : window_delegate_(delegate),
107 last_key_is_ctrl_left_down(false),
108 should_synthesize_ctrl_left_up(false),
109 processing_event_(false) {}
118 pending_redispatches_.push_back(
message);
122 FML_LOG(ERROR) <<
"Unable to synthesize event for keyboard event.";
125 if (pending_redispatches_.size() > kMaxPendingEvents) {
127 <<
"There are " << pending_redispatches_.size()
128 <<
" keyboard events that have not yet received a response from the "
129 <<
"framework. Are responses being sent?";
133 bool KeyboardManager::RemoveRedispatchedMessage(UINT
const action,
135 LPARAM
const lparam) {
136 for (
auto iter = pending_redispatches_.begin();
137 iter != pending_redispatches_.end(); ++iter) {
138 if (
action == iter->action && wparam == iter->wparam) {
139 pending_redispatches_.erase(iter);
148 LPARAM
const lparam) {
149 if (RemoveRedispatchedMessage(
action, wparam, lparam)) {
159 current_session_.push_back(
message);
168 current_session_.size() <= 1
170 : ¤t_session_[current_session_.size() - 2];
187 if (current_session_.front().IsGeneralKeyDown()) {
188 const Win32Message first_message = current_session_.front();
189 const uint8_t
scancode = (lparam >> 16) & 0xff;
190 const uint16_t key_code = first_message.
wparam;
191 const bool extended = ((lparam >> 24) & 0x01) == 0x01;
192 const bool was_down = lparam & 0x40000000;
197 if (
action == WM_DEADCHAR ||
action == WM_SYSDEADCHAR) {
204 character = IsPrintable(code_point) ? code_point : 0;
206 auto event = std::make_unique<PendingEvent>(
PendingEvent{
209 .action =
static_cast<UINT
>(
action == WM_SYSCHAR ? WM_SYSKEYDOWN
214 .session = std::move(current_session_),
217 pending_events_.push_back(std::move(event));
222 return !IsSysAction(
action);
233 auto event = std::make_unique<PendingEvent>(
PendingEvent{
235 .character = code_point,
236 .session = std::move(current_session_),
238 pending_events_.push_back(std::move(event));
248 if (wparam == VK_PACKET) {
252 const uint8_t
scancode = (lparam >> 16) & 0xff;
253 const bool extended = ((lparam >> 24) & 0x01) == 0x01;
256 const bool was_down = lparam & 0x40000000;
261 if (last_key_is_ctrl_left_down) {
262 should_synthesize_ctrl_left_up =
true;
265 if (IsKeyDownCtrlLeft(
action, key_code)) {
266 last_key_is_ctrl_left_down =
true;
268 should_synthesize_ctrl_left_up =
false;
270 last_key_is_ctrl_left_down =
false;
273 if (should_synthesize_ctrl_left_up) {
274 should_synthesize_ctrl_left_up =
false;
275 const LPARAM lParam =
276 (1 << 0) | (ctrl_left_scancode << 16) |
277 (0 << 24) | (1 << 30) |
283 current_session_.clear();
284 current_session_.push_back(
286 const bool is_keydown_message =
294 UINT next_key_action = PeekNextMessageType(WM_KEYFIRST, WM_KEYLAST);
295 bool has_char_action =
296 (next_key_action == WM_DEADCHAR ||
297 next_key_action == WM_SYSDEADCHAR || next_key_action == WM_CHAR ||
298 next_key_action == WM_SYSCHAR);
299 if (
character > 0 && is_keydown_message && has_char_action) {
309 auto event = std::make_unique<PendingEvent>(
PendingEvent{
316 .session = std::move(current_session_),
318 pending_events_.push_back(std::move(event));
322 return !IsSysAction(
action);
325 FML_LOG(FATAL) <<
"No event handler for keyboard event with action "
331 void KeyboardManager::ProcessNextEvent() {
332 if (processing_event_ || pending_events_.empty()) {
335 processing_event_ =
true;
336 auto pending_event = std::move(pending_events_.front());
337 pending_events_.pop_front();
338 PerformProcessEvent(std::move(pending_event), [
this] {
339 FML_DCHECK(processing_event_);
340 processing_event_ =
false;
345 void KeyboardManager::PerformProcessEvent(std::unique_ptr<PendingEvent> event,
349 if (event->action == WM_CHAR) {
350 DispatchText(*event);
358 PendingEvent* event_p =
event.release();
359 window_delegate_->
OnKey(
360 event_p->key, event_p->scancode, event_p->action, event_p->character,
361 event_p->extended, event_p->was_down,
363 HandleOnKeyResult(std::unique_ptr<PendingEvent>(event_p), handled);
368 void KeyboardManager::HandleOnKeyResult(std::unique_ptr<PendingEvent> event,
369 bool framework_handled) {
370 const UINT last_action =
event->session.back().action;
373 bool handled = framework_handled || IsSysAction(last_action);
382 if (last_action == WM_CHAR) {
383 DispatchText(*event);
389 void KeyboardManager::DispatchText(
const PendingEvent& event) {
395 FML_DCHECK(!event.session.empty());
396 bool is_printable = IsPrintable(event.session.back().wparam);
397 bool valid =
event.character != 0 && is_printable;
404 UINT KeyboardManager::PeekNextMessageType(UINT wMsgFilterMin,
405 UINT wMsgFilterMax) {
408 &next_message, wMsgFilterMin, wMsgFilterMax, PM_NOREMOVE);
412 return next_message.message;