Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / util / win32 / Win32Window.cpp
1 //
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.
5 //
6
7 #include "win32/Win32Window.h"
8
9 #include <sstream>
10
11 Key VirtualKeyCodeToKey(WPARAM key, LPARAM flags)
12 {
13     switch (key)
14     {
15         // Check the scancode to distinguish between left and right shift
16       case VK_SHIFT:
17         {
18             static unsigned int lShift = MapVirtualKey(VK_LSHIFT, MAPVK_VK_TO_VSC);
19             unsigned int scancode = static_cast<unsigned int>((flags & (0xFF << 16)) >> 16);
20             return scancode == lShift ? KEY_LSHIFT : KEY_RSHIFT;
21         }
22
23         // Check the "extended" flag to distinguish between left and right alt
24       case VK_MENU:       return (HIWORD(flags) & KF_EXTENDED) ? KEY_RALT : KEY_LALT;
25
26         // Check the "extended" flag to distinguish between left and right control
27       case VK_CONTROL:    return (HIWORD(flags) & KF_EXTENDED) ? KEY_RCONTROL : KEY_LCONTROL;
28
29         // Other keys are reported properly
30       case VK_LWIN:       return KEY_LSYSTEM;
31       case VK_RWIN:       return KEY_RSYSTEM;
32       case VK_APPS:       return KEY_MENU;
33       case VK_OEM_1:      return KEY_SEMICOLON;
34       case VK_OEM_2:      return KEY_SLASH;
35       case VK_OEM_PLUS:   return KEY_EQUAL;
36       case VK_OEM_MINUS:  return KEY_DASH;
37       case VK_OEM_4:      return KEY_LBRACKET;
38       case VK_OEM_6:      return KEY_RBRACKET;
39       case VK_OEM_COMMA:  return KEY_COMMA;
40       case VK_OEM_PERIOD: return KEY_PERIOD;
41       case VK_OEM_7:      return KEY_QUOTE;
42       case VK_OEM_5:      return KEY_BACKSLASH;
43       case VK_OEM_3:      return KEY_TILDE;
44       case VK_ESCAPE:     return KEY_ESCAPE;
45       case VK_SPACE:      return KEY_SPACE;
46       case VK_RETURN:     return KEY_RETURN;
47       case VK_BACK:       return KEY_BACK;
48       case VK_TAB:        return KEY_TAB;
49       case VK_PRIOR:      return KEY_PAGEUP;
50       case VK_NEXT:       return KEY_PAGEDOWN;
51       case VK_END:        return KEY_END;
52       case VK_HOME:       return KEY_HOME;
53       case VK_INSERT:     return KEY_INSERT;
54       case VK_DELETE:     return KEY_DELETE;
55       case VK_ADD:        return KEY_ADD;
56       case VK_SUBTRACT:   return KEY_SUBTRACT;
57       case VK_MULTIPLY:   return KEY_MULTIPLY;
58       case VK_DIVIDE:     return KEY_DIVIDE;
59       case VK_PAUSE:      return KEY_PAUSE;
60       case VK_F1:         return KEY_F1;
61       case VK_F2:         return KEY_F2;
62       case VK_F3:         return KEY_F3;
63       case VK_F4:         return KEY_F4;
64       case VK_F5:         return KEY_F5;
65       case VK_F6:         return KEY_F6;
66       case VK_F7:         return KEY_F7;
67       case VK_F8:         return KEY_F8;
68       case VK_F9:         return KEY_F9;
69       case VK_F10:        return KEY_F10;
70       case VK_F11:        return KEY_F11;
71       case VK_F12:        return KEY_F12;
72       case VK_F13:        return KEY_F13;
73       case VK_F14:        return KEY_F14;
74       case VK_F15:        return KEY_F15;
75       case VK_LEFT:       return KEY_LEFT;
76       case VK_RIGHT:      return KEY_RIGHT;
77       case VK_UP:         return KEY_UP;
78       case VK_DOWN:       return KEY_DOWN;
79       case VK_NUMPAD0:    return KEY_NUMPAD0;
80       case VK_NUMPAD1:    return KEY_NUMPAD1;
81       case VK_NUMPAD2:    return KEY_NUMPAD2;
82       case VK_NUMPAD3:    return KEY_NUMPAD3;
83       case VK_NUMPAD4:    return KEY_NUMPAD4;
84       case VK_NUMPAD5:    return KEY_NUMPAD5;
85       case VK_NUMPAD6:    return KEY_NUMPAD6;
86       case VK_NUMPAD7:    return KEY_NUMPAD7;
87       case VK_NUMPAD8:    return KEY_NUMPAD8;
88       case VK_NUMPAD9:    return KEY_NUMPAD9;
89       case 'A':           return KEY_A;
90       case 'Z':           return KEY_Z;
91       case 'E':           return KEY_E;
92       case 'R':           return KEY_R;
93       case 'T':           return KEY_T;
94       case 'Y':           return KEY_Y;
95       case 'U':           return KEY_U;
96       case 'I':           return KEY_I;
97       case 'O':           return KEY_O;
98       case 'P':           return KEY_P;
99       case 'Q':           return KEY_Q;
100       case 'S':           return KEY_S;
101       case 'D':           return KEY_D;
102       case 'F':           return KEY_F;
103       case 'G':           return KEY_G;
104       case 'H':           return KEY_H;
105       case 'J':           return KEY_J;
106       case 'K':           return KEY_K;
107       case 'L':           return KEY_L;
108       case 'M':           return KEY_M;
109       case 'W':           return KEY_W;
110       case 'X':           return KEY_X;
111       case 'C':           return KEY_C;
112       case 'V':           return KEY_V;
113       case 'B':           return KEY_B;
114       case 'N':           return KEY_N;
115       case '0':           return KEY_NUM0;
116       case '1':           return KEY_NUM1;
117       case '2':           return KEY_NUM2;
118       case '3':           return KEY_NUM3;
119       case '4':           return KEY_NUM4;
120       case '5':           return KEY_NUM5;
121       case '6':           return KEY_NUM6;
122       case '7':           return KEY_NUM7;
123       case '8':           return KEY_NUM8;
124       case '9':           return KEY_NUM9;
125     }
126
127     return Key(0);
128 }
129
130 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
131 {
132     switch(message)
133     {
134       case WM_NCCREATE:
135         {
136             LPCREATESTRUCT pCreateStruct = (LPCREATESTRUCT)lParam;
137             SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pCreateStruct->lpCreateParams);
138             return DefWindowProcA(hWnd, message, wParam, lParam);
139         }
140     }
141
142     OSWindow *window = (OSWindow*)(LONG_PTR)GetWindowLongPtr(hWnd, GWLP_USERDATA);
143     if (window)
144     {
145         switch (message)
146         {
147           case WM_DESTROY:
148           case WM_CLOSE:
149             {
150                 Event event;
151                 event.Type = Event::EVENT_CLOSED;
152                 window->pushEvent(event);
153                 break;
154             }
155
156           case WM_MOVE:
157             {
158                 RECT winRect;
159                 GetClientRect(hWnd, &winRect);
160
161                 POINT topLeft;
162                 topLeft.x = winRect.left;
163                 topLeft.y = winRect.top;
164                 ClientToScreen(hWnd, &topLeft);
165
166                 Event event;
167                 event.Type        = Event::EVENT_MOVED;
168                 event.Move.X      = topLeft.x;
169                 event.Move.Y      = topLeft.y;
170                 window->pushEvent(event);
171
172                 break;
173             }
174
175           case WM_SIZE:
176             {
177                 RECT winRect;
178                 GetClientRect(hWnd, &winRect);
179
180                 POINT topLeft;
181                 topLeft.x = winRect.left;
182                 topLeft.y = winRect.top;
183                 ClientToScreen(hWnd, &topLeft);
184
185                 POINT botRight;
186                 botRight.x = winRect.right;
187                 botRight.y = winRect.bottom;
188                 ClientToScreen(hWnd, &botRight);
189
190                 Event event;
191                 event.Type        = Event::EVENT_RESIZED;
192                 event.Size.Width  = botRight.x - topLeft.x;
193                 event.Size.Height = botRight.y - topLeft.y;
194                 window->pushEvent(event);
195
196                 break;
197             }
198
199           case WM_SETFOCUS:
200             {
201                 Event event;
202                 event.Type = Event::EVENT_GAINED_FOCUS;
203                 window->pushEvent(event);
204                 break;
205             }
206
207           case WM_KILLFOCUS:
208             {
209                 Event event;
210                 event.Type = Event::EVENT_LOST_FOCUS;
211                 window->pushEvent(event);
212                 break;
213             }
214
215           case WM_KEYDOWN:
216           case WM_SYSKEYDOWN:
217           case WM_KEYUP:
218           case WM_SYSKEYUP:
219             {
220                 bool down = (message == WM_KEYDOWN || message == WM_SYSKEYDOWN);
221
222                 Event event;
223                 event.Type        = down ? Event::EVENT_KEY_PRESSED : Event::EVENT_KEY_RELEASED;
224                 event.Key.Alt     = HIWORD(GetAsyncKeyState(VK_MENU))    != 0;
225                 event.Key.Control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
226                 event.Key.Shift   = HIWORD(GetAsyncKeyState(VK_SHIFT))   != 0;
227                 event.Key.System  = HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN));
228                 event.Key.Code    = VirtualKeyCodeToKey(wParam, lParam);
229                 window->pushEvent(event);
230
231                 break;
232             }
233
234           case WM_MOUSEWHEEL:
235             {
236                 Event event;
237                 event.Type = Event::EVENT_MOUSE_WHEEL_MOVED;
238                 event.MouseWheel.Delta = static_cast<short>(HIWORD(wParam)) / 120;
239                 window->pushEvent(event);
240                 break;
241             }
242
243           case WM_LBUTTONDOWN:
244           case WM_LBUTTONDBLCLK:
245             {
246                 Event event;
247                 event.Type               = Event::EVENT_MOUSE_BUTTON_PRESSED;
248                 event.MouseButton.Button = MOUSEBUTTON_LEFT;
249                 event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
250                 event.MouseButton.Y      = static_cast<short>(HIWORD(lParam));
251                 window->pushEvent(event);
252                 break;
253             }
254
255           case WM_LBUTTONUP:
256             {
257                 Event event;
258                 event.Type               = Event::EVENT_MOUSE_BUTTON_RELEASED;
259                 event.MouseButton.Button = MOUSEBUTTON_LEFT;
260                 event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
261                 event.MouseButton.Y      = static_cast<short>(HIWORD(lParam));
262                 window->pushEvent(event);
263                 break;
264             }
265
266           case WM_RBUTTONDOWN:
267           case WM_RBUTTONDBLCLK:
268             {
269                 Event event;
270                 event.Type               = Event::EVENT_MOUSE_BUTTON_PRESSED;
271                 event.MouseButton.Button = MOUSEBUTTON_RIGHT;
272                 event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
273                 event.MouseButton.Y      = static_cast<short>(HIWORD(lParam));
274                 window->pushEvent(event);
275                 break;
276             }
277
278             // Mouse right button up event
279           case WM_RBUTTONUP:
280             {
281                 Event event;
282                 event.Type               = Event::EVENT_MOUSE_BUTTON_RELEASED;
283                 event.MouseButton.Button = MOUSEBUTTON_RIGHT;
284                 event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
285                 event.MouseButton.Y      = static_cast<short>(HIWORD(lParam));
286                 window->pushEvent(event);
287                 break;
288             }
289
290             // Mouse wheel button down event
291           case WM_MBUTTONDOWN:
292           case WM_MBUTTONDBLCLK:
293             {
294                 Event event;
295                 event.Type               = Event::EVENT_MOUSE_BUTTON_PRESSED;
296                 event.MouseButton.Button = MOUSEBUTTON_MIDDLE;
297                 event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
298                 event.MouseButton.Y      = static_cast<short>(HIWORD(lParam));
299                 window->pushEvent(event);
300                 break;
301             }
302
303             // Mouse wheel button up event
304           case WM_MBUTTONUP:
305             {
306                 Event event;
307                 event.Type               = Event::EVENT_MOUSE_BUTTON_RELEASED;
308                 event.MouseButton.Button = MOUSEBUTTON_MIDDLE;
309                 event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
310                 event.MouseButton.Y      = static_cast<short>(HIWORD(lParam));
311                 window->pushEvent(event);
312                 break;
313             }
314
315             // Mouse X button down event
316           case WM_XBUTTONDOWN:
317           case WM_XBUTTONDBLCLK:
318             {
319                 Event event;
320                 event.Type               = Event::EVENT_MOUSE_BUTTON_PRESSED;
321                 event.MouseButton.Button = (HIWORD(wParam) == XBUTTON1) ? MOUSEBUTTON_BUTTON4 : MOUSEBUTTON_BUTTON5;
322                 event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
323                 event.MouseButton.Y      = static_cast<short>(HIWORD(lParam));
324                 window->pushEvent(event);
325                 break;
326             }
327
328             // Mouse X button up event
329           case WM_XBUTTONUP:
330             {
331                 Event event;
332                 event.Type               = Event::EVENT_MOUSE_BUTTON_RELEASED;
333                 event.MouseButton.Button = (HIWORD(wParam) == XBUTTON1) ? MOUSEBUTTON_BUTTON4 : MOUSEBUTTON_BUTTON5;
334                 event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
335                 event.MouseButton.Y      = static_cast<short>(HIWORD(lParam));
336                 window->pushEvent(event);
337                 break;
338             }
339
340           case WM_MOUSEMOVE:
341             {
342                 int mouseX = static_cast<short>(LOWORD(lParam));
343                 int mouseY = static_cast<short>(HIWORD(lParam));
344
345                 Event event;
346                 event.Type        = Event::EVENT_MOUSE_MOVED;
347                 event.MouseMove.X = mouseX;
348                 event.MouseMove.Y = mouseY;
349                 window->pushEvent(event);
350                 break;
351             }
352
353           case WM_MOUSELEAVE:
354             {
355                 Event event;
356                 event.Type = Event::EVENT_MOUSE_LEFT;
357                 window->pushEvent(event);
358                 break;
359             }
360         }
361
362     }
363     return DefWindowProcA(hWnd, message, wParam, lParam);
364 }
365
366 Win32Window::Win32Window()
367     : mNativeWindow(0),
368       mParentWindow(0),
369       mNativeDisplay(0)
370 {
371 }
372
373 Win32Window::~Win32Window()
374 {
375     destroy();
376 }
377
378 bool Win32Window::initialize(const std::string &name, size_t width, size_t height)
379 {
380     destroy();
381
382     // Use a new window class name for ever window to ensure that a new window can be created
383     // even if the last one was not properly destroyed
384     static size_t windowIdx = 0;
385     std::ostringstream nameStream;
386     nameStream << name << "_" << windowIdx++;
387
388     mParentClassName = nameStream.str();
389     mChildClassName = mParentClassName + "_Child";
390
391     // Work around compile error from not defining "UNICODE" while Chromium does
392     const LPSTR idcArrow = MAKEINTRESOURCEA(32512);
393
394     WNDCLASSEXA parentWindowClass = { 0 };
395     parentWindowClass.cbSize = sizeof(WNDCLASSEXA);
396     parentWindowClass.style = 0;
397     parentWindowClass.lpfnWndProc = WndProc;
398     parentWindowClass.cbClsExtra = 0;
399     parentWindowClass.cbWndExtra = 0;
400     parentWindowClass.hInstance = GetModuleHandle(NULL);
401     parentWindowClass.hIcon = NULL;
402     parentWindowClass.hCursor = LoadCursorA(NULL, idcArrow);
403     parentWindowClass.hbrBackground = 0;
404     parentWindowClass.lpszMenuName = NULL;
405     parentWindowClass.lpszClassName = mParentClassName.c_str();
406     if (!RegisterClassExA(&parentWindowClass))
407     {
408         return false;
409     }
410
411     WNDCLASSEXA childWindowClass = { 0 };
412     childWindowClass.cbSize = sizeof(WNDCLASSEXA);
413     childWindowClass.style = CS_OWNDC;
414     childWindowClass.lpfnWndProc = WndProc;
415     childWindowClass.cbClsExtra = 0;
416     childWindowClass.cbWndExtra = 0;
417     childWindowClass.hInstance = GetModuleHandle(NULL);
418     childWindowClass.hIcon = NULL;
419     childWindowClass.hCursor = LoadCursorA(NULL, idcArrow);
420     childWindowClass.hbrBackground = 0;
421     childWindowClass.lpszMenuName = NULL;
422     childWindowClass.lpszClassName = mChildClassName.c_str();
423     if (!RegisterClassExA(&childWindowClass))
424     {
425         return false;
426     }
427
428     DWORD parentStyle = WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU;
429     DWORD parentExtendedStyle = WS_EX_APPWINDOW;
430
431     RECT sizeRect = { 0, 0, width, height };
432     AdjustWindowRectEx(&sizeRect, parentStyle, FALSE, parentExtendedStyle);
433
434     mParentWindow = CreateWindowExA(parentExtendedStyle, mParentClassName.c_str(), name.c_str(), parentStyle, CW_USEDEFAULT, CW_USEDEFAULT,
435                                     sizeRect.right - sizeRect.left, sizeRect.bottom - sizeRect.top, NULL, NULL,
436                                     GetModuleHandle(NULL), this);
437
438     mNativeWindow = CreateWindowExA(0, mChildClassName.c_str(), name.c_str(), WS_CHILD, 0, 0, width, height,
439                                     mParentWindow, NULL, GetModuleHandle(NULL), this);
440
441     mNativeDisplay = GetDC(mNativeWindow);
442     if (!mNativeDisplay)
443     {
444         destroy();
445         return false;
446     }
447
448     return true;
449 }
450
451 void Win32Window::destroy()
452 {
453     if (mNativeDisplay)
454     {
455         ReleaseDC(mNativeWindow, mNativeDisplay);
456         mNativeDisplay = 0;
457     }
458
459     if (mNativeWindow)
460     {
461         DestroyWindow(mNativeWindow);
462         mNativeWindow = 0;
463     }
464
465     if (mParentWindow)
466     {
467         DestroyWindow(mParentWindow);
468         mParentWindow = 0;
469     }
470
471     UnregisterClassA(mParentClassName.c_str(), NULL);
472     UnregisterClassA(mChildClassName.c_str(), NULL);
473 }
474
475 EGLNativeWindowType Win32Window::getNativeWindow() const
476 {
477     return mNativeWindow;
478 }
479
480 EGLNativeDisplayType Win32Window::getNativeDisplay() const
481 {
482     return mNativeDisplay;
483 }
484
485 void Win32Window::messageLoop()
486 {
487     MSG msg;
488     while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
489     {
490         TranslateMessage(&msg);
491         DispatchMessage(&msg);
492     }
493 }
494
495 void Win32Window::setMousePosition(int x, int y)
496 {
497     RECT winRect;
498     GetClientRect(mNativeWindow, &winRect);
499
500     POINT topLeft;
501     topLeft.x = winRect.left;
502     topLeft.y = winRect.top;
503     ClientToScreen(mNativeWindow, &topLeft);
504
505     SetCursorPos(topLeft.x + x, topLeft.y + y);
506 }
507
508 OSWindow *CreateOSWindow()
509 {
510     return new Win32Window();
511 }
512
513 bool Win32Window::resize(int width, int height)
514 {
515     if (width == mWidth && height == mHeight)
516     {
517         return true;
518     }
519
520     RECT windowRect;
521     if (!GetWindowRect(mParentWindow, &windowRect))
522     {
523         return false;
524     }
525
526     RECT clientRect;
527     if (!GetClientRect(mParentWindow, &clientRect))
528     {
529         return false;
530     }
531
532     LONG diffX = (windowRect.right - windowRect.left) - clientRect.right;
533     LONG diffY = (windowRect.bottom - windowRect.top) - clientRect.bottom;
534     if (!MoveWindow(mParentWindow, windowRect.left, windowRect.top, width + diffX, height + diffY, FALSE))
535     {
536         return false;
537     }
538
539     if (!MoveWindow(mNativeWindow, 0, 0, width, height, FALSE))
540     {
541         return false;
542     }
543
544     return true;
545 }
546
547 void Win32Window::setVisible(bool isVisible)
548 {
549     int flag = (isVisible ? SW_SHOW : SW_HIDE);
550
551     ShowWindow(mParentWindow, flag);
552     ShowWindow(mNativeWindow, flag);
553 }
554
555 void Win32Window::pushEvent(Event event)
556 {
557     OSWindow::pushEvent(event);
558
559     switch (event.Type)
560     {
561       case Event::EVENT_RESIZED:
562         MoveWindow(mNativeWindow, 0, 0, mWidth, mHeight, FALSE);
563         break;
564     }
565 }