Flutter Engine
The Flutter Engine
Window_win.cpp
Go to the documentation of this file.
1/*
2* Copyright 2016 Google Inc.
3*
4* Use of this source code is governed by a BSD-style license that can be
5* found in the LICENSE file.
6*/
7
9
10#include <tchar.h>
11#include <windows.h>
12#include <windowsx.h>
13
14#include "src/base/SkUTF.h"
18
19#ifdef SK_VULKAN
21#endif
22
23namespace sk_app {
24
25static int gWindowX = CW_USEDEFAULT;
26static int gWindowY = 0;
27static int gWindowWidth = CW_USEDEFAULT;
28static int gWindowHeight = 0;
29
30Window* Window::CreateNativeWindow(void* platformData) {
31 HINSTANCE hInstance = (HINSTANCE)platformData;
32
34 if (!window->init(hInstance)) {
35 delete window;
36 return nullptr;
37 }
38
39 return window;
40}
41
42void Window_win::closeWindow() {
43 RECT r;
44 if (GetWindowRect(fHWnd, &r)) {
45 gWindowX = r.left;
46 gWindowY = r.top;
47 gWindowWidth = r.right - r.left;
48 gWindowHeight = r.bottom - r.top;
49 }
50 DestroyWindow(fHWnd);
51}
52
54 this->closeWindow();
55}
56
57LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
58
59
60bool Window_win::init(HINSTANCE hInstance) {
61 fHInstance = hInstance ? hInstance : GetModuleHandle(nullptr);
62
63 // The main window class name
64 static const TCHAR gSZWindowClass[] = _T("SkiaApp");
65
66 static WNDCLASSEX wcex;
67 static bool wcexInit = false;
68 if (!wcexInit) {
69 wcex.cbSize = sizeof(WNDCLASSEX);
70
71 wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
72 wcex.lpfnWndProc = WndProc;
73 wcex.cbClsExtra = 0;
74 wcex.cbWndExtra = 0;
75 wcex.hInstance = fHInstance;
76 wcex.hIcon = LoadIcon(fHInstance, (LPCTSTR)IDI_WINLOGO);
77 wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
78 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
79 wcex.lpszMenuName = nullptr;
80 wcex.lpszClassName = gSZWindowClass;
81 wcex.hIconSm = LoadIcon(fHInstance, (LPCTSTR)IDI_WINLOGO);
82
83 if (!RegisterClassEx(&wcex)) {
84 return false;
85 }
86 wcexInit = true;
87 }
88
89 /*
90 if (fullscreen)
91 {
92 DEVMODE dmScreenSettings;
93 // If full screen set the screen to maximum size of the users desktop and 32bit.
94 memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
95 dmScreenSettings.dmSize = sizeof(dmScreenSettings);
96 dmScreenSettings.dmPelsWidth = (unsigned long)width;
97 dmScreenSettings.dmPelsHeight = (unsigned long)height;
98 dmScreenSettings.dmBitsPerPel = 32;
99 dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
100
101 // Change the display settings to full screen.
102 ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
103
104 // Set the position of the window to the top left corner.
105 posX = posY = 0;
106 }
107 */
108 // gIsFullscreen = fullscreen;
109
110 fHWnd = CreateWindow(gSZWindowClass, nullptr, WS_OVERLAPPEDWINDOW,
112 nullptr, nullptr, fHInstance, nullptr);
113 if (!fHWnd)
114 {
115 return false;
116 }
117
118 SetWindowLongPtr(fHWnd, GWLP_USERDATA, (LONG_PTR)this);
119 RegisterTouchWindow(fHWnd, 0);
120
121 return true;
122}
123
125 static const struct {
126 WPARAM fVK;
127 skui::Key fKey;
128 } gPair[] = {
129 { VK_BACK, skui::Key::kBack },
130 { VK_CLEAR, skui::Key::kBack },
131 { VK_RETURN, skui::Key::kOK },
132 { VK_UP, skui::Key::kUp },
133 { VK_DOWN, skui::Key::kDown },
134 { VK_LEFT, skui::Key::kLeft },
135 { VK_RIGHT, skui::Key::kRight },
136 { VK_TAB, skui::Key::kTab },
137 { VK_PRIOR, skui::Key::kPageUp },
138 { VK_NEXT, skui::Key::kPageDown },
139 { VK_HOME, skui::Key::kHome },
140 { VK_END, skui::Key::kEnd },
141 { VK_DELETE, skui::Key::kDelete },
142 { VK_ESCAPE, skui::Key::kEscape },
143 { VK_SHIFT, skui::Key::kShift },
144 { VK_CONTROL, skui::Key::kCtrl },
145 { VK_MENU, skui::Key::kOption },
146 { 'A', skui::Key::kA },
147 { 'C', skui::Key::kC },
148 { 'V', skui::Key::kV },
149 { 'X', skui::Key::kX },
150 { 'Y', skui::Key::kY },
151 { 'Z', skui::Key::kZ },
152 };
153 for (size_t i = 0; i < std::size(gPair); i++) {
154 if (gPair[i].fVK == vk) {
155 return gPair[i].fKey;
156 }
157 }
158 return skui::Key::kNONE;
159}
160
163
164 switch (message) {
165 case WM_UNICHAR:
166 case WM_CHAR:
167 if (0 == (lParam & (1 << 30))) {
169 }
170 if (lParam & (1 << 29)) {
171 modifiers |= skui::ModifierKey::kOption;
172 }
173 break;
174
175 case WM_KEYDOWN:
176 case WM_SYSKEYDOWN:
177 if (0 == (lParam & (1 << 30))) {
179 }
180 if (lParam & (1 << 29)) {
181 modifiers |= skui::ModifierKey::kOption;
182 }
183 break;
184
185 case WM_KEYUP:
186 case WM_SYSKEYUP:
187 if (lParam & (1 << 29)) {
188 modifiers |= skui::ModifierKey::kOption;
189 }
190 break;
191
192 case WM_LBUTTONDOWN:
193 case WM_LBUTTONUP:
194 case WM_MOUSEMOVE:
195 case WM_MOUSEWHEEL:
196 if (wParam & MK_CONTROL) {
197 modifiers |= skui::ModifierKey::kControl;
198 }
199 if (wParam & MK_SHIFT) {
200 modifiers |= skui::ModifierKey::kShift;
201 }
202 break;
203 }
204
205 return modifiers;
206}
207
208LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
209{
210 PAINTSTRUCT ps;
211
212 Window_win* window = (Window_win*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
213
214 bool eventHandled = false;
215
216 switch (message) {
217 case WM_PAINT:
218 BeginPaint(hWnd, &ps);
219 window->onPaint();
220 EndPaint(hWnd, &ps);
221 eventHandled = true;
222 break;
223
224 case WM_CLOSE:
225 PostQuitMessage(0);
226 eventHandled = true;
227 break;
228
229 case WM_ACTIVATE:
230 // disable/enable rendering here, depending on wParam != WA_INACTIVE
231 break;
232
233 case WM_SIZE:
234 window->onResize(LOWORD(lParam), HIWORD(lParam));
235 eventHandled = true;
236 break;
237
238 case WM_UNICHAR:
239 eventHandled = window->onChar((SkUnichar)wParam,
240 get_modifiers(message, wParam, lParam));
241 break;
242
243 case WM_CHAR: {
244 const uint16_t* cPtr = reinterpret_cast<uint16_t*>(&wParam);
245 SkUnichar c = SkUTF::NextUTF16(&cPtr, cPtr + 2);
246 eventHandled = window->onChar(c, get_modifiers(message, wParam, lParam));
247 } break;
248
249 case WM_KEYDOWN:
250 case WM_SYSKEYDOWN:
251 eventHandled = window->onKey(get_key(wParam), skui::InputState::kDown,
252 get_modifiers(message, wParam, lParam));
253 break;
254
255 case WM_KEYUP:
256 case WM_SYSKEYUP:
257 eventHandled = window->onKey(get_key(wParam), skui::InputState::kUp,
258 get_modifiers(message, wParam, lParam));
259 break;
260
261 case WM_LBUTTONDOWN:
262 case WM_LBUTTONUP: {
263 int xPos = GET_X_LPARAM(lParam);
264 int yPos = GET_Y_LPARAM(lParam);
265
266 //if (!gIsFullscreen)
267 //{
268 // RECT rc = { 0, 0, 640, 480 };
269 // AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
270 // xPos -= rc.left;
271 // yPos -= rc.top;
272 //}
273
274 skui::InputState istate = ((wParam & MK_LBUTTON) != 0) ? skui::InputState::kDown
276
277 eventHandled = window->onMouse(xPos, yPos, istate,
278 get_modifiers(message, wParam, lParam));
279 } break;
280
281 case WM_MOUSEMOVE: {
282 int xPos = GET_X_LPARAM(lParam);
283 int yPos = GET_Y_LPARAM(lParam);
284
285 //if (!gIsFullscreen)
286 //{
287 // RECT rc = { 0, 0, 640, 480 };
288 // AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
289 // xPos -= rc.left;
290 // yPos -= rc.top;
291 //}
292
293 eventHandled = window->onMouse(xPos, yPos, skui::InputState::kMove,
294 get_modifiers(message, wParam, lParam));
295 } break;
296
297 case WM_MOUSEWHEEL: {
298 int xPos = GET_X_LPARAM(lParam);
299 int yPos = GET_Y_LPARAM(lParam);
300 eventHandled = window->onMouseWheel(GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f,
301 xPos,
302 yPos,
303 get_modifiers(message, wParam, lParam));
304 } break;
305
306 case WM_TOUCH: {
307 uint16_t numInputs = LOWORD(wParam);
308 std::unique_ptr<TOUCHINPUT[]> inputs(new TOUCHINPUT[numInputs]);
309 if (GetTouchInputInfo((HTOUCHINPUT)lParam, numInputs, inputs.get(),
310 sizeof(TOUCHINPUT))) {
311 POINT topLeft = {0, 0};
312 ClientToScreen(hWnd, &topLeft);
313 for (uint16_t i = 0; i < numInputs; ++i) {
314 TOUCHINPUT ti = inputs[i];
316 if (ti.dwFlags & TOUCHEVENTF_DOWN) {
318 } else if (ti.dwFlags & TOUCHEVENTF_MOVE) {
320 } else if (ti.dwFlags & TOUCHEVENTF_UP) {
322 } else {
323 continue;
324 }
325 // TOUCHINPUT coordinates are in 100ths of pixels
326 // Adjust for that, and make them window relative
327 LONG tx = (ti.x / 100) - topLeft.x;
328 LONG ty = (ti.y / 100) - topLeft.y;
329 eventHandled = window->onTouch(ti.dwID, state, tx, ty) || eventHandled;
330 }
331 }
332 } break;
333
334 default:
335 return DefWindowProc(hWnd, message, wParam, lParam);
336 }
337
338 return eventHandled ? 0 : 1;
339}
340
341void Window_win::setTitle(const char* title) {
342 SetWindowTextA(fHWnd, title);
343}
344
346 ShowWindow(fHWnd, SW_SHOW);
347}
348
349
351 fBackend = attachType;
352 fInitializedBackend = true;
353
354 switch (attachType) {
355#ifdef SK_GL
356 case kNativeGL_BackendType:
358 break;
359#endif
360#if SK_ANGLE
361 case kANGLE_BackendType:
363 break;
364#endif
365#ifdef SK_DAWN
366#if defined(SK_GRAPHITE)
367 case kGraphiteDawn_BackendType:
369 break;
370#endif
371#endif
374 break;
375#ifdef SK_VULKAN
376 case kVulkan_BackendType:
378 break;
379#if defined(SK_GRAPHITE)
380 case kGraphiteVulkan_BackendType:
382 break;
383#endif
384#endif
385#ifdef SK_DIRECT3D
386 case kDirect3D_BackendType:
388 break;
389#endif
390 }
391 this->onBackendCreated();
392
393 return (SkToBool(fWindowContext));
394}
395
397 InvalidateRect(fHWnd, nullptr, false);
398}
399
401 // GL on Windows doesn't let us change MSAA after the window is created
402 if (params.fMSAASampleCount != this->getRequestedDisplayParams().fMSAASampleCount
403 && allowReattach) {
404 // Need to change these early, so attach() creates the window context correctly
406
407 fWindowContext = nullptr;
408 this->closeWindow();
409 this->init(fHInstance);
410 if (fInitializedBackend) {
411 this->attach(fBackend);
412 }
413 }
414
416}
417
418} // namespace sk_app
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
int32_t SkUnichar
Definition: SkTypes.h:175
void show() override
Definition: Window_win.cpp:345
void onInval() override
Definition: Window_win.cpp:396
void setRequestedDisplayParams(const DisplayParams &, bool allowReattach) override
Definition: Window_win.cpp:400
bool init(HINSTANCE instance)
Definition: Window_win.cpp:60
bool attach(BackendType) override
Definition: Window_win.cpp:350
~Window_win() override
Definition: Window_win.cpp:53
void setTitle(const char *) override
Definition: Window_win.cpp:341
static Window * CreateNativeWindow(void *platformData)
@ kRaster_BackendType
Definition: Window.h:90
virtual void setRequestedDisplayParams(const DisplayParams &, bool allowReattach=true)
Definition: Window.cpp:137
DisplayParams fRequestedDisplayParams
Definition: Window.h:176
std::unique_ptr< skwindow::WindowContext > fWindowContext
Definition: Window.h:179
void onBackendCreated()
Definition: Window.cpp:44
const EmbeddedViewParams * params
GLFWwindow * window
Definition: main.cc:45
AtkStateType state
Win32Message message
SK_SPI SkUnichar NextUTF16(const uint16_t **ptr, const uint16_t *end)
Definition: SkUTF.cpp:159
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
vk
Definition: malisc.py:42
static int gWindowY
Definition: Window_win.cpp:26
static int gWindowX
Definition: Window_win.cpp:25
static int gWindowWidth
Definition: Window_win.cpp:27
static int gWindowHeight
Definition: Window_win.cpp:28
static skui::ModifierKey get_modifiers(const XEvent &event)
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
Definition: Window_win.cpp:208
static skui::Key get_key(KeySym keysym)
InputState
Definition: InputState.h:6
ModifierKey
Definition: ModifierKey.h:9
Key
Definition: Key.h:6
@ kBack
(CLR)
@ kHome
the home key - added to match android
@ kEnd
the red key
@ kOK
the center key
std::unique_ptr< WindowContext > MakeVulkanForWin(HWND hwnd, const DisplayParams &params)
std::unique_ptr< WindowContext > MakeD3D12ForWin(HWND hwnd, const DisplayParams &params)
std::unique_ptr< WindowContext > MakeRasterForWin(HWND wnd, const DisplayParams &params)
std::unique_ptr< WindowContext > MakeANGLEForWin(HWND wnd, const DisplayParams &params)
std::unique_ptr< WindowContext > MakeGLForWin(HWND wnd, const DisplayParams &params)
std::unique_ptr< WindowContext > MakeGraphiteDawnD3D12ForWin(HWND hwnd, const DisplayParams &params)
std::unique_ptr< WindowContext > MakeGraphiteVulkanForWin(HWND hwnd, const DisplayParams &params)
long LONG
Definition: windows_types.h:23
LONG_PTR LRESULT
Definition: windows_types.h:61
unsigned int UINT
Definition: windows_types.h:32
LONG_PTR LPARAM
Definition: windows_types.h:60
__w64 long LONG_PTR
Definition: windows_types.h:55
#define LoadIcon
UINT_PTR WPARAM
Definition: windows_types.h:59
#define CALLBACK