2 // Copyright (c) 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.
7 #include "win32/Win32Window.h"
9 Key VirtualKeyCodeToKey(WPARAM key, LPARAM flags)
13 // Check the scancode to distinguish between left and right shift
16 static unsigned int lShift = MapVirtualKey(VK_LSHIFT, MAPVK_VK_TO_VSC);
17 unsigned int scancode = static_cast<unsigned int>((flags & (0xFF << 16)) >> 16);
18 return scancode == lShift ? KEY_LSHIFT : KEY_RSHIFT;
21 // Check the "extended" flag to distinguish between left and right alt
22 case VK_MENU: return (HIWORD(flags) & KF_EXTENDED) ? KEY_RALT : KEY_LALT;
24 // Check the "extended" flag to distinguish between left and right control
25 case VK_CONTROL: return (HIWORD(flags) & KF_EXTENDED) ? KEY_RCONTROL : KEY_LCONTROL;
27 // Other keys are reported properly
28 case VK_LWIN: return KEY_LSYSTEM;
29 case VK_RWIN: return KEY_RSYSTEM;
30 case VK_APPS: return KEY_MENU;
31 case VK_OEM_1: return KEY_SEMICOLON;
32 case VK_OEM_2: return KEY_SLASH;
33 case VK_OEM_PLUS: return KEY_EQUAL;
34 case VK_OEM_MINUS: return KEY_DASH;
35 case VK_OEM_4: return KEY_LBRACKET;
36 case VK_OEM_6: return KEY_RBRACKET;
37 case VK_OEM_COMMA: return KEY_COMMA;
38 case VK_OEM_PERIOD: return KEY_PERIOD;
39 case VK_OEM_7: return KEY_QUOTE;
40 case VK_OEM_5: return KEY_BACKSLASH;
41 case VK_OEM_3: return KEY_TILDE;
42 case VK_ESCAPE: return KEY_ESCAPE;
43 case VK_SPACE: return KEY_SPACE;
44 case VK_RETURN: return KEY_RETURN;
45 case VK_BACK: return KEY_BACK;
46 case VK_TAB: return KEY_TAB;
47 case VK_PRIOR: return KEY_PAGEUP;
48 case VK_NEXT: return KEY_PAGEDOWN;
49 case VK_END: return KEY_END;
50 case VK_HOME: return KEY_HOME;
51 case VK_INSERT: return KEY_INSERT;
52 case VK_DELETE: return KEY_DELETE;
53 case VK_ADD: return KEY_ADD;
54 case VK_SUBTRACT: return KEY_SUBTRACT;
55 case VK_MULTIPLY: return KEY_MULTIPLY;
56 case VK_DIVIDE: return KEY_DIVIDE;
57 case VK_PAUSE: return KEY_PAUSE;
58 case VK_F1: return KEY_F1;
59 case VK_F2: return KEY_F2;
60 case VK_F3: return KEY_F3;
61 case VK_F4: return KEY_F4;
62 case VK_F5: return KEY_F5;
63 case VK_F6: return KEY_F6;
64 case VK_F7: return KEY_F7;
65 case VK_F8: return KEY_F8;
66 case VK_F9: return KEY_F9;
67 case VK_F10: return KEY_F10;
68 case VK_F11: return KEY_F11;
69 case VK_F12: return KEY_F12;
70 case VK_F13: return KEY_F13;
71 case VK_F14: return KEY_F14;
72 case VK_F15: return KEY_F15;
73 case VK_LEFT: return KEY_LEFT;
74 case VK_RIGHT: return KEY_RIGHT;
75 case VK_UP: return KEY_UP;
76 case VK_DOWN: return KEY_DOWN;
77 case VK_NUMPAD0: return KEY_NUMPAD0;
78 case VK_NUMPAD1: return KEY_NUMPAD1;
79 case VK_NUMPAD2: return KEY_NUMPAD2;
80 case VK_NUMPAD3: return KEY_NUMPAD3;
81 case VK_NUMPAD4: return KEY_NUMPAD4;
82 case VK_NUMPAD5: return KEY_NUMPAD5;
83 case VK_NUMPAD6: return KEY_NUMPAD6;
84 case VK_NUMPAD7: return KEY_NUMPAD7;
85 case VK_NUMPAD8: return KEY_NUMPAD8;
86 case VK_NUMPAD9: return KEY_NUMPAD9;
87 case 'A': return KEY_A;
88 case 'Z': return KEY_Z;
89 case 'E': return KEY_E;
90 case 'R': return KEY_R;
91 case 'T': return KEY_T;
92 case 'Y': return KEY_Y;
93 case 'U': return KEY_U;
94 case 'I': return KEY_I;
95 case 'O': return KEY_O;
96 case 'P': return KEY_P;
97 case 'Q': return KEY_Q;
98 case 'S': return KEY_S;
99 case 'D': return KEY_D;
100 case 'F': return KEY_F;
101 case 'G': return KEY_G;
102 case 'H': return KEY_H;
103 case 'J': return KEY_J;
104 case 'K': return KEY_K;
105 case 'L': return KEY_L;
106 case 'M': return KEY_M;
107 case 'W': return KEY_W;
108 case 'X': return KEY_X;
109 case 'C': return KEY_C;
110 case 'V': return KEY_V;
111 case 'B': return KEY_B;
112 case 'N': return KEY_N;
113 case '0': return KEY_NUM0;
114 case '1': return KEY_NUM1;
115 case '2': return KEY_NUM2;
116 case '3': return KEY_NUM3;
117 case '4': return KEY_NUM4;
118 case '5': return KEY_NUM5;
119 case '6': return KEY_NUM6;
120 case '7': return KEY_NUM7;
121 case '8': return KEY_NUM8;
122 case '9': return KEY_NUM9;
128 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
134 LPCREATESTRUCT pCreateStruct = (LPCREATESTRUCT)lParam;
135 SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pCreateStruct->lpCreateParams);
136 return DefWindowProcA(hWnd, message, wParam, lParam);
140 Window *window = (Window*)(LONG_PTR)GetWindowLongPtr(hWnd, GWLP_USERDATA);
149 event.Type = Event::EVENT_CLOSED;
150 window->pushEvent(event);
157 GetClientRect(hWnd, &winRect);
160 topLeft.x = winRect.left;
161 topLeft.y = winRect.top;
162 ClientToScreen(hWnd, &topLeft);
165 event.Type = Event::EVENT_MOVED;
166 event.Move.X = topLeft.x;
167 event.Move.Y = topLeft.y;
168 window->pushEvent(event);
176 GetClientRect(hWnd, &winRect);
179 topLeft.x = winRect.left;
180 topLeft.y = winRect.top;
181 ClientToScreen(hWnd, &topLeft);
184 botRight.x = winRect.right;
185 botRight.y = winRect.bottom;
186 ClientToScreen(hWnd, &botRight);
189 event.Type = Event::EVENT_RESIZED;
190 event.Size.Width = botRight.x - topLeft.x;
191 event.Size.Height = botRight.y - topLeft.y;
192 window->pushEvent(event);
200 event.Type = Event::EVENT_GAINED_FOCUS;
201 window->pushEvent(event);
208 event.Type = Event::EVENT_LOST_FOCUS;
209 window->pushEvent(event);
218 bool down = (message == WM_KEYDOWN || message == WM_SYSKEYDOWN);
221 event.Type = down ? Event::EVENT_KEY_PRESSED : Event::EVENT_KEY_RELEASED;
222 event.Key.Alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
223 event.Key.Control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
224 event.Key.Shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
225 event.Key.System = HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN));
226 event.Key.Code = VirtualKeyCodeToKey(wParam, lParam);
227 window->pushEvent(event);
235 event.Type = Event::EVENT_MOUSE_WHEEL_MOVED;
236 event.MouseWheel.Delta = static_cast<short>(HIWORD(wParam)) / 120;
237 window->pushEvent(event);
242 case WM_LBUTTONDBLCLK:
245 event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED;
246 event.MouseButton.Button = MOUSEBUTTON_LEFT;
247 event.MouseButton.X = static_cast<short>(LOWORD(lParam));
248 event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
249 window->pushEvent(event);
256 event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED;
257 event.MouseButton.Button = MOUSEBUTTON_LEFT;
258 event.MouseButton.X = static_cast<short>(LOWORD(lParam));
259 event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
260 window->pushEvent(event);
265 case WM_RBUTTONDBLCLK:
268 event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED;
269 event.MouseButton.Button = MOUSEBUTTON_RIGHT;
270 event.MouseButton.X = static_cast<short>(LOWORD(lParam));
271 event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
272 window->pushEvent(event);
276 // Mouse right button up event
280 event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED;
281 event.MouseButton.Button = MOUSEBUTTON_RIGHT;
282 event.MouseButton.X = static_cast<short>(LOWORD(lParam));
283 event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
284 window->pushEvent(event);
288 // Mouse wheel button down event
290 case WM_MBUTTONDBLCLK:
293 event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED;
294 event.MouseButton.Button = MOUSEBUTTON_MIDDLE;
295 event.MouseButton.X = static_cast<short>(LOWORD(lParam));
296 event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
297 window->pushEvent(event);
301 // Mouse wheel button up event
305 event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED;
306 event.MouseButton.Button = MOUSEBUTTON_MIDDLE;
307 event.MouseButton.X = static_cast<short>(LOWORD(lParam));
308 event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
309 window->pushEvent(event);
313 // Mouse X button down event
315 case WM_XBUTTONDBLCLK:
318 event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED;
319 event.MouseButton.Button = (HIWORD(wParam) == XBUTTON1) ? MOUSEBUTTON_BUTTON4 : MOUSEBUTTON_BUTTON5;
320 event.MouseButton.X = static_cast<short>(LOWORD(lParam));
321 event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
322 window->pushEvent(event);
326 // Mouse X button up event
330 event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED;
331 event.MouseButton.Button = (HIWORD(wParam) == XBUTTON1) ? MOUSEBUTTON_BUTTON4 : MOUSEBUTTON_BUTTON5;
332 event.MouseButton.X = static_cast<short>(LOWORD(lParam));
333 event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
334 window->pushEvent(event);
340 int mouseX = static_cast<short>(LOWORD(lParam));
341 int mouseY = static_cast<short>(HIWORD(lParam));
344 event.Type = Event::EVENT_MOUSE_MOVED;
345 event.MouseMove.X = mouseX;
346 event.MouseMove.Y = mouseY;
347 window->pushEvent(event);
354 event.Type = Event::EVENT_MOUSE_LEFT;
355 window->pushEvent(event);
361 return DefWindowProcA(hWnd, message, wParam, lParam);
364 Win32Window::Win32Window()
371 Win32Window::~Win32Window()
376 bool Win32Window::initialize(const std::string &name, size_t width, size_t height)
382 WNDCLASSEXA windowClass = { 0 };
383 windowClass.cbSize = sizeof(WNDCLASSEXA);
384 windowClass.style = CS_OWNDC;
385 windowClass.lpfnWndProc = WndProc;
386 windowClass.cbClsExtra = 0;
387 windowClass.cbWndExtra = 0;
388 windowClass.hInstance = GetModuleHandle(NULL);
389 windowClass.hIcon = NULL;
390 windowClass.hCursor = LoadCursorA(NULL, IDC_ARROW);
391 windowClass.hbrBackground = 0;
392 windowClass.lpszMenuName = NULL;
393 windowClass.lpszClassName = mClassName.c_str();
394 if (!RegisterClassExA(&windowClass))
399 DWORD style = WS_VISIBLE | WS_CAPTION | WS_MINIMIZEBOX | WS_THICKFRAME | WS_MAXIMIZEBOX | WS_SYSMENU;
400 DWORD extendedStyle = WS_EX_APPWINDOW;
402 RECT sizeRect = { 0, 0, width, height };
403 AdjustWindowRectEx(&sizeRect, style, false, extendedStyle);
405 mNativeWindow = CreateWindowExA(extendedStyle, mClassName.c_str(), name.c_str(), style, CW_USEDEFAULT, CW_USEDEFAULT,
406 sizeRect.right - sizeRect.left, sizeRect.bottom - sizeRect.top, NULL, NULL,
407 GetModuleHandle(NULL), this);
409 SetWindowLongPtrA(mNativeWindow, GWLP_USERDATA, reinterpret_cast<LONG>(this));
411 ShowWindow(mNativeWindow, SW_SHOW);
413 mNativeDisplay = GetDC(mNativeWindow);
423 void Win32Window::destroy()
427 ReleaseDC(mNativeWindow, mNativeDisplay);
433 DestroyWindow(mNativeWindow);
437 UnregisterClassA(mClassName.c_str(), NULL);
440 EGLNativeWindowType Win32Window::getNativeWindow() const
442 return mNativeWindow;
445 EGLNativeDisplayType Win32Window::getNativeDisplay() const
447 return mNativeDisplay;
450 void Win32Window::messageLoop()
453 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
455 TranslateMessage(&msg);
456 DispatchMessage(&msg);
460 void Win32Window::setMousePosition(int x, int y)
463 GetClientRect(mNativeWindow, &winRect);
466 topLeft.x = winRect.left;
467 topLeft.y = winRect.top;
468 ClientToScreen(mNativeWindow, &topLeft);
470 SetCursorPos(topLeft.x + x, topLeft.y + y);