• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // Win32Window.cpp: Implementation of OSWindow for Win32 (Windows)
8 
9 #include "util/windows/win32/Win32Window.h"
10 
11 #include <sstream>
12 
13 #include "common/debug.h"
14 
VirtualKeyCodeToKey(WPARAM key,LPARAM flags)15 Key VirtualKeyCodeToKey(WPARAM key, LPARAM flags)
16 {
17     switch (key)
18     {
19         // Check the scancode to distinguish between left and right shift
20         case VK_SHIFT:
21         {
22             static unsigned int lShift = MapVirtualKey(VK_LSHIFT, MAPVK_VK_TO_VSC);
23             unsigned int scancode      = static_cast<unsigned int>((flags & (0xFF << 16)) >> 16);
24             return scancode == lShift ? KEY_LSHIFT : KEY_RSHIFT;
25         }
26 
27         // Check the "extended" flag to distinguish between left and right alt
28         case VK_MENU:
29             return (HIWORD(flags) & KF_EXTENDED) ? KEY_RALT : KEY_LALT;
30 
31         // Check the "extended" flag to distinguish between left and right control
32         case VK_CONTROL:
33             return (HIWORD(flags) & KF_EXTENDED) ? KEY_RCONTROL : KEY_LCONTROL;
34 
35         // Other keys are reported properly
36         case VK_LWIN:
37             return KEY_LSYSTEM;
38         case VK_RWIN:
39             return KEY_RSYSTEM;
40         case VK_APPS:
41             return KEY_MENU;
42         case VK_OEM_1:
43             return KEY_SEMICOLON;
44         case VK_OEM_2:
45             return KEY_SLASH;
46         case VK_OEM_PLUS:
47             return KEY_EQUAL;
48         case VK_OEM_MINUS:
49             return KEY_DASH;
50         case VK_OEM_4:
51             return KEY_LBRACKET;
52         case VK_OEM_6:
53             return KEY_RBRACKET;
54         case VK_OEM_COMMA:
55             return KEY_COMMA;
56         case VK_OEM_PERIOD:
57             return KEY_PERIOD;
58         case VK_OEM_7:
59             return KEY_QUOTE;
60         case VK_OEM_5:
61             return KEY_BACKSLASH;
62         case VK_OEM_3:
63             return KEY_TILDE;
64         case VK_ESCAPE:
65             return KEY_ESCAPE;
66         case VK_SPACE:
67             return KEY_SPACE;
68         case VK_RETURN:
69             return KEY_RETURN;
70         case VK_BACK:
71             return KEY_BACK;
72         case VK_TAB:
73             return KEY_TAB;
74         case VK_PRIOR:
75             return KEY_PAGEUP;
76         case VK_NEXT:
77             return KEY_PAGEDOWN;
78         case VK_END:
79             return KEY_END;
80         case VK_HOME:
81             return KEY_HOME;
82         case VK_INSERT:
83             return KEY_INSERT;
84         case VK_DELETE:
85             return KEY_DELETE;
86         case VK_ADD:
87             return KEY_ADD;
88         case VK_SUBTRACT:
89             return KEY_SUBTRACT;
90         case VK_MULTIPLY:
91             return KEY_MULTIPLY;
92         case VK_DIVIDE:
93             return KEY_DIVIDE;
94         case VK_PAUSE:
95             return KEY_PAUSE;
96         case VK_F1:
97             return KEY_F1;
98         case VK_F2:
99             return KEY_F2;
100         case VK_F3:
101             return KEY_F3;
102         case VK_F4:
103             return KEY_F4;
104         case VK_F5:
105             return KEY_F5;
106         case VK_F6:
107             return KEY_F6;
108         case VK_F7:
109             return KEY_F7;
110         case VK_F8:
111             return KEY_F8;
112         case VK_F9:
113             return KEY_F9;
114         case VK_F10:
115             return KEY_F10;
116         case VK_F11:
117             return KEY_F11;
118         case VK_F12:
119             return KEY_F12;
120         case VK_F13:
121             return KEY_F13;
122         case VK_F14:
123             return KEY_F14;
124         case VK_F15:
125             return KEY_F15;
126         case VK_LEFT:
127             return KEY_LEFT;
128         case VK_RIGHT:
129             return KEY_RIGHT;
130         case VK_UP:
131             return KEY_UP;
132         case VK_DOWN:
133             return KEY_DOWN;
134         case VK_NUMPAD0:
135             return KEY_NUMPAD0;
136         case VK_NUMPAD1:
137             return KEY_NUMPAD1;
138         case VK_NUMPAD2:
139             return KEY_NUMPAD2;
140         case VK_NUMPAD3:
141             return KEY_NUMPAD3;
142         case VK_NUMPAD4:
143             return KEY_NUMPAD4;
144         case VK_NUMPAD5:
145             return KEY_NUMPAD5;
146         case VK_NUMPAD6:
147             return KEY_NUMPAD6;
148         case VK_NUMPAD7:
149             return KEY_NUMPAD7;
150         case VK_NUMPAD8:
151             return KEY_NUMPAD8;
152         case VK_NUMPAD9:
153             return KEY_NUMPAD9;
154         case 'A':
155             return KEY_A;
156         case 'Z':
157             return KEY_Z;
158         case 'E':
159             return KEY_E;
160         case 'R':
161             return KEY_R;
162         case 'T':
163             return KEY_T;
164         case 'Y':
165             return KEY_Y;
166         case 'U':
167             return KEY_U;
168         case 'I':
169             return KEY_I;
170         case 'O':
171             return KEY_O;
172         case 'P':
173             return KEY_P;
174         case 'Q':
175             return KEY_Q;
176         case 'S':
177             return KEY_S;
178         case 'D':
179             return KEY_D;
180         case 'F':
181             return KEY_F;
182         case 'G':
183             return KEY_G;
184         case 'H':
185             return KEY_H;
186         case 'J':
187             return KEY_J;
188         case 'K':
189             return KEY_K;
190         case 'L':
191             return KEY_L;
192         case 'M':
193             return KEY_M;
194         case 'W':
195             return KEY_W;
196         case 'X':
197             return KEY_X;
198         case 'C':
199             return KEY_C;
200         case 'V':
201             return KEY_V;
202         case 'B':
203             return KEY_B;
204         case 'N':
205             return KEY_N;
206         case '0':
207             return KEY_NUM0;
208         case '1':
209             return KEY_NUM1;
210         case '2':
211             return KEY_NUM2;
212         case '3':
213             return KEY_NUM3;
214         case '4':
215             return KEY_NUM4;
216         case '5':
217             return KEY_NUM5;
218         case '6':
219             return KEY_NUM6;
220         case '7':
221             return KEY_NUM7;
222         case '8':
223             return KEY_NUM8;
224         case '9':
225             return KEY_NUM9;
226     }
227 
228     return Key(0);
229 }
230 
WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)231 LRESULT CALLBACK Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
232 {
233     switch (message)
234     {
235         case WM_NCCREATE:
236         {
237             LPCREATESTRUCT pCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
238             SetWindowLongPtr(hWnd, GWLP_USERDATA,
239                              reinterpret_cast<LONG_PTR>(pCreateStruct->lpCreateParams));
240             return DefWindowProcA(hWnd, message, wParam, lParam);
241         }
242     }
243 
244     Win32Window *window = reinterpret_cast<Win32Window *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
245     if (window)
246     {
247         switch (message)
248         {
249             case WM_DESTROY:
250             case WM_CLOSE:
251             {
252                 Event event;
253                 event.Type = Event::EVENT_CLOSED;
254                 window->pushEvent(event);
255                 break;
256             }
257 
258             case WM_MOVE:
259             {
260                 RECT winRect;
261                 GetClientRect(hWnd, &winRect);
262 
263                 POINT topLeft;
264                 topLeft.x = winRect.left;
265                 topLeft.y = winRect.top;
266                 ClientToScreen(hWnd, &topLeft);
267 
268                 Event event;
269                 event.Type   = Event::EVENT_MOVED;
270                 event.Move.X = topLeft.x;
271                 event.Move.Y = topLeft.y;
272                 window->pushEvent(event);
273 
274                 break;
275             }
276 
277             case WM_SIZE:
278             {
279                 RECT winRect;
280                 GetClientRect(hWnd, &winRect);
281 
282                 POINT topLeft;
283                 topLeft.x = winRect.left;
284                 topLeft.y = winRect.top;
285                 ClientToScreen(hWnd, &topLeft);
286 
287                 POINT botRight;
288                 botRight.x = winRect.right;
289                 botRight.y = winRect.bottom;
290                 ClientToScreen(hWnd, &botRight);
291 
292                 Event event;
293                 event.Type        = Event::EVENT_RESIZED;
294                 event.Size.Width  = botRight.x - topLeft.x;
295                 event.Size.Height = botRight.y - topLeft.y;
296                 window->pushEvent(event);
297 
298                 break;
299             }
300 
301             case WM_SETFOCUS:
302             {
303                 Event event;
304                 event.Type = Event::EVENT_GAINED_FOCUS;
305                 window->pushEvent(event);
306                 break;
307             }
308 
309             case WM_KILLFOCUS:
310             {
311                 Event event;
312                 event.Type = Event::EVENT_LOST_FOCUS;
313                 window->pushEvent(event);
314                 break;
315             }
316 
317             case WM_KEYDOWN:
318             case WM_SYSKEYDOWN:
319             case WM_KEYUP:
320             case WM_SYSKEYUP:
321             {
322                 bool down = (message == WM_KEYDOWN || message == WM_SYSKEYDOWN);
323 
324                 Event event;
325                 event.Type        = down ? Event::EVENT_KEY_PRESSED : Event::EVENT_KEY_RELEASED;
326                 event.Key.Alt     = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
327                 event.Key.Control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
328                 event.Key.Shift   = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
329                 event.Key.System =
330                     HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN));
331                 event.Key.Code = VirtualKeyCodeToKey(wParam, lParam);
332                 window->pushEvent(event);
333 
334                 break;
335             }
336 
337             case WM_MOUSEWHEEL:
338             {
339                 Event event;
340                 event.Type             = Event::EVENT_MOUSE_WHEEL_MOVED;
341                 event.MouseWheel.Delta = static_cast<short>(HIWORD(wParam)) / 120;
342                 window->pushEvent(event);
343                 break;
344             }
345 
346             case WM_LBUTTONDOWN:
347             case WM_LBUTTONDBLCLK:
348             {
349                 Event event;
350                 event.Type               = Event::EVENT_MOUSE_BUTTON_PRESSED;
351                 event.MouseButton.Button = MOUSEBUTTON_LEFT;
352                 event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
353                 event.MouseButton.Y      = static_cast<short>(HIWORD(lParam));
354                 window->pushEvent(event);
355                 break;
356             }
357 
358             case WM_LBUTTONUP:
359             {
360                 Event event;
361                 event.Type               = Event::EVENT_MOUSE_BUTTON_RELEASED;
362                 event.MouseButton.Button = MOUSEBUTTON_LEFT;
363                 event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
364                 event.MouseButton.Y      = static_cast<short>(HIWORD(lParam));
365                 window->pushEvent(event);
366                 break;
367             }
368 
369             case WM_RBUTTONDOWN:
370             case WM_RBUTTONDBLCLK:
371             {
372                 Event event;
373                 event.Type               = Event::EVENT_MOUSE_BUTTON_PRESSED;
374                 event.MouseButton.Button = MOUSEBUTTON_RIGHT;
375                 event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
376                 event.MouseButton.Y      = static_cast<short>(HIWORD(lParam));
377                 window->pushEvent(event);
378                 break;
379             }
380 
381             // Mouse right button up event
382             case WM_RBUTTONUP:
383             {
384                 Event event;
385                 event.Type               = Event::EVENT_MOUSE_BUTTON_RELEASED;
386                 event.MouseButton.Button = MOUSEBUTTON_RIGHT;
387                 event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
388                 event.MouseButton.Y      = static_cast<short>(HIWORD(lParam));
389                 window->pushEvent(event);
390                 break;
391             }
392 
393             // Mouse wheel button down event
394             case WM_MBUTTONDOWN:
395             case WM_MBUTTONDBLCLK:
396             {
397                 Event event;
398                 event.Type               = Event::EVENT_MOUSE_BUTTON_PRESSED;
399                 event.MouseButton.Button = MOUSEBUTTON_MIDDLE;
400                 event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
401                 event.MouseButton.Y      = static_cast<short>(HIWORD(lParam));
402                 window->pushEvent(event);
403                 break;
404             }
405 
406             // Mouse wheel button up event
407             case WM_MBUTTONUP:
408             {
409                 Event event;
410                 event.Type               = Event::EVENT_MOUSE_BUTTON_RELEASED;
411                 event.MouseButton.Button = MOUSEBUTTON_MIDDLE;
412                 event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
413                 event.MouseButton.Y      = static_cast<short>(HIWORD(lParam));
414                 window->pushEvent(event);
415                 break;
416             }
417 
418             // Mouse X button down event
419             case WM_XBUTTONDOWN:
420             case WM_XBUTTONDBLCLK:
421             {
422                 Event event;
423                 event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED;
424                 event.MouseButton.Button =
425                     (HIWORD(wParam) == XBUTTON1) ? MOUSEBUTTON_BUTTON4 : MOUSEBUTTON_BUTTON5;
426                 event.MouseButton.X = static_cast<short>(LOWORD(lParam));
427                 event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
428                 window->pushEvent(event);
429                 break;
430             }
431 
432             // Mouse X button up event
433             case WM_XBUTTONUP:
434             {
435                 Event event;
436                 event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED;
437                 event.MouseButton.Button =
438                     (HIWORD(wParam) == XBUTTON1) ? MOUSEBUTTON_BUTTON4 : MOUSEBUTTON_BUTTON5;
439                 event.MouseButton.X = static_cast<short>(LOWORD(lParam));
440                 event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
441                 window->pushEvent(event);
442                 break;
443             }
444 
445             case WM_MOUSEMOVE:
446             {
447                 if (!window->mIsMouseInWindow)
448                 {
449                     window->mIsMouseInWindow = true;
450                     Event event;
451                     event.Type = Event::EVENT_MOUSE_ENTERED;
452                     window->pushEvent(event);
453                 }
454 
455                 int mouseX = static_cast<short>(LOWORD(lParam));
456                 int mouseY = static_cast<short>(HIWORD(lParam));
457 
458                 Event event;
459                 event.Type        = Event::EVENT_MOUSE_MOVED;
460                 event.MouseMove.X = mouseX;
461                 event.MouseMove.Y = mouseY;
462                 window->pushEvent(event);
463                 break;
464             }
465 
466             case WM_MOUSELEAVE:
467             {
468                 Event event;
469                 event.Type = Event::EVENT_MOUSE_LEFT;
470                 window->pushEvent(event);
471                 window->mIsMouseInWindow = false;
472                 break;
473             }
474 
475             case WM_USER:
476             {
477                 Event testEvent;
478                 testEvent.Type = Event::EVENT_TEST;
479                 window->pushEvent(testEvent);
480                 break;
481             }
482         }
483     }
484     return DefWindowProcA(hWnd, message, wParam, lParam);
485 }
486 
Win32Window()487 Win32Window::Win32Window()
488     : mIsVisible(false),
489       mIsMouseInWindow(false),
490       mNativeWindow(0),
491       mParentWindow(0),
492       mNativeDisplay(0)
493 {}
494 
~Win32Window()495 Win32Window::~Win32Window()
496 {
497     destroy();
498 }
499 
initialize(const std::string & name,int width,int height)500 bool Win32Window::initialize(const std::string &name, int width, int height)
501 {
502     destroy();
503 
504     // Use a new window class name for ever window to ensure that a new window can be created
505     // even if the last one was not properly destroyed
506     static size_t windowIdx = 0;
507     std::ostringstream nameStream;
508     nameStream << name << "_" << windowIdx++;
509 
510     mParentClassName = nameStream.str();
511     mChildClassName  = mParentClassName + "_Child";
512 
513     // Work around compile error from not defining "UNICODE" while Chromium does
514     const LPSTR idcArrow = MAKEINTRESOURCEA(32512);
515 
516     WNDCLASSEXA parentWindowClass   = {};
517     parentWindowClass.cbSize        = sizeof(WNDCLASSEXA);
518     parentWindowClass.style         = 0;
519     parentWindowClass.lpfnWndProc   = WndProc;
520     parentWindowClass.cbClsExtra    = 0;
521     parentWindowClass.cbWndExtra    = 0;
522     parentWindowClass.hInstance     = GetModuleHandle(nullptr);
523     parentWindowClass.hIcon         = nullptr;
524     parentWindowClass.hCursor       = LoadCursorA(nullptr, idcArrow);
525     parentWindowClass.hbrBackground = 0;
526     parentWindowClass.lpszMenuName  = nullptr;
527     parentWindowClass.lpszClassName = mParentClassName.c_str();
528     if (!RegisterClassExA(&parentWindowClass))
529     {
530         return false;
531     }
532 
533     WNDCLASSEXA childWindowClass   = {};
534     childWindowClass.cbSize        = sizeof(WNDCLASSEXA);
535     childWindowClass.style         = CS_OWNDC;
536     childWindowClass.lpfnWndProc   = WndProc;
537     childWindowClass.cbClsExtra    = 0;
538     childWindowClass.cbWndExtra    = 0;
539     childWindowClass.hInstance     = GetModuleHandle(nullptr);
540     childWindowClass.hIcon         = nullptr;
541     childWindowClass.hCursor       = LoadCursorA(nullptr, idcArrow);
542     childWindowClass.hbrBackground = 0;
543     childWindowClass.lpszMenuName  = nullptr;
544     childWindowClass.lpszClassName = mChildClassName.c_str();
545     if (!RegisterClassExA(&childWindowClass))
546     {
547         return false;
548     }
549 
550     DWORD parentStyle = WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU;
551     DWORD parentExtendedStyle = WS_EX_APPWINDOW | WS_EX_TOOLWINDOW;
552 
553     RECT sizeRect = {0, 0, static_cast<LONG>(width), static_cast<LONG>(height)};
554     AdjustWindowRectEx(&sizeRect, parentStyle, FALSE, parentExtendedStyle);
555 
556     mParentWindow = CreateWindowExA(parentExtendedStyle, mParentClassName.c_str(), name.c_str(),
557                                     parentStyle, CW_USEDEFAULT, CW_USEDEFAULT,
558                                     sizeRect.right - sizeRect.left, sizeRect.bottom - sizeRect.top,
559                                     nullptr, nullptr, GetModuleHandle(nullptr), this);
560 
561     mNativeWindow = CreateWindowExA(0, mChildClassName.c_str(), name.c_str(), WS_CHILD, 0, 0,
562                                     static_cast<int>(width), static_cast<int>(height),
563                                     mParentWindow, nullptr, GetModuleHandle(nullptr), this);
564 
565     mNativeDisplay = GetDC(mNativeWindow);
566     if (!mNativeDisplay)
567     {
568         destroy();
569         return false;
570     }
571 
572     return true;
573 }
574 
destroy()575 void Win32Window::destroy()
576 {
577     if (mNativeDisplay)
578     {
579         ReleaseDC(mNativeWindow, mNativeDisplay);
580         mNativeDisplay = 0;
581     }
582 
583     if (mNativeWindow)
584     {
585         DestroyWindow(mNativeWindow);
586         mNativeWindow = 0;
587     }
588 
589     if (mParentWindow)
590     {
591         DestroyWindow(mParentWindow);
592         mParentWindow = 0;
593     }
594 
595     UnregisterClassA(mParentClassName.c_str(), nullptr);
596     UnregisterClassA(mChildClassName.c_str(), nullptr);
597 }
598 
takeScreenshot(uint8_t * pixelData)599 bool Win32Window::takeScreenshot(uint8_t *pixelData)
600 {
601     if (mIsVisible)
602     {
603         return false;
604     }
605 
606     bool error = false;
607 
608     // Hack for DWM: There is no way to wait for DWM animations to finish, so we just have to wait
609     // for a while before issuing screenshot if window was just made visible.
610     {
611         static const double WAIT_WINDOW_VISIBLE_MS = 0.5;  // Half a second for the animation
612         double timeSinceVisible                    = mSetVisibleTimer.getElapsedTime();
613 
614         if (timeSinceVisible < WAIT_WINDOW_VISIBLE_MS)
615         {
616             Sleep(static_cast<DWORD>((WAIT_WINDOW_VISIBLE_MS - timeSinceVisible) * 1000));
617         }
618     }
619 
620     HDC screenDC      = nullptr;
621     HDC windowDC      = nullptr;
622     HDC tmpDC         = nullptr;
623     HBITMAP tmpBitmap = nullptr;
624 
625     if (!error)
626     {
627         screenDC = GetDC(HWND_DESKTOP);
628         error    = screenDC == nullptr;
629     }
630 
631     if (!error)
632     {
633         windowDC = GetDC(mNativeWindow);
634         error    = windowDC == nullptr;
635     }
636 
637     if (!error)
638     {
639         tmpDC = CreateCompatibleDC(screenDC);
640         error = tmpDC == nullptr;
641     }
642 
643     if (!error)
644     {
645         tmpBitmap = CreateCompatibleBitmap(screenDC, mWidth, mHeight);
646         error     = tmpBitmap == nullptr;
647     }
648 
649     POINT topLeft = {0, 0};
650     if (!error)
651     {
652         error = (MapWindowPoints(mNativeWindow, HWND_DESKTOP, &topLeft, 1) == 0);
653     }
654 
655     if (!error)
656     {
657         error = SelectObject(tmpDC, tmpBitmap) == nullptr;
658     }
659 
660     if (!error)
661     {
662         error = BitBlt(tmpDC, 0, 0, mWidth, mHeight, screenDC, topLeft.x, topLeft.y, SRCCOPY) == 0;
663     }
664 
665     if (!error)
666     {
667         BITMAPINFOHEADER bitmapInfo;
668         bitmapInfo.biSize          = sizeof(BITMAPINFOHEADER);
669         bitmapInfo.biWidth         = mWidth;
670         bitmapInfo.biHeight        = -mHeight;
671         bitmapInfo.biPlanes        = 1;
672         bitmapInfo.biBitCount      = 32;
673         bitmapInfo.biCompression   = BI_RGB;
674         bitmapInfo.biSizeImage     = 0;
675         bitmapInfo.biXPelsPerMeter = 0;
676         bitmapInfo.biYPelsPerMeter = 0;
677         bitmapInfo.biClrUsed       = 0;
678         bitmapInfo.biClrImportant  = 0;
679         int getBitsResult          = GetDIBits(screenDC, tmpBitmap, 0, mHeight, pixelData,
680                                       reinterpret_cast<BITMAPINFO *>(&bitmapInfo), DIB_RGB_COLORS);
681         error                      = (getBitsResult == 0);
682     }
683 
684     if (tmpBitmap != nullptr)
685     {
686         DeleteObject(tmpBitmap);
687     }
688     if (tmpDC != nullptr)
689     {
690         DeleteDC(tmpDC);
691     }
692     if (screenDC != nullptr)
693     {
694         ReleaseDC(nullptr, screenDC);
695     }
696     if (windowDC != nullptr)
697     {
698         ReleaseDC(mNativeWindow, windowDC);
699     }
700 
701     return !error;
702 }
703 
resetNativeWindow()704 void Win32Window::resetNativeWindow() {}
705 
getNativeWindow() const706 EGLNativeWindowType Win32Window::getNativeWindow() const
707 {
708     return mNativeWindow;
709 }
710 
getNativeDisplay() const711 EGLNativeDisplayType Win32Window::getNativeDisplay() const
712 {
713     return mNativeDisplay;
714 }
715 
messageLoop()716 void Win32Window::messageLoop()
717 {
718     MSG msg;
719     while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
720     {
721         TranslateMessage(&msg);
722         DispatchMessage(&msg);
723     }
724 }
725 
setMousePosition(int x,int y)726 void Win32Window::setMousePosition(int x, int y)
727 {
728     RECT winRect;
729     GetClientRect(mNativeWindow, &winRect);
730 
731     POINT topLeft;
732     topLeft.x = winRect.left;
733     topLeft.y = winRect.top;
734     ClientToScreen(mNativeWindow, &topLeft);
735 
736     SetCursorPos(topLeft.x + x, topLeft.y + y);
737 }
738 
setPosition(int x,int y)739 bool Win32Window::setPosition(int x, int y)
740 {
741     if (mX == x && mY == y)
742     {
743         return true;
744     }
745 
746     RECT windowRect;
747     if (!GetWindowRect(mParentWindow, &windowRect))
748     {
749         return false;
750     }
751 
752     if (!MoveWindow(mParentWindow, x, y, windowRect.right - windowRect.left,
753                     windowRect.bottom - windowRect.top, TRUE))
754     {
755         return false;
756     }
757 
758     return true;
759 }
760 
resize(int width,int height)761 bool Win32Window::resize(int width, int height)
762 {
763     if (width == mWidth && height == mHeight)
764     {
765         return true;
766     }
767 
768     RECT windowRect;
769     if (!GetWindowRect(mParentWindow, &windowRect))
770     {
771         return false;
772     }
773 
774     RECT clientRect;
775     if (!GetClientRect(mParentWindow, &clientRect))
776     {
777         return false;
778     }
779 
780     LONG diffX = (windowRect.right - windowRect.left) - clientRect.right;
781     LONG diffY = (windowRect.bottom - windowRect.top) - clientRect.bottom;
782     if (!MoveWindow(mParentWindow, windowRect.left, windowRect.top, width + diffX, height + diffY,
783                     TRUE))
784     {
785         return false;
786     }
787 
788     if (!MoveWindow(mNativeWindow, 0, 0, width, height, FALSE))
789     {
790         return false;
791     }
792 
793     return true;
794 }
795 
setVisible(bool isVisible)796 void Win32Window::setVisible(bool isVisible)
797 {
798     int flag = (isVisible ? SW_SHOW : SW_HIDE);
799 
800     ShowWindow(mParentWindow, flag);
801     ShowWindow(mNativeWindow, flag);
802 
803     if (isVisible)
804     {
805         mSetVisibleTimer.stop();
806         mSetVisibleTimer.start();
807     }
808 }
809 
pushEvent(Event event)810 void Win32Window::pushEvent(Event event)
811 {
812     OSWindow::pushEvent(event);
813 
814     switch (event.Type)
815     {
816         case Event::EVENT_RESIZED:
817             MoveWindow(mNativeWindow, 0, 0, mWidth, mHeight, FALSE);
818             break;
819         default:
820             break;
821     }
822 }
823 
signalTestEvent()824 void Win32Window::signalTestEvent()
825 {
826     PostMessage(mNativeWindow, WM_USER, 0, 0);
827 }
828 
829 // static
New()830 OSWindow *OSWindow::New()
831 {
832     return new Win32Window();
833 }
834