Flutter Windows Embedder
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 
10 
11 namespace flutter {
12 
13 DWORD HostWindowDialog::GetWindowStyleForDialog(
14  std::optional<HWND> const& owner_window,
15  bool resizable) {
16  DWORD window_style = WS_OVERLAPPED | WS_CAPTION;
17  if (resizable) {
18  window_style |= WS_THICKFRAME;
19  }
20  if (!owner_window) {
21  // If the dialog has no owner, add a minimize box and a system menu.
22  window_style |= WS_MINIMIZEBOX | WS_SYSMENU;
23  }
24  return window_style;
25 }
26 
27 DWORD HostWindowDialog::GetExtendedWindowStyleForDialog(
28  std::optional<HWND> const& owner_window) {
29  DWORD extended_window_style = WS_EX_DLGMODALFRAME;
30  if (owner_window) {
31  // If the owner window has WS_EX_TOOLWINDOW style, apply the same
32  // style to the dialog.
33  if (GetWindowLongPtr(*owner_window, GWL_EXSTYLE) & WS_EX_TOOLWINDOW) {
34  extended_window_style |= WS_EX_TOOLWINDOW;
35  }
36  }
37  return extended_window_style;
38 }
39 
41  FlutterWindowsEngine* engine,
42  const WindowSizeRequest& preferred_size,
43  const BoxConstraints& constraints,
44  LPCWSTR title,
45  std::optional<HWND> const& owner_window,
46  bool sized_to_content,
47  bool resizable)
48  : HostWindowSized(window_manager, engine, resizable) {
49  FML_CHECK(sized_to_content || preferred_size.has_preferred_view_size);
52  .window_style = GetWindowStyleForDialog(owner_window, resizable),
53  .extended_window_style = GetExtendedWindowStyleForDialog(owner_window),
54  .box_constraints = constraints,
55  .initial_window_rect =
56  GetInitialRect(engine, preferred_size, constraints, owner_window,
57  sized_to_content, resizable),
58  .title = title,
59  .owner_window = owner_window,
60  .sizing_delegate = sized_to_content ? AsSizingDelegate() : nullptr,
61  .is_sized_to_content = sized_to_content,
62  });
63 
64  auto hwnd = window_handle_;
65  if (owner_window) {
66  if (HMENU hMenu = GetSystemMenu(hwnd, FALSE)) {
67  EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
68  }
69  }
70 
71  if (owner_window) {
72  UpdateModalState();
73  }
74 }
75 
77  // Reset the view while this most-derived object is still fully alive, to stop
78  // the raster thread from sizing it before any subobject is torn down. See the
79  // destructor comment in host_window_sized.h for the rationale.
80  view_controller_.reset();
81 }
82 
83 Rect HostWindowDialog::GetInitialRect(FlutterWindowsEngine* engine,
84  const WindowSizeRequest& preferred_size,
85  const BoxConstraints& constraints,
86  std::optional<HWND> const& owner_window,
87  bool sized_to_content,
88  bool resizable) {
89  auto const window_style = GetWindowStyleForDialog(owner_window, resizable);
90  auto const extended_window_style =
91  GetExtendedWindowStyleForDialog(owner_window);
92 
93  double client_width;
94  double client_height;
95  if (sized_to_content) {
96  // Use the minimum constraint as the initial window size. The window will
97  // be resized to match the rendered content after the first frame.
98  client_width = std::max(1.0, constraints.smallest().width());
99  client_height = std::max(1.0, constraints.smallest().height());
100  } else {
101  client_width = preferred_size.preferred_view_width;
102  client_height = preferred_size.preferred_view_height;
103  }
104 
105  std::optional<Size> const window_size =
107  *engine->windows_proc_table(), Size(client_width, client_height),
108  constraints.smallest(), constraints.biggest(), window_style,
109  extended_window_style, owner_window);
110 
111  Point window_origin = {CW_USEDEFAULT, CW_USEDEFAULT};
112  if (!sized_to_content && owner_window && window_size.has_value()) {
113  // Center dialog in the owner's frame.
114  RECT frame;
115  DwmGetWindowAttribute(*owner_window, DWMWA_EXTENDED_FRAME_BOUNDS, &frame,
116  sizeof(frame));
117  window_origin = {(frame.left + frame.right - window_size->width()) * 0.5,
118  (frame.top + frame.bottom - window_size->height()) * 0.5};
119  }
120 
121  return {window_origin,
122  window_size ? *window_size : Size{CW_USEDEFAULT, CW_USEDEFAULT}};
123 }
124 
126  UINT message,
127  WPARAM wparam,
128  LPARAM lparam) {
129  switch (message) {
130  case WM_DESTROY:
131  is_being_destroyed_ = true;
132  if (HostWindow* const owner_window = GetOwnerWindow()) {
133  UpdateModalState();
134  FocusRootViewOf(owner_window);
135  }
136  break;
137 
138  case WM_ACTIVATE:
139  // Forward the message to Dart before handling it on the C++ side.
140  // This ensures that Dart-side handlers (e.g. popup dismiss logic)
141  // can observe activation changes caused by dialog windows.
142  if (auto const result =
144  window_handle_, message, wparam, lparam)) {
145  return *result;
146  }
147 
148  HandleWindowActivation(hwnd, wparam);
149  return 0;
150  }
151 
152  return HostWindow::HandleMessage(hwnd, message, wparam, lparam);
153 }
154 
155 void HostWindowDialog::UpdateModalState() {
156  // Find the root window of the window hierarchy and process
157  // modal state update for the entire branch.
158  HostWindow* root = this;
159  while (HostWindow* const owner = root->GetOwnerWindow()) {
160  root = owner;
161  }
162  root->UpdateModalStateLayer();
163 }
164 
166  bool fullscreen,
167  std::optional<FlutterEngineDisplayId> display_id) {}
168 
170  return false;
171 }
172 
173 } // namespace flutter
std::shared_ptr< WindowsProcTable > windows_proc_table()
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)
Definition: host_window.cc:232
void HandleWindowActivation(HWND hwnd, WPARAM wparam)
Definition: host_window.cc:356
std::unique_ptr< FlutterWindowsViewController > view_controller_
Definition: host_window.h:259
HostWindow * GetOwnerWindow() const
Definition: host_window.cc:843
void UpdateModalStateLayer()
Definition: host_window.cc:859
static void FocusRootViewOf(HostWindow *window)
Definition: host_window.cc:349
FlutterWindowsEngine * engine_
Definition: host_window.h:254
virtual LRESULT HandleMessage(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
Definition: host_window.cc:396
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)
Definition: host_window.cc:751
FlutterWindowsViewSizingDelegate * AsSizingDelegate()
std::optional< LRESULT > OnTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) const
Win32Message message