Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions shell/platform/windows/flutter_windows_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,10 @@ bool FlutterWindowsEngine::RunWithEntrypoint(const char* entrypoint) {
auto host = static_cast<FlutterWindowsEngine*>(user_data);
return host->HandlePlatformMessage(engine_message);
};
args.on_pre_engine_restart_callback = [](void* user_data) {
auto host = static_cast<FlutterWindowsEngine*>(user_data);
host->view()->OnPreEngineRestart();
};

args.custom_task_runners = &custom_task_runners;

Expand Down
32 changes: 21 additions & 11 deletions shell/platform/windows/flutter_windows_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,7 @@ void FlutterWindowsView::SetEngine(

// Set up the system channel handlers.
auto internal_plugin_messenger = internal_plugin_registrar_->messenger();
#ifdef WINUWP
flutter::KeyboardKeyHandler::EventDispatcher dispatch_event = nullptr;
flutter::KeyboardKeyEmbedderHandler::GetKeyStateHandler get_key_state =
nullptr;
#else
flutter::KeyboardKeyHandler::EventDispatcher dispatch_event = SendInput;
flutter::KeyboardKeyEmbedderHandler::GetKeyStateHandler get_key_state =
GetKeyState;
#endif
RegisterKeyboardHandlers(internal_plugin_messenger, dispatch_event,
get_key_state);
InitializeKeyboard();
platform_handler_ = PlatformHandler::Create(internal_plugin_messenger, this);
cursor_handler_ = std::make_unique<flutter::CursorHandler>(
internal_plugin_messenger, binding_handler_.get());
Expand Down Expand Up @@ -137,6 +127,11 @@ void FlutterWindowsView::ForceRedraw() {
}
}

void FlutterWindowsView::OnPreEngineRestart() {
keyboard_handlers_.clear();
InitializeKeyboard();
}

void FlutterWindowsView::OnWindowSizeChanged(size_t width, size_t height) {
// Called on the platform thread.
std::unique_lock<std::mutex> lock(resize_mutex_);
Expand Down Expand Up @@ -257,6 +252,21 @@ void FlutterWindowsView::OnCursorRectUpdated(const Rect& rect) {
binding_handler_->OnCursorRectUpdated(rect);
}

void FlutterWindowsView::InitializeKeyboard() {
auto internal_plugin_messenger = internal_plugin_registrar_->messenger();
#ifdef WINUWP
flutter::KeyboardKeyHandler::EventDispatcher dispatch_event = nullptr;
flutter::KeyboardKeyEmbedderHandler::GetKeyStateHandler get_key_state =
nullptr;
#else
flutter::KeyboardKeyHandler::EventDispatcher dispatch_event = SendInput;
flutter::KeyboardKeyEmbedderHandler::GetKeyStateHandler get_key_state =
GetKeyState;
#endif
RegisterKeyboardHandlers(internal_plugin_messenger, dispatch_event,
get_key_state);
}

// Sends new size information to FlutterEngine.
void FlutterWindowsView::SendWindowMetrics(size_t width,
size_t height,
Expand Down
11 changes: 11 additions & 0 deletions shell/platform/windows/flutter_windows_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ class FlutterWindowsView : public WindowBindingHandlerDelegate,
// Returns the frame buffer id for the engine to render to.
uint32_t GetFrameBufferId(size_t width, size_t height);

// Called when the engine is restarted.
//
// This should reset necessary states to as if the view has just been
// created. This is typically caused by a hot restart (Shift-R in CLI.)
void OnPreEngineRestart();

// |WindowBindingHandlerDelegate|
void OnWindowSizeChanged(size_t width, size_t height) override;

Expand Down Expand Up @@ -207,6 +213,11 @@ class FlutterWindowsView : public WindowBindingHandlerDelegate,
kDone,
};

// Initialize states related to keyboard.
//
// This is called when the view is first created, or restarted.
void InitializeKeyboard();

// Sends a window metrics update to the Flutter engine using current window
// dimensions in physical
void SendWindowMetrics(size_t width, size_t height, double dpiscale) const;
Expand Down
34 changes: 33 additions & 1 deletion shell/platform/windows/flutter_windows_view_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ struct TestResponseHandle {
void* user_data;
};

static const bool test_response = false;
static bool test_response = false;

constexpr uint64_t kKeyEventFromChannel = 0x11;
constexpr uint64_t kKeyEventFromEmbedder = 0x22;
Expand Down Expand Up @@ -80,6 +80,8 @@ std::unique_ptr<FlutterWindowsEngine> GetTestEngine() {
TEST(FlutterWindowsViewTest, KeySequence) {
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();

test_response = false;

auto window_binding_handler =
std::make_unique<::testing::NiceMock<MockWindowBindingHandler>>();
FlutterWindowsView view(std::move(window_binding_handler));
Expand All @@ -94,5 +96,35 @@ TEST(FlutterWindowsViewTest, KeySequence) {
key_event_logs.clear();
}

TEST(FlutterWindowsViewTest, RestartClearsKeyboardState) {
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();

auto window_binding_handler =
std::make_unique<::testing::NiceMock<MockWindowBindingHandler>>();
FlutterWindowsView view(std::move(window_binding_handler));
view.SetEngine(std::move(engine));

test_response = false;

// Receives a KeyA down. Events are dispatched and decided unhandled. Now the
// keyboard key handler is waiting for the redispatched event.
view.OnKey(kVirtualKeyA, kScanCodeKeyA, WM_KEYDOWN, 'a', false, false);
EXPECT_EQ(key_event_logs.size(), 2);
EXPECT_EQ(key_event_logs[0], kKeyEventFromEmbedder);
EXPECT_EQ(key_event_logs[1], kKeyEventFromChannel);
key_event_logs.clear();

// Resets state so that the keyboard key handler is no longer waiting.
view.OnPreEngineRestart();

// Receives another KeyA down. If the state had not been cleared, this event
// will be considered the redispatched event and ignored.
view.OnKey(kVirtualKeyA, kScanCodeKeyA, WM_KEYDOWN, 'a', false, false);
EXPECT_EQ(key_event_logs.size(), 2);
EXPECT_EQ(key_event_logs[0], kKeyEventFromEmbedder);
EXPECT_EQ(key_event_logs[1], kKeyEventFromChannel);
key_event_logs.clear();
}

} // namespace testing
} // namespace flutter