| // 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_KEYBOARD_KEY_HANDLER_H_ | |
| #define FLUTTER_SHELL_PLATFORM_WINDOWS_KEYBOARD_KEY_HANDLER_H_ | |
| #include <windows.h> | |
| #include <deque> | |
| #include <memory> | |
| #include <string> | |
| #include "flutter/shell/platform/common/client_wrapper/include/flutter/basic_message_channel.h" | |
| #include "flutter/shell/platform/windows/keyboard_handler_base.h" | |
| #include "rapidjson/document.h" | |
| namespace flutter { | |
| // Handles key events. | |
| // | |
| // This class detects whether an incoming event is a redispatched one, | |
| // dispatches native events to delegates and collect their responses, | |
| // and redispatches events unhandled by Flutter back to the system. | |
| // See |KeyboardHook| for more information about dispatching. | |
| // | |
| // This class owns multiple |KeyboardKeyHandlerDelegate|s, which | |
| // implements the exact behavior to asynchronously handle events. In | |
| // reality, this design is only to support sending events through | |
| // "channel" (RawKeyEvent) and "embedder" (KeyEvent) simultaneously, | |
| // the former of which shall be removed after the deprecation window | |
| // of the RawKeyEvent system. | |
| class KeyboardKeyHandler : public KeyboardHandlerBase { | |
| public: | |
| // An interface for concrete definition of how to asynchronously handle key | |
| // events. | |
| class KeyboardKeyHandlerDelegate { | |
| public: | |
| // Defines how to how to asynchronously handle key events. | |
| // | |
| // |KeyboardHook| should invoke |callback| with the response (whether the | |
| // event is handled) later for exactly once. | |
| virtual void KeyboardHook(int key, | |
| int scancode, | |
| int action, | |
| char32_t character, | |
| bool extended, | |
| bool was_down, | |
| KeyEventCallback callback) = 0; | |
| virtual ~KeyboardKeyHandlerDelegate(); | |
| }; | |
| // Create a KeyboardKeyHandler. | |
| explicit KeyboardKeyHandler(); | |
| ~KeyboardKeyHandler(); | |
| // Add a delegate that handles events received by |KeyboardHook|. | |
| void AddDelegate(std::unique_ptr<KeyboardKeyHandlerDelegate> delegate); | |
| // Handles a key event. | |
| // | |
| // Returns whether this handler claims to handle the event, which is true if | |
| // and only if the event is a non-synthesized event. | |
| // | |
| // Windows requires a synchronous response of whether a key event should be | |
| // handled, while the query to Flutter is always asynchronous. This is | |
| // resolved by the "redispatching" algorithm: by default, the response to a | |
| // fresh event is always always true. The event is then sent to the framework. | |
| // If the framework later decides not to handle the event, this class will | |
| // create an identical event and dispatch it to the system, and remember all | |
| // synthesized events. The fist time an exact event (by |ComputeEventHash|) is | |
| // received in the future, the new event is considered a synthesized one, | |
| // causing |KeyboardHook| to return false to fall back to other keyboard | |
| // handlers. | |
| // | |
| // Whether a non-synthesized event is considered handled by the framework is | |
| // decided by dispatching the event to all delegates, simultaneously, | |
| // unconditionally, in insertion order, and collecting their responses later. | |
| // It's not supported to prevent any delegates to process the events, because | |
| // in reality this will only support 2 hardcoded delegates, and only to | |
| // continue supporting the legacy API (channel) during the deprecation window, | |
| // after which the channel delegate should be removed. | |
| // | |
| // Inherited from |KeyboardHandlerBase|. | |
| void KeyboardHook(int key, | |
| int scancode, | |
| int action, | |
| char32_t character, | |
| bool extended, | |
| bool was_down, | |
| KeyEventCallback callback) override; | |
| private: | |
| struct PendingEvent { | |
| // Self-incrementing ID attached to an event sent to the framework. | |
| uint64_t sequence_id; | |
| // The number of delegates that haven't replied. | |
| size_t unreplied; | |
| // Whether any replied delegates reported true (handled). | |
| bool any_handled; | |
| // Where to report the delegates' result to. | |
| // | |
| // Typically a callback provided by KeyboardManager32. | |
| KeyEventCallback callback; | |
| }; | |
| void ResolvePendingEvent(uint64_t sequence_id, bool handled); | |
| std::vector<std::unique_ptr<KeyboardKeyHandlerDelegate>> delegates_; | |
| // The queue of key events that have been sent to the framework but have not | |
| // yet received a response. | |
| std::deque<std::unique_ptr<PendingEvent>> pending_responds_; | |
| // The sequence_id attached to the last event sent to the framework. | |
| uint64_t last_sequence_id_; | |
| }; | |
| } // namespace flutter | |
| #endif // FLUTTER_SHELL_PLATFORM_WINDOWS_KEYBOARD_KEY_HANDLER_H_ |