8 #include "flutter/fml/logging.h"
18 constexpr
int kMaxPendingEvents = 1000;
43 bool IsKeyDownAltRight(
int action,
int virtual_key,
bool extended) {
44 return virtual_key == VK_RMENU &&
extended &&
52 return virtual_key == VK_RMENU &&
extended &&
59 bool IsKeyDownCtrlLeft(
int action,
int virtual_key) {
60 return virtual_key == VK_LCONTROL &&
65 bool IsDeadKey(uint32_t ch) {
69 char32_t CodePointFromSurrogatePair(
wchar_t high,
wchar_t low) {
70 return 0x10000 + ((
static_cast<char32_t
>(high) & 0x000003FF) << 10) +
74 uint16_t ResolveKeyCode(uint16_t original,
bool extended, uint8_t
scancode) {
78 return MapVirtualKey(
scancode, MAPVK_VSC_TO_VK_EX);
81 return extended ? VK_RMENU : VK_LMENU;
84 return extended ? VK_RCONTROL : VK_LCONTROL;
90 bool IsPrintable(uint32_t c) {
91 constexpr char32_t kMinPrintable =
' ';
92 constexpr char32_t kDelete = 0x7F;
93 return c >= kMinPrintable && c != kDelete;
96 bool IsSysAction(UINT
action) {
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?";
131 bool KeyboardManager::RemoveRedispatchedMessage(UINT
const action,
133 LPARAM
const lparam) {
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);
146 LPARAM
const lparam) {
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;
273 const LPARAM lParam =
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 "
329 void 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] {
337 FML_DCHECK(processing_event_);
338 processing_event_ =
false;
343 void 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);
366 void 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);
387 void KeyboardManager::DispatchText(
const PendingEvent& event) {
393 FML_DCHECK(!event.session.empty());
394 bool is_printable = IsPrintable(event.session.back().wparam);
395 bool valid =
event.character != 0 && is_printable;
402 UINT KeyboardManager::PeekNextMessageType(UINT wMsgFilterMin,
403 UINT wMsgFilterMax) {
406 &next_message, wMsgFilterMin, wMsgFilterMax, PM_NOREMOVE);
410 return next_message.message;