Flutter Windows Embedder
flutter::HostWindow Class Reference

#include <host_window.h>

Public Member Functions

virtual ~HostWindow ()
 
HWND GetWindowHandle () const
 
void SetContentSize (const WindowSizing &size)
 

Static Public Member Functions

static std::unique_ptr< HostWindowCreateRegularWindow (WindowManager *controller, FlutterWindowsEngine *engine, const WindowSizing &content_size)
 
static HostWindowGetThisFromHandle (HWND hwnd)
 

Detailed Description

Definition at line 24 of file host_window.h.

Constructor & Destructor Documentation

◆ ~HostWindow()

flutter::HostWindow::~HostWindow ( )
virtual

Definition at line 332 of file host_window.cc.

332  {
333  if (view_controller_) {
334  // Unregister the window class. Fail silently if other windows are still
335  // using the class, as only the last window can successfully unregister it.
336  if (!UnregisterClass(kWindowClassName, GetModuleHandle(nullptr))) {
337  // Clear the error state after the failed unregistration.
338  SetLastError(ERROR_SUCCESS);
339  }
340  }
341 }

Member Function Documentation

◆ CreateRegularWindow()

std::unique_ptr< HostWindow > flutter::HostWindow::CreateRegularWindow ( WindowManager controller,
FlutterWindowsEngine engine,
const WindowSizing content_size 
)
static

Definition at line 200 of file host_window.cc.

203  {
204  DWORD window_style = WS_OVERLAPPEDWINDOW;
205  DWORD extended_window_style = 0;
206  std::optional<Size> smallest = std::nullopt;
207  std::optional<Size> biggest = std::nullopt;
208 
209  if (content_size.has_view_constraints) {
210  smallest = Size(content_size.view_min_width, content_size.view_min_height);
211  if (content_size.view_max_width > 0 && content_size.view_max_height > 0) {
212  biggest = Size(content_size.view_max_width, content_size.view_max_height);
213  }
214  }
215 
216  // TODO(knopp): What about windows sized to content?
217  FML_CHECK(content_size.has_preferred_view_size);
218 
219  // Calculate the screen space window rectangle for the new window.
220  // Default positioning values (CW_USEDEFAULT) are used
221  // if the window has no owner.
222  Rect const initial_window_rect = [&]() -> Rect {
223  std::optional<Size> const window_size = GetWindowSizeForClientSize(
224  *engine->windows_proc_table(),
225  Size(content_size.preferred_view_width,
226  content_size.preferred_view_height),
227  smallest, biggest, window_style, extended_window_style, nullptr);
228  return {{CW_USEDEFAULT, CW_USEDEFAULT},
229  window_size ? *window_size : Size{CW_USEDEFAULT, CW_USEDEFAULT}};
230  }();
231 
232  // Set up the view.
233  auto view_window = std::make_unique<FlutterWindow>(
234  initial_window_rect.width(), initial_window_rect.height(),
235  engine->windows_proc_table());
236 
237  std::unique_ptr<FlutterWindowsView> view =
238  engine->CreateView(std::move(view_window));
239  if (view == nullptr) {
240  FML_LOG(ERROR) << "Failed to create view";
241  return nullptr;
242  }
243 
244  std::unique_ptr<FlutterWindowsViewController> view_controller =
245  std::make_unique<FlutterWindowsViewController>(nullptr, std::move(view));
246  FML_CHECK(engine->running());
247  // The Windows embedder listens to accessibility updates using the
248  // view's HWND. The embedder's accessibility features may be stale if
249  // the app was in headless mode.
250  engine->UpdateAccessibilityFeatures();
251 
252  // Register the window class.
253  if (!IsClassRegistered(kWindowClassName)) {
254  auto const idi_app_icon = 101;
255  WNDCLASSEX window_class = {};
256  window_class.cbSize = sizeof(WNDCLASSEX);
257  window_class.style = CS_HREDRAW | CS_VREDRAW;
258  window_class.lpfnWndProc = HostWindow::WndProc;
259  window_class.hInstance = GetModuleHandle(nullptr);
260  window_class.hIcon =
261  LoadIcon(window_class.hInstance, MAKEINTRESOURCE(idi_app_icon));
262  if (!window_class.hIcon) {
263  window_class.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
264  }
265  window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
266  window_class.lpszClassName = kWindowClassName;
267 
268  if (!RegisterClassEx(&window_class)) {
269  FML_LOG(ERROR) << "Cannot register window class " << kWindowClassName
270  << ": " << GetLastErrorAsString();
271  return nullptr;
272  }
273  }
274 
275  // Create the native window.
276  HWND hwnd = CreateWindowEx(
277  extended_window_style, kWindowClassName, L"", window_style,
278  initial_window_rect.left(), initial_window_rect.top(),
279  initial_window_rect.width(), initial_window_rect.height(), nullptr,
280  nullptr, GetModuleHandle(nullptr), engine->windows_proc_table().get());
281  if (!hwnd) {
282  FML_LOG(ERROR) << "Cannot create window: " << GetLastErrorAsString();
283  return nullptr;
284  }
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(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &frame_rect,
292  sizeof(frame_rect));
293  RECT window_rect;
294  GetWindowRect(hwnd, &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(hwnd, nullptr, window_rect.left - left_dropshadow_width,
298  window_rect.top - top_dropshadow_height, 0, 0,
299  SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
300 
301  UpdateTheme(hwnd);
302 
303  SetChildContent(view_controller->view()->GetWindowHandle(), hwnd);
304 
305  // TODO(loicsharma): Hide the window until the first frame is rendered.
306  // Single window apps use the engine's next frame callback to show the
307  // window. This doesn't work for multi window apps as the engine cannot have
308  // multiple next frame callbacks. If multiple windows are created, only the
309  // last one will be shown.
310  ShowWindow(hwnd, SW_SHOWNORMAL);
311  return std::unique_ptr<HostWindow>(new HostWindow(
312  window_manager, engine, WindowArchetype::kRegular,
313  std::move(view_controller), BoxConstraints(smallest, biggest), hwnd));
314 }

References flutter::FlutterWindowsEngine::CreateView(), flutter::WindowSizing::has_preferred_view_size, flutter::WindowSizing::has_view_constraints, flutter::Rect::height(), flutter::kRegular, flutter::Rect::left(), flutter::WindowSizing::preferred_view_height, flutter::WindowSizing::preferred_view_width, flutter::FlutterWindowsEngine::running(), flutter::Rect::top(), flutter::FlutterWindowsEngine::UpdateAccessibilityFeatures(), flutter::WindowSizing::view_max_height, flutter::WindowSizing::view_max_width, flutter::WindowSizing::view_min_height, flutter::WindowSizing::view_min_width, flutter::Rect::width(), and flutter::FlutterWindowsEngine::windows_proc_table().

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

◆ GetThisFromHandle()

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

Definition at line 343 of file host_window.cc.

343  {
344  return reinterpret_cast<HostWindow*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
345 }

Referenced by InternalFlutterWindows_WindowManager_SetWindowContentSize().

◆ GetWindowHandle()

HWND flutter::HostWindow::GetWindowHandle ( ) const

Definition at line 347 of file host_window.cc.

347  {
348  return window_handle_;
349 }

◆ SetContentSize()

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

Definition at line 466 of file host_window.cc.

466  {
467  WINDOWINFO window_info = {.cbSize = sizeof(WINDOWINFO)};
468  GetWindowInfo(window_handle_, &window_info);
469 
470  std::optional<Size> smallest, biggest;
471  if (size.has_view_constraints) {
472  smallest = Size(size.view_min_width, size.view_min_height);
473  if (size.view_max_width > 0 && size.view_max_height > 0) {
474  biggest = Size(size.view_max_width, size.view_max_height);
475  }
476  }
477 
478  box_constraints_ = BoxConstraints(smallest, biggest);
479 
480  if (size.has_preferred_view_size) {
481  std::optional<Size> const window_size = GetWindowSizeForClientSize(
482  *engine_->windows_proc_table(),
483  Size(size.preferred_view_width, size.preferred_view_height),
484  box_constraints_.smallest(), box_constraints_.biggest(),
485  window_info.dwStyle, window_info.dwExStyle, nullptr);
486 
487  if (window_size) {
488  SetWindowPos(window_handle_, NULL, 0, 0, window_size->width(),
489  window_size->height(),
490  SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
491  }
492  }
493 }
Size smallest() const
Definition: geometry.h:97
Size biggest() const
Definition: geometry.h:96
std::shared_ptr< WindowsProcTable > windows_proc_table()

References flutter::BoxConstraints::biggest(), flutter::WindowSizing::has_preferred_view_size, flutter::WindowSizing::has_view_constraints, flutter::WindowSizing::preferred_view_height, flutter::WindowSizing::preferred_view_width, flutter::BoxConstraints::smallest(), flutter::WindowSizing::view_max_height, flutter::WindowSizing::view_max_width, flutter::WindowSizing::view_min_height, flutter::WindowSizing::view_min_width, and flutter::FlutterWindowsEngine::windows_proc_table().

Referenced by InternalFlutterWindows_WindowManager_SetWindowContentSize().


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