Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 081b9fc

Browse files
authored
[Windows] Prepare keyboard & text input plugins for multi-view (#39464)
* Start * Add keyboard reset hook * Update comment * Format
1 parent 9a40a38 commit 081b9fc

11 files changed

+253
-206
lines changed

shell/platform/windows/flutter_windows_engine.cc

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "flutter/shell/platform/common/path_utils.h"
1818
#include "flutter/shell/platform/windows/accessibility_bridge_windows.h"
1919
#include "flutter/shell/platform/windows/flutter_windows_view.h"
20+
#include "flutter/shell/platform/windows/keyboard_key_channel_handler.h"
2021
#include "flutter/shell/platform/windows/system_utils.h"
2122
#include "flutter/shell/platform/windows/task_runner.h"
2223
#include "flutter/third_party/accessibility/ax/ax_node.h"
@@ -206,6 +207,8 @@ FlutterWindowsEngine::FlutterWindowsEngine(
206207
// Set up internal channels.
207208
// TODO: Replace this with an embedder.h API. See
208209
// https://github.com/flutter/flutter/issues/71099
210+
internal_plugin_registrar_ =
211+
std::make_unique<PluginRegistrar>(plugin_registrar_.get());
209212
cursor_handler_ =
210213
std::make_unique<CursorHandler>(messenger_wrapper_.get(), this);
211214
platform_handler_ =
@@ -322,7 +325,7 @@ bool FlutterWindowsEngine::Run(std::string_view entrypoint) {
322325
};
323326
args.on_pre_engine_restart_callback = [](void* user_data) {
324327
auto host = static_cast<FlutterWindowsEngine*>(user_data);
325-
host->view()->OnPreEngineRestart();
328+
host->OnPreEngineRestart();
326329
};
327330
args.update_semantics_callback = [](const FlutterSemanticsUpdate* update,
328331
void* user_data) {
@@ -401,6 +404,7 @@ bool FlutterWindowsEngine::Stop() {
401404

402405
void FlutterWindowsEngine::SetView(FlutterWindowsView* view) {
403406
view_ = view;
407+
InitializeKeyboard();
404408
}
405409

406410
void FlutterWindowsEngine::OnVsync(intptr_t baton) {
@@ -561,6 +565,47 @@ void FlutterWindowsEngine::SendSystemLocales() {
561565
flutter_locale_list.size());
562566
}
563567

568+
void FlutterWindowsEngine::InitializeKeyboard() {
569+
if (view_ == nullptr) {
570+
FML_LOG(ERROR) << "Cannot initialize keyboard on Windows headless mode.";
571+
}
572+
573+
auto internal_plugin_messenger = internal_plugin_registrar_->messenger();
574+
KeyboardKeyEmbedderHandler::GetKeyStateHandler get_key_state = GetKeyState;
575+
KeyboardKeyEmbedderHandler::MapVirtualKeyToScanCode map_vk_to_scan =
576+
[](UINT virtual_key, bool extended) {
577+
return MapVirtualKey(virtual_key,
578+
extended ? MAPVK_VK_TO_VSC_EX : MAPVK_VK_TO_VSC);
579+
};
580+
keyboard_key_handler_ = std::move(CreateKeyboardKeyHandler(
581+
internal_plugin_messenger, get_key_state, map_vk_to_scan));
582+
text_input_plugin_ =
583+
std::move(CreateTextInputPlugin(internal_plugin_messenger));
584+
}
585+
586+
std::unique_ptr<KeyboardHandlerBase>
587+
FlutterWindowsEngine::CreateKeyboardKeyHandler(
588+
BinaryMessenger* messenger,
589+
KeyboardKeyEmbedderHandler::GetKeyStateHandler get_key_state,
590+
KeyboardKeyEmbedderHandler::MapVirtualKeyToScanCode map_vk_to_scan) {
591+
auto keyboard_key_handler = std::make_unique<KeyboardKeyHandler>();
592+
keyboard_key_handler->AddDelegate(
593+
std::make_unique<KeyboardKeyEmbedderHandler>(
594+
[this](const FlutterKeyEvent& event, FlutterKeyEventCallback callback,
595+
void* user_data) {
596+
return SendKeyEvent(event, callback, user_data);
597+
},
598+
get_key_state, map_vk_to_scan));
599+
keyboard_key_handler->AddDelegate(
600+
std::make_unique<KeyboardKeyChannelHandler>(messenger));
601+
return keyboard_key_handler;
602+
}
603+
604+
std::unique_ptr<TextInputPlugin> FlutterWindowsEngine::CreateTextInputPlugin(
605+
BinaryMessenger* messenger) {
606+
return std::make_unique<TextInputPlugin>(messenger, view_);
607+
}
608+
564609
bool FlutterWindowsEngine::RegisterExternalTexture(int64_t texture_id) {
565610
return (embedder_api_.RegisterExternalTexture(engine_, texture_id) ==
566611
kSuccess);
@@ -625,6 +670,13 @@ FlutterWindowsEngine::CreateAccessibilityBridge(FlutterWindowsEngine* engine,
625670
return std::make_shared<AccessibilityBridgeWindows>(engine, view);
626671
}
627672

673+
void FlutterWindowsEngine::OnPreEngineRestart() {
674+
// Reset the keyboard's state on hot restart.
675+
if (view_) {
676+
InitializeKeyboard();
677+
}
678+
}
679+
628680
gfx::NativeViewAccessible FlutterWindowsEngine::GetNativeAccessibleFromId(
629681
AccessibilityNodeId id) {
630682
if (!accessibility_bridge_) {

shell/platform/windows/flutter_windows_engine.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@
2525
#include "flutter/shell/platform/windows/flutter_desktop_messenger.h"
2626
#include "flutter/shell/platform/windows/flutter_project_bundle.h"
2727
#include "flutter/shell/platform/windows/flutter_windows_texture_registrar.h"
28+
#include "flutter/shell/platform/windows/keyboard_handler_base.h"
29+
#include "flutter/shell/platform/windows/keyboard_key_embedder_handler.h"
2830
#include "flutter/shell/platform/windows/platform_handler.h"
2931
#include "flutter/shell/platform/windows/public/flutter_windows.h"
3032
#include "flutter/shell/platform/windows/settings_plugin.h"
3133
#include "flutter/shell/platform/windows/task_runner.h"
34+
#include "flutter/shell/platform/windows/text_input_plugin.h"
3235
#include "flutter/shell/platform/windows/window_proc_delegate_manager.h"
3336
#include "flutter/shell/platform/windows/window_state.h"
3437
#include "flutter/shell/platform/windows/windows_registry.h"
@@ -163,6 +166,11 @@ class FlutterWindowsEngine {
163166
FlutterKeyEventCallback callback,
164167
void* user_data);
165168

169+
KeyboardHandlerBase* keyboard_key_handler() {
170+
return keyboard_key_handler_.get();
171+
}
172+
TextInputPlugin* text_input_plugin() { return text_input_plugin_.get(); }
173+
166174
// Sends the given message to the engine, calling |reply| with |user_data|
167175
// when a response is received from the engine if they are non-null.
168176
bool SendPlatformMessage(const char* channel,
@@ -249,6 +257,22 @@ class FlutterWindowsEngine {
249257
void UpdateAccessibilityFeatures(FlutterAccessibilityFeature flags);
250258

251259
protected:
260+
// Creates the keyboard key handler.
261+
//
262+
// Exposing this method allows unit tests to override in order to
263+
// capture information.
264+
virtual std::unique_ptr<KeyboardHandlerBase> CreateKeyboardKeyHandler(
265+
BinaryMessenger* messenger,
266+
KeyboardKeyEmbedderHandler::GetKeyStateHandler get_key_state,
267+
KeyboardKeyEmbedderHandler::MapVirtualKeyToScanCode map_vk_to_scan);
268+
269+
// Creates the text input plugin.
270+
//
271+
// Exposing this method allows unit tests to override in order to
272+
// capture information.
273+
virtual std::unique_ptr<TextInputPlugin> CreateTextInputPlugin(
274+
BinaryMessenger* messenger);
275+
252276
// Creates an accessibility bridge with the provided parameters.
253277
//
254278
// By default this method calls AccessibilityBridge's constructor. Exposing
@@ -257,6 +281,12 @@ class FlutterWindowsEngine {
257281
FlutterWindowsEngine* engine,
258282
FlutterWindowsView* view);
259283

284+
// Invoked by the engine right before the engine is restarted.
285+
//
286+
// This should reset necessary states to as if the engine has just been
287+
// created. This is typically caused by a hot restart (Shift-R in CLI.)
288+
void OnPreEngineRestart();
289+
260290
private:
261291
// Allows swapping out embedder_api_ calls in tests.
262292
friend class EngineModifier;
@@ -267,6 +297,12 @@ class FlutterWindowsEngine {
267297
// system changes.
268298
void SendSystemLocales();
269299

300+
// Create the keyboard & text input sub-systems.
301+
//
302+
// This requires that a view is attached to the engine.
303+
// Calling this method again resets the keyboard state.
304+
void InitializeKeyboard();
305+
270306
void HandleAccessibilityMessage(FlutterDesktopMessengerRef messenger,
271307
const FlutterDesktopMessage* message);
272308

@@ -309,12 +345,21 @@ class FlutterWindowsEngine {
309345
// May be nullptr if ANGLE failed to initialize.
310346
std::unique_ptr<AngleSurfaceManager> surface_manager_;
311347

348+
// The plugin registrar managing internal plugins.
349+
std::unique_ptr<PluginRegistrar> internal_plugin_registrar_;
350+
312351
// Handler for cursor events.
313352
std::unique_ptr<CursorHandler> cursor_handler_;
314353

315354
// Handler for the flutter/platform channel.
316355
std::unique_ptr<PlatformHandler> platform_handler_;
317356

357+
// Handlers for keyboard events from Windows.
358+
std::unique_ptr<KeyboardHandlerBase> keyboard_key_handler_;
359+
360+
// Handlers for text events from Windows.
361+
std::unique_ptr<TextInputPlugin> text_input_plugin_;
362+
318363
// The settings plugin.
319364
std::unique_ptr<SettingsPlugin> settings_plugin_;
320365

shell/platform/windows/flutter_windows_view.cc

Lines changed: 9 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include "flutter/fml/platform/win/wstring_conversion.h"
1010
#include "flutter/shell/platform/common/accessibility_bridge.h"
1111
#include "flutter/shell/platform/windows/keyboard_key_channel_handler.h"
12-
#include "flutter/shell/platform/windows/keyboard_key_embedder_handler.h"
1312
#include "flutter/shell/platform/windows/text_input_plugin.h"
1413
#include "flutter/third_party/accessibility/ax/platform/ax_platform_node_win.h"
1514

@@ -59,42 +58,12 @@ void FlutterWindowsView::SetEngine(
5958

6059
engine_->SetView(this);
6160

62-
internal_plugin_registrar_ =
63-
std::make_unique<PluginRegistrar>(engine_->GetRegistrar());
64-
65-
// Set up the system channel handlers.
66-
auto internal_plugin_messenger = internal_plugin_registrar_->messenger();
67-
InitializeKeyboard();
68-
6961
PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds();
7062

7163
SendWindowMetrics(bounds.width, bounds.height,
7264
binding_handler_->GetDpiScale());
7365
}
7466

75-
std::unique_ptr<KeyboardHandlerBase>
76-
FlutterWindowsView::CreateKeyboardKeyHandler(
77-
BinaryMessenger* messenger,
78-
KeyboardKeyEmbedderHandler::GetKeyStateHandler get_key_state,
79-
KeyboardKeyEmbedderHandler::MapVirtualKeyToScanCode map_vk_to_scan) {
80-
auto keyboard_key_handler = std::make_unique<KeyboardKeyHandler>();
81-
keyboard_key_handler->AddDelegate(
82-
std::make_unique<KeyboardKeyEmbedderHandler>(
83-
[this](const FlutterKeyEvent& event, FlutterKeyEventCallback callback,
84-
void* user_data) {
85-
return engine_->SendKeyEvent(event, callback, user_data);
86-
},
87-
get_key_state, map_vk_to_scan));
88-
keyboard_key_handler->AddDelegate(
89-
std::make_unique<KeyboardKeyChannelHandler>(messenger));
90-
return keyboard_key_handler;
91-
}
92-
93-
std::unique_ptr<TextInputPlugin> FlutterWindowsView::CreateTextInputPlugin(
94-
BinaryMessenger* messenger) {
95-
return std::make_unique<TextInputPlugin>(messenger, this);
96-
}
97-
9867
uint32_t FlutterWindowsView::GetFrameBufferId(size_t width, size_t height) {
9968
// Called on an engine-controlled (non-platform) thread.
10069
std::unique_lock<std::mutex> lock(resize_mutex_);
@@ -129,10 +98,6 @@ void FlutterWindowsView::ForceRedraw() {
12998
}
13099
}
131100

132-
void FlutterWindowsView::OnPreEngineRestart() {
133-
InitializeKeyboard();
134-
}
135-
136101
void FlutterWindowsView::OnWindowSizeChanged(size_t width, size_t height) {
137102
// Called on the platform thread.
138103
std::unique_lock<std::mutex> lock(resize_mutex_);
@@ -176,7 +141,7 @@ void FlutterWindowsView::OnPointerMove(double x,
176141
FlutterPointerDeviceKind device_kind,
177142
int32_t device_id,
178143
int modifiers_state) {
179-
keyboard_key_handler_->SyncModifiersIfNeeded(modifiers_state);
144+
engine_->keyboard_key_handler()->SyncModifiersIfNeeded(modifiers_state);
180145
SendPointerMove(x, y, GetOrCreatePointerState(device_kind, device_id));
181146
}
182147

@@ -293,20 +258,6 @@ void FlutterWindowsView::OnResetImeComposing() {
293258
binding_handler_->OnResetImeComposing();
294259
}
295260

296-
void FlutterWindowsView::InitializeKeyboard() {
297-
auto internal_plugin_messenger = internal_plugin_registrar_->messenger();
298-
KeyboardKeyEmbedderHandler::GetKeyStateHandler get_key_state = GetKeyState;
299-
KeyboardKeyEmbedderHandler::MapVirtualKeyToScanCode map_vk_to_scan =
300-
[](UINT virtual_key, bool extended) {
301-
return MapVirtualKey(virtual_key,
302-
extended ? MAPVK_VK_TO_VSC_EX : MAPVK_VK_TO_VSC);
303-
};
304-
keyboard_key_handler_ = std::move(CreateKeyboardKeyHandler(
305-
internal_plugin_messenger, get_key_state, map_vk_to_scan));
306-
text_input_plugin_ =
307-
std::move(CreateTextInputPlugin(internal_plugin_messenger));
308-
}
309-
310261
// Sends new size information to FlutterEngine.
311262
void FlutterWindowsView::SendWindowMetrics(size_t width,
312263
size_t height,
@@ -454,7 +405,7 @@ void FlutterWindowsView::SendPointerPanZoomEnd(int32_t device_id) {
454405
}
455406

456407
void FlutterWindowsView::SendText(const std::u16string& text) {
457-
text_input_plugin_->TextHook(text);
408+
engine_->text_input_plugin()->TextHook(text);
458409
}
459410

460411
void FlutterWindowsView::SendKey(int key,
@@ -464,32 +415,32 @@ void FlutterWindowsView::SendKey(int key,
464415
bool extended,
465416
bool was_down,
466417
KeyEventCallback callback) {
467-
keyboard_key_handler_->KeyboardHook(
418+
engine_->keyboard_key_handler()->KeyboardHook(
468419
key, scancode, action, character, extended, was_down,
469420
[=, callback = std::move(callback)](bool handled) {
470421
if (!handled) {
471-
text_input_plugin_->KeyboardHook(key, scancode, action, character,
472-
extended, was_down);
422+
engine_->text_input_plugin()->KeyboardHook(
423+
key, scancode, action, character, extended, was_down);
473424
}
474425
callback(handled);
475426
});
476427
}
477428

478429
void FlutterWindowsView::SendComposeBegin() {
479-
text_input_plugin_->ComposeBeginHook();
430+
engine_->text_input_plugin()->ComposeBeginHook();
480431
}
481432

482433
void FlutterWindowsView::SendComposeCommit() {
483-
text_input_plugin_->ComposeCommitHook();
434+
engine_->text_input_plugin()->ComposeCommitHook();
484435
}
485436

486437
void FlutterWindowsView::SendComposeEnd() {
487-
text_input_plugin_->ComposeEndHook();
438+
engine_->text_input_plugin()->ComposeEndHook();
488439
}
489440

490441
void FlutterWindowsView::SendComposeChange(const std::u16string& text,
491442
int cursor_pos) {
492-
text_input_plugin_->ComposeChangeHook(text, cursor_pos);
443+
engine_->text_input_plugin()->ComposeChangeHook(text, cursor_pos);
493444
}
494445

495446
void FlutterWindowsView::SendScroll(double x,

0 commit comments

Comments
 (0)