58224d6d51817c2647655a2c651b2867f309a354
[platform/upstream/libSkiaSharp.git] / tools / vulkan / win / Window_win.cpp
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
8 #include "Window_win.h"
9
10 #include <tchar.h>
11 #include <windows.h>
12 #include <windowsx.h>
13
14 #include "SkUtils.h"
15 #include "VulkanTestContext_win.h"
16
17 Window* Window::CreateNativeWindow(void* platformData) {
18     HINSTANCE hInstance = (HINSTANCE)platformData;
19
20     Window_win* window = new Window_win();
21     if (!window->init(hInstance)) {
22         delete window;
23         return nullptr;
24     }
25
26     return window;
27 }
28
29 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
30
31 bool Window_win::init(HINSTANCE hInstance) {
32     fHInstance = hInstance ? hInstance : GetModuleHandle(nullptr);
33
34     WNDCLASSEX wcex;
35     // The main window class name
36     static const TCHAR gSZWindowClass[] = _T("SkiaApp");
37
38     wcex.cbSize = sizeof(WNDCLASSEX);
39
40     wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
41     wcex.lpfnWndProc = WndProc;
42     wcex.cbClsExtra = 0;
43     wcex.cbWndExtra = 0;
44     wcex.hInstance = fHInstance;
45     wcex.hIcon = LoadIcon(fHInstance, (LPCTSTR)IDI_WINLOGO);
46     wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);;
47     wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
48     wcex.lpszMenuName = nullptr;
49     wcex.lpszClassName = gSZWindowClass;
50     wcex.hIconSm = LoadIcon(fHInstance, (LPCTSTR)IDI_WINLOGO);;
51
52     if (!RegisterClassEx(&wcex)) {
53         return false;
54     }
55
56    /*
57     if (fullscreen)
58     {
59         DEVMODE dmScreenSettings;
60         // If full screen set the screen to maximum size of the users desktop and 32bit.
61         memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
62         dmScreenSettings.dmSize = sizeof(dmScreenSettings);
63         dmScreenSettings.dmPelsWidth = (unsigned long)width;
64         dmScreenSettings.dmPelsHeight = (unsigned long)height;
65         dmScreenSettings.dmBitsPerPel = 32;
66         dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
67
68         // Change the display settings to full screen.
69         ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
70
71         // Set the position of the window to the top left corner.
72         posX = posY = 0;
73     } 
74     */
75  //   gIsFullscreen = fullscreen;
76
77     fHWnd = CreateWindow(gSZWindowClass, nullptr, WS_OVERLAPPEDWINDOW,
78                          CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, fHInstance, nullptr);
79     if (!fHWnd)
80     {
81         return false;
82     }
83
84     SetWindowLongPtr(fHWnd, GWLP_USERDATA, (LONG_PTR)this);
85
86     return true;
87 }
88
89 static Window::Key get_key(WPARAM vk) {
90     static const struct {
91         WPARAM      fVK;
92         Window::Key fKey;
93     } gPair[] = {
94         { VK_BACK, Window::kBack_Key },
95         { VK_CLEAR, Window::kBack_Key },
96         { VK_RETURN, Window::kOK_Key },
97         { VK_UP, Window::kUp_Key },
98         { VK_DOWN, Window::kDown_Key },
99         { VK_LEFT, Window::kLeft_Key },
100         { VK_RIGHT, Window::kRight_Key }
101     };
102     for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
103         if (gPair[i].fVK == vk) {
104             return gPair[i].fKey;
105         }
106     }
107     return Window::kNONE_Key;
108 }
109
110 static uint32_t get_modifiers(UINT message, WPARAM wParam, LPARAM lParam) {
111     uint32_t modifiers = 0;
112
113     switch (message) {
114         case WM_UNICHAR:
115         case WM_CHAR:
116             if (0 == (lParam & (1 << 30))) {
117                 modifiers |= Window::kFirstPress_ModifierKey;
118             }
119             if (lParam & (1 << 29)) {
120                 modifiers |= Window::kOption_ModifierKey;
121             }
122             break;
123
124         case WM_KEYDOWN:
125         case WM_SYSKEYDOWN:
126             if (0 == (lParam & (1 << 30))) {
127                 modifiers |= Window::kFirstPress_ModifierKey;
128             }
129             if (lParam & (1 << 29)) {
130                 modifiers |= Window::kOption_ModifierKey;
131             }
132             break;
133
134         case WM_KEYUP:
135         case WM_SYSKEYUP:
136             if (lParam & (1 << 29)) {
137                 modifiers |= Window::kOption_ModifierKey;
138             }
139             break;
140
141         case WM_LBUTTONDOWN:
142         case WM_LBUTTONUP:
143         case WM_MOUSEMOVE:
144             if (wParam & MK_CONTROL) {
145                 modifiers |= Window::kControl_ModifierKey;
146             }
147             if (wParam & MK_SHIFT) {
148                 modifiers |= Window::kShift_ModifierKey;
149             }
150     }
151
152     return modifiers;
153 }
154
155 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
156 {
157     PAINTSTRUCT ps;
158     HDC hdc;
159
160     Window_win* window = (Window_win*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
161
162     bool eventHandled = false;
163
164     switch (message) {
165         case WM_PAINT:
166             hdc = BeginPaint(hWnd, &ps);
167             window->onPaint();
168             EndPaint(hWnd, &ps);
169             eventHandled = true;
170             break;
171
172         case WM_CLOSE:
173         case WM_DESTROY:
174             PostQuitMessage(0);
175             eventHandled = true;
176             break;
177
178         case WM_ACTIVATE:
179             // disable/enable rendering here, depending on wParam != WA_INACTIVE
180             break;
181
182         case WM_SIZE:
183             window->onResize(LOWORD(lParam), HIWORD(lParam));
184             eventHandled = true;
185             break;
186
187         case WM_UNICHAR:
188             eventHandled = window->onChar((SkUnichar)wParam, 
189                                           get_modifiers(message, wParam, lParam));
190             break;
191
192         case WM_CHAR: {
193             const uint16_t* c = reinterpret_cast<uint16_t*>(&wParam);
194             eventHandled = window->onChar(SkUTF16_NextUnichar(&c), 
195                                           get_modifiers(message, wParam, lParam));
196         } break;
197
198         case WM_KEYDOWN:
199         case WM_SYSKEYDOWN:
200             eventHandled = window->onKey(get_key(wParam), Window::kDown_InputState, 
201                                          get_modifiers(message, wParam, lParam));
202             break;
203
204         case WM_KEYUP:
205         case WM_SYSKEYUP:
206             eventHandled = window->onKey(get_key(wParam), Window::kUp_InputState,
207                                          get_modifiers(message, wParam, lParam));
208             break;
209
210         case WM_LBUTTONDOWN:
211         case WM_LBUTTONUP: {
212             int xPos = GET_X_LPARAM(lParam);
213             int yPos = GET_Y_LPARAM(lParam);
214
215             //if (!gIsFullscreen)
216             //{
217             //    RECT rc = { 0, 0, 640, 480 };
218             //    AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
219             //    xPos -= rc.left;
220             //    yPos -= rc.top;
221             //}
222
223             Window::InputState istate = ((wParam & MK_LBUTTON) != 0) ? Window::kDown_InputState
224                                                                      : Window::kUp_InputState;
225
226             eventHandled = window->onMouse(xPos, yPos, istate, 
227                                             get_modifiers(message, wParam, lParam));
228         } break;
229
230         case WM_MOUSEMOVE: 
231             // only track if left button is down
232             if ((wParam & MK_LBUTTON) != 0) {
233                 int xPos = GET_X_LPARAM(lParam);
234                 int yPos = GET_Y_LPARAM(lParam);
235
236                 //if (!gIsFullscreen)
237                 //{
238                 //    RECT rc = { 0, 0, 640, 480 };
239                 //    AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
240                 //    xPos -= rc.left;
241                 //    yPos -= rc.top;
242                 //}
243
244                 eventHandled = window->onMouse(xPos, yPos, Window::kMove_InputState,
245                                                get_modifiers(message, wParam, lParam));
246             }
247             break;
248
249         default:
250             return DefWindowProc(hWnd, message, wParam, lParam);
251     }
252
253     return eventHandled ? 0 : 1;
254 }
255
256 void Window_win::setTitle(const char* title) {
257     SetWindowTextA(fHWnd, title);
258 }
259
260 void Window_win::show() {
261     ShowWindow(fHWnd, SW_SHOW);
262 }
263
264
265 bool Window_win::attach(BackEndType attachType, int msaaSampleCount) {
266     if (kVulkan_BackendType != attachType) {
267         return false;
268     }
269
270     ContextPlatformData_win platformData;
271     platformData.fHInstance = fHInstance;
272     platformData.fHWnd = fHWnd;
273
274     fTestContext = VulkanTestContext::Create((void*)&platformData, msaaSampleCount);
275
276     return (SkToBool(fTestContext));
277 }
278
279 void Window_win::inval() {
280     InvalidateRect(fHWnd, nullptr, false);
281 }