| Flutter Windows Embedder |

keyboard_key_handler.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "flutter/shell/platform/windows/keyboard_key_handler.h"
6
7 #include <windows.h>
8
9 #include "flutter/fml/logging.h"
10 #include "flutter/shell/platform/common/client_wrapper/include/flutter/standard_method_codec.h"
11 #include "flutter/shell/platform/windows/keyboard_utils.h"
12
13 namespace flutter {
14
15 namespace {
16
17 // The maximum number of pending events to keep before
18 // emitting a warning on the console about unhandled events.
19 static constexpr int kMaxPendingEvents = 1000;
20
21 // The name of the channel for keyboard state queries.
22 static constexpr char kChannelName[] = "flutter/keyboard";
23
24 static constexpr char kGetKeyboardStateMethod[] = "getKeyboardState";
25
26 } // namespace
27
28 KeyboardKeyHandler::KeyboardKeyHandlerDelegate::~KeyboardKeyHandlerDelegate() =
29 default;
30
31 KeyboardKeyHandler::KeyboardKeyHandler(flutter::BinaryMessenger* messenger)
32 : last_sequence_id_(1),
33 channel_(std::make_unique<MethodChannel<EncodableValue>>(
34 messenger,
35 kChannelName,
36 &StandardMethodCodec::GetInstance())) {}
37
38 KeyboardKeyHandler::~KeyboardKeyHandler() = default;
39
40 void KeyboardKeyHandler::InitKeyboardChannel() {
41 channel_->SetMethodCallHandler(
42 [this](const MethodCall<EncodableValue>& call,
43 std::unique_ptr<MethodResult<EncodableValue>> result) {
44 HandleMethodCall(call, std::move(result));
45 });
46 }
47
48 void KeyboardKeyHandler::HandleMethodCall(
49 const MethodCall<EncodableValue>& method_call,
50 std::unique_ptr<MethodResult<EncodableValue>> result) {
51 const std::string& method = method_call.method_name();
52 if (method.compare(kGetKeyboardStateMethod) == 0) {
53 EncodableMap value;
54 const auto& pressed_state = GetPressedState();
55 for (const auto& pressed_key : pressed_state) {
56 EncodableValue physical_value(static_cast<long long>(pressed_key.first));
57 EncodableValue logical_value(static_cast<long long>(pressed_key.second));
58 value[physical_value] = logical_value;
59 }
60 result->Success(EncodableValue(value));
61 } else {
62 result->NotImplemented();
63 }
64 }
65
66 void KeyboardKeyHandler::AddDelegate(
67 std::unique_ptr<KeyboardKeyHandlerDelegate> delegate) {
68 delegates_.push_back(std::move(delegate));
69 }
70
71 void KeyboardKeyHandler::SyncModifiersIfNeeded(int modifiers_state) {
72 // Only call SyncModifierIfNeeded on the key embedder handler.
73 auto& key_embedder_handler = delegates_.front();
74 key_embedder_handler->SyncModifiersIfNeeded(modifiers_state);
75 }
76
77 std::map<uint64_t, uint64_t> KeyboardKeyHandler::GetPressedState() {
78 // The embedder responder is the first element in delegates_.
79 auto& key_embedder_handler = delegates_.front();
80 return key_embedder_handler->GetPressedState();
81 }
82
83 void KeyboardKeyHandler::KeyboardHook(int key,
84 int scancode,
85 int action,
86 char32_t character,
87 bool extended,
88 bool was_down,
89 KeyEventCallback callback) {
90 std::unique_ptr<PendingEvent> incoming = std::make_unique<PendingEvent>();
91
92 uint64_t sequence_id = ++last_sequence_id_;
93 incoming->sequence_id = sequence_id;
94 incoming->unreplied = delegates_.size();
95 incoming->any_handled = false;
96 incoming->callback = std::move(callback);
97
98 if (pending_responds_.size() > kMaxPendingEvents) {
99 FML_LOG(ERROR)
100 << "There are " << pending_responds_.size()
101 << " keyboard events that have not yet received a response from the "
102 << "framework. Are responses being sent?";
103 }
104 pending_responds_.push_back(std::move(incoming));
105
106 for (const auto& delegate : delegates_) {
107 delegate->KeyboardHook(key, scancode, action, character, extended, was_down,
108 [sequence_id, this](bool handled) {
109 ResolvePendingEvent(sequence_id, handled);
110 });
111 }
112
113 // |ResolvePendingEvent| might trigger redispatching synchronously,
114 // which might occur before |KeyboardHook| is returned. This won't
115 // make events out of order though, because |KeyboardHook| will always
116 // return true at this time, preventing this event from affecting
117 // others.
118 }
119
120 void KeyboardKeyHandler::ResolvePendingEvent(uint64_t sequence_id,
121 bool handled) {
122 // Find the pending event
123 for (auto iter = pending_responds_.begin(); iter != pending_responds_.end();
124 ++iter) {
125 if ((*iter)->sequence_id == sequence_id) {
126 PendingEvent& event = **iter;
127 event.any_handled = event.any_handled || handled;
128 event.unreplied -= 1;
129 FML_DCHECK(event.unreplied >= 0)
130 << "Pending events must have unreplied count > 0";
131 // If all delegates have replied, report if any of them handled the event.
132 if (event.unreplied == 0) {
133 std::unique_ptr<PendingEvent> event_ptr = std::move(*iter);
134 pending_responds_.erase(iter);
135 event.callback(event.any_handled);
136 }
137 // Return here; |iter| can't do ++ after erase.
138 return;
139 }
140 }
141 // The pending event should always be found.
142 FML_LOG(FATAL) << "Could not find pending key event for sequence ID "
143 << sequence_id;
144 }
145
146 } // namespace flutter
scancode
int scancode
Definition: keyboard_key_handler_unittests.cc:115
was_down
bool was_down
Definition: keyboard_key_handler_unittests.cc:119
extended
bool extended
Definition: keyboard_key_handler_unittests.cc:118
flutter::MethodChannel
Definition: method_channel.h:34
character
char32_t character
Definition: keyboard_key_handler_unittests.cc:117
flutter::KeyboardKeyHandler::SyncModifiersIfNeeded
void SyncModifiersIfNeeded(int modifiers_state) override
Definition: keyboard_key_handler.cc:71
flutter::StandardMethodCodec
Definition: standard_method_codec.h:18
standard_method_codec.h
flutter::KeyboardHandlerBase::KeyEventCallback
std::function< void(bool)> KeyEventCallback
Definition: keyboard_handler_base.h:20
flutter::KeyboardKeyHandler::KeyboardHook
void KeyboardHook(int key, int scancode, int action, char32_t character, bool extended, bool was_down, KeyEventCallback callback) override
Definition: keyboard_key_handler.cc:83
flutter::BinaryMessenger
Definition: binary_messenger.h:28
flutter::KeyboardKeyHandler::InitKeyboardChannel
void InitKeyboardChannel()
Definition: keyboard_key_handler.cc:40
keyboard_utils.h
flutter::MethodCall
Definition: method_call.h:18
flutter::KeyboardKeyHandler::GetPressedState
std::map< uint64_t, uint64_t > GetPressedState() override
Definition: keyboard_key_handler.cc:77
flutter::KeyboardKeyHandler::~KeyboardKeyHandler
~KeyboardKeyHandler()
flutter::KeyboardKeyHandler::KeyboardKeyHandler
KeyboardKeyHandler(flutter::BinaryMessenger *messenger)
Definition: keyboard_key_handler.cc:31
flutter
Definition: accessibility_bridge_windows.cc:11
flutter::KeyboardKeyHandler::KeyboardKeyHandlerDelegate::~KeyboardKeyHandlerDelegate
virtual ~KeyboardKeyHandlerDelegate()
kChannelName
static constexpr char kChannelName[]
Definition: cursor_handler.cc:13
flutter::EncodableValue
Definition: encodable_value.h:165
flutter::MethodCall::method_name
const std::string & method_name() const
Definition: method_call.h:31
flutter::MethodResult< EncodableValue >
keyboard_key_handler.h
flutter::KeyboardKeyHandler::AddDelegate
void AddDelegate(std::unique_ptr< KeyboardKeyHandlerDelegate > delegate)
Definition: keyboard_key_handler.cc:66
action
int action
Definition: keyboard_key_handler_unittests.cc:116
flutter::EncodableMap
std::map< EncodableValue, EncodableValue > EncodableMap
Definition: encodable_value.h:95
key
int key
Definition: keyboard_key_handler_unittests.cc:114
callback
FlutterDesktopBinaryReply callback
Definition: flutter_windows_view_unittests.cc:51