Flutter Engine
flutter::Win32Window Class Referenceabstract

#include <win32_window.h>

Inheritance diagram for flutter::Win32Window:
flutter::testing::MockWin32Window flutter::Win32FlutterWindow flutter::testing::Win32FlutterWindowTest

Public Member Functions

 Win32Window ()
 
virtual ~Win32Window ()
 
void InitializeChild (const char *title, unsigned int width, unsigned int height)
 
HWND GetWindowHandle ()
 

Protected Member Functions

std::wstring NarrowToWide (const char *source)
 
WNDCLASS RegisterWindowClass (std::wstring &title)
 
LRESULT HandleMessage (UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
 
LRESULT HandleDpiChange (HWND hWnd, WPARAM wParam, LPARAM lParam, bool top_level)
 
virtual void OnDpiScale (UINT dpi)=0
 
virtual void OnResize (UINT width, UINT height)=0
 
virtual void OnPointerMove (double x, double y)=0
 
virtual void OnPointerDown (double x, double y, UINT button)=0
 
virtual void OnPointerUp (double x, double y, UINT button)=0
 
virtual void OnPointerLeave ()=0
 
virtual void OnSetCursor ()=0
 
virtual void OnText (const std::u16string &text)=0
 
virtual void OnKey (int key, int scancode, int action, char32_t character)=0
 
virtual void OnScroll (double delta_x, double delta_y)=0
 
UINT GetCurrentDPI ()
 
UINT GetCurrentWidth ()
 
UINT GetCurrentHeight ()
 

Static Protected Member Functions

static LRESULT CALLBACK WndProc (HWND const window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
 

Detailed Description

Definition at line 19 of file win32_window.h.

Constructor & Destructor Documentation

◆ Win32Window()

flutter::Win32Window::Win32Window ( )

Definition at line 20 of file win32_window.cc.

References flutter::GetDpiForHWND().

20  {
21  // Get the DPI of the primary monitor as the initial DPI. If Per-Monitor V2 is
22  // supported, |current_dpi_| should be updated in the
23  // kWmDpiChangedBeforeParent message.
24  current_dpi_ = GetDpiForHWND(nullptr);
25 }
UINT GetDpiForHWND(HWND hwnd)

◆ ~Win32Window()

flutter::Win32Window::~Win32Window ( )
virtual

Definition at line 27 of file win32_window.cc.

27  {
28  Destroy();
29 }

Member Function Documentation

◆ GetCurrentDPI()

UINT flutter::Win32Window::GetCurrentDPI ( )
protected

Definition at line 278 of file win32_window.cc.

Referenced by flutter::testing::MockWin32Window::GetDpi(), and flutter::Win32FlutterWindow::GetDpiScale().

278  {
279  return current_dpi_;
280 }

◆ GetCurrentHeight()

UINT flutter::Win32Window::GetCurrentHeight ( )
protected

Definition at line 286 of file win32_window.cc.

Referenced by flutter::Win32FlutterWindow::GetPhysicalWindowBounds().

286  {
287  return current_height_;
288 }

◆ GetCurrentWidth()

UINT flutter::Win32Window::GetCurrentWidth ( )
protected

Definition at line 282 of file win32_window.cc.

Referenced by flutter::Win32FlutterWindow::GetPhysicalWindowBounds().

282  {
283  return current_width_;
284 }

◆ GetWindowHandle()

HWND flutter::Win32Window::GetWindowHandle ( )

Definition at line 290 of file win32_window.cc.

References height, OnResize(), and width.

Referenced by flutter::Win32FlutterWindow::GetRenderTarget(), and flutter::Win32FlutterWindow::OnScroll().

290  {
291  return window_handle_;
292 }

◆ HandleDpiChange()

LRESULT flutter::Win32Window::HandleDpiChange ( HWND  hWnd,
WPARAM  wParam,
LPARAM  lParam,
bool  top_level 
)
protected

◆ HandleMessage()

LRESULT flutter::Win32Window::HandleMessage ( UINT const  message,
WPARAM const  wparam,
LPARAM const  lparam 
)
protectednoexcept

Definition at line 113 of file win32_window.cc.

References action, flutter::GetDpiForHWND(), height, OnDpiScale(), OnKey(), OnPointerDown(), OnPointerLeave(), OnPointerMove(), OnPointerUp(), OnScroll(), OnSetCursor(), OnText(), TRUE, and width.

Referenced by flutter::testing::MockWin32Window::InjectWindowMessage().

115  {
116  int xPos = 0, yPos = 0;
117  UINT width = 0, height = 0;
118  UINT button_pressed = 0;
119 
120  switch (message) {
121  case kWmDpiChangedBeforeParent:
122  current_dpi_ = GetDpiForHWND(window_handle_);
123  OnDpiScale(current_dpi_);
124  return 0;
125  case WM_SIZE:
126  width = LOWORD(lparam);
127  height = HIWORD(lparam);
128 
129  current_width_ = width;
130  current_height_ = height;
131  HandleResize(width, height);
132  break;
133  case WM_MOUSEMOVE:
134  TrackMouseLeaveEvent(window_handle_);
135 
136  xPos = GET_X_LPARAM(lparam);
137  yPos = GET_Y_LPARAM(lparam);
138  OnPointerMove(static_cast<double>(xPos), static_cast<double>(yPos));
139  break;
140  case WM_MOUSELEAVE:;
141  OnPointerLeave();
142  // Once the tracked event is received, the TrackMouseEvent function
143  // resets. Set to false to make sure it's called once mouse movement is
144  // detected again.
145  tracking_mouse_leave_ = false;
146  break;
147  case WM_SETCURSOR: {
148  UINT hit_test_result = LOWORD(lparam);
149  if (hit_test_result == HTCLIENT) {
150  OnSetCursor();
151  return TRUE;
152  }
153  break;
154  }
155  case WM_LBUTTONDOWN:
156  case WM_RBUTTONDOWN:
157  case WM_MBUTTONDOWN:
158  case WM_XBUTTONDOWN:
159  if (message == WM_LBUTTONDOWN) {
160  // Capture the pointer in case the user drags outside the client area.
161  // In this case, the "mouse leave" event is delayed until the user
162  // releases the button. It's only activated on left click given that
163  // it's more common for apps to handle dragging with only the left
164  // button.
165  SetCapture(window_handle_);
166  }
167  button_pressed = message;
168  if (message == WM_XBUTTONDOWN) {
169  button_pressed = GET_XBUTTON_WPARAM(wparam);
170  }
171  xPos = GET_X_LPARAM(lparam);
172  yPos = GET_Y_LPARAM(lparam);
173  OnPointerDown(static_cast<double>(xPos), static_cast<double>(yPos),
174  button_pressed);
175  break;
176  case WM_LBUTTONUP:
177  case WM_RBUTTONUP:
178  case WM_MBUTTONUP:
179  case WM_XBUTTONUP:
180  if (message == WM_LBUTTONUP) {
181  ReleaseCapture();
182  }
183  button_pressed = message;
184  if (message == WM_XBUTTONUP) {
185  button_pressed = GET_XBUTTON_WPARAM(wparam);
186  }
187  xPos = GET_X_LPARAM(lparam);
188  yPos = GET_Y_LPARAM(lparam);
189  OnPointerUp(static_cast<double>(xPos), static_cast<double>(yPos),
190  button_pressed);
191  break;
192  case WM_MOUSEWHEEL:
193  OnScroll(0.0, -(static_cast<short>(HIWORD(wparam)) /
194  static_cast<double>(WHEEL_DELTA)));
195  break;
196  case WM_MOUSEHWHEEL:
197  OnScroll((static_cast<short>(HIWORD(wparam)) /
198  static_cast<double>(WHEEL_DELTA)),
199  0.0);
200  break;
201  case WM_UNICHAR: {
202  // Tell third-pary app, we can support Unicode.
203  if (wparam == UNICODE_NOCHAR)
204  return TRUE;
205  // DefWindowProc will send WM_CHAR for this WM_UNICHAR.
206  break;
207  }
208  case WM_DEADCHAR:
209  case WM_SYSDEADCHAR:
210  case WM_CHAR:
211  case WM_SYSCHAR: {
212  static wchar_t s_pending_high_surrogate = 0;
213 
214  wchar_t character = static_cast<wchar_t>(wparam);
215  std::u16string text({character});
216  char32_t code_point = character;
217  if (IS_HIGH_SURROGATE(character)) {
218  // Save to send later with the trailing surrogate.
219  s_pending_high_surrogate = character;
220  } else if (IS_LOW_SURROGATE(character) && s_pending_high_surrogate != 0) {
221  text.insert(text.begin(), s_pending_high_surrogate);
222  // Merge the surrogate pairs for the key event.
223  code_point =
224  CodePointFromSurrogatePair(s_pending_high_surrogate, character);
225  s_pending_high_surrogate = 0;
226  }
227 
228  // Of the messages handled here, only WM_CHAR should be treated as
229  // characters. WM_SYS*CHAR are not part of text input, and WM_DEADCHAR
230  // will be incorporated into a later WM_CHAR with the full character.
231  // Also filter out:
232  // - Lead surrogates, which like dead keys will be send once combined.
233  // - ASCII control characters, which are sent as WM_CHAR events for all
234  // control key shortcuts.
235  if (message == WM_CHAR && s_pending_high_surrogate == 0 &&
236  character >= u' ') {
237  OnText(text);
238  }
239 
240  // All key presses that generate a character should be sent from
241  // WM_CHAR. In order to send the full key press information, the keycode
242  // is persisted in keycode_for_char_message_ obtained from WM_KEYDOWN.
243  if (keycode_for_char_message_ != 0) {
244  const unsigned int scancode = (lparam >> 16) & 0xff;
245  OnKey(keycode_for_char_message_, scancode, WM_KEYDOWN, code_point);
246  keycode_for_char_message_ = 0;
247  }
248  break;
249  }
250  case WM_KEYDOWN:
251  case WM_SYSKEYDOWN:
252  case WM_KEYUP:
253  case WM_SYSKEYUP:
254  const bool is_keydown_message =
255  (message == WM_KEYDOWN || message == WM_SYSKEYDOWN);
256  // Check if this key produces a character. If so, the key press should
257  // be sent with the character produced at WM_CHAR. Store the produced
258  // keycode (it's not accessible from WM_CHAR) to be used in WM_CHAR.
259  const unsigned int character = MapVirtualKey(wparam, MAPVK_VK_TO_CHAR);
260  if (character > 0 && is_keydown_message) {
261  keycode_for_char_message_ = wparam;
262  break;
263  }
264  unsigned int keyCode(wparam);
265  const unsigned int scancode = (lparam >> 16) & 0xff;
266  // If the key is a modifier, get its side.
267  if (keyCode == VK_SHIFT || keyCode == VK_MENU || keyCode == VK_CONTROL) {
268  keyCode = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX);
269  }
270  const int action = is_keydown_message ? WM_KEYDOWN : WM_KEYUP;
271  OnKey(keyCode, scancode, action, 0);
272  break;
273  }
274 
275  return DefWindowProc(window_handle_, message, wparam, lparam);
276 }
virtual void OnDpiScale(UINT dpi)=0
virtual void OnSetCursor()=0
UINT GetDpiForHWND(HWND hwnd)
virtual void OnText(const std::u16string &text)=0
virtual void OnKey(int key, int scancode, int action, char32_t character)=0
virtual void OnPointerUp(double x, double y, UINT button)=0
virtual void OnScroll(double delta_x, double delta_y)=0
SemanticsAction action
int32_t height
int32_t width
virtual void OnPointerLeave()=0
virtual void OnPointerDown(double x, double y, UINT button)=0
return TRUE
Definition: fl_view.cc:107
virtual void OnPointerMove(double x, double y)=0

◆ InitializeChild()

void flutter::Win32Window::InitializeChild ( const char *  title,
unsigned int  width,
unsigned int  height 
)

Definition at line 31 of file win32_window.cc.

References error, height, NarrowToWide(), RegisterWindowClass(), fml::size(), and width.

Referenced by flutter::Win32FlutterWindow::Win32FlutterWindow().

33  {
34  Destroy();
35  std::wstring converted_title = NarrowToWide(title);
36 
37  WNDCLASS window_class = RegisterWindowClass(converted_title);
38 
39  auto* result = CreateWindowEx(
40  0, window_class.lpszClassName, converted_title.c_str(),
41  WS_CHILD | WS_VISIBLE, CW_DEFAULT, CW_DEFAULT, width, height,
42  HWND_MESSAGE, nullptr, window_class.hInstance, this);
43 
44  if (result == nullptr) {
45  auto error = GetLastError();
46  LPWSTR message = nullptr;
47  size_t size = FormatMessageW(
48  FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
49  FORMAT_MESSAGE_IGNORE_INSERTS,
50  NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
51  reinterpret_cast<LPWSTR>(&message), 0, NULL);
52  OutputDebugString(message);
53  LocalFree(message);
54  }
55 }
WNDCLASS RegisterWindowClass(std::wstring &title)
Definition: win32_window.cc:65
FlMethodResponse GError ** error
constexpr std::size_t size(T(&array)[N])
Definition: size.h:13
int32_t height
int32_t width
std::wstring NarrowToWide(const char *source)
Definition: win32_window.cc:57

◆ NarrowToWide()

std::wstring flutter::Win32Window::NarrowToWide ( const char *  source)
protected

Definition at line 57 of file win32_window.cc.

References length.

Referenced by InitializeChild().

57  {
58  size_t length = strlen(source);
59  size_t outlen = 0;
60  std::wstring wideTitle(length, L'#');
61  mbstowcs_s(&outlen, &wideTitle[0], length + 1, source, length);
62  return wideTitle;
63 }
size_t length

◆ OnDpiScale()

virtual void flutter::Win32Window::OnDpiScale ( UINT  dpi)
protectedpure virtual

Referenced by HandleMessage().

◆ OnKey()

virtual void flutter::Win32Window::OnKey ( int  key,
int  scancode,
int  action,
char32_t  character 
)
protectedpure virtual

Implemented in flutter::Win32FlutterWindow.

Referenced by HandleMessage().

◆ OnPointerDown()

virtual void flutter::Win32Window::OnPointerDown ( double  x,
double  y,
UINT  button 
)
protectedpure virtual

Implemented in flutter::Win32FlutterWindow.

Referenced by HandleMessage().

◆ OnPointerLeave()

virtual void flutter::Win32Window::OnPointerLeave ( )
protectedpure virtual

Implemented in flutter::Win32FlutterWindow.

Referenced by HandleMessage().

◆ OnPointerMove()

virtual void flutter::Win32Window::OnPointerMove ( double  x,
double  y 
)
protectedpure virtual

Implemented in flutter::Win32FlutterWindow.

Referenced by HandleMessage().

◆ OnPointerUp()

virtual void flutter::Win32Window::OnPointerUp ( double  x,
double  y,
UINT  button 
)
protectedpure virtual

Implemented in flutter::Win32FlutterWindow.

Referenced by HandleMessage().

◆ OnResize()

virtual void flutter::Win32Window::OnResize ( UINT  width,
UINT  height 
)
protectedpure virtual

Referenced by GetWindowHandle().

◆ OnScroll()

virtual void flutter::Win32Window::OnScroll ( double  delta_x,
double  delta_y 
)
protectedpure virtual

Implemented in flutter::Win32FlutterWindow.

Referenced by HandleMessage().

◆ OnSetCursor()

virtual void flutter::Win32Window::OnSetCursor ( )
protectedpure virtual

Implemented in flutter::Win32FlutterWindow.

Referenced by HandleMessage().

◆ OnText()

virtual void flutter::Win32Window::OnText ( const std::u16string &  text)
protectedpure virtual

Implemented in flutter::Win32FlutterWindow.

Referenced by HandleMessage().

◆ RegisterWindowClass()

WNDCLASS flutter::Win32Window::RegisterWindowClass ( std::wstring &  title)
protected

Definition at line 65 of file win32_window.cc.

References WndProc().

Referenced by InitializeChild().

65  {
66  window_class_name_ = title;
67 
68  WNDCLASS window_class{};
69  window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
70  window_class.lpszClassName = title.c_str();
71  window_class.style = CS_HREDRAW | CS_VREDRAW;
72  window_class.cbClsExtra = 0;
73  window_class.cbWndExtra = 0;
74  window_class.hInstance = GetModuleHandle(nullptr);
75  window_class.hIcon = nullptr;
76  window_class.hbrBackground = 0;
77  window_class.lpszMenuName = nullptr;
78  window_class.lpfnWndProc = WndProc;
79  RegisterClass(&window_class);
80  return window_class;
81 }
static LRESULT CALLBACK WndProc(HWND const window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
Definition: win32_window.cc:83

◆ WndProc()

LRESULT CALLBACK flutter::Win32Window::WndProc ( HWND const  window,
UINT const  message,
WPARAM const  wparam,
LPARAM const  lparam 
)
staticprotectednoexcept

Definition at line 83 of file win32_window.cc.

Referenced by RegisterWindowClass().

86  {
87  if (message == WM_NCCREATE) {
88  auto cs = reinterpret_cast<CREATESTRUCT*>(lparam);
89  SetWindowLongPtr(window, GWLP_USERDATA,
90  reinterpret_cast<LONG_PTR>(cs->lpCreateParams));
91 
92  auto that = static_cast<Win32Window*>(cs->lpCreateParams);
93  that->window_handle_ = window;
94  } else if (Win32Window* that = GetThisFromHandle(window)) {
95  return that->HandleMessage(message, wparam, lparam);
96  }
97 
98  return DefWindowProc(window, message, wparam, lparam);
99 }

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