flutter_flutter/shell/platform/windows/key_event_handler.h
Greg Spencer c8620c3fc1
Implement delayed key event synthesis for Windows (#23524)
This changes the Windows text handling so that keyboard events are sent to the framework first for handling, and then passed to the text input plugin, so that the framework has a chance to handle keys before they get given to the text field.

This is complicated by the async nature of the interaction with the framework, since Windows wants a synchronous response. So, in this change, I always tell Windows that the event was handled, and if the framework (eventually) responds that it wasn't, then I synthesize a new event and send it with SendEvent.

I also added support for detecting "extended" keys, since that was missing, and converted the OnKey handlers in the API to return a bool to indicate whether or not they have handled the event.
2021-01-22 18:14:39 -08:00

74 lines
2.5 KiB
C++

// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_KEY_EVENT_HANDLER_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_KEY_EVENT_HANDLER_H_
#include <deque>
#include <memory>
#include <string>
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/basic_message_channel.h"
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/binary_messenger.h"
#include "flutter/shell/platform/windows/keyboard_hook_handler.h"
#include "flutter/shell/platform/windows/public/flutter_windows.h"
#include "rapidjson/document.h"
namespace flutter {
class FlutterWindowsView;
// Implements a KeyboardHookHandler
//
// Handles key events and forwards them to the Flutter engine.
class KeyEventHandler : public KeyboardHookHandler {
public:
using SendInputDelegate =
std::function<UINT(UINT cInputs, LPINPUT pInputs, int cbSize)>;
explicit KeyEventHandler(flutter::BinaryMessenger* messenger,
SendInputDelegate delegate = SendInput);
virtual ~KeyEventHandler();
// |KeyboardHookHandler|
bool KeyboardHook(FlutterWindowsView* window,
int key,
int scancode,
int action,
char32_t character,
bool extended) override;
// |KeyboardHookHandler|
void TextHook(FlutterWindowsView* window,
const std::u16string& text) override;
private:
KEYBDINPUT* FindPendingEvent(uint64_t id);
void RemovePendingEvent(uint64_t id);
void AddPendingEvent(uint64_t id, int scancode, int action, bool extended);
void HandleResponse(bool handled,
uint64_t id,
int action,
bool extended,
int scancode,
int character);
// The Flutter system channel for key event messages.
std::unique_ptr<flutter::BasicMessageChannel<rapidjson::Document>> channel_;
// The queue of key events that have been sent to the framework but have not
// yet received a response.
std::deque<std::pair<uint64_t, KEYBDINPUT>> pending_events_;
// A function used to dispatch synthesized events. Used in testing to inject a
// test function to collect events. Defaults to the Windows function
// SendInput.
SendInputDelegate send_input_;
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_KEY_EVENT_HANDLER_H_