146 {
147 if (RemoveRedispatchedMessage(
action, wparam, lparam)) {
148 return false;
149 }
151 case WM_DEADCHAR:
152 case WM_SYSDEADCHAR:
153 case WM_CHAR:
154 case WM_SYSCHAR: {
156 Win32Message{.
action =
action, .wparam = wparam, .lparam = lparam};
157 current_session_.push_back(
message);
158
159 char32_t code_point;
161
162
163 return true;
165 const Win32Message* last_message =
166 current_session_.size() <= 1
167 ? nullptr
168 : ¤t_session_[current_session_.size() - 2];
169 if (last_message == nullptr || !last_message->IsHighSurrogate()) {
170 return false;
171 }
172
173
174 code_point =
175 CodePointFromSurrogatePair(last_message->wparam,
message.
wparam);
176 } else {
177
178
180 }
181
182
183
184
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;
191
192
193
195 if (
action == WM_DEADCHAR ||
action == WM_SYSDEADCHAR) {
196
197
198
201 } else {
202 character = IsPrintable(code_point) ? code_point : 0;
203 }
204 auto event = std::make_unique<PendingEvent>(PendingEvent{
205 .key = key_code,
207 .action =
static_cast<UINT>(
action == WM_SYSCHAR ? WM_SYSKEYDOWN
208 : WM_KEYDOWN),
212 .session = std::move(current_session_),
213 });
214
215 pending_events_.push_back(std::move(
event));
216 ProcessNextEvent();
217
218
219
220 return !IsSysAction(
action);
221 }
222
223
224
225
226
227
228
229
231 auto event = std::make_unique<PendingEvent>(PendingEvent{
232 .action = WM_CHAR,
233 .character = code_point,
234 .session = std::move(current_session_),
235 });
236 pending_events_.push_back(std::move(
event));
237 ProcessNextEvent();
238 }
239 return true;
240 }
241
242 case WM_KEYDOWN:
243 case WM_SYSKEYDOWN:
244 case WM_KEYUP:
245 case WM_SYSKEYUP: {
246 if (wparam == VK_PACKET) {
247 return false;
248 }
249
250 const uint8_t
scancode = (lparam >> 16) & 0xff;
251 const bool extended = ((lparam >> 24) & 0x01) == 0x01;
252
254 const bool was_down = lparam & 0x40000000;
255
256
257
259 if (last_key_is_ctrl_left_down) {
260 should_synthesize_ctrl_left_up = true;
261 }
262 }
263 if (IsKeyDownCtrlLeft(
action, key_code)) {
264 last_key_is_ctrl_left_down = true;
266 should_synthesize_ctrl_left_up = false;
267 } else {
268 last_key_is_ctrl_left_down = false;
269 }
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) |
276 (1 << 31);
278 }
279 }
280
281 current_session_.clear();
282 current_session_.push_back(
283 Win32Message{.action =
action, .wparam = wparam, .lparam = lparam});
284 const bool is_keydown_message =
286
287
288
289
290
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) {
298
299
300
301
302 return true;
303 }
304
305
306
307 auto event = std::make_unique<PendingEvent>(PendingEvent{
308 .key = key_code,
311 .character = 0,
314 .session = std::move(current_session_),
315 });
316 pending_events_.push_back(std::move(
event));
317 ProcessNextEvent();
318
319
320 return !IsSysAction(
action);
321 }
322 default:
323 FML_LOG(
FATAL) <<
"No event handler for keyboard event with action "
325 }
326 return false;
327}
virtual UINT Win32DispatchMessage(UINT Msg, WPARAM wParam, LPARAM lParam)=0
virtual uint32_t Win32MapVkToChar(uint32_t virtual_key)=0
#define FML_LOG(severity)
constexpr int kDeadKeyCharMask
bool IsHighSurrogate() const
bool IsLowSurrogate() const