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

Commit 94b535a

Browse files
committed
[Windows] Don't always stop engine on view destruction
1 parent 5fc95a3 commit 94b535a

10 files changed

Lines changed: 81 additions & 13 deletions

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41819,6 +41819,7 @@ ORIGIN: ../../../flutter/shell/platform/windows/flutter_windows_texture_registra
4181941819
ORIGIN: ../../../flutter/shell/platform/windows/flutter_windows_texture_registrar.h + ../../../flutter/LICENSE
4182041820
ORIGIN: ../../../flutter/shell/platform/windows/flutter_windows_view.cc + ../../../flutter/LICENSE
4182141821
ORIGIN: ../../../flutter/shell/platform/windows/flutter_windows_view.h + ../../../flutter/LICENSE
41822+
ORIGIN: ../../../flutter/shell/platform/windows/flutter_windows_view_controller.cc + ../../../flutter/LICENSE
4182241823
ORIGIN: ../../../flutter/shell/platform/windows/flutter_windows_view_controller.h + ../../../flutter/LICENSE
4182341824
ORIGIN: ../../../flutter/shell/platform/windows/keyboard_handler_base.h + ../../../flutter/LICENSE
4182441825
ORIGIN: ../../../flutter/shell/platform/windows/keyboard_key_channel_handler.cc + ../../../flutter/LICENSE
@@ -44723,6 +44724,7 @@ FILE: ../../../flutter/shell/platform/windows/flutter_windows_texture_registrar.
4472344724
FILE: ../../../flutter/shell/platform/windows/flutter_windows_texture_registrar.h
4472444725
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.cc
4472544726
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.h
44727+
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view_controller.cc
4472644728
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view_controller.h
4472744729
FILE: ../../../flutter/shell/platform/windows/keyboard_handler_base.h
4472844730
FILE: ../../../flutter/shell/platform/windows/keyboard_key_channel_handler.cc

shell/platform/windows/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ source_set("flutter_windows_source") {
8787
"flutter_windows_texture_registrar.h",
8888
"flutter_windows_view.cc",
8989
"flutter_windows_view.h",
90+
"flutter_windows_view_controller.cc",
9091
"flutter_windows_view_controller.h",
9192
"keyboard_handler_base.h",
9293
"keyboard_key_channel_handler.cc",

shell/platform/windows/flutter_windows.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ FlutterDesktopViewControllerRef FlutterDesktopEngineCreateViewController(
130130

131131
void FlutterDesktopViewControllerDestroy(FlutterDesktopViewControllerRef ref) {
132132
auto controller = ViewControllerFromHandle(ref);
133+
controller->Destroy();
134+
133135
delete controller;
134136
}
135137

shell/platform/windows/flutter_windows_engine.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,24 @@ std::unique_ptr<FlutterWindowsView> FlutterWindowsEngine::CreateView(
502502
return std::move(view);
503503
}
504504

505+
void FlutterWindowsEngine::RemoveView(FlutterViewId view_id) {
506+
FML_DCHECK(running());
507+
FML_DCHECK(views_.find(view_id) != views_.end());
508+
509+
if (view_id == kImplicitViewId) {
510+
// The engine and framework assume the implicit view always exists.
511+
// Attempts to render to the implicit view will be ignored.
512+
views_.erase(view_id);
513+
return;
514+
}
515+
516+
// TODO(loicsharma): Remove the view from the engine using the
517+
// `FlutterEngineRemoveView` embedder API. Windows does not
518+
// support views other than the implicit view yet.
519+
// https://github.com/flutter/flutter/issues/144810
520+
FML_UNREACHABLE();
521+
}
522+
505523
void FlutterWindowsEngine::OnVsync(intptr_t baton) {
506524
std::chrono::nanoseconds current_time =
507525
std::chrono::nanoseconds(embedder_api_.GetCurrentTime());

shell/platform/windows/flutter_windows_engine.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ class FlutterWindowsEngine {
124124
std::unique_ptr<FlutterWindowsView> CreateView(
125125
std::unique_ptr<WindowBindingHandler> window);
126126

127+
// Remove a view. The engine will no longer render into it.
128+
virtual void RemoveView(FlutterViewId view_id);
129+
127130
// Get a view that displays this engine's content.
128131
//
129132
// Returns null if the view does not exist.

shell/platform/windows/flutter_windows_unittests.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ TEST_F(WindowsTest, EngineCanTransitionToHeadless) {
139139

140140
// The engine is back in headless mode now.
141141
ASSERT_NE(engine, nullptr);
142+
143+
auto engine_ptr = reinterpret_cast<FlutterWindowsEngine*>(engine.get());
144+
ASSERT_TRUE(engine_ptr->running());
142145
}
143146

144147
// Verify that accessibility features are initialized when a view is created.

shell/platform/windows/flutter_windows_view.cc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,6 @@ FlutterWindowsView::~FlutterWindowsView() {
105105
// Notify the engine the view's child window will no longer be visible.
106106
engine_->OnWindowStateEvent(GetWindowHandle(), WindowStateEvent::kHide);
107107

108-
// The engine renders into the view's surface. The engine must be
109-
// shutdown before the view's resources can be destroyed.
110-
engine_->Stop();
111-
112108
DestroyRenderSurface();
113109
}
114110

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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/flutter_windows_view_controller.h"
6+
7+
namespace flutter {
8+
9+
FlutterWindowsViewController::~FlutterWindowsViewController() {
10+
Destroy();
11+
}
12+
13+
void FlutterWindowsViewController::Destroy() {
14+
if (!view_) {
15+
return;
16+
}
17+
18+
// Prevent the engine from rendering into this view.
19+
if (view_->GetEngine()->running()) {
20+
auto view_id = view_->view_id();
21+
22+
view_->GetEngine()->RemoveView(view_id);
23+
}
24+
25+
// Destroy the view, followed by the engine if it is owned by this controller.
26+
view_.reset();
27+
engine_.reset();
28+
}
29+
30+
} // namespace flutter

shell/platform/windows/flutter_windows_view_controller.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77

88
#include <memory>
99

10-
#include "flutter_windows_engine.h"
11-
#include "flutter_windows_view.h"
10+
#include "flutter/fml/macros.h"
11+
#include "flutter/shell/platform/windows/flutter_windows_engine.h"
12+
#include "flutter/shell/platform/windows/flutter_windows_view.h"
1213

1314
namespace flutter {
1415

@@ -19,6 +20,13 @@ class FlutterWindowsViewController {
1920
std::unique_ptr<FlutterWindowsView> view)
2021
: engine_(std::move(engine)), view_(std::move(view)) {}
2122

23+
~FlutterWindowsViewController();
24+
25+
// Destroy this view controller and its view.
26+
//
27+
// If this view controller owns the engine, the engine is also destroyed.
28+
void Destroy();
29+
2230
FlutterWindowsEngine* engine() { return view_->GetEngine(); }
2331
FlutterWindowsView* view() { return view_.get(); }
2432

@@ -36,6 +44,8 @@ class FlutterWindowsViewController {
3644
std::unique_ptr<FlutterWindowsEngine> engine_;
3745

3846
std::unique_ptr<FlutterWindowsView> view_;
47+
48+
FML_DISALLOW_COPY_AND_ASSIGN(FlutterWindowsViewController);
3949
};
4050

4151
} // namespace flutter

shell/platform/windows/flutter_windows_view_unittests.cc

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "flutter/shell/platform/windows/flutter_window.h"
1919
#include "flutter/shell/platform/windows/flutter_windows_engine.h"
2020
#include "flutter/shell/platform/windows/flutter_windows_texture_registrar.h"
21+
#include "flutter/shell/platform/windows/flutter_windows_view_controller.h"
2122
#include "flutter/shell/platform/windows/testing/egl/mock_context.h"
2223
#include "flutter/shell/platform/windows/testing/egl/mock_manager.h"
2324
#include "flutter/shell/platform/windows/testing/egl/mock_window_surface.h"
@@ -121,6 +122,7 @@ class MockFlutterWindowsEngine : public FlutterWindowsEngine {
121122

122123
MOCK_METHOD(bool, running, (), (const));
123124
MOCK_METHOD(bool, Stop, (), ());
125+
MOCK_METHOD(void, RemoveView, (FlutterViewId view_id), ());
124126
MOCK_METHOD(bool, PostRasterThreadTask, (fml::closure), (const));
125127

126128
private:
@@ -241,6 +243,8 @@ TEST(FlutterWindowsViewTest, Shutdown) {
241243
std::make_unique<NiceMock<MockWindowBindingHandler>>();
242244
auto egl_manager = std::make_unique<egl::MockManager>();
243245
auto surface = std::make_unique<egl::MockWindowSurface>();
246+
247+
auto engine_ptr = engine.get();
244248
auto surface_ptr = surface.get();
245249

246250
EngineModifier modifier{engine.get()};
@@ -250,12 +254,16 @@ TEST(FlutterWindowsViewTest, Shutdown) {
250254
std::unique_ptr<FlutterWindowsView> view =
251255
engine->CreateView(std::move(window_binding_handler));
252256

257+
auto view_id = view->view_id();
253258
ViewModifier view_modifier{view.get()};
254259
view_modifier.SetSurface(std::move(surface));
255260

256-
// The engine must be stopped before the surface can be destroyed.
261+
FlutterWindowsViewController controller{std::move(engine), std::move(view)};
262+
263+
// The view must be removed before the surface can be destroyed.
257264
InSequence s;
258-
EXPECT_CALL(*engine.get(), Stop).Times(1);
265+
EXPECT_CALL(*engine_ptr, running).WillOnce(Return(true));
266+
EXPECT_CALL(*engine_ptr, RemoveView(view_id)).Times(1);
259267
EXPECT_CALL(*surface_ptr, Destroy).Times(1);
260268
}
261269
}
@@ -1392,7 +1400,6 @@ TEST(FlutterWindowsViewTest, DisablesVSyncAtStartup) {
13921400
EXPECT_CALL(*surface_ptr, SetVSyncEnabled(false)).WillOnce(Return(true));
13931401
EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(true));
13941402

1395-
EXPECT_CALL(*engine.get(), Stop).Times(1);
13961403
EXPECT_CALL(*surface_ptr, Destroy).Times(1);
13971404

13981405
EngineModifier modifier{engine.get()};
@@ -1430,7 +1437,6 @@ TEST(FlutterWindowsViewTest, EnablesVSyncAtStartup) {
14301437
EXPECT_CALL(*surface_ptr, SetVSyncEnabled(true)).WillOnce(Return(true));
14311438
EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(true));
14321439

1433-
EXPECT_CALL(*engine.get(), Stop).Times(1);
14341440
EXPECT_CALL(*surface_ptr, Destroy).Times(1);
14351441

14361442
EngineModifier modifier{engine.get()};
@@ -1471,7 +1477,6 @@ TEST(FlutterWindowsViewTest, DisablesVSyncAfterStartup) {
14711477
EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(true));
14721478
EXPECT_CALL(*surface_ptr, SetVSyncEnabled(false)).WillOnce(Return(true));
14731479
EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(true));
1474-
EXPECT_CALL(*engine.get(), Stop).Times(1);
14751480
EXPECT_CALL(*surface_ptr, Destroy).Times(1);
14761481

14771482
EngineModifier modifier{engine.get()};
@@ -1514,7 +1519,6 @@ TEST(FlutterWindowsViewTest, EnablesVSyncAfterStartup) {
15141519
EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(true));
15151520
EXPECT_CALL(*surface_ptr, SetVSyncEnabled(true)).WillOnce(Return(true));
15161521
EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(true));
1517-
EXPECT_CALL(*engine.get(), Stop).Times(1);
15181522
EXPECT_CALL(*surface_ptr, Destroy).Times(1);
15191523

15201524
EngineModifier modifier{engine.get()};
@@ -1563,7 +1567,6 @@ TEST(FlutterWindowsViewTest, UpdatesVSyncOnDwmUpdates) {
15631567
EXPECT_CALL(*surface_ptr, SetVSyncEnabled(false)).WillOnce(Return(true));
15641568
EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(true));
15651569

1566-
EXPECT_CALL(*engine.get(), Stop).Times(1);
15671570
EXPECT_CALL(*surface_ptr, Destroy).Times(1);
15681571

15691572
EngineModifier engine_modifier{engine.get()};

0 commit comments

Comments
 (0)