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

Commit 2feb085

Browse files
authored
[Windows] Add force redraw to the C++ client wrapper (#42061)
This change adds a C++ client wrapper to Windows's "force redraw" C API. This API can be used to schedule a frame. Part of flutter/flutter#119415 ## Background The Windows runner has a race at startup: 1. **Platform thread**: creates a hidden window 2. **Platform thread**: launches the Flutter engine 3. **UI/Raster threads**: renders the first frame 4. **Platform thread**: Registers a callback to show the window once the next frame has been rendered. Steps 3 and 4 happen in parallel and it is possible for step 3 to complete before step 4 starts. In this scenario, the next frame callback is never called and the window is never shown. The Windows runner will be updated to call the "force redraw" API after it registers the next frame callback. If step 3 hasn't completed yet, the "force redraw" will no-op as a frame is already scheduled. If step 3 has already completed, the "force redraw" will schedule another frame, which will call the next frame callback and show the window. See this discussion below on why we cannot avoid changing the Windows runner to fix this issue: #42061 (comment) [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent 3d645f3 commit 2feb085

File tree

6 files changed

+36
-2
lines changed

6 files changed

+36
-2
lines changed

shell/platform/windows/client_wrapper/flutter_view_controller.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ FlutterViewController::~FlutterViewController() {
2929
}
3030
}
3131

32+
void FlutterViewController::ForceRedraw() {
33+
FlutterDesktopViewControllerForceRedraw(controller_);
34+
}
35+
3236
std::optional<LRESULT> FlutterViewController::HandleTopLevelWindowProc(
3337
HWND hwnd,
3438
UINT message,

shell/platform/windows/client_wrapper/flutter_view_controller_unittests.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ class TestWindowsApi : public testing::StubFlutterWindowsApi {
2727
// |flutter::testing::StubFlutterWindowsApi|
2828
void ViewControllerDestroy() override { view_controller_destroyed_ = true; }
2929

30+
// |flutter::testing::StubFlutterWindowsApi|
31+
void ViewControllerForceRedraw() override {
32+
view_controller_force_redrawed_ = true;
33+
}
34+
3035
// |flutter::testing::StubFlutterWindowsApi|
3136
FlutterDesktopEngineRef EngineCreate(
3237
const FlutterDesktopEngineProperties& engine_properties) override {
@@ -41,10 +46,14 @@ class TestWindowsApi : public testing::StubFlutterWindowsApi {
4146

4247
bool engine_destroyed() { return engine_destroyed_; }
4348
bool view_controller_destroyed() { return view_controller_destroyed_; }
49+
bool view_controller_force_redrawed() {
50+
return view_controller_force_redrawed_;
51+
}
4452

4553
private:
4654
bool engine_destroyed_ = false;
4755
bool view_controller_destroyed_ = false;
56+
bool view_controller_force_redrawed_ = false;
4857
};
4958

5059
} // namespace
@@ -79,4 +88,15 @@ TEST(FlutterViewControllerTest, GetView) {
7988
EXPECT_NE(controller.view(), nullptr);
8089
}
8190

91+
TEST(FlutterViewControllerTest, ForceRedraw) {
92+
DartProject project(L"data");
93+
testing::ScopedStubFlutterWindowsApi scoped_api_stub(
94+
std::make_unique<TestWindowsApi>());
95+
auto test_api = static_cast<TestWindowsApi*>(scoped_api_stub.stub());
96+
FlutterViewController controller(100, 100, project);
97+
98+
controller.ForceRedraw();
99+
EXPECT_TRUE(test_api->view_controller_force_redrawed());
100+
}
101+
82102
} // namespace flutter

shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ class FlutterViewController {
4444
// Returns the view managed by this controller.
4545
FlutterView* view() { return view_.get(); }
4646

47+
// Requests new frame from the engine and repaints the view.
48+
void ForceRedraw();
49+
4750
// Allows the Flutter engine and any interested plugins an opportunity to
4851
// handle the given message.
4952
//

shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,11 @@ FlutterDesktopViewRef FlutterDesktopViewControllerGetView(
6565
}
6666

6767
void FlutterDesktopViewControllerForceRedraw(
68-
FlutterDesktopViewControllerRef controller) {}
68+
FlutterDesktopViewControllerRef controller) {
69+
if (s_stub_implementation) {
70+
s_stub_implementation->ViewControllerForceRedraw();
71+
}
72+
}
6973

7074
bool FlutterDesktopViewControllerHandleTopLevelWindowProc(
7175
FlutterDesktopViewControllerRef controller,

shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ class StubFlutterWindowsApi {
3838
// Called for FlutterDesktopViewControllerDestroy.
3939
virtual void ViewControllerDestroy() {}
4040

41+
// Called for FlutterDesktopViewControllerForceRedraw.
42+
virtual void ViewControllerForceRedraw() {}
43+
4144
// Called for FlutterDesktopViewControllerHandleTopLevelWindowProc.
4245
virtual bool ViewControllerHandleTopLevelWindowProc(HWND hwnd,
4346
UINT message,

shell/platform/windows/public/flutter_windows.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ FLUTTER_EXPORT FlutterDesktopEngineRef FlutterDesktopViewControllerGetEngine(
107107
FLUTTER_EXPORT FlutterDesktopViewRef
108108
FlutterDesktopViewControllerGetView(FlutterDesktopViewControllerRef controller);
109109

110-
// Requests new frame from engine and repaints the view
110+
// Requests new frame from the engine and repaints the view.
111111
FLUTTER_EXPORT void FlutterDesktopViewControllerForceRedraw(
112112
FlutterDesktopViewControllerRef controller);
113113

0 commit comments

Comments
 (0)