Flutter Windows Embedder
flutter::HostWindow Class Reference

#include <host_window.h>

Inheritance diagram for flutter::HostWindow:
flutter::HostWindowDialog flutter::HostWindowRegular

Classes

struct  SavedWindowInfo
 

Public Member Functions

virtual ~HostWindow ()
 
HWND GetWindowHandle () const
 
void SetContentSize (const WindowSizeRequest &size)
 
void SetConstraints (const WindowConstraints &constraints)
 
virtual void SetFullscreen (bool fullscreen, std::optional< FlutterEngineDisplayId > display_id)
 
virtual bool GetFullscreen () const
 
HostWindowGetOwnerWindow () const
 
void UpdateModalStateLayer ()
 

Static Public Member Functions

static std::unique_ptr< HostWindowCreateRegularWindow (WindowManager *window_manager, FlutterWindowsEngine *engine, const WindowSizeRequest &preferred_size, const WindowConstraints &preferred_constraints, LPCWSTR title)
 
static std::unique_ptr< HostWindowCreateDialogWindow (WindowManager *window_manager, FlutterWindowsEngine *engine, const WindowSizeRequest &preferred_size, const WindowConstraints &preferred_constraints, LPCWSTR title, HWND parent)
 
static HostWindowGetThisFromHandle (HWND hwnd)
 
static ActualWindowSize GetWindowContentSize (HWND hwnd)
 

Protected Member Functions

 HostWindow (WindowManager *window_manager, FlutterWindowsEngine *engine, WindowArchetype archetype, DWORD window_style, DWORD extended_window_style, const BoxConstraints &box_constraints, Rect const initial_window_rect, LPCWSTR title, std::optional< HWND > const &owner_window)
 
virtual LRESULT HandleMessage (HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
 
void EnableRecursively (bool enable)
 
HostWindowFindFirstEnabledDescendant () const
 
std::vector< HostWindow * > GetOwnedWindows () const
 
void DisableRecursively ()
 
 FML_DISALLOW_COPY_AND_ASSIGN (HostWindow)
 

Static Protected Member Functions

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)
 
static void FocusRootViewOf (HostWindow *window)
 
static LRESULT WndProc (HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
 

Protected Attributes

friend WindowManager
 
WindowManager *const window_manager_ = nullptr
 
FlutterWindowsEngineengine_
 
std::unique_ptr< FlutterWindowsViewControllerview_controller_
 
WindowArchetype archetype_ = WindowArchetype::kRegular
 
HWND window_handle_
 
BoxConstraints box_constraints_
 
bool is_being_destroyed_ = false
 
bool is_fullscreen_ = false
 
SavedWindowInfo saved_window_info_
 
Microsoft::WRL::ComPtr< ITaskbarList2 > task_bar_list_
 

Detailed Description

Definition at line 27 of file host_window.h.

Constructor & Destructor Documentation

◆ ~HostWindow()

flutter::HostWindow::~HostWindow ( )
virtual

Definition at line 316 of file host_window.cc.

316  {
317  if (view_controller_) {
318  // Unregister the window class. Fail silently if other windows are still
319  // using the class, as only the last window can successfully unregister it.
320  if (!UnregisterClass(kWindowClassName, GetModuleHandle(nullptr))) {
321  // Clear the error state after the failed unregistration.
322  SetLastError(ERROR_SUCCESS);
323  }
324  }
325 }
std::unique_ptr< FlutterWindowsViewController > view_controller_
Definition: host_window.h:193

References view_controller_.

◆ HostWindow()

flutter::HostWindow::HostWindow ( WindowManager window_manager,
FlutterWindowsEngine engine,
WindowArchetype  archetype,
DWORD  window_style,
DWORD  extended_window_style,
const BoxConstraints &  box_constraints,
Rect const  initial_window_rect,
LPCWSTR  title,
std::optional< HWND > const &  owner_window 
)
protected

Definition at line 228 of file host_window.cc.

237  : window_manager_(window_manager),
238  engine_(engine),
239  archetype_(archetype),
240  box_constraints_(box_constraints) {
241  // Set up the view.
242  auto view_window = std::make_unique<FlutterWindow>(
243  initial_window_rect.width(), initial_window_rect.height(),
244  engine->display_manager(), engine->windows_proc_table());
245 
246  std::unique_ptr<FlutterWindowsView> view =
247  engine->CreateView(std::move(view_window));
248  FML_CHECK(view != nullptr);
249 
251  std::make_unique<FlutterWindowsViewController>(nullptr, std::move(view));
252  FML_CHECK(engine->running());
253  // The Windows embedder listens to accessibility updates using the
254  // view's HWND. The embedder's accessibility features may be stale if
255  // the app was in headless mode.
256  engine->UpdateAccessibilityFeatures();
257 
258  // Register the window class.
259  if (!IsClassRegistered(kWindowClassName)) {
260  auto const idi_app_icon = 101;
261  WNDCLASSEX window_class = {};
262  window_class.cbSize = sizeof(WNDCLASSEX);
263  window_class.style = CS_HREDRAW | CS_VREDRAW;
264  window_class.lpfnWndProc = HostWindow::WndProc;
265  window_class.hInstance = GetModuleHandle(nullptr);
266  window_class.hIcon =
267  LoadIcon(window_class.hInstance, MAKEINTRESOURCE(idi_app_icon));
268  if (!window_class.hIcon) {
269  window_class.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
270  }
271  window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
272  window_class.lpszClassName = kWindowClassName;
273 
274  FML_CHECK(RegisterClassEx(&window_class));
275  }
276 
277  // Create the native window.
278  window_handle_ = CreateWindowEx(
279  extended_window_style, kWindowClassName, title, window_style,
280  initial_window_rect.left(), initial_window_rect.top(),
281  initial_window_rect.width(), initial_window_rect.height(),
282  owner_window ? *owner_window : nullptr, nullptr, GetModuleHandle(nullptr),
283  engine->windows_proc_table().get());
284  FML_CHECK(window_handle_ != nullptr);
285 
286  // Adjust the window position so its origin aligns with the top-left corner
287  // of the window frame, not the window rectangle (which includes the
288  // drop-shadow). This adjustment must be done post-creation since the frame
289  // rectangle is only available after the window has been created.
290  RECT frame_rect;
291  DwmGetWindowAttribute(window_handle_, DWMWA_EXTENDED_FRAME_BOUNDS,
292  &frame_rect, sizeof(frame_rect));
293  RECT window_rect;
294  GetWindowRect(window_handle_, &window_rect);
295  LONG const left_dropshadow_width = frame_rect.left - window_rect.left;
296  LONG const top_dropshadow_height = window_rect.top - frame_rect.top;
297  SetWindowPos(window_handle_, nullptr,
298  window_rect.left - left_dropshadow_width,
299  window_rect.top - top_dropshadow_height, 0, 0,
300  SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
301 
302  UpdateTheme(window_handle_);
303 
304  SetChildContent(view_controller_->view()->GetWindowHandle(), window_handle_);
305 
306  // TODO(loicsharma): Hide the window until the first frame is rendered.
307  // Single window apps use the engine's next frame callback to show the
308  // window. This doesn't work for multi window apps as the engine cannot have
309  // multiple next frame callbacks. If multiple windows are created, only the
310  // last one will be shown.
311  ShowWindow(window_handle_, SW_SHOWNORMAL);
312  SetWindowLongPtr(window_handle_, GWLP_USERDATA,
313  reinterpret_cast<LONG_PTR>(this));
314 }
BoxConstraints box_constraints_
Definition: host_window.h:202
WindowArchetype archetype_
Definition: host_window.h:196
static LRESULT WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
Definition: host_window.cc:353
FlutterWindowsEngine * engine_
Definition: host_window.h:188
WindowManager *const window_manager_
Definition: host_window.h:185

Member Function Documentation

◆ CreateDialogWindow()

std::unique_ptr< HostWindow > flutter::HostWindow::CreateDialogWindow ( WindowManager window_manager,
FlutterWindowsEngine engine,
const WindowSizeRequest preferred_size,
const WindowConstraints preferred_constraints,
LPCWSTR  title,
HWND  parent 
)
static

Definition at line 215 of file host_window.cc.

221  {
222  return std::unique_ptr<HostWindow>(
223  new HostWindowDialog(window_manager, engine, preferred_size,
224  FromWindowConstraints(preferred_constraints), title,
225  parent ? parent : std::optional<HWND>()));
226 }

Referenced by flutter::WindowManager::CreateDialogWindow().

◆ CreateRegularWindow()

std::unique_ptr< HostWindow > flutter::HostWindow::CreateRegularWindow ( WindowManager window_manager,
FlutterWindowsEngine engine,
const WindowSizeRequest preferred_size,
const WindowConstraints preferred_constraints,
LPCWSTR  title 
)
static

Definition at line 204 of file host_window.cc.

209  {
210  return std::unique_ptr<HostWindow>(new HostWindowRegular(
211  window_manager, engine, preferred_size,
212  FromWindowConstraints(preferred_constraints), title));
213 }

Referenced by flutter::WindowManager::CreateRegularWindow().

◆ DisableRecursively()

void flutter::HostWindow::DisableRecursively ( )
protected

Definition at line 824 of file host_window.cc.

824  {
825  // Disable the window itself.
826  EnableWindow(window_handle_, false);
827 
828  for (HostWindow* const owned : GetOwnedWindows()) {
829  owned->DisableRecursively();
830  }
831 }
HostWindow(WindowManager *window_manager, FlutterWindowsEngine *engine, WindowArchetype archetype, DWORD window_style, DWORD extended_window_style, const BoxConstraints &box_constraints, Rect const initial_window_rect, LPCWSTR title, std::optional< HWND > const &owner_window)
Definition: host_window.cc:228
std::vector< HostWindow * > GetOwnedWindows() const
Definition: host_window.cc:794

References GetOwnedWindows(), and window_handle_.

◆ EnableRecursively()

void flutter::HostWindow::EnableRecursively ( bool  enable)
protected

Definition at line 772 of file host_window.cc.

772  {
773  EnableWindow(window_handle_, enable);
774 
775  for (HostWindow* const owned : GetOwnedWindows()) {
776  owned->EnableRecursively(enable);
777  }
778 }

References GetOwnedWindows(), and window_handle_.

◆ FindFirstEnabledDescendant()

HostWindow * flutter::HostWindow::FindFirstEnabledDescendant ( ) const
protected

Definition at line 780 of file host_window.cc.

780  {
781  if (IsWindowEnabled(window_handle_)) {
782  return const_cast<HostWindow*>(this);
783  }
784 
785  for (HostWindow* const owned : GetOwnedWindows()) {
786  if (HostWindow* const result = owned->FindFirstEnabledDescendant()) {
787  return result;
788  }
789  }
790 
791  return nullptr;
792 }

References FindFirstEnabledDescendant(), GetOwnedWindows(), and window_handle_.

Referenced by FindFirstEnabledDescendant(), and flutter::HostWindowDialog::HandleMessage().

◆ FML_DISALLOW_COPY_AND_ASSIGN()

flutter::HostWindow::FML_DISALLOW_COPY_AND_ASSIGN ( HostWindow  )
protected

◆ FocusRootViewOf()

void flutter::HostWindow::FocusRootViewOf ( HostWindow window)
staticprotected

Definition at line 346 of file host_window.cc.

346  {
347  auto child_content = window->view_controller_->view()->GetWindowHandle();
348  if (window != nullptr && child_content != nullptr) {
349  SetFocus(child_content);
350  }
351 };

References view_controller_.

Referenced by HandleMessage(), and flutter::HostWindowDialog::HandleMessage().

◆ GetFullscreen()

bool flutter::HostWindow::GetFullscreen ( ) const
virtual

Reimplemented in flutter::HostWindowDialog.

Definition at line 708 of file host_window.cc.

708  {
709  return is_fullscreen_;
710 }

References is_fullscreen_.

Referenced by InternalFlutterWindows_WindowManager_GetFullscreen(), SetConstraints(), SetContentSize(), and SetFullscreen().

◆ GetOwnedWindows()

std::vector< HostWindow * > flutter::HostWindow::GetOwnedWindows ( ) const
protected

Definition at line 794 of file host_window.cc.

794  {
795  std::vector<HostWindow*> owned_windows;
796  struct EnumData {
797  HWND owner_window_handle;
798  std::vector<HostWindow*>* owned_windows;
799  } data{window_handle_, &owned_windows};
800 
801  EnumWindows(
802  [](HWND hwnd, LPARAM lparam) -> BOOL {
803  auto* const data = reinterpret_cast<EnumData*>(lparam);
804  if (GetWindow(hwnd, GW_OWNER) == data->owner_window_handle) {
805  HostWindow* const window = GetThisFromHandle(hwnd);
806  if (window && !window->is_being_destroyed_) {
807  data->owned_windows->push_back(window);
808  }
809  }
810  return TRUE;
811  },
812  reinterpret_cast<LPARAM>(&data));
813 
814  return owned_windows;
815 }
static HostWindow * GetThisFromHandle(HWND hwnd)
Definition: host_window.cc:327

References GetThisFromHandle(), is_being_destroyed_, and window_handle_.

Referenced by DisableRecursively(), EnableRecursively(), FindFirstEnabledDescendant(), and UpdateModalStateLayer().

◆ GetOwnerWindow()

HostWindow * flutter::HostWindow::GetOwnerWindow ( ) const

Definition at line 817 of file host_window.cc.

817  {
818  if (HWND const owner_window_handle = GetWindow(GetWindowHandle(), GW_OWNER)) {
819  return GetThisFromHandle(owner_window_handle);
820  }
821  return nullptr;
822 };
HWND GetWindowHandle() const
Definition: host_window.cc:342

References GetThisFromHandle(), and GetWindowHandle().

Referenced by flutter::HostWindowDialog::HandleMessage(), and flutter::testing::TEST_F().

◆ GetThisFromHandle()

HostWindow * flutter::HostWindow::GetThisFromHandle ( HWND  hwnd)
static

Definition at line 327 of file host_window.cc.

327  {
328  wchar_t class_name[256];
329  if (!GetClassName(hwnd, class_name, sizeof(class_name) / sizeof(wchar_t))) {
330  FML_LOG(ERROR) << "Failed to get class name for window handle " << hwnd
331  << ": " << GetLastErrorAsString();
332  return nullptr;
333  }
334  // Ignore window handles that do not match the expected class name.
335  if (wcscmp(class_name, kWindowClassName) != 0) {
336  return nullptr;
337  }
338 
339  return reinterpret_cast<HostWindow*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
340 }

Referenced by GetOwnedWindows(), GetOwnerWindow(), InternalFlutterWindows_WindowManager_GetFullscreen(), InternalFlutterWindows_WindowManager_SetFullscreen(), InternalFlutterWindows_WindowManager_SetWindowConstraints(), InternalFlutterWindows_WindowManager_SetWindowSize(), flutter::testing::TEST_F(), and WndProc().

◆ GetWindowContentSize()

ActualWindowSize flutter::HostWindow::GetWindowContentSize ( HWND  hwnd)
static

Definition at line 712 of file host_window.cc.

712  {
713  RECT rect;
714  GetClientRect(hwnd, &rect);
715  double const dpr = FlutterDesktopGetDpiForHWND(hwnd) /
716  static_cast<double>(USER_DEFAULT_SCREEN_DPI);
717  double const width = rect.right / dpr;
718  double const height = rect.bottom / dpr;
719  return {
720  .width = rect.right / dpr,
721  .height = rect.bottom / dpr,
722  };
723 }
UINT FlutterDesktopGetDpiForHWND(HWND hwnd)

References FlutterDesktopGetDpiForHWND().

Referenced by InternalFlutterWindows_WindowManager_GetWindowContentSize(), SetConstraints(), and SetFullscreen().

◆ GetWindowHandle()

HWND flutter::HostWindow::GetWindowHandle ( ) const

Definition at line 342 of file host_window.cc.

342  {
343  return window_handle_;
344 }

References window_handle_.

Referenced by GetOwnerWindow(), and flutter::testing::TEST_F().

◆ GetWindowSizeForClientSize()

std::optional< Size > flutter::HostWindow::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 
)
staticprotected

Definition at line 725 of file host_window.cc.

732  {
733  UINT const dpi = GetDpiForHWND(owner_hwnd ? *owner_hwnd : nullptr);
734  double const scale_factor =
735  static_cast<double>(dpi) / USER_DEFAULT_SCREEN_DPI;
736  RECT rect = {
737  .right = static_cast<LONG>(client_size.width() * scale_factor),
738  .bottom = static_cast<LONG>(client_size.height() * scale_factor)};
739 
740  if (!win32.AdjustWindowRectExForDpi(&rect, window_style, FALSE,
741  extended_window_style, dpi)) {
742  FML_LOG(ERROR) << "Failed to run AdjustWindowRectExForDpi: "
743  << GetLastErrorAsString();
744  return std::nullopt;
745  }
746 
747  double width = static_cast<double>(rect.right - rect.left);
748  double height = static_cast<double>(rect.bottom - rect.top);
749 
750  // Apply size constraints.
751  double const non_client_width = width - (client_size.width() * scale_factor);
752  double const non_client_height =
753  height - (client_size.height() * scale_factor);
754  if (smallest) {
755  flutter::Size min_physical_size = ClampToVirtualScreen(
756  flutter::Size(smallest->width() * scale_factor + non_client_width,
757  smallest->height() * scale_factor + non_client_height));
758  width = std::max(width, min_physical_size.width());
759  height = std::max(height, min_physical_size.height());
760  }
761  if (biggest) {
762  flutter::Size max_physical_size = ClampToVirtualScreen(
763  flutter::Size(biggest->width() * scale_factor + non_client_width,
764  biggest->height() * scale_factor + non_client_height));
765  width = std::min(width, max_physical_size.width());
766  height = std::min(height, max_physical_size.height());
767  }
768 
769  return flutter::Size{width, height};
770 }
UINT GetDpiForHWND(HWND hwnd)
Definition: dpi_utils.cc:128

References flutter::WindowsProcTable::AdjustWindowRectExForDpi(), and flutter::GetDpiForHWND().

Referenced by SetConstraints(), and SetContentSize().

◆ HandleMessage()

LRESULT flutter::HostWindow::HandleMessage ( HWND  hwnd,
UINT  message,
WPARAM  wparam,
LPARAM  lparam 
)
protectedvirtual

Reimplemented in flutter::HostWindowDialog.

Definition at line 370 of file host_window.cc.

373  {
375  window_handle_, message, wparam, lparam);
376  if (result) {
377  return *result;
378  }
379 
380  switch (message) {
381  case WM_DESTROY:
382  is_being_destroyed_ = true;
383  break;
384 
385  case WM_NCLBUTTONDOWN: {
386  // Fix for 500ms hang after user clicks on the title bar, but before
387  // moving mouse. Reference:
388  // https://gamedev.net/forums/topic/672094-keeping-things-moving-during-win32-moveresize-events/5254386/
389  if (SendMessage(window_handle_, WM_NCHITTEST, wparam, lparam) ==
390  HTCAPTION) {
391  POINT cursorPos;
392  // Get the current cursor position and synthesize WM_MOUSEMOVE to
393  // unblock default window proc implementation for WM_NCLBUTTONDOWN at
394  // HTCAPTION.
395  GetCursorPos(&cursorPos);
396  ScreenToClient(window_handle_, &cursorPos);
397  PostMessage(window_handle_, WM_MOUSEMOVE, 0,
398  MAKELPARAM(cursorPos.x, cursorPos.y));
399  }
400  break;
401  }
402 
403  case WM_DPICHANGED: {
404  auto* const new_scaled_window_rect = reinterpret_cast<RECT*>(lparam);
405  LONG const width =
406  new_scaled_window_rect->right - new_scaled_window_rect->left;
407  LONG const height =
408  new_scaled_window_rect->bottom - new_scaled_window_rect->top;
409  SetWindowPos(hwnd, nullptr, new_scaled_window_rect->left,
410  new_scaled_window_rect->top, width, height,
411  SWP_NOZORDER | SWP_NOACTIVATE);
412  return 0;
413  }
414 
415  case WM_GETMINMAXINFO: {
416  RECT window_rect;
417  GetWindowRect(hwnd, &window_rect);
418  RECT client_rect;
419  GetClientRect(hwnd, &client_rect);
420  LONG const non_client_width = (window_rect.right - window_rect.left) -
421  (client_rect.right - client_rect.left);
422  LONG const non_client_height = (window_rect.bottom - window_rect.top) -
423  (client_rect.bottom - client_rect.top);
424 
425  UINT const dpi = flutter::GetDpiForHWND(hwnd);
426  double const scale_factor =
427  static_cast<double>(dpi) / USER_DEFAULT_SCREEN_DPI;
428 
429  MINMAXINFO* info = reinterpret_cast<MINMAXINFO*>(lparam);
430  Size const min_physical_size = ClampToVirtualScreen(Size(
431  box_constraints_.smallest().width() * scale_factor + non_client_width,
432  box_constraints_.smallest().height() * scale_factor +
433  non_client_height));
434 
435  info->ptMinTrackSize.x = min_physical_size.width();
436  info->ptMinTrackSize.y = min_physical_size.height();
437  Size const max_physical_size = ClampToVirtualScreen(Size(
438  box_constraints_.biggest().width() * scale_factor + non_client_width,
439  box_constraints_.biggest().height() * scale_factor +
440  non_client_height));
441 
442  info->ptMaxTrackSize.x = max_physical_size.width();
443  info->ptMaxTrackSize.y = max_physical_size.height();
444  return 0;
445  }
446 
447  case WM_SIZE: {
448  auto child_content = view_controller_->view()->GetWindowHandle();
449  if (child_content != nullptr) {
450  // Resize and reposition the child content window.
451  RECT client_rect;
452  GetClientRect(hwnd, &client_rect);
453  MoveWindow(child_content, client_rect.left, client_rect.top,
454  client_rect.right - client_rect.left,
455  client_rect.bottom - client_rect.top, TRUE);
456  }
457  return 0;
458  }
459 
460  case WM_ACTIVATE:
461  FocusRootViewOf(this);
462  return 0;
463 
464  case WM_DWMCOLORIZATIONCOLORCHANGED:
465  UpdateTheme(hwnd);
466  return 0;
467 
468  default:
469  break;
470  }
471 
472  if (!view_controller_) {
473  return 0;
474  }
475 
476  return DefWindowProc(hwnd, message, wparam, lparam);
477 }
WindowProcDelegateManager * window_proc_delegate_manager()
static void FocusRootViewOf(HostWindow *window)
Definition: host_window.cc:346
std::optional< LRESULT > OnTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) const
Win32Message message

References box_constraints_, engine_, FocusRootViewOf(), flutter::GetDpiForHWND(), is_being_destroyed_, message, flutter::WindowProcDelegateManager::OnTopLevelWindowProc(), view_controller_, window_handle_, and flutter::FlutterWindowsEngine::window_proc_delegate_manager().

Referenced by flutter::HostWindowDialog::HandleMessage().

◆ SetConstraints()

void flutter::HostWindow::SetConstraints ( const WindowConstraints constraints)

Definition at line 521 of file host_window.cc.

521  {
522  box_constraints_ = FromWindowConstraints(constraints);
523 
524  if (GetFullscreen()) {
525  std::optional<Size> const window_size = GetWindowSizeForClientSize(
529  box_constraints_.smallest(), box_constraints_.biggest(),
531  if (!window_size) {
532  return;
533  }
534 
535  saved_window_info_.rect.right =
536  saved_window_info_.rect.left + static_cast<LONG>(window_size->width());
537  saved_window_info_.rect.bottom =
538  saved_window_info_.rect.top + static_cast<LONG>(window_size->height());
539  } else {
540  auto const client_size = GetWindowContentSize(window_handle_);
541  auto const current_size = Size(client_size.width, client_size.height);
542  WINDOWINFO window_info = {.cbSize = sizeof(WINDOWINFO)};
543  GetWindowInfo(window_handle_, &window_info);
544  std::optional<Size> const window_size = GetWindowSizeForClientSize(
545  *engine_->windows_proc_table(), current_size,
546  box_constraints_.smallest(), box_constraints_.biggest(),
547  window_info.dwStyle, window_info.dwExStyle, nullptr);
548 
549  if (window_size && current_size != window_size) {
550  SetWindowPos(window_handle_, NULL, 0, 0, window_size->width(),
551  window_size->height(),
552  SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
553  }
554  }
555 }
std::shared_ptr< WindowsProcTable > windows_proc_table()
SavedWindowInfo saved_window_info_
Definition: host_window.h:211
static ActualWindowSize GetWindowContentSize(HWND hwnd)
Definition: host_window.cc:712
virtual bool GetFullscreen() const
Definition: host_window.cc:708
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:725

References box_constraints_, flutter::HostWindow::SavedWindowInfo::client_size, engine_, flutter::HostWindow::SavedWindowInfo::ex_style, GetFullscreen(), GetWindowContentSize(), GetWindowSizeForClientSize(), flutter::ActualWindowSize::height, flutter::HostWindow::SavedWindowInfo::rect, saved_window_info_, flutter::HostWindow::SavedWindowInfo::style, flutter::ActualWindowSize::width, window_handle_, and flutter::FlutterWindowsEngine::windows_proc_table().

Referenced by InternalFlutterWindows_WindowManager_SetWindowConstraints().

◆ SetContentSize()

void flutter::HostWindow::SetContentSize ( const WindowSizeRequest size)

Definition at line 479 of file host_window.cc.

479  {
480  if (!size.has_preferred_view_size) {
481  return;
482  }
483 
484  if (GetFullscreen()) {
485  std::optional<Size> const window_size = GetWindowSizeForClientSize(
487  Size(size.preferred_view_width, size.preferred_view_height),
488  box_constraints_.smallest(), box_constraints_.biggest(),
490  if (!window_size) {
491  return;
492  }
493 
495  ActualWindowSize{.width = size.preferred_view_width,
496  .height = size.preferred_view_height};
497  saved_window_info_.rect.right =
498  saved_window_info_.rect.left + static_cast<LONG>(window_size->width());
499  saved_window_info_.rect.bottom =
500  saved_window_info_.rect.top + static_cast<LONG>(window_size->height());
501  } else {
502  WINDOWINFO window_info = {.cbSize = sizeof(WINDOWINFO)};
503  GetWindowInfo(window_handle_, &window_info);
504 
505  std::optional<Size> const window_size = GetWindowSizeForClientSize(
507  Size(size.preferred_view_width, size.preferred_view_height),
508  box_constraints_.smallest(), box_constraints_.biggest(),
509  window_info.dwStyle, window_info.dwExStyle, nullptr);
510 
511  if (!window_size) {
512  return;
513  }
514 
515  SetWindowPos(window_handle_, NULL, 0, 0, window_size->width(),
516  window_size->height(),
517  SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
518  }
519 }

References box_constraints_, flutter::HostWindow::SavedWindowInfo::client_size, engine_, flutter::HostWindow::SavedWindowInfo::ex_style, GetFullscreen(), GetWindowSizeForClientSize(), flutter::WindowSizeRequest::has_preferred_view_size, flutter::WindowSizeRequest::preferred_view_height, flutter::WindowSizeRequest::preferred_view_width, flutter::HostWindow::SavedWindowInfo::rect, saved_window_info_, flutter::HostWindow::SavedWindowInfo::style, flutter::ActualWindowSize::width, window_handle_, and flutter::FlutterWindowsEngine::windows_proc_table().

Referenced by InternalFlutterWindows_WindowManager_SetWindowSize().

◆ SetFullscreen()

void flutter::HostWindow::SetFullscreen ( bool  fullscreen,
std::optional< FlutterEngineDisplayId >  display_id 
)
virtual

Reimplemented in flutter::HostWindowDialog.

Definition at line 562 of file host_window.cc.

564  {
565  if (fullscreen == GetFullscreen()) {
566  return;
567  }
568 
569  if (fullscreen) {
570  WINDOWINFO window_info = {.cbSize = sizeof(WINDOWINFO)};
571  GetWindowInfo(window_handle_, &window_info);
572  saved_window_info_.style = window_info.dwStyle;
573  saved_window_info_.ex_style = window_info.dwExStyle;
574  // Store the original window rect, DPI, and monitor info to detect changes
575  // and more accurately restore window placements when exiting fullscreen.
576  ::GetWindowRect(window_handle_, &saved_window_info_.rect);
580  MonitorFromWindow(window_handle_, MONITOR_DEFAULTTONEAREST);
583  GetMonitorInfo(saved_window_info_.monitor,
585  }
586 
587  if (fullscreen) {
588  // Next, get the raw HMONITOR that we want to be fullscreened on
589  HMONITOR monitor =
590  MonitorFromWindow(window_handle_, MONITOR_DEFAULTTONEAREST);
591  if (display_id) {
592  if (auto const display =
593  engine_->display_manager()->FindById(display_id.value())) {
594  monitor = reinterpret_cast<HMONITOR>(display->display_id);
595  }
596  }
597 
598  MONITORINFO monitor_info;
599  monitor_info.cbSize = sizeof(monitor_info);
600  if (!GetMonitorInfo(monitor, &monitor_info)) {
601  FML_LOG(ERROR) << "Cannot set window fullscreen because the monitor info "
602  "was not found";
603  }
604 
605  auto const width = RectWidth(monitor_info.rcMonitor);
606  auto const height = RectHeight(monitor_info.rcMonitor);
607  WINDOWINFO window_info = {.cbSize = sizeof(WINDOWINFO)};
608  GetWindowInfo(window_handle_, &window_info);
609 
610  // Set new window style and size.
611  SetWindowLong(window_handle_, GWL_STYLE,
612  saved_window_info_.style & ~(WS_CAPTION | WS_THICKFRAME));
613  SetWindowLong(
614  window_handle_, GWL_EXSTYLE,
615  saved_window_info_.ex_style & ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE |
616  WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
617 
618  // We call SetWindowPos first to set the window flags immediately. This
619  // makes it so that the WM_GETMINMAXINFO gets called with the correct window
620  // and content sizes.
621  SetWindowPos(window_handle_, NULL, 0, 0, 0, 0,
622  SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
623 
624  SetWindowPos(window_handle_, nullptr, monitor_info.rcMonitor.left,
625  monitor_info.rcMonitor.top, width, height,
626  SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
627  } else {
628  // Restore the window style and bounds saved prior to entering fullscreen.
629  // Use WS_VISIBLE for windows shown after SetFullscreen: crbug.com/1062251.
630  // Making multiple window adjustments here is ugly, but if SetWindowPos()
631  // doesn't redraw, the taskbar won't be repainted.
632  SetWindowLong(window_handle_, GWL_STYLE,
633  saved_window_info_.style | WS_VISIBLE);
634  SetWindowLong(window_handle_, GWL_EXSTYLE, saved_window_info_.ex_style);
635 
636  // We call SetWindowPos first to set the window flags immediately. This
637  // makes it so that the WM_GETMINMAXINFO gets called with the correct window
638  // and content sizes.
639  SetWindowPos(window_handle_, NULL, 0, 0, 0, 0,
640  SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
641 
642  HMONITOR monitor =
643  MonitorFromRect(&saved_window_info_.rect, MONITOR_DEFAULTTONEAREST);
644  MONITORINFO monitor_info;
645  monitor_info.cbSize = sizeof(monitor_info);
646  GetMonitorInfo(monitor, &monitor_info);
647 
648  auto window_rect = saved_window_info_.rect;
649 
650  // Adjust the window bounds to restore, if displays were disconnected,
651  // virtually rearranged, or otherwise changed metrics during fullscreen.
652  if (monitor != saved_window_info_.monitor ||
654  monitor_info.rcWork)) {
655  window_rect = AdjustToFit(monitor_info.rcWork, window_rect);
656  }
657 
658  auto const fullscreen_dpi = GetDpiForHWND(window_handle_);
659  SetWindowPos(window_handle_, nullptr, window_rect.left, window_rect.top,
660  RectWidth(window_rect), RectHeight(window_rect),
661  SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
662  auto const final_dpi = GetDpiForHWND(window_handle_);
663  if (final_dpi != saved_window_info_.dpi || final_dpi != fullscreen_dpi) {
664  // Reissue SetWindowPos if the DPI changed from saved or fullscreen DPIs.
665  // The first call may misinterpret bounds spanning displays, if the
666  // fullscreen display's DPI does not match the target display's DPI.
667  //
668  // Scale and clamp the bounds if the final DPI changed from the saved DPI.
669  // This more accurately matches the original placement, while avoiding
670  // unexpected offscreen placement in a recongifured multi-screen space.
671  if (final_dpi != saved_window_info_.dpi) {
672  auto const scale =
673  final_dpi / static_cast<float>(saved_window_info_.dpi);
674  auto const width = static_cast<LONG>(scale * RectWidth(window_rect));
675  auto const height = static_cast<LONG>(scale * RectHeight(window_rect));
676  window_rect.right = window_rect.left + width;
677  window_rect.bottom = window_rect.top + height;
678  window_rect = AdjustToFit(monitor_info.rcWork, window_rect);
679  }
680 
681  SetWindowPos(window_handle_, nullptr, window_rect.left, window_rect.top,
682  RectWidth(window_rect), RectHeight(window_rect),
683  SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
684  }
685  }
686 
687  if (!task_bar_list_) {
688  HRESULT hr =
689  ::CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER,
690  IID_PPV_ARGS(&task_bar_list_));
691  if (SUCCEEDED(hr) && FAILED(task_bar_list_->HrInit())) {
692  task_bar_list_ = nullptr;
693  }
694  }
695 
696  // As per MSDN marking the window as fullscreen should ensure that the
697  // taskbar is moved to the bottom of the Z-order when the fullscreen window
698  // is activated. If the window is not fullscreen, the Shell falls back to
699  // heuristics to determine how the window should be treated, which means
700  // that it could still consider the window as fullscreen. :(
701  if (task_bar_list_) {
702  task_bar_list_->MarkFullscreenWindow(window_handle_, !!fullscreen);
703  }
704 
705  is_fullscreen_ = fullscreen;
706 }
std::shared_ptr< DisplayManagerWin32 > display_manager()
Microsoft::WRL::ComPtr< ITaskbarList2 > task_bar_list_
Definition: host_window.h:214
LONG RectWidth(const RECT &r)
Definition: rect_helper.h:11
bool AreRectsEqual(const RECT &a, const RECT &b)
Definition: rect_helper.h:19
LONG RectHeight(const RECT &r)
Definition: rect_helper.h:15

References flutter::AreRectsEqual(), flutter::HostWindow::SavedWindowInfo::client_size, flutter::FlutterWindowsEngine::display_manager(), flutter::HostWindow::SavedWindowInfo::dpi, engine_, flutter::HostWindow::SavedWindowInfo::ex_style, flutter::GetDpiForHWND(), GetFullscreen(), GetWindowContentSize(), is_fullscreen_, flutter::HostWindow::SavedWindowInfo::monitor, flutter::HostWindow::SavedWindowInfo::monitor_info, flutter::HostWindow::SavedWindowInfo::rect, flutter::RectHeight(), flutter::RectWidth(), saved_window_info_, flutter::HostWindow::SavedWindowInfo::style, task_bar_list_, and window_handle_.

Referenced by InternalFlutterWindows_WindowManager_SetFullscreen().

◆ UpdateModalStateLayer()

void flutter::HostWindow::UpdateModalStateLayer ( )

Definition at line 833 of file host_window.cc.

833  {
834  auto children = GetOwnedWindows();
835  if (children.empty()) {
836  // Leaf window in the active path, enable it.
837  EnableWindow(window_handle_, true);
838  } else {
839  // Non-leaf window in the active path, disable it and process children.
840  EnableWindow(window_handle_, false);
841 
842  // On same level of window hierarchy the most recently created window
843  // will remain enabled.
844  auto latest_child = *std::max_element(
845  children.begin(), children.end(), [](HostWindow* a, HostWindow* b) {
846  return a->view_controller_->view()->view_id() <
847  b->view_controller_->view()->view_id();
848  });
849 
850  for (HostWindow* const child : children) {
851  if (child == latest_child) {
852  child->UpdateModalStateLayer();
853  } else {
854  child->DisableRecursively();
855  }
856  }
857  }
858 }

References GetOwnedWindows(), and window_handle_.

◆ WndProc()

LRESULT flutter::HostWindow::WndProc ( HWND  hwnd,
UINT  message,
WPARAM  wparam,
LPARAM  lparam 
)
staticprotected

Definition at line 353 of file host_window.cc.

356  {
357  if (message == WM_NCCREATE) {
358  auto* const create_struct = reinterpret_cast<CREATESTRUCT*>(lparam);
359  auto* const windows_proc_table =
360  static_cast<WindowsProcTable*>(create_struct->lpCreateParams);
361  windows_proc_table->EnableNonClientDpiScaling(hwnd);
362  EnableTransparentWindowBackground(hwnd, *windows_proc_table);
363  } else if (HostWindow* const window = GetThisFromHandle(hwnd)) {
364  return window->HandleMessage(hwnd, message, wparam, lparam);
365  }
366 
367  return DefWindowProc(hwnd, message, wparam, lparam);
368 }

References flutter::WindowsProcTable::EnableNonClientDpiScaling(), GetThisFromHandle(), and message.

Member Data Documentation

◆ archetype_

WindowArchetype flutter::HostWindow::archetype_ = WindowArchetype::kRegular
protected

Definition at line 196 of file host_window.h.

◆ box_constraints_

BoxConstraints flutter::HostWindow::box_constraints_
protected

Definition at line 202 of file host_window.h.

Referenced by HandleMessage(), SetConstraints(), and SetContentSize().

◆ engine_

FlutterWindowsEngine* flutter::HostWindow::engine_
protected

Definition at line 188 of file host_window.h.

Referenced by HandleMessage(), SetConstraints(), SetContentSize(), and SetFullscreen().

◆ is_being_destroyed_

bool flutter::HostWindow::is_being_destroyed_ = false
protected

◆ is_fullscreen_

bool flutter::HostWindow::is_fullscreen_ = false
protected

Definition at line 208 of file host_window.h.

Referenced by GetFullscreen(), and SetFullscreen().

◆ saved_window_info_

SavedWindowInfo flutter::HostWindow::saved_window_info_
protected

Definition at line 211 of file host_window.h.

Referenced by SetConstraints(), SetContentSize(), and SetFullscreen().

◆ task_bar_list_

Microsoft::WRL::ComPtr<ITaskbarList2> flutter::HostWindow::task_bar_list_
protected

Definition at line 214 of file host_window.h.

Referenced by SetFullscreen().

◆ view_controller_

std::unique_ptr<FlutterWindowsViewController> flutter::HostWindow::view_controller_
protected

Definition at line 193 of file host_window.h.

Referenced by FocusRootViewOf(), HandleMessage(), and ~HostWindow().

◆ window_handle_

◆ window_manager_

WindowManager* const flutter::HostWindow::window_manager_ = nullptr
protected

Definition at line 185 of file host_window.h.

◆ WindowManager

friend flutter::HostWindow::WindowManager
protected

Definition at line 106 of file host_window.h.


The documentation for this class was generated from the following files: