PageRenderTime 72ms CodeModel.GetById 11ms app.highlight 57ms RepoModel.GetById 1ms app.codeStats 0ms

/platform/win/scaffold/window.d

http://github.com/wilkie/djehuty
D | 391 lines | 234 code | 90 blank | 67 comment | 32 complexity | a98a93dfbaa5c207ffc9821adbddd339 MD5 | raw file
  1/*
  2 * window.d
  3 *
  4 * This file implements the Scaffold for platform specific Window
  5 * operations in Windows.
  6 *
  7 * Author: Dave Wilkinson
  8 *
  9 */
 10
 11module scaffold.window;
 12
 13import scaffold.system;
 14
 15import binding.win32.windef;
 16import binding.win32.winnt;
 17import binding.win32.winbase;
 18import binding.win32.wingdi;
 19import binding.win32.winuser;
 20
 21import Gdiplus = binding.win32.gdiplus;
 22
 23import platform.win.main;
 24
 25import platform.vars.window;
 26import platform.vars.view;
 27
 28import graphics.view;
 29
 30import core.color;
 31import core.string;
 32import core.main;
 33import core.definitions;
 34import core.unicode;
 35
 36import gui.window;
 37
 38import opengl.window;
 39
 40import synch.thread;
 41
 42import io.console;
 43
 44// all windows
 45void WindowCreate(ref Window window, WindowPlatformVars* windowVars) {
 46	windowVars.oldWidth = window.width;
 47	windowVars.oldHeight = window.height;
 48
 49	windowVars.oldX = window.x;
 50	windowVars.oldY = window.y;
 51
 52	windowVars.oldTitle = window.text;
 53
 54	windowVars.userData = cast(void*)window;
 55
 56	_ClientSizeToWindowSize(window, windowVars.oldWidth, windowVars.oldHeight);
 57
 58	_GatherStyleInformation(window, windowVars.istyle, windowVars.iexstyle);
 59
 60	windowVars.windowClass = window;
 61
 62	if (cast(GLWindow)window !is null) {
 63		windowVars.msgThread = new Thread(&windowVars.gameLoop);
 64	}
 65	else {
 66		windowVars.msgThread = new Thread(&windowVars.msgLoop);
 67	}
 68
 69	ThreadSetWindow(windowVars.msgThread, window);
 70
 71	windowVars.msgThread.start();
 72
 73	RAWINPUTDEVICE Rid;
 74
 75	Rid.usUsagePage = 0x01;
 76	Rid.usUsage = 0x02;
 77	Rid.dwFlags = RIDEV_INPUTSINK;
 78	Rid.hwndTarget = windowVars.hWnd;
 79
 80	RegisterRawInputDevices(&Rid, 1, Rid.sizeof);
 81}
 82
 83void WindowCreate(ref Window parent, WindowPlatformVars* windowVars, ref Window window, WindowPlatformVars* parentVars) {
 84	/*
 85	int width, height, x, y;
 86
 87	width = window.width();
 88	height = window.height();
 89
 90	x = window.getX();
 91	y = window.getY();
 92
 93	width = window.width();
 94	height = window.height();
 95
 96	_ClientSizeToWindowSize(window, width, height);
 97
 98	uint istyle;
 99	uint iexstyle;
100
101	_GatherStyleInformation(window, istyle, iexstyle);
102
103	windowVars.hWnd = CreateWindowExW(iexstyle, djehutyClassName.ptr,window.getText().ptr, istyle | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
104		x, y, width, height, parentVars.hWnd,
105		cast(HMENU) null, null, cast(void*)window);
106
107	assert(windowVars.hWnd);
108
109	RAWINPUTDEVICE Rid;
110
111	Rid.usUsagePage = 0x01;
112	Rid.usUsage = 0x02;
113	Rid.dwFlags = RIDEV_INPUTSINK;
114	Rid.hwndTarget = windowVars.hWnd;
115
116	RegisterRawInputDevices(&Rid, 1, Rid.sizeof);
117	*/
118}
119
120void WindowSetStyle(ref Window window, WindowPlatformVars* windowVars) {
121	bool wasMaximized = false;
122
123	if (window.state == WindowState.Maximized) {
124		ShowWindow(windowVars.hWnd, SW_HIDE);
125		wasMaximized = true;
126		window.state = WindowState.Normal;
127	}
128
129	int width, height;
130
131	width = window.width;
132	height = window.height;
133
134	_ClientSizeToWindowSize(window, width, height);
135
136	uint istyle;
137	uint iexstyle;
138
139	_GatherStyleInformation(window, istyle, iexstyle);
140
141	SetWindowLongW(windowVars.hWnd, GWL_STYLE, istyle);
142	SetWindowLongW(windowVars.hWnd, GWL_EXSTYLE, iexstyle);
143
144	windowVars.supress_WM_MOVE = true;
145	SetWindowPos(windowVars.hWnd, null, 0,0, width, height, SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
146	windowVars.supress_WM_MOVE = false;
147
148	if (wasMaximized) {
149		window.state = WindowState.Maximized;
150
151		if (window.visible) {
152			ShowWindow(windowVars.hWnd, SW_SHOW);
153		}
154	}
155}
156
157void WindowReposition(ref Window window, WindowPlatformVars* windowVars) {
158	SetWindowPos(windowVars.hWnd, null, window.x,window.y, 0, 0, SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOZORDER);
159}
160
161void WindowSetState(ref Window window, WindowPlatformVars* windowVars) {
162	if (window.state == WindowState.Fullscreen) {
163		windowVars.oldX = window.x;
164		windowVars.oldY = window.y;
165
166		windowVars.oldWidth = window.width;
167		windowVars.oldHeight = window.height;
168
169		windowVars.supress_WM_MOVE = true;
170		windowVars.supress_WM_SIZE = true;
171
172		windowVars.oldStyle = SetWindowLongW(windowVars.hWnd, GWL_STYLE, WS_POPUP);
173
174		windowVars.supress_WM_SIZE = false;
175		windowVars.supress_WM_MOVE = false;
176
177		windowVars.supress_WM_MOVE = true;
178		windowVars.supress_WM_SIZE = true;
179		windowVars.oldExStyle = SetWindowLongW(windowVars.hWnd, GWL_EXSTYLE, 0);
180		windowVars.supress_WM_SIZE = false;
181		windowVars.supress_WM_MOVE = false;
182
183		SetWindowPos(windowVars.hWnd, null, 0,0, SystemGetDisplayWidth(SystemGetPrimaryDisplay()), SystemGetDisplayHeight(SystemGetPrimaryDisplay()), SWP_NOOWNERZORDER | SWP_NOZORDER);
184
185		SetWindowRgn(windowVars.hWnd, null, true);
186
187		if (window.visible) {
188			ShowWindow(windowVars.hWnd, SW_SHOW);
189		}
190
191		windowVars.infullscreen = true;
192	}
193	else if (window.visible) {
194		if (windowVars.infullscreen) {
195			SetWindowLongW(windowVars.hWnd, GWL_STYLE, cast(DWORD)windowVars.oldStyle);
196			SetWindowLongW(windowVars.hWnd, GWL_EXSTYLE, cast(DWORD)windowVars.oldExStyle);
197
198			int width, height;
199			width = window.width;
200			height = window.height;
201
202			_ClientSizeToWindowSize(window, width, height);
203
204			SetWindowPos(windowVars.hWnd, null, window.x,window.y, width, height, SWP_NOOWNERZORDER | SWP_NOZORDER);
205			InvalidateRect(null, null, 0);
206
207			windowVars.infullscreen = false;
208		}
209
210		switch(window.state) {
211			case WindowState.Normal:
212
213				windowVars.supress_WM_SIZE_state = true;
214				ShowWindow(windowVars.hWnd, SW_RESTORE);
215				break;
216
217			case WindowState.Minimized:
218
219				windowVars.supress_WM_SIZE_state = true;
220				ShowWindow(windowVars.hWnd, SW_MINIMIZE);
221				break;
222
223			case WindowState.Maximized:
224
225				windowVars.supress_WM_SIZE_state = true;
226				ShowWindow(windowVars.hWnd, SW_MAXIMIZE);
227				break;
228
229			default: break;
230		}
231	}
232}
233
234void _GatherStyleInformation(ref Window window, ref uint istyle, ref uint iexstyle) {
235	if (window.style == WindowStyle.Fixed) {
236		istyle = WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;
237
238                /+
239                istyle &= ~(WS_BORDER | WS_THICKFRAME);
240                iexstyle &= ~(WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
241                istyle |= WS_CAPTION | WS_DLGFRAME;
242                iexstyle |= WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE;
243                +/
244
245		istyle &= ~(WS_THICKFRAME | WS_DLGFRAME);
246		iexstyle &= ~(WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE | WS_EX_WINDOWEDGE | WS_EX_STATICEDGE);
247
248		istyle |= WS_BORDER | WS_CAPTION;
249		iexstyle |= WS_EX_DLGMODALFRAME;
250	}
251	else if (window.style == WindowStyle.Popup) {
252		istyle = WS_POPUP;
253	}
254	else { //Sizable
255		istyle = WS_OVERLAPPEDWINDOW;
256	}
257	//iexstyle |= 0x02000000;
258
259	if (window.visible) {
260		istyle |= WS_VISIBLE;
261	}
262}
263
264void _ClientSizeToWindowSize(ref Window window, ref int width, ref int height) {
265	if (width == Default) {
266		width = CW_USEDEFAULT;
267	}
268	else {
269		//normalize sizes
270
271		//account for borders and title bar...
272		//because windows is retarded in this
273		//respect
274
275		if (window.style == WindowStyle.Fixed) {
276			int border_width, border_height;
277			border_width = ( GetSystemMetrics(SM_CXBORDER) + GetSystemMetrics(SM_CXDLGFRAME) ) * 2;
278			border_height = (GetSystemMetrics(SM_CYDLGFRAME) * 2) + GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYCAPTION);
279
280			width += border_width;
281			height += border_height;
282		}
283		else if (window.style == WindowStyle.Popup) {
284			//do nothing
285		}
286		else { 
287			//Sizable
288			int border_width, border_height;
289			border_width = GetSystemMetrics(SM_CXFRAME) * 2;
290			border_height = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYDLGFRAME) + GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYCAPTION);
291
292			width += border_width;
293			height += border_height;
294		}
295
296		// account for menubar
297	}
298}
299
300void WindowRebound(ref Window window, WindowPlatformVars* windowVars) {
301	int width, height;
302
303	width = window.width;
304	height = window.height;
305
306	_ClientSizeToWindowSize(window, width, height);
307
308	windowVars.supress_WM_SIZE = true;
309	SetWindowPos(windowVars.hWnd, null, 0,0, width, height, SWP_NOMOVE | SWP_NOOWNERZORDER);
310}
311
312void WindowDestroy(ref Window window, WindowPlatformVars* windowVars) {
313	PostMessageW(windowVars.hWnd, WM_CLOSE, 0, 0);
314}
315
316void WindowSetVisible(ref Window window, WindowPlatformVars* windowVars, bool bShow) {
317	if (bShow) {
318		ShowWindow(windowVars.hWnd, SW_SHOW);
319	}
320	else {
321		ShowWindow(windowVars.hWnd, SW_HIDE);
322	}
323}
324
325void WindowSetTitle(ref Window window, WindowPlatformVars* windowVars) {
326	wstring s = Unicode.toUtf16(window.text);
327	s ~= '\0';
328	SetWindowTextW(windowVars.hWnd, cast(wchar*)s.ptr);
329}
330
331// CLIENT TO SCREEN
332
333// Takes a point on the window's client area and returns the actual screen
334// coordinates for that point.
335
336void WindowClientToScreen(ref Window window, WindowPlatformVars* windowVars, ref int x, ref int y) {
337	Coord pt = {x,y};
338	ClientToScreen(windowVars.hWnd, cast(POINT*)&pt);
339	x = pt.x;
340	y = pt.y;
341}
342
343void WindowClientToScreen(ref Window window, WindowPlatformVars* windowVars, ref Coord pt) {
344	ClientToScreen(windowVars.hWnd, cast(POINT*)&pt);
345}
346
347void WindowClientToScreen(ref Window window, WindowPlatformVars* windowVars, ref Rect rt) {
348// could optimize by directly accessing a point worth from the rect
349	Coord pt = {rt.left,rt.top};
350	ClientToScreen(windowVars.hWnd, cast(POINT*)&pt);
351	rt.left = pt.x;
352	rt.top = pt.y;
353	Coord pt2 = {rt.right,rt.bottom};
354	ClientToScreen(windowVars.hWnd, cast(POINT*)&pt2);
355	rt.right = pt2.x;
356	rt.bottom = pt2.y;
357}
358
359
360// Viewable windows
361void WindowStartDraw(ref Window window, WindowPlatformVars* windowVars, ref WindowView view, ref ViewPlatformVars viewVars) {
362	//the starting pen and brush is black and white respectively
363	if (viewVars.aa) {
364		Gdiplus.GdipSetSmoothingMode(viewVars.g, Gdiplus.SmoothingMode.SmoothingModeAntiAlias);
365	}
366	else {
367		Gdiplus.GdipSetSmoothingMode(viewVars.g, Gdiplus.SmoothingMode.SmoothingModeDefault);
368	}
369}
370
371void WindowEndDraw(ref Window window, WindowPlatformVars* windowVars, ref WindowView view, ref ViewPlatformVars viewVars) {
372	HDC hdc;
373	hdc = GetDC(windowVars.hWnd);
374//	Gdiplus.GpGraphics* g;
375//	Gdiplus.GdipCreateFromHDC(hdc, &g);
376//	Gdiplus.GdipDrawImageI(g, viewVars.image, 0, 0);
377
378	BitBlt(hdc, 0, 0, window.width(), window.height(), viewVars.dc, 0, 0, SRCCOPY);
379
380	ReleaseDC(windowVars.hWnd, hdc);
381}
382
383void WindowCaptureMouse(ref Window window, WindowPlatformVars* windowVars) {
384	const int WM_MOUSECAPTURE = 0xffff;
385
386	SendMessageW(windowVars.hWnd, WM_MOUSECAPTURE, 0, 0);
387}
388
389void WindowReleaseMouse(ref Window window, WindowPlatformVars* windowVars) {
390	ReleaseCapture();
391}