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 
6 
7 #include <windows.h>
8 
9 #include "flutter/fml/logging.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 
29  default;
30 
32  : last_sequence_id_(1),
33  channel_(std::make_unique<MethodChannel<EncodableValue>>(
34  messenger,
36  &StandardMethodCodec::GetInstance())) {}
37 
39 
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 
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 
84  int scancode,
85  int action,
86  char32_t character,
87  bool extended,
88  bool was_down,
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:52