1/*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
4 *
5 * Copyright 2016 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Generic Win32 window class.
22 *//*--------------------------------------------------------------------*/
23
24#include "tcuWin32Window.hpp"
25
26namespace tcu
27{
28namespace win32
29{
30
31static LRESULT CALLBACK windowProcCallback (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
32{
33	Window* window = reinterpret_cast<Window*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
34	if (window)
35		return window->windowProc(uMsg, wParam, lParam);
36	else
37		return DefWindowProc(hWnd, uMsg, wParam, lParam);
38}
39
40Window::Window (HINSTANCE instance, int width, int height)
41	: m_window	(DE_NULL)
42{
43	try
44	{
45		static const char	s_className[]	= "dEQP Test Process Class";
46		static const char	s_windowName[]	= "dEQP Test Process";
47
48		{
49			WNDCLASS wndClass;
50			memset(&wndClass, 0, sizeof(wndClass));
51			wndClass.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
52			wndClass.lpfnWndProc	= windowProcCallback;
53			wndClass.cbClsExtra		= 0;
54			wndClass.cbWndExtra		= 0;
55			wndClass.hInstance		= instance;
56			wndClass.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
57			wndClass.hCursor		= LoadCursor(NULL, IDC_ARROW);
58			wndClass.hbrBackground	= CreateSolidBrush(RGB(0, 0, 0));
59			wndClass.lpszMenuName	= NULL;
60			wndClass.lpszClassName	= s_className;
61
62			RegisterClass(&wndClass);
63		}
64
65		m_window = CreateWindow(s_className, s_windowName,
66								WS_CLIPCHILDREN | WS_POPUP,
67								CW_USEDEFAULT, CW_USEDEFAULT,
68								width, height,
69								NULL, NULL, instance, NULL);
70
71		if (!m_window)
72			TCU_THROW(ResourceError, "Failed to create Win32 window");
73
74		// Store this as userdata
75		SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR)this);
76
77		setSize(width, height);
78	}
79	catch (...)
80	{
81		if (m_window)
82			DestroyWindow(m_window);
83
84		throw;
85	}
86}
87
88Window::~Window (void)
89{
90	if (m_window)
91	{
92		// Clear this pointer from windowproc
93		SetWindowLongPtr(m_window, GWLP_USERDATA, 0);
94	}
95
96	DestroyWindow(m_window);
97}
98
99void Window::setVisible (bool visible)
100{
101	ShowWindow(m_window, visible ? SW_SHOW : SW_HIDE);
102	processEvents();
103}
104
105void Window::setForeground(void)
106{
107	SetForegroundWindow(m_window);
108	processEvents();
109}
110
111void Window::setSize (int width, int height)
112{
113	RECT rc;
114
115	rc.left		= 0;
116	rc.top		= 0;
117	rc.right	= width;
118	rc.bottom	= height;
119
120	if (!AdjustWindowRect(&rc, GetWindowLong(m_window, GWL_STYLE), GetMenu(m_window) != NULL))
121		TCU_THROW(TestError, "AdjustWindowRect() failed");
122
123	if (!SetWindowPos(m_window, NULL, 0, 0,
124					  rc.right - rc.left, rc.bottom - rc.top,
125					  SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER))
126		TCU_THROW(TestError, "SetWindowPos() failed");
127}
128
129void Window::setMinimized(bool minimize)
130{
131	ShowWindow(m_window, minimize ? SW_MINIMIZE : SW_RESTORE);
132	processEvents();
133}
134
135IVec2 Window::getSize (void) const
136{
137	RECT rc;
138	if (!GetClientRect(m_window, &rc))
139		TCU_THROW(TestError, "GetClientRect() failed");
140
141	return IVec2(rc.right - rc.left,
142				 rc.bottom - rc.top);
143}
144
145void Window::processEvents (void)
146{
147	MSG msg;
148	while (PeekMessage(&msg, m_window, 0, 0, PM_REMOVE))
149		DispatchMessage(&msg);
150}
151
152LRESULT Window::windowProc (UINT uMsg, WPARAM wParam, LPARAM lParam)
153{
154	switch (uMsg)
155	{
156		// \todo [2014-03-12 pyry] Handle WM_SIZE?
157
158		case WM_DESTROY:
159			PostQuitMessage(0);
160			return 0;
161
162		case WM_KEYDOWN:
163			if (wParam == VK_ESCAPE)
164			{
165				PostQuitMessage(0);
166				return 0;
167			}
168			// fall-through
169
170		default:
171			return DefWindowProc(m_window, uMsg, wParam, lParam);
172	}
173}
174
175} // win32
176} // tcu
177