Flutter Windows Embedder
host_window_tooltip.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 #include <cstdio>
9 
10 namespace flutter {
12  WindowManager* window_manager,
13  FlutterWindowsEngine* engine,
14  const BoxConstraints& constraints,
15  bool is_sized_to_content,
16  GetWindowPositionCallback get_position_callback,
17  HWND parent)
18  : HostWindow(window_manager, engine),
19  get_position_callback_(get_position_callback),
20  parent_(parent),
21  isolate_(Isolate::Current()),
22  view_alive_(std::make_shared<int>(0)) {
23  // Use minimum constraints as initial size to ensure the view can be created
24  // with valid metrics. If is_sized_to_content is true, the size will be
25  // updated when content is rendered.
26  auto const initial_width =
27  static_cast<double>(constraints.smallest().width());
28  auto const initial_height =
29  static_cast<double>(constraints.smallest().height());
30 
33  .window_style = WS_POPUP,
34  .extended_window_style = WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW,
35  .box_constraints = constraints,
36  .initial_window_rect = {{0, 0}, {initial_width, initial_height}},
37  .title = L"",
38  .owner_window = parent,
39  .nCmdShow = SW_SHOWNOACTIVATE,
40  .sizing_delegate = this,
41  .is_sized_to_content = is_sized_to_content});
42  SetWindowLongPtr(window_handle_, GWLP_HWNDPARENT,
43  reinterpret_cast<LONG_PTR>(parent_));
44 }
45 
46 void HostWindowTooltip::DidUpdateViewSize(int32_t width, int32_t height) {
47  // This is called from the raster thread.
48  std::weak_ptr<int> weak_view_alive = view_alive_;
49  engine_->task_runner()->PostTask([this, width, height, weak_view_alive]() {
50  auto const view_alive = weak_view_alive.lock();
51  if (!view_alive) {
52  return;
53  }
54  if (width_ == width && height_ == height) {
55  return;
56  }
57 
58  if (is_being_destroyed_) {
59  return;
60  }
61 
62  width_ = width;
63  height_ = height;
65  });
66 }
67 
68 WindowRect HostWindowTooltip::GetWorkArea() const {
69  constexpr int32_t kDefaultWorkAreaSize = 10000;
70  WindowRect work_area = {0, 0, kDefaultWorkAreaSize, kDefaultWorkAreaSize};
71  HMONITOR monitor = MonitorFromWindow(parent_, MONITOR_DEFAULTTONEAREST);
72  if (monitor) {
73  MONITORINFO monitor_info = {0};
74  monitor_info.cbSize = sizeof(monitor_info);
75  if (GetMonitorInfo(monitor, &monitor_info)) {
76  work_area.left = monitor_info.rcWork.left;
77  work_area.top = monitor_info.rcWork.top;
78  work_area.width = monitor_info.rcWork.right - monitor_info.rcWork.left;
79  work_area.height = monitor_info.rcWork.bottom - monitor_info.rcWork.top;
80  }
81  }
82  return work_area;
83 }
84 
86  RECT parent_client_rect;
87  GetClientRect(parent_, &parent_client_rect);
88 
89  // Convert top-left and bottom-right points to screen coordinates.
90  POINT parent_top_left = {parent_client_rect.left, parent_client_rect.top};
91  POINT parent_bottom_right = {parent_client_rect.right,
92  parent_client_rect.bottom};
93 
94  ClientToScreen(parent_, &parent_top_left);
95  ClientToScreen(parent_, &parent_bottom_right);
96 
97  // Get monitor from HWND and usable work area.
98  HMONITOR monitor = MonitorFromWindow(parent_, MONITOR_DEFAULTTONEAREST);
99  WindowRect work_area = GetWorkArea();
100 
101  IsolateScope scope(isolate_);
102  auto rect = get_position_callback_(
103  WindowSize{width_, height_},
104  WindowRect{parent_top_left.x, parent_top_left.y,
105  parent_bottom_right.x - parent_top_left.x,
106  parent_bottom_right.y - parent_top_left.y},
107  work_area);
108  SetWindowPos(window_handle_, nullptr, rect->left, rect->top, rect->width,
109  rect->height, SWP_NOACTIVATE | SWP_NOOWNERZORDER);
110  free(rect);
111 
112  // The positioner constrained the dimensions more than current size, apply
113  // positioner constraints.
114  if (rect->width < width_ || rect->height < height_) {
115  auto metrics_event = view_controller_->view()->CreateWindowMetricsEvent();
116  view_controller_->engine()->SendWindowMetricsEvent(metrics_event);
117  }
118 }
119 
121  UINT message,
122  WPARAM wparam,
123  LPARAM lparam) {
124  switch (message) {
125  case WM_MOUSEACTIVATE:
126  // Prevent activation when clicked
127  return MA_NOACTIVATE;
128 
129  case WM_NCACTIVATE:
130  // Return TRUE to prevent visual activation changes
131  return TRUE;
132 
133  case WM_ACTIVATE:
134  // Immediately deactivate if somehow activated
135  if (LOWORD(wparam) != WA_INACTIVE) {
136  HWND hFocus = GetFocus();
137  SetFocus(nullptr);
138  }
139  break;
140  }
141 
142  return HostWindow::HandleMessage(hwnd, message, wparam, lparam);
143 }
144 
145 } // namespace flutter
void InitializeFlutterView(HostWindowInitializationParams const &params)
Definition: host_window.cc:245
std::unique_ptr< FlutterWindowsViewController > view_controller_
Definition: host_window.h:217
FlutterWindowsEngine * engine_
Definition: host_window.h:212
virtual LRESULT HandleMessage(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
Definition: host_window.cc:382
HostWindowTooltip(WindowManager *window_manager, FlutterWindowsEngine *engine, const BoxConstraints &constraints, bool is_sized_to_content, GetWindowPositionCallback get_position_callback, HWND parent)
LRESULT HandleMessage(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) override
void PostTask(TaskClosure task)
Definition: task_runner.cc:88
Win32Message message
WindowRect *(* GetWindowPositionCallback)(const WindowSize &child_size, const WindowRect &parent_rect, const WindowRect &output_rect)