Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
host_window_dialog.cc
Go to the documentation of this file.
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
6
9
10namespace flutter {
11
12DWORD HostWindowDialog::GetWindowStyleForDialog(
13 std::optional<HWND> const& owner_window,
14 bool resizable) {
15 DWORD window_style = WS_OVERLAPPED | WS_CAPTION;
16 if (resizable) {
17 window_style |= WS_THICKFRAME;
18 }
19 if (!owner_window) {
20 // If the dialog has no owner, add a minimize box and a system menu.
21 window_style |= WS_MINIMIZEBOX | WS_SYSMENU;
22 }
23 return window_style;
24}
25
26DWORD HostWindowDialog::GetExtendedWindowStyleForDialog(
27 std::optional<HWND> const& owner_window) {
28 DWORD extended_window_style = WS_EX_DLGMODALFRAME;
29 if (owner_window) {
30 // If the owner window has WS_EX_TOOLWINDOW style, apply the same
31 // style to the dialog.
32 if (GetWindowLongPtr(*owner_window, GWL_EXSTYLE) & WS_EX_TOOLWINDOW) {
33 extended_window_style |= WS_EX_TOOLWINDOW;
34 }
35 }
36 return extended_window_style;
37}
38
41 const WindowSizeRequest& preferred_size,
42 const BoxConstraints& constraints,
43 LPCWSTR title,
44 std::optional<HWND> const& owner_window,
45 bool sized_to_content,
46 bool resizable)
47 : HostWindowSized(window_manager, engine, resizable) {
48 FML_CHECK(sized_to_content || preferred_size.has_preferred_view_size);
51 .window_style = GetWindowStyleForDialog(owner_window, resizable),
52 .extended_window_style = GetExtendedWindowStyleForDialog(owner_window),
53 .box_constraints = constraints,
54 .initial_window_rect =
55 GetInitialRect(engine, preferred_size, constraints, owner_window,
56 sized_to_content, resizable),
57 .title = title,
58 .owner_window = owner_window,
59 .sizing_delegate = sized_to_content ? AsSizingDelegate() : nullptr,
60 .is_sized_to_content = sized_to_content,
61 });
62
63 auto hwnd = window_handle_;
64 if (owner_window) {
65 if (HMENU hMenu = GetSystemMenu(hwnd, FALSE)) {
66 EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
67 }
68 }
69
70 if (owner_window) {
71 UpdateModalState();
72 }
73}
74
75Rect HostWindowDialog::GetInitialRect(FlutterWindowsEngine* engine,
76 const WindowSizeRequest& preferred_size,
77 const BoxConstraints& constraints,
78 std::optional<HWND> const& owner_window,
79 bool sized_to_content,
80 bool resizable) {
81 auto const window_style = GetWindowStyleForDialog(owner_window, resizable);
82 auto const extended_window_style =
83 GetExtendedWindowStyleForDialog(owner_window);
84
85 double client_width;
86 double client_height;
87 if (sized_to_content) {
88 // Use the minimum constraint as the initial window size. The window will
89 // be resized to match the rendered content after the first frame.
90 client_width = std::max(1.0, constraints.smallest().width());
91 client_height = std::max(1.0, constraints.smallest().height());
92 } else {
93 client_width = preferred_size.preferred_view_width;
94 client_height = preferred_size.preferred_view_height;
95 }
96
97 std::optional<Size> const window_size =
99 *engine->windows_proc_table(), Size(client_width, client_height),
100 constraints.smallest(), constraints.biggest(), window_style,
101 extended_window_style, owner_window);
102
103 Point window_origin = {CW_USEDEFAULT, CW_USEDEFAULT};
104 if (!sized_to_content && owner_window && window_size.has_value()) {
105 // Center dialog in the owner's frame.
106 RECT frame;
107 DwmGetWindowAttribute(*owner_window, DWMWA_EXTENDED_FRAME_BOUNDS, &frame,
108 sizeof(frame));
109 window_origin = {(frame.left + frame.right - window_size->width()) * 0.5,
110 (frame.top + frame.bottom - window_size->height()) * 0.5};
111 }
112
113 return {window_origin,
114 window_size ? *window_size : Size{CW_USEDEFAULT, CW_USEDEFAULT}};
115}
116
119 WPARAM wparam,
120 LPARAM lparam) {
121 switch (message) {
122 case WM_DESTROY:
123 is_being_destroyed_ = true;
124 if (HostWindow* const owner_window = GetOwnerWindow()) {
125 UpdateModalState();
126 FocusRootViewOf(owner_window);
127 }
128 break;
129
130 case WM_ACTIVATE:
131 // Forward the message to Dart before handling it on the C++ side.
132 // This ensures that Dart-side handlers (e.g. popup dismiss logic)
133 // can observe activation changes caused by dialog windows.
134 if (auto const result =
136 window_handle_, message, wparam, lparam)) {
137 return *result;
138 }
139
140 if (LOWORD(wparam) != WA_INACTIVE) {
141 // Prevent disabled window from being activated using the task
142 // switcher.
143 if (!IsWindowEnabled(hwnd)) {
144 // Redirect focus and activation to the first enabled descendant.
145 if (HostWindow* enabled_descendant = FindFirstEnabledDescendant()) {
146 SetActiveWindow(enabled_descendant->GetWindowHandle());
147 FocusRootViewOf(this);
148 }
149 return 0;
150 }
151 FocusRootViewOf(this);
152 }
153 return 0;
154 }
155
156 return HostWindow::HandleMessage(hwnd, message, wparam, lparam);
157}
158
159void HostWindowDialog::UpdateModalState() {
160 // Find the root window of the window hierarchy and process
161 // modal state update for the entire branch.
162 HostWindow* root = this;
163 while (HostWindow* const owner = root->GetOwnerWindow()) {
164 root = owner;
165 }
166 root->UpdateModalStateLayer();
167}
168
170 bool fullscreen,
171 std::optional<FlutterEngineDisplayId> display_id) {}
172
174 return false;
175}
176
177} // namespace flutter
Size smallest() const
Definition geometry.h:94
Size biggest() const
Definition geometry.h:93
WindowProcDelegateManager * window_proc_delegate_manager()
bool GetFullscreen() const override
void SetFullscreen(bool fullscreen, std::optional< FlutterEngineDisplayId > display_id) override
LRESULT HandleMessage(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) override
HostWindowDialog(WindowManager *window_manager, FlutterWindowsEngine *engine, const WindowSizeRequest &preferred_size, const BoxConstraints &constraints, LPCWSTR title, std::optional< HWND > const &owner_window, bool sized_to_content, bool resizable)
void InitializeFlutterView(HostWindowInitializationParams const &params)
HostWindow * GetOwnerWindow() const
static void FocusRootViewOf(HostWindow *window)
FlutterWindowsEngine * engine_
virtual LRESULT HandleMessage(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
static std::optional< Size > GetWindowSizeForClientSize(WindowsProcTable const &win32, Size const &client_size, std::optional< Size > smallest, std::optional< Size > biggest, DWORD window_style, DWORD extended_window_style, std::optional< HWND > const &owner_hwnd)
HostWindow * FindFirstEnabledDescendant() const
FlutterWindowsViewSizingDelegate * AsSizingDelegate()
double height() const
Definition geometry.h:45
double width() const
Definition geometry.h:44
std::optional< LRESULT > OnTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) const
FlutterEngine engine
Definition main.cc:84
const char * message
#define FML_CHECK(condition)
Definition logging.h:104
TPoint< Scalar > Point
Definition point.h:426
TSize< Scalar > Size
Definition size.h:159
LONG_PTR LRESULT
unsigned int UINT
LONG_PTR LPARAM
UINT_PTR WPARAM
unsigned long DWORD