Skip to content

Commit 3142352

Browse files
authored
Merge pull request flutter#3 from canonical/multi-window
Adds support for multiple regular windows and popups to the Windows embedder
2 parents 207f088 + 2d96bda commit 3142352

17 files changed

+1745
-47
lines changed

lib/ui/window/pointer_data_packet_converter.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ void PointerDataPacketConverter::ConvertPointerData(
7474
break;
7575
}
7676
case PointerData::Change::kAdd: {
77+
states_.erase(pointer_data.device);
7778
FML_DCHECK(states_.find(pointer_data.device) == states_.end());
7879
EnsurePointerState(pointer_data);
7980
converted_pointers.push_back(pointer_data);
@@ -82,6 +83,8 @@ void PointerDataPacketConverter::ConvertPointerData(
8283
case PointerData::Change::kRemove: {
8384
// Makes sure we have an existing pointer
8485
auto iter = states_.find(pointer_data.device);
86+
if (iter == states_.end())
87+
break;
8588
FML_DCHECK(iter != states_.end());
8689
PointerState state = iter->second;
8790

shell/platform/windows/client_wrapper/BUILD.gn

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,18 @@ _wrapper_includes = [
1111
"include/flutter/flutter_engine.h",
1212
"include/flutter/flutter_view_controller.h",
1313
"include/flutter/flutter_view.h",
14+
"include/flutter/flutter_win32_window.h",
15+
"include/flutter/flutter_window_controller.h",
1416
"include/flutter/plugin_registrar_windows.h",
17+
"include/flutter/win32_window.h",
1518
]
1619

1720
_wrapper_sources = [
1821
"flutter_engine.cc",
1922
"flutter_view_controller.cc",
23+
"flutter_win32_window.cc",
24+
"flutter_window_controller.cc",
25+
"win32_window.cc",
2026
]
2127

2228
# This code will be merged into .../common/client_wrapper for client use,
@@ -40,6 +46,8 @@ source_set("client_wrapper_windows") {
4046
"//flutter/shell/platform/windows:flutter_windows_headers",
4147
]
4248

49+
libs = [ "dwmapi.lib" ]
50+
4351
configs +=
4452
[ "//flutter/shell/platform/common:desktop_library_implementation" ]
4553

@@ -110,6 +118,9 @@ client_wrapper_file_archive_list = [
110118
win_client_wrapper_file_archive_list = [
111119
"flutter_engine.cc",
112120
"flutter_view_controller.cc",
121+
"flutter_win32_window.cc",
122+
"flutter_window_controller.cc",
123+
"win32_window.cc",
113124
]
114125

115126
zip_bundle("client_wrapper_archive") {

shell/platform/windows/client_wrapper/flutter_engine.cc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ bool FlutterEngine::Run(const char* entry_point) {
6363
}
6464

6565
void FlutterEngine::ShutDown() {
66-
if (engine_ && owns_engine_) {
66+
if (engine_) {
6767
FlutterDesktopEngineDestroy(engine_);
6868
}
6969
engine_ = nullptr;
@@ -113,8 +113,7 @@ std::optional<LRESULT> FlutterEngine::ProcessExternalWindowMessage(
113113
return std::nullopt;
114114
}
115115

116-
FlutterDesktopEngineRef FlutterEngine::RelinquishEngine() {
117-
owns_engine_ = false;
116+
FlutterDesktopEngineRef FlutterEngine::engine() const {
118117
return engine_;
119118
}
120119

shell/platform/windows/client_wrapper/flutter_view_controller.cc

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,22 @@ namespace flutter {
1111

1212
FlutterViewController::FlutterViewController(int width,
1313
int height,
14-
const DartProject& project) {
15-
engine_ = std::make_shared<FlutterEngine>(project);
16-
controller_ = FlutterDesktopViewControllerCreate(width, height,
17-
engine_->RelinquishEngine());
14+
const DartProject& project)
15+
: FlutterViewController(width,
16+
height,
17+
std::make_shared<FlutterEngine>(project)) {}
18+
19+
FlutterViewController::FlutterViewController(
20+
int width,
21+
int height,
22+
std::shared_ptr<FlutterEngine> engine) {
23+
FlutterDesktopViewControllerProperties properties = {};
24+
properties.width = width;
25+
properties.height = height;
26+
27+
engine_ = std::move(engine);
28+
controller_ =
29+
FlutterDesktopEngineCreateViewController(engine_->engine(), &properties);
1830
if (!controller_) {
1931
std::cerr << "Failed to create view controller." << std::endl;
2032
return;

shell/platform/windows/client_wrapper/flutter_view_controller_unittests.cc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,8 @@ namespace {
1717
class TestWindowsApi : public testing::StubFlutterWindowsApi {
1818
public:
1919
// |flutter::testing::StubFlutterWindowsApi|
20-
FlutterDesktopViewControllerRef ViewControllerCreate(
21-
int width,
22-
int height,
23-
FlutterDesktopEngineRef engine) override {
20+
FlutterDesktopViewControllerRef EngineCreateViewController(
21+
const FlutterDesktopViewControllerProperties* properties) override {
2422
return reinterpret_cast<FlutterDesktopViewControllerRef>(2);
2523
}
2624

@@ -63,11 +61,13 @@ TEST(FlutterViewControllerTest, CreateDestroy) {
6361
testing::ScopedStubFlutterWindowsApi scoped_api_stub(
6462
std::make_unique<TestWindowsApi>());
6563
auto test_api = static_cast<TestWindowsApi*>(scoped_api_stub.stub());
64+
65+
// Create and destroy a view controller.
66+
// This should also create and destroy an engine.
6667
{ FlutterViewController controller(100, 100, project); }
68+
6769
EXPECT_TRUE(test_api->view_controller_destroyed());
68-
// Per the C API, once a view controller has taken ownership of an engine
69-
// the engine destruction method should not be called.
70-
EXPECT_FALSE(test_api->engine_destroyed());
70+
EXPECT_TRUE(test_api->engine_destroyed());
7171
}
7272

7373
TEST(FlutterViewControllerTest, GetViewId) {
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#include "include/flutter/flutter_win32_window.h"
2+
3+
#include "include/flutter/encodable_value.h"
4+
#include "include/flutter/flutter_window_controller.h"
5+
6+
#include <windows.h>
7+
8+
namespace flutter {
9+
10+
FlutterWin32Window::FlutterWin32Window(std::shared_ptr<FlutterEngine> engine)
11+
: engine_(std::move(engine)) {}
12+
13+
auto FlutterWin32Window::flutter_controller()
14+
-> std::unique_ptr<FlutterViewController> const& {
15+
return flutter_controller_;
16+
}
17+
18+
bool FlutterWin32Window::OnCreate() {
19+
if (!Win32Window::OnCreate()) {
20+
return false;
21+
}
22+
23+
RECT const frame = GetClientArea();
24+
25+
// The size here must match the window dimensions to avoid unnecessary surface
26+
// creation / destruction in the startup path.
27+
flutter_controller_ = std::make_unique<FlutterViewController>(
28+
frame.right - frame.left, frame.bottom - frame.top, engine_);
29+
// Ensure that basic setup of the controller was successful.
30+
if (!flutter_controller_->view()) {
31+
return false;
32+
}
33+
34+
SetChildContent(flutter_controller_->view()->GetNativeWindow());
35+
36+
// TODO(loicsharma): Hide the window until the first frame is rendered.
37+
// Single window apps use the engine's next frame callback to show the window.
38+
// This doesn't work for multi window apps as the engine cannot have multiple
39+
// next frame callbacks. If multiple windows are created, only the last one
40+
// will be shown.
41+
return true;
42+
}
43+
44+
void FlutterWin32Window::OnDestroy() {
45+
if (flutter_controller_) {
46+
FlutterWindowController::instance().destroyWindow(
47+
flutter_controller_->view_id(), false);
48+
if (flutter_controller_) {
49+
flutter_controller_ = nullptr;
50+
}
51+
}
52+
53+
Win32Window::OnDestroy();
54+
}
55+
56+
LRESULT
57+
FlutterWin32Window::MessageHandler(HWND hwnd,
58+
UINT const message,
59+
WPARAM const wparam,
60+
LPARAM const lparam) {
61+
// Give Flutter, including plugins, an opportunity to handle window messages.
62+
if (flutter_controller_) {
63+
std::optional<LRESULT> result =
64+
flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
65+
lparam);
66+
if (result) {
67+
return *result;
68+
}
69+
}
70+
71+
switch (message) {
72+
case WM_FONTCHANGE:
73+
engine_->ReloadSystemFonts();
74+
break;
75+
case WM_SIZE:
76+
if (flutter_controller_) {
77+
FlutterWindowController::instance().sendOnWindowResized(
78+
flutter_controller_->view_id());
79+
}
80+
break;
81+
default:
82+
break;
83+
}
84+
85+
return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
86+
}
87+
88+
} // namespace flutter

0 commit comments

Comments
 (0)