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