summaryrefslogtreecommitdiff
path: root/Source/ThirdParty/ANGLE/util/windows/win32/Win32Window.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/ThirdParty/ANGLE/util/windows/win32/Win32Window.cpp')
-rw-r--r--Source/ThirdParty/ANGLE/util/windows/win32/Win32Window.cpp831
1 files changed, 831 insertions, 0 deletions
diff --git a/Source/ThirdParty/ANGLE/util/windows/win32/Win32Window.cpp b/Source/ThirdParty/ANGLE/util/windows/win32/Win32Window.cpp
new file mode 100644
index 000000000..abd1132b2
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/util/windows/win32/Win32Window.cpp
@@ -0,0 +1,831 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Win32Window.cpp: Implementation of OSWindow for Win32 (Windows)
+
+#include "windows/win32/Win32Window.h"
+
+#include <sstream>
+
+#include "common/debug.h"
+
+Key VirtualKeyCodeToKey(WPARAM key, LPARAM flags)
+{
+ switch (key)
+ {
+ // Check the scancode to distinguish between left and right shift
+ case VK_SHIFT:
+ {
+ static unsigned int lShift = MapVirtualKey(VK_LSHIFT, MAPVK_VK_TO_VSC);
+ unsigned int scancode = static_cast<unsigned int>((flags & (0xFF << 16)) >> 16);
+ return scancode == lShift ? KEY_LSHIFT : KEY_RSHIFT;
+ }
+
+ // Check the "extended" flag to distinguish between left and right alt
+ case VK_MENU:
+ return (HIWORD(flags) & KF_EXTENDED) ? KEY_RALT : KEY_LALT;
+
+ // Check the "extended" flag to distinguish between left and right control
+ case VK_CONTROL:
+ return (HIWORD(flags) & KF_EXTENDED) ? KEY_RCONTROL : KEY_LCONTROL;
+
+ // Other keys are reported properly
+ case VK_LWIN:
+ return KEY_LSYSTEM;
+ case VK_RWIN:
+ return KEY_RSYSTEM;
+ case VK_APPS:
+ return KEY_MENU;
+ case VK_OEM_1:
+ return KEY_SEMICOLON;
+ case VK_OEM_2:
+ return KEY_SLASH;
+ case VK_OEM_PLUS:
+ return KEY_EQUAL;
+ case VK_OEM_MINUS:
+ return KEY_DASH;
+ case VK_OEM_4:
+ return KEY_LBRACKET;
+ case VK_OEM_6:
+ return KEY_RBRACKET;
+ case VK_OEM_COMMA:
+ return KEY_COMMA;
+ case VK_OEM_PERIOD:
+ return KEY_PERIOD;
+ case VK_OEM_7:
+ return KEY_QUOTE;
+ case VK_OEM_5:
+ return KEY_BACKSLASH;
+ case VK_OEM_3:
+ return KEY_TILDE;
+ case VK_ESCAPE:
+ return KEY_ESCAPE;
+ case VK_SPACE:
+ return KEY_SPACE;
+ case VK_RETURN:
+ return KEY_RETURN;
+ case VK_BACK:
+ return KEY_BACK;
+ case VK_TAB:
+ return KEY_TAB;
+ case VK_PRIOR:
+ return KEY_PAGEUP;
+ case VK_NEXT:
+ return KEY_PAGEDOWN;
+ case VK_END:
+ return KEY_END;
+ case VK_HOME:
+ return KEY_HOME;
+ case VK_INSERT:
+ return KEY_INSERT;
+ case VK_DELETE:
+ return KEY_DELETE;
+ case VK_ADD:
+ return KEY_ADD;
+ case VK_SUBTRACT:
+ return KEY_SUBTRACT;
+ case VK_MULTIPLY:
+ return KEY_MULTIPLY;
+ case VK_DIVIDE:
+ return KEY_DIVIDE;
+ case VK_PAUSE:
+ return KEY_PAUSE;
+ case VK_F1:
+ return KEY_F1;
+ case VK_F2:
+ return KEY_F2;
+ case VK_F3:
+ return KEY_F3;
+ case VK_F4:
+ return KEY_F4;
+ case VK_F5:
+ return KEY_F5;
+ case VK_F6:
+ return KEY_F6;
+ case VK_F7:
+ return KEY_F7;
+ case VK_F8:
+ return KEY_F8;
+ case VK_F9:
+ return KEY_F9;
+ case VK_F10:
+ return KEY_F10;
+ case VK_F11:
+ return KEY_F11;
+ case VK_F12:
+ return KEY_F12;
+ case VK_F13:
+ return KEY_F13;
+ case VK_F14:
+ return KEY_F14;
+ case VK_F15:
+ return KEY_F15;
+ case VK_LEFT:
+ return KEY_LEFT;
+ case VK_RIGHT:
+ return KEY_RIGHT;
+ case VK_UP:
+ return KEY_UP;
+ case VK_DOWN:
+ return KEY_DOWN;
+ case VK_NUMPAD0:
+ return KEY_NUMPAD0;
+ case VK_NUMPAD1:
+ return KEY_NUMPAD1;
+ case VK_NUMPAD2:
+ return KEY_NUMPAD2;
+ case VK_NUMPAD3:
+ return KEY_NUMPAD3;
+ case VK_NUMPAD4:
+ return KEY_NUMPAD4;
+ case VK_NUMPAD5:
+ return KEY_NUMPAD5;
+ case VK_NUMPAD6:
+ return KEY_NUMPAD6;
+ case VK_NUMPAD7:
+ return KEY_NUMPAD7;
+ case VK_NUMPAD8:
+ return KEY_NUMPAD8;
+ case VK_NUMPAD9:
+ return KEY_NUMPAD9;
+ case 'A':
+ return KEY_A;
+ case 'Z':
+ return KEY_Z;
+ case 'E':
+ return KEY_E;
+ case 'R':
+ return KEY_R;
+ case 'T':
+ return KEY_T;
+ case 'Y':
+ return KEY_Y;
+ case 'U':
+ return KEY_U;
+ case 'I':
+ return KEY_I;
+ case 'O':
+ return KEY_O;
+ case 'P':
+ return KEY_P;
+ case 'Q':
+ return KEY_Q;
+ case 'S':
+ return KEY_S;
+ case 'D':
+ return KEY_D;
+ case 'F':
+ return KEY_F;
+ case 'G':
+ return KEY_G;
+ case 'H':
+ return KEY_H;
+ case 'J':
+ return KEY_J;
+ case 'K':
+ return KEY_K;
+ case 'L':
+ return KEY_L;
+ case 'M':
+ return KEY_M;
+ case 'W':
+ return KEY_W;
+ case 'X':
+ return KEY_X;
+ case 'C':
+ return KEY_C;
+ case 'V':
+ return KEY_V;
+ case 'B':
+ return KEY_B;
+ case 'N':
+ return KEY_N;
+ case '0':
+ return KEY_NUM0;
+ case '1':
+ return KEY_NUM1;
+ case '2':
+ return KEY_NUM2;
+ case '3':
+ return KEY_NUM3;
+ case '4':
+ return KEY_NUM4;
+ case '5':
+ return KEY_NUM5;
+ case '6':
+ return KEY_NUM6;
+ case '7':
+ return KEY_NUM7;
+ case '8':
+ return KEY_NUM8;
+ case '9':
+ return KEY_NUM9;
+ }
+
+ return Key(0);
+}
+
+LRESULT CALLBACK Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_NCCREATE:
+ {
+ LPCREATESTRUCT pCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
+ SetWindowLongPtr(hWnd, GWLP_USERDATA,
+ reinterpret_cast<LONG_PTR>(pCreateStruct->lpCreateParams));
+ return DefWindowProcA(hWnd, message, wParam, lParam);
+ }
+ }
+
+ Win32Window *window = reinterpret_cast<Win32Window *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
+ if (window)
+ {
+ switch (message)
+ {
+ case WM_DESTROY:
+ case WM_CLOSE:
+ {
+ Event event;
+ event.Type = Event::EVENT_CLOSED;
+ window->pushEvent(event);
+ break;
+ }
+
+ case WM_MOVE:
+ {
+ RECT winRect;
+ GetClientRect(hWnd, &winRect);
+
+ POINT topLeft;
+ topLeft.x = winRect.left;
+ topLeft.y = winRect.top;
+ ClientToScreen(hWnd, &topLeft);
+
+ Event event;
+ event.Type = Event::EVENT_MOVED;
+ event.Move.X = topLeft.x;
+ event.Move.Y = topLeft.y;
+ window->pushEvent(event);
+
+ break;
+ }
+
+ case WM_SIZE:
+ {
+ RECT winRect;
+ GetClientRect(hWnd, &winRect);
+
+ POINT topLeft;
+ topLeft.x = winRect.left;
+ topLeft.y = winRect.top;
+ ClientToScreen(hWnd, &topLeft);
+
+ POINT botRight;
+ botRight.x = winRect.right;
+ botRight.y = winRect.bottom;
+ ClientToScreen(hWnd, &botRight);
+
+ Event event;
+ event.Type = Event::EVENT_RESIZED;
+ event.Size.Width = botRight.x - topLeft.x;
+ event.Size.Height = botRight.y - topLeft.y;
+ window->pushEvent(event);
+
+ break;
+ }
+
+ case WM_SETFOCUS:
+ {
+ Event event;
+ event.Type = Event::EVENT_GAINED_FOCUS;
+ window->pushEvent(event);
+ break;
+ }
+
+ case WM_KILLFOCUS:
+ {
+ Event event;
+ event.Type = Event::EVENT_LOST_FOCUS;
+ window->pushEvent(event);
+ break;
+ }
+
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ {
+ bool down = (message == WM_KEYDOWN || message == WM_SYSKEYDOWN);
+
+ Event event;
+ event.Type = down ? Event::EVENT_KEY_PRESSED : Event::EVENT_KEY_RELEASED;
+ event.Key.Alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
+ event.Key.Control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
+ event.Key.Shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
+ event.Key.System =
+ HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN));
+ event.Key.Code = VirtualKeyCodeToKey(wParam, lParam);
+ window->pushEvent(event);
+
+ break;
+ }
+
+ case WM_MOUSEWHEEL:
+ {
+ Event event;
+ event.Type = Event::EVENT_MOUSE_WHEEL_MOVED;
+ event.MouseWheel.Delta = static_cast<short>(HIWORD(wParam)) / 120;
+ window->pushEvent(event);
+ break;
+ }
+
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ {
+ Event event;
+ event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED;
+ event.MouseButton.Button = MOUSEBUTTON_LEFT;
+ event.MouseButton.X = static_cast<short>(LOWORD(lParam));
+ event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
+ window->pushEvent(event);
+ break;
+ }
+
+ case WM_LBUTTONUP:
+ {
+ Event event;
+ event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED;
+ event.MouseButton.Button = MOUSEBUTTON_LEFT;
+ event.MouseButton.X = static_cast<short>(LOWORD(lParam));
+ event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
+ window->pushEvent(event);
+ break;
+ }
+
+ case WM_RBUTTONDOWN:
+ case WM_RBUTTONDBLCLK:
+ {
+ Event event;
+ event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED;
+ event.MouseButton.Button = MOUSEBUTTON_RIGHT;
+ event.MouseButton.X = static_cast<short>(LOWORD(lParam));
+ event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
+ window->pushEvent(event);
+ break;
+ }
+
+ // Mouse right button up event
+ case WM_RBUTTONUP:
+ {
+ Event event;
+ event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED;
+ event.MouseButton.Button = MOUSEBUTTON_RIGHT;
+ event.MouseButton.X = static_cast<short>(LOWORD(lParam));
+ event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
+ window->pushEvent(event);
+ break;
+ }
+
+ // Mouse wheel button down event
+ case WM_MBUTTONDOWN:
+ case WM_MBUTTONDBLCLK:
+ {
+ Event event;
+ event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED;
+ event.MouseButton.Button = MOUSEBUTTON_MIDDLE;
+ event.MouseButton.X = static_cast<short>(LOWORD(lParam));
+ event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
+ window->pushEvent(event);
+ break;
+ }
+
+ // Mouse wheel button up event
+ case WM_MBUTTONUP:
+ {
+ Event event;
+ event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED;
+ event.MouseButton.Button = MOUSEBUTTON_MIDDLE;
+ event.MouseButton.X = static_cast<short>(LOWORD(lParam));
+ event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
+ window->pushEvent(event);
+ break;
+ }
+
+ // Mouse X button down event
+ case WM_XBUTTONDOWN:
+ case WM_XBUTTONDBLCLK:
+ {
+ Event event;
+ event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED;
+ event.MouseButton.Button =
+ (HIWORD(wParam) == XBUTTON1) ? MOUSEBUTTON_BUTTON4 : MOUSEBUTTON_BUTTON5;
+ event.MouseButton.X = static_cast<short>(LOWORD(lParam));
+ event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
+ window->pushEvent(event);
+ break;
+ }
+
+ // Mouse X button up event
+ case WM_XBUTTONUP:
+ {
+ Event event;
+ event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED;
+ event.MouseButton.Button =
+ (HIWORD(wParam) == XBUTTON1) ? MOUSEBUTTON_BUTTON4 : MOUSEBUTTON_BUTTON5;
+ event.MouseButton.X = static_cast<short>(LOWORD(lParam));
+ event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
+ window->pushEvent(event);
+ break;
+ }
+
+ case WM_MOUSEMOVE:
+ {
+ if (!window->mIsMouseInWindow)
+ {
+ window->mIsMouseInWindow = true;
+ Event event;
+ event.Type = Event::EVENT_MOUSE_ENTERED;
+ window->pushEvent(event);
+ }
+
+ int mouseX = static_cast<short>(LOWORD(lParam));
+ int mouseY = static_cast<short>(HIWORD(lParam));
+
+ Event event;
+ event.Type = Event::EVENT_MOUSE_MOVED;
+ event.MouseMove.X = mouseX;
+ event.MouseMove.Y = mouseY;
+ window->pushEvent(event);
+ break;
+ }
+
+ case WM_MOUSELEAVE:
+ {
+ Event event;
+ event.Type = Event::EVENT_MOUSE_LEFT;
+ window->pushEvent(event);
+ window->mIsMouseInWindow = false;
+ break;
+ }
+
+ case WM_USER:
+ {
+ Event testEvent;
+ testEvent.Type = Event::EVENT_TEST;
+ window->pushEvent(testEvent);
+ break;
+ }
+ }
+ }
+ return DefWindowProcA(hWnd, message, wParam, lParam);
+}
+
+Win32Window::Win32Window()
+ : mIsVisible(false),
+ mSetVisibleTimer(CreateTimer()),
+ mIsMouseInWindow(false),
+ mNativeWindow(0),
+ mParentWindow(0),
+ mNativeDisplay(0)
+{
+}
+
+Win32Window::~Win32Window()
+{
+ destroy();
+ delete mSetVisibleTimer;
+}
+
+bool Win32Window::initialize(const std::string &name, size_t width, size_t height)
+{
+ destroy();
+
+ // Use a new window class name for ever window to ensure that a new window can be created
+ // even if the last one was not properly destroyed
+ static size_t windowIdx = 0;
+ std::ostringstream nameStream;
+ nameStream << name << "_" << windowIdx++;
+
+ mParentClassName = nameStream.str();
+ mChildClassName = mParentClassName + "_Child";
+
+ // Work around compile error from not defining "UNICODE" while Chromium does
+ const LPSTR idcArrow = MAKEINTRESOURCEA(32512);
+
+ WNDCLASSEXA parentWindowClass = {0};
+ parentWindowClass.cbSize = sizeof(WNDCLASSEXA);
+ parentWindowClass.style = 0;
+ parentWindowClass.lpfnWndProc = WndProc;
+ parentWindowClass.cbClsExtra = 0;
+ parentWindowClass.cbWndExtra = 0;
+ parentWindowClass.hInstance = GetModuleHandle(NULL);
+ parentWindowClass.hIcon = NULL;
+ parentWindowClass.hCursor = LoadCursorA(NULL, idcArrow);
+ parentWindowClass.hbrBackground = 0;
+ parentWindowClass.lpszMenuName = NULL;
+ parentWindowClass.lpszClassName = mParentClassName.c_str();
+ if (!RegisterClassExA(&parentWindowClass))
+ {
+ return false;
+ }
+
+ WNDCLASSEXA childWindowClass = {0};
+ childWindowClass.cbSize = sizeof(WNDCLASSEXA);
+ childWindowClass.style = CS_OWNDC;
+ childWindowClass.lpfnWndProc = WndProc;
+ childWindowClass.cbClsExtra = 0;
+ childWindowClass.cbWndExtra = 0;
+ childWindowClass.hInstance = GetModuleHandle(NULL);
+ childWindowClass.hIcon = NULL;
+ childWindowClass.hCursor = LoadCursorA(NULL, idcArrow);
+ childWindowClass.hbrBackground = 0;
+ childWindowClass.lpszMenuName = NULL;
+ childWindowClass.lpszClassName = mChildClassName.c_str();
+ if (!RegisterClassExA(&childWindowClass))
+ {
+ return false;
+ }
+
+ DWORD parentStyle = WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU;
+ DWORD parentExtendedStyle = WS_EX_APPWINDOW;
+
+ RECT sizeRect = {0, 0, static_cast<LONG>(width), static_cast<LONG>(height)};
+ AdjustWindowRectEx(&sizeRect, parentStyle, FALSE, parentExtendedStyle);
+
+ mParentWindow =
+ CreateWindowExA(parentExtendedStyle, mParentClassName.c_str(), name.c_str(), parentStyle,
+ CW_USEDEFAULT, CW_USEDEFAULT, sizeRect.right - sizeRect.left,
+ sizeRect.bottom - sizeRect.top, NULL, NULL, GetModuleHandle(NULL), this);
+
+ mNativeWindow = CreateWindowExA(0, mChildClassName.c_str(), name.c_str(), WS_CHILD, 0, 0,
+ static_cast<int>(width), static_cast<int>(height),
+ mParentWindow, NULL, GetModuleHandle(NULL), this);
+
+ mNativeDisplay = GetDC(mNativeWindow);
+ if (!mNativeDisplay)
+ {
+ destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void Win32Window::destroy()
+{
+ if (mNativeDisplay)
+ {
+ ReleaseDC(mNativeWindow, mNativeDisplay);
+ mNativeDisplay = 0;
+ }
+
+ if (mNativeWindow)
+ {
+ DestroyWindow(mNativeWindow);
+ mNativeWindow = 0;
+ }
+
+ if (mParentWindow)
+ {
+ DestroyWindow(mParentWindow);
+ mParentWindow = 0;
+ }
+
+ UnregisterClassA(mParentClassName.c_str(), NULL);
+ UnregisterClassA(mChildClassName.c_str(), NULL);
+}
+
+bool Win32Window::takeScreenshot(uint8_t *pixelData)
+{
+ if (mIsVisible)
+ {
+ return false;
+ }
+
+ bool error = false;
+
+ // Hack for DWM: There is no way to wait for DWM animations to finish, so we just have to wait
+ // for a while before issuing screenshot if window was just made visible.
+ {
+ static const double WAIT_WINDOW_VISIBLE_MS = 0.5; // Half a second for the animation
+ double timeSinceVisible = mSetVisibleTimer->getElapsedTime();
+
+ if (timeSinceVisible < WAIT_WINDOW_VISIBLE_MS)
+ {
+ Sleep(static_cast<DWORD>((WAIT_WINDOW_VISIBLE_MS - timeSinceVisible) * 1000));
+ }
+ }
+
+ HDC screenDC = nullptr;
+ HDC windowDC = nullptr;
+ HDC tmpDC = nullptr;
+ HBITMAP tmpBitmap = nullptr;
+
+ if (!error)
+ {
+ screenDC = GetDC(nullptr);
+ error = screenDC == nullptr;
+ }
+
+ if (!error)
+ {
+ windowDC = GetDC(mNativeWindow);
+ error = windowDC == nullptr;
+ }
+
+ if (!error)
+ {
+ tmpDC = CreateCompatibleDC(screenDC);
+ error = tmpDC == nullptr;
+ }
+
+ if (!error)
+ {
+ tmpBitmap = CreateCompatibleBitmap(screenDC, mWidth, mHeight);
+ error = tmpBitmap == nullptr;
+ }
+
+ RECT rect = {0, 0, 0, 0};
+ if (!error)
+ {
+ MapWindowPoints(mNativeWindow, nullptr, reinterpret_cast<LPPOINT>(&rect), 0);
+
+ error = SelectObject(tmpDC, tmpBitmap) == nullptr;
+ }
+
+ if (!error)
+ {
+ error =
+ BitBlt(tmpDC, 0, 0, mWidth, mHeight, screenDC, rect.left, rect.top, SRCCOPY) == TRUE;
+ }
+
+ if (!error)
+ {
+ BITMAPINFOHEADER bitmapInfo;
+ bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
+ bitmapInfo.biWidth = mWidth;
+ bitmapInfo.biHeight = -mHeight;
+ bitmapInfo.biPlanes = 1;
+ bitmapInfo.biBitCount = 32;
+ bitmapInfo.biCompression = BI_RGB;
+ bitmapInfo.biSizeImage = 0;
+ bitmapInfo.biXPelsPerMeter = 0;
+ bitmapInfo.biYPelsPerMeter = 0;
+ bitmapInfo.biClrUsed = 0;
+ bitmapInfo.biClrImportant = 0;
+ int getBitsResult = GetDIBits(screenDC, tmpBitmap, 0, mHeight, pixelData,
+ reinterpret_cast<BITMAPINFO *>(&bitmapInfo), DIB_RGB_COLORS);
+ error = getBitsResult != 0;
+ }
+
+ if (tmpBitmap != nullptr)
+ {
+ DeleteObject(tmpBitmap);
+ }
+ if (tmpDC != nullptr)
+ {
+ DeleteDC(tmpDC);
+ }
+ if (screenDC != nullptr)
+ {
+ ReleaseDC(nullptr, screenDC);
+ }
+ if (windowDC != nullptr)
+ {
+ ReleaseDC(mNativeWindow, windowDC);
+ }
+
+ return !error;
+}
+
+EGLNativeWindowType Win32Window::getNativeWindow() const
+{
+ return mNativeWindow;
+}
+
+EGLNativeDisplayType Win32Window::getNativeDisplay() const
+{
+ return mNativeDisplay;
+}
+
+void Win32Window::messageLoop()
+{
+ MSG msg;
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+}
+
+void Win32Window::setMousePosition(int x, int y)
+{
+ RECT winRect;
+ GetClientRect(mNativeWindow, &winRect);
+
+ POINT topLeft;
+ topLeft.x = winRect.left;
+ topLeft.y = winRect.top;
+ ClientToScreen(mNativeWindow, &topLeft);
+
+ SetCursorPos(topLeft.x + x, topLeft.y + y);
+}
+
+OSWindow *CreateOSWindow()
+{
+ return new Win32Window();
+}
+
+bool Win32Window::setPosition(int x, int y)
+{
+ if (mX == x && mY == y)
+ {
+ return true;
+ }
+
+ RECT windowRect;
+ if (!GetWindowRect(mParentWindow, &windowRect))
+ {
+ return false;
+ }
+
+ if (!MoveWindow(mParentWindow, x, y, windowRect.right - windowRect.left,
+ windowRect.bottom - windowRect.top, TRUE))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool Win32Window::resize(int width, int height)
+{
+ if (width == mWidth && height == mHeight)
+ {
+ return true;
+ }
+
+ RECT windowRect;
+ if (!GetWindowRect(mParentWindow, &windowRect))
+ {
+ return false;
+ }
+
+ RECT clientRect;
+ if (!GetClientRect(mParentWindow, &clientRect))
+ {
+ return false;
+ }
+
+ LONG diffX = (windowRect.right - windowRect.left) - clientRect.right;
+ LONG diffY = (windowRect.bottom - windowRect.top) - clientRect.bottom;
+ if (!MoveWindow(mParentWindow, windowRect.left, windowRect.top, width + diffX, height + diffY,
+ TRUE))
+ {
+ return false;
+ }
+
+ if (!MoveWindow(mNativeWindow, 0, 0, width, height, FALSE))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void Win32Window::setVisible(bool isVisible)
+{
+ int flag = (isVisible ? SW_SHOW : SW_HIDE);
+
+ ShowWindow(mParentWindow, flag);
+ ShowWindow(mNativeWindow, flag);
+
+ if (isVisible)
+ {
+ mSetVisibleTimer->stop();
+ mSetVisibleTimer->start();
+ }
+}
+
+void Win32Window::pushEvent(Event event)
+{
+ OSWindow::pushEvent(event);
+
+ switch (event.Type)
+ {
+ case Event::EVENT_RESIZED:
+ MoveWindow(mNativeWindow, 0, 0, mWidth, mHeight, FALSE);
+ break;
+ default:
+ break;
+ }
+}
+
+void Win32Window::signalTestEvent()
+{
+ PostMessage(mNativeWindow, WM_USER, 0, 0);
+}