Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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:
357 fWindowContext = skwindow::MakeGLForWin(fHWnd, fRequestedDisplayParams);
358 break;
359#endif
360#if SK_ANGLE
361 case kANGLE_BackendType:
362 fWindowContext = skwindow::MakeANGLEForWin(fHWnd, fRequestedDisplayParams);
363 break;
364#endif
365#ifdef SK_DAWN
366#if defined(SK_GRAPHITE)
367 case kGraphiteDawn_BackendType:
368 fWindowContext = skwindow::MakeGraphiteDawnD3D12ForWin(fHWnd, fRequestedDisplayParams);
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:
387 fWindowContext = skwindow::MakeD3D12ForWin(fHWnd, fRequestedDisplayParams);
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
void onInval() override
void setRequestedDisplayParams(const DisplayParams &, bool allowReattach) override
bool init(HINSTANCE instance)
bool attach(BackendType) override
~Window_win() override
void setTitle(const char *) override
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:171
std::unique_ptr< skwindow::WindowContext > fWindowContext
Definition Window.h:174
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
static int gWindowY
static int gWindowX
static int gWindowWidth
static int gWindowHeight
static skui::ModifierKey get_modifiers(const XEvent &event)
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
static skui::Key get_key(KeySym keysym)
InputState
Definition InputState.h:6
ModifierKey
Definition ModifierKey.h:9
Key
Definition Key.h:6
std::unique_ptr< WindowContext > MakeVulkanForWin(HWND hwnd, const DisplayParams &params)
std::unique_ptr< WindowContext > MakeRasterForWin(HWND wnd, const DisplayParams &params)
std::unique_ptr< WindowContext > MakeGraphiteVulkanForWin(HWND hwnd, const DisplayParams &params)
long LONG
LONG_PTR LRESULT
unsigned int UINT
LONG_PTR LPARAM
__w64 long LONG_PTR
#define LoadIcon
UINT_PTR WPARAM
#define CALLBACK