Flutter Windows Embedder
flutter::HostWindow Class Reference

#include <host_window.h>

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

Classes

struct  HostWindowInitializationParams
 
struct  SavedWindowInfo
 

Public Member Functions

virtual ~HostWindow ()
 
HWND GetWindowHandle () const
 
HWND GetFlutterViewWindowHandle () 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 std::unique_ptr< HostWindowCreateTooltipWindow (WindowManager *window_manager, FlutterWindowsEngine *engine, const WindowConstraints &preferred_constraints, bool is_sized_to_content, GetWindowPositionCallback get_position_callback, HWND parent)
 
static HostWindowGetThisFromHandle (HWND hwnd)
 
static ActualWindowSize GetWindowContentSize (HWND hwnd)
 

Protected Member Functions

void InitializeFlutterView (HostWindowInitializationParams const &params)
 
 HostWindow (WindowManager *window_manager, FlutterWindowsEngine *engine)
 
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 29 of file host_window.h.

Constructor & Destructor Documentation

◆ ~HostWindow()

flutter::HostWindow::~HostWindow ( )
virtual

Definition at line 324 of file host_window.cc.

324  {
325  if (view_controller_) {
326  // Unregister the window class. Fail silently if other windows are still
327  // using the class, as only the last window can successfully unregister it.
328  if (!UnregisterClass(kWindowClassName, GetModuleHandle(nullptr))) {
329  // Clear the error state after the failed unregistration.
330  SetLastError(ERROR_SUCCESS);
331  }
332  }
333 }
std::unique_ptr< FlutterWindowsViewController > view_controller_
Definition: host_window.h:217

References view_controller_.

◆ HostWindow()

flutter::HostWindow::HostWindow ( WindowManager window_manager,
FlutterWindowsEngine engine 
)
protected

Definition at line 241 of file host_window.cc.

243  : window_manager_(window_manager), engine_(engine) {}
FlutterWindowsEngine * engine_
Definition: host_window.h:212
WindowManager *const window_manager_
Definition: host_window.h:209

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 216 of file host_window.cc.

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

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 205 of file host_window.cc.

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

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

◆ CreateTooltipWindow()

std::unique_ptr< HostWindow > flutter::HostWindow::CreateTooltipWindow ( WindowManager window_manager,
FlutterWindowsEngine engine,
const WindowConstraints preferred_constraints,
bool  is_sized_to_content,
GetWindowPositionCallback  get_position_callback,
HWND  parent 
)
static

Definition at line 229 of file host_window.cc.

235  {
236  return std::unique_ptr<HostWindowTooltip>(new HostWindowTooltip(
237  window_manager, engine, FromWindowConstraints(preferred_constraints),
238  is_sized_to_content, get_position_callback, parent));
239 }

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

◆ DisableRecursively()

void flutter::HostWindow::DisableRecursively ( )
protected

Definition at line 836 of file host_window.cc.

836  {
837  // Disable the window itself.
838  EnableWindow(window_handle_, false);
839 
840  for (HostWindow* const owned : GetOwnedWindows()) {
841  owned->DisableRecursively();
842  }
843 }
HostWindow(WindowManager *window_manager, FlutterWindowsEngine *engine)
Definition: host_window.cc:241
std::vector< HostWindow * > GetOwnedWindows() const
Definition: host_window.cc:806

References GetOwnedWindows(), and window_handle_.

◆ EnableRecursively()

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

Definition at line 784 of file host_window.cc.

784  {
785  EnableWindow(window_handle_, enable);
786 
787  for (HostWindow* const owned : GetOwnedWindows()) {
788  owned->EnableRecursively(enable);
789  }
790 }

References GetOwnedWindows(), and window_handle_.

◆ FindFirstEnabledDescendant()

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

Definition at line 792 of file host_window.cc.

792  {
793  if (IsWindowEnabled(window_handle_)) {
794  return const_cast<HostWindow*>(this);
795  }
796 
797  for (HostWindow* const owned : GetOwnedWindows()) {
798  if (HostWindow* const result = owned->FindFirstEnabledDescendant()) {
799  return result;
800  }
801  }
802 
803  return nullptr;
804 }

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 358 of file host_window.cc.

358  {
359  auto child_content = window->view_controller_->view()->GetWindowHandle();
360  if (window != nullptr && child_content != nullptr) {
361  SetFocus(child_content);
362  }
363 };

References view_controller_.

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

◆ GetFlutterViewWindowHandle()

HWND flutter::HostWindow::GetFlutterViewWindowHandle ( ) const

Definition at line 354 of file host_window.cc.

354  {
355  return view_controller_->view()->GetWindowHandle();
356 }

References view_controller_.

Referenced by InternalFlutterWindows_WindowManager_OnDestroyWindow().

◆ GetFullscreen()

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

Reimplemented in flutter::HostWindowDialog.

Definition at line 720 of file host_window.cc.

720  {
721  return is_fullscreen_;
722 }

References is_fullscreen_.

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

◆ GetOwnedWindows()

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

Definition at line 806 of file host_window.cc.

806  {
807  std::vector<HostWindow*> owned_windows;
808  struct EnumData {
809  HWND owner_window_handle;
810  std::vector<HostWindow*>* owned_windows;
811  } data{window_handle_, &owned_windows};
812 
813  EnumWindows(
814  [](HWND hwnd, LPARAM lparam) -> BOOL {
815  auto* const data = reinterpret_cast<EnumData*>(lparam);
816  if (GetWindow(hwnd, GW_OWNER) == data->owner_window_handle) {
817  HostWindow* const window = GetThisFromHandle(hwnd);
818  if (window && !window->is_being_destroyed_) {
819  data->owned_windows->push_back(window);
820  }
821  }
822  return TRUE;
823  },
824  reinterpret_cast<LPARAM>(&data));
825 
826  return owned_windows;
827 }
static HostWindow * GetThisFromHandle(HWND hwnd)
Definition: host_window.cc:335

References GetThisFromHandle(), is_being_destroyed_, and window_handle_.

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

◆ GetOwnerWindow()

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

Definition at line 829 of file host_window.cc.

829  {
830  if (HWND const owner_window_handle = GetWindow(GetWindowHandle(), GW_OWNER)) {
831  return GetThisFromHandle(owner_window_handle);
832  }
833  return nullptr;
834 };
HWND GetWindowHandle() const
Definition: host_window.cc:350

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 335 of file host_window.cc.

335  {
336  wchar_t class_name[256];
337  if (!GetClassName(hwnd, class_name, sizeof(class_name) / sizeof(wchar_t))) {
338  FML_LOG(ERROR) << "Failed to get class name for window handle " << hwnd
339  << ": " << GetLastErrorAsString();
340  return nullptr;
341  }
342  // Ignore window handles that do not match the expected class name.
343  if (wcscmp(class_name, kWindowClassName) != 0) {
344  return nullptr;
345  }
346 
347  return reinterpret_cast<HostWindow*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
348 }

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

◆ GetWindowContentSize()

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

Definition at line 724 of file host_window.cc.

724  {
725  RECT rect;
726  GetClientRect(hwnd, &rect);
727  double const dpr = FlutterDesktopGetDpiForHWND(hwnd) /
728  static_cast<double>(USER_DEFAULT_SCREEN_DPI);
729  double const width = rect.right / dpr;
730  double const height = rect.bottom / dpr;
731  return {
732  .width = rect.right / dpr,
733  .height = rect.bottom / dpr,
734  };
735 }
UINT FlutterDesktopGetDpiForHWND(HWND hwnd)

References FlutterDesktopGetDpiForHWND().

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

◆ GetWindowHandle()

HWND flutter::HostWindow::GetWindowHandle ( ) const

Definition at line 350 of file host_window.cc.

350  {
351  return window_handle_;
352 }

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 737 of file host_window.cc.

744  {
745  UINT const dpi = GetDpiForHWND(owner_hwnd ? *owner_hwnd : nullptr);
746  double const scale_factor =
747  static_cast<double>(dpi) / USER_DEFAULT_SCREEN_DPI;
748  RECT rect = {
749  .right = static_cast<LONG>(client_size.width() * scale_factor),
750  .bottom = static_cast<LONG>(client_size.height() * scale_factor)};
751 
752  if (!win32.AdjustWindowRectExForDpi(&rect, window_style, FALSE,
753  extended_window_style, dpi)) {
754  FML_LOG(ERROR) << "Failed to run AdjustWindowRectExForDpi: "
755  << GetLastErrorAsString();
756  return std::nullopt;
757  }
758 
759  double width = static_cast<double>(rect.right - rect.left);
760  double height = static_cast<double>(rect.bottom - rect.top);
761 
762  // Apply size constraints.
763  double const non_client_width = width - (client_size.width() * scale_factor);
764  double const non_client_height =
765  height - (client_size.height() * scale_factor);
766  if (smallest) {
767  flutter::Size min_physical_size = ClampToVirtualScreen(
768  flutter::Size(smallest->width() * scale_factor + non_client_width,
769  smallest->height() * scale_factor + non_client_height));
770  width = std::max(width, min_physical_size.width());
771  height = std::max(height, min_physical_size.height());
772  }
773  if (biggest) {
774  flutter::Size max_physical_size = ClampToVirtualScreen(
775  flutter::Size(biggest->width() * scale_factor + non_client_width,
776  biggest->height() * scale_factor + non_client_height));
777  width = std::min(width, max_physical_size.width());
778  height = std::min(height, max_physical_size.height());
779  }
780 
781  return flutter::Size{width, height};
782 }
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::HostWindowTooltip, and flutter::HostWindowDialog.

Definition at line 382 of file host_window.cc.

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

◆ InitializeFlutterView()

void flutter::HostWindow::InitializeFlutterView ( HostWindowInitializationParams const &  params)
protected

Definition at line 245 of file host_window.cc.

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

References flutter::HostWindow::HostWindowInitializationParams::box_constraints, flutter::FlutterWindowsEngine::CreateView(), flutter::FlutterWindowsEngine::display_manager(), engine_, flutter::HostWindow::HostWindowInitializationParams::extended_window_style, flutter::HostWindow::HostWindowInitializationParams::initial_window_rect, flutter::HostWindow::HostWindowInitializationParams::is_sized_to_content, flutter::HostWindow::HostWindowInitializationParams::nCmdShow, flutter::HostWindow::HostWindowInitializationParams::owner_window, flutter::FlutterWindowsEngine::running(), flutter::HostWindow::HostWindowInitializationParams::sizing_delegate, flutter::HostWindow::HostWindowInitializationParams::title, flutter::FlutterWindowsEngine::UpdateAccessibilityFeatures(), view_controller_, window_handle_, flutter::HostWindow::HostWindowInitializationParams::window_style, flutter::FlutterWindowsEngine::windows_proc_table(), and WndProc().

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

◆ SetConstraints()

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

Definition at line 533 of file host_window.cc.

533  {
534  box_constraints_ = FromWindowConstraints(constraints);
535 
536  if (GetFullscreen()) {
537  std::optional<Size> const window_size = GetWindowSizeForClientSize(
541  box_constraints_.smallest(), box_constraints_.biggest(),
543  if (!window_size) {
544  return;
545  }
546 
547  saved_window_info_.rect.right =
548  saved_window_info_.rect.left + static_cast<LONG>(window_size->width());
549  saved_window_info_.rect.bottom =
550  saved_window_info_.rect.top + static_cast<LONG>(window_size->height());
551  } else {
552  auto const client_size = GetWindowContentSize(window_handle_);
553  auto const current_size = Size(client_size.width, client_size.height);
554  WINDOWINFO window_info = {.cbSize = sizeof(WINDOWINFO)};
555  GetWindowInfo(window_handle_, &window_info);
556  std::optional<Size> const window_size = GetWindowSizeForClientSize(
557  *engine_->windows_proc_table(), current_size,
558  box_constraints_.smallest(), box_constraints_.biggest(),
559  window_info.dwStyle, window_info.dwExStyle, nullptr);
560 
561  if (window_size && current_size != window_size) {
562  SetWindowPos(window_handle_, NULL, 0, 0, window_size->width(),
563  window_size->height(),
564  SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
565  }
566  }
567 }
SavedWindowInfo saved_window_info_
Definition: host_window.h:235
static ActualWindowSize GetWindowContentSize(HWND hwnd)
Definition: host_window.cc:724
virtual bool GetFullscreen() const
Definition: host_window.cc:720
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:737

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 491 of file host_window.cc.

491  {
492  if (!size.has_preferred_view_size) {
493  return;
494  }
495 
496  if (GetFullscreen()) {
497  std::optional<Size> const window_size = GetWindowSizeForClientSize(
499  Size(size.preferred_view_width, size.preferred_view_height),
500  box_constraints_.smallest(), box_constraints_.biggest(),
502  if (!window_size) {
503  return;
504  }
505 
507  ActualWindowSize{.width = size.preferred_view_width,
508  .height = size.preferred_view_height};
509  saved_window_info_.rect.right =
510  saved_window_info_.rect.left + static_cast<LONG>(window_size->width());
511  saved_window_info_.rect.bottom =
512  saved_window_info_.rect.top + static_cast<LONG>(window_size->height());
513  } else {
514  WINDOWINFO window_info = {.cbSize = sizeof(WINDOWINFO)};
515  GetWindowInfo(window_handle_, &window_info);
516 
517  std::optional<Size> const window_size = GetWindowSizeForClientSize(
519  Size(size.preferred_view_width, size.preferred_view_height),
520  box_constraints_.smallest(), box_constraints_.biggest(),
521  window_info.dwStyle, window_info.dwExStyle, nullptr);
522 
523  if (!window_size) {
524  return;
525  }
526 
527  SetWindowPos(window_handle_, NULL, 0, 0, window_size->width(),
528  window_size->height(),
529  SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
530  }
531 }

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 574 of file host_window.cc.

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

845  {
846  auto children = GetOwnedWindows();
847  if (children.empty()) {
848  // Leaf window in the active path, enable it.
849  EnableWindow(window_handle_, true);
850  } else {
851  // Non-leaf window in the active path, disable it and process children.
852  EnableWindow(window_handle_, false);
853 
854  // On same level of window hierarchy the most recently created window
855  // will remain enabled.
856  auto latest_child = *std::max_element(
857  children.begin(), children.end(), [](HostWindow* a, HostWindow* b) {
858  return a->view_controller_->view()->view_id() <
859  b->view_controller_->view()->view_id();
860  });
861 
862  for (HostWindow* const child : children) {
863  if (child == latest_child) {
864  child->UpdateModalStateLayer();
865  } else {
866  child->DisableRecursively();
867  }
868  }
869  }
870 }

References GetOwnedWindows(), and window_handle_.

◆ WndProc()

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

Definition at line 365 of file host_window.cc.

368  {
369  if (message == WM_NCCREATE) {
370  auto* const create_struct = reinterpret_cast<CREATESTRUCT*>(lparam);
371  auto* const windows_proc_table =
372  static_cast<WindowsProcTable*>(create_struct->lpCreateParams);
373  windows_proc_table->EnableNonClientDpiScaling(hwnd);
374  EnableTransparentWindowBackground(hwnd, *windows_proc_table);
375  } else if (HostWindow* const window = GetThisFromHandle(hwnd)) {
376  return window->HandleMessage(hwnd, message, wparam, lparam);
377  }
378 
379  return DefWindowProc(hwnd, message, wparam, lparam);
380 }

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

Referenced by InitializeFlutterView().

Member Data Documentation

◆ archetype_

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

Definition at line 220 of file host_window.h.

◆ box_constraints_

BoxConstraints flutter::HostWindow::box_constraints_
protected

Definition at line 226 of file host_window.h.

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

◆ engine_

FlutterWindowsEngine* flutter::HostWindow::engine_
protected

◆ is_being_destroyed_

bool flutter::HostWindow::is_being_destroyed_ = false
protected

◆ is_fullscreen_

bool flutter::HostWindow::is_fullscreen_ = false
protected

Definition at line 232 of file host_window.h.

Referenced by GetFullscreen(), and SetFullscreen().

◆ saved_window_info_

SavedWindowInfo flutter::HostWindow::saved_window_info_
protected

Definition at line 235 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 238 of file host_window.h.

Referenced by SetFullscreen().

◆ view_controller_

◆ window_handle_

◆ window_manager_

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

Definition at line 209 of file host_window.h.

◆ WindowManager

friend flutter::HostWindow::WindowManager
protected

Definition at line 139 of file host_window.h.


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