1/*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
4 *
5 * Copyright 2014 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{
28
29static LRESULT CALLBACK win32WindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
30{
31	Win32Window* window = reinterpret_cast<Win32Window*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
32	if (window)
33		return window->windowProc(uMsg, wParam, lParam);
34	else
35		return DefWindowProc(hWnd, uMsg, wParam, lParam);
36}
37
38Win32Window::Win32Window (HINSTANCE instance, int width, int height)
39	: m_window		(DE_NULL)
40{
41	try
42	{
43		static const char	s_className[]	= "dEQP Tester Core Class";
44		static const char	s_windowName[]	= "dEQP Tester Core";
45
46		{
47			WNDCLASS wndClass;
48			memset(&wndClass, 0, sizeof(wndClass));
49			wndClass.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
50			wndClass.lpfnWndProc	= win32WindowProc;
51			wndClass.cbClsExtra		= 0;
52			wndClass.cbWndExtra		= 0;
53			wndClass.hInstance		= instance;
54			wndClass.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
55			wndClass.hCursor		= LoadCursor(NULL, IDC_ARROW);
56			wndClass.hbrBackground	= CreateSolidBrush(RGB(0, 0, 0));
57			wndClass.lpszMenuName	= NULL;
58			wndClass.lpszClassName	= s_className;
59
60			RegisterClass(&wndClass);
61		}
62
63		m_window = CreateWindow(s_className, s_windowName,
64								WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW,
65								CW_USEDEFAULT, CW_USEDEFAULT,
66								width, height,
67								NULL, NULL, instance, NULL);
68
69		if (!m_window)
70			throw ResourceError("Failed to create Win32 window", "", __FILE__, __LINE__);
71
72		// Store this as userdata
73		SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR)this);
74
75		setSize(width, height);
76	}
77	catch (...)
78	{
79		if (m_window)
80			DestroyWindow(m_window);
81
82		throw;
83	}
84}
85
86Win32Window::~Win32Window (void)
87{
88	if (m_window)
89	{
90		// Clear this pointer from windowproc
91		SetWindowLongPtr(m_window, GWLP_USERDATA, 0);
92	}
93
94	DestroyWindow(m_window);
95}
96
97void Win32Window::setVisible (bool visible)
98{
99	ShowWindow(m_window, visible ? SW_SHOW : SW_HIDE);
100}
101
102void Win32Window::setSize (int width, int height)
103{
104	RECT rc;
105
106	rc.left		= 0;
107	rc.top		= 0;
108	rc.right	= width;
109	rc.bottom	= height;
110
111	if (!AdjustWindowRect(&rc, GetWindowLong(m_window, GWL_STYLE), GetMenu(m_window) != NULL))
112		throw tcu::TestError("AdjustWindowRect() failed", DE_NULL, __FILE__, __LINE__);
113
114	if (!SetWindowPos(m_window, NULL, 0, 0,
115					  rc.right - rc.left, rc.bottom - rc.top,
116					  SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER))
117		throw tcu::TestError("SetWindowPos() failed", DE_NULL, __FILE__, __LINE__);
118}
119
120IVec2 Win32Window::getSize (void) const
121{
122	RECT rc;
123	if (!GetClientRect(m_window, &rc))
124		throw tcu::TestError("GetClientRect() failed", DE_NULL, __FILE__, __LINE__);
125
126	return IVec2(rc.right - rc.left,
127				 rc.bottom - rc.top);
128}
129
130void Win32Window::processEvents (void)
131{
132	MSG msg;
133	while (PeekMessage(&msg, m_window, 0, 0, PM_REMOVE))
134		DispatchMessage(&msg);
135}
136
137LRESULT Win32Window::windowProc (UINT uMsg, WPARAM wParam, LPARAM lParam)
138{
139	switch (uMsg)
140	{
141		// \todo [2014-03-12 pyry] Handle WM_SIZE?
142
143		case WM_DESTROY:
144			PostQuitMessage(0);
145			return 0;
146
147		case WM_KEYDOWN:
148			if (wParam == VK_ESCAPE)
149			{
150				PostQuitMessage(0);
151				return 0;
152			}
153			// fall-through
154
155		default:
156			return DefWindowProc(m_window, uMsg, wParam, lParam);
157	}
158}
159
160} // tcu
161