CmWin32Window.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. #ifndef _WIN32_WINNT
  2. #define _WIN32_WINNT 0x0500
  3. #endif
  4. #include "CmWin32Window.h"
  5. #include "CmInput.h"
  6. #include "CmRenderSystem.h"
  7. #include "CmCoreThread.h"
  8. #include "CmException.h"
  9. #include "CmWin32GLSupport.h"
  10. #include "CmWin32Context.h"
  11. #include "Win32/CmPlatformWndProc.h"
  12. #include "CmWin32VideoModeInfo.h"
  13. #include "CmGLPixelFormat.h"
  14. GLenum GLEWAPIENTRY wglewContextInit(BansheeEngine::GLSupport *glSupport);
  15. namespace BansheeEngine
  16. {
  17. #define _MAX_CLASS_NAME_ 128
  18. Win32Window::Win32Window(const RENDER_WINDOW_DESC& desc, Win32GLSupport &glsupport):
  19. RenderWindow(desc),
  20. mGLSupport(glsupport),
  21. mContext(0)
  22. {
  23. mIsFullScreen = false;
  24. mHWnd = 0;
  25. mIsExternal = false;
  26. mIsExternalGLControl = false;
  27. mSizing = false;
  28. mClosed = false;
  29. mDisplayFrequency = 0;
  30. mActive = false;
  31. mDeviceName = NULL;
  32. }
  33. Win32Window::~Win32Window()
  34. {
  35. }
  36. void Win32Window::initialize_internal()
  37. {
  38. #ifdef CM_STATIC_LIB
  39. HINSTANCE hInst = GetModuleHandle(NULL);
  40. #else
  41. HINSTANCE hInst = GetModuleHandle(MODULE_NAME.c_str());
  42. #endif
  43. mHWnd = 0;
  44. mName = mDesc.title;
  45. mIsFullScreen = mDesc.fullscreen;
  46. mClosed = false;
  47. mIsChild = false;
  48. mDisplayFrequency = Math::roundToInt(mDesc.videoMode.getRefreshRate());
  49. mColorDepth = 32;
  50. HWND parent = 0;
  51. NameValuePairList::const_iterator opt;
  52. NameValuePairList::const_iterator end = mDesc.platformSpecific.end();
  53. if ((opt = mDesc.platformSpecific.find("externalWindowHandle")) != end)
  54. {
  55. mHWnd = (HWND)parseUnsignedInt(opt->second);
  56. if (mHWnd)
  57. {
  58. mIsExternal = true;
  59. }
  60. if ((opt = mDesc.platformSpecific.find("externalGLControl")) != end) {
  61. mIsExternalGLControl = parseBool(opt->second);
  62. }
  63. }
  64. HGLRC glrc = 0;
  65. if ((opt = mDesc.platformSpecific.find("externalGLContext")) != end)
  66. {
  67. glrc = (HGLRC)parseUnsignedLong(opt->second);
  68. }
  69. if ((opt = mDesc.platformSpecific.find("parentWindowHandle")) != end)
  70. {
  71. parent = (HWND)parseUnsignedInt(opt->second);
  72. mIsChild = true;
  73. mIsFullScreen = false;
  74. }
  75. HMONITOR hMonitor = NULL;
  76. const Win32VideoModeInfo& videoModeInfo = static_cast<const Win32VideoModeInfo&>(RenderSystem::instance().getVideoModeInfo());
  77. UINT32 numOutputs = videoModeInfo.getNumOutputs();
  78. if (numOutputs > 0)
  79. {
  80. UINT32 actualMonitorIdx = std::min(mDesc.videoMode.getOutputIdx(), numOutputs - 1);
  81. const Win32VideoOutputInfo& outputInfo = static_cast<const Win32VideoOutputInfo&>(videoModeInfo.getOutputInfo(actualMonitorIdx));
  82. hMonitor = outputInfo.getMonitorHandle();
  83. }
  84. if (!mIsFullScreen)
  85. {
  86. // Make sure we don't exceed desktop color depth
  87. if ((int)mColorDepth > GetDeviceCaps(GetDC(0), BITSPIXEL))
  88. mColorDepth = GetDeviceCaps(GetDC(0), BITSPIXEL);
  89. }
  90. if (!mIsExternal)
  91. {
  92. DWORD dwStyle = WS_VISIBLE | WS_CLIPCHILDREN;
  93. DWORD dwStyleEx = 0;
  94. MONITORINFOEX monitorInfoEx;
  95. RECT rc;
  96. // If we didn't specified the adapter index, or if it didn't find it
  97. if (hMonitor == NULL)
  98. {
  99. POINT windowAnchorPoint;
  100. // Fill in anchor point.
  101. windowAnchorPoint.x = mDesc.left;
  102. windowAnchorPoint.y = mDesc.top;
  103. // Get the nearest monitor to this window.
  104. hMonitor = MonitorFromPoint(windowAnchorPoint, MONITOR_DEFAULTTONEAREST);
  105. }
  106. // Get the target monitor info
  107. memset(&monitorInfoEx, 0, sizeof(MONITORINFOEX));
  108. monitorInfoEx.cbSize = sizeof(MONITORINFOEX);
  109. GetMonitorInfo(hMonitor, &monitorInfoEx);
  110. size_t devNameLen = strlen(monitorInfoEx.szDevice);
  111. mDeviceName = (char*)cm_alloc<ScratchAlloc>((UINT32)(devNameLen + 1));
  112. strcpy_s(mDeviceName, devNameLen + 1, monitorInfoEx.szDevice);
  113. UINT32 left = mDesc.left;
  114. UINT32 top = mDesc.top;
  115. // No specified top left -> Center the window in the middle of the monitor
  116. if (left == -1 || top == -1)
  117. {
  118. int screenw = monitorInfoEx.rcWork.right - monitorInfoEx.rcWork.left;
  119. int screenh = monitorInfoEx.rcWork.bottom - monitorInfoEx.rcWork.top;
  120. unsigned int winWidth, winHeight;
  121. _adjustWindow(mDesc.videoMode.getWidth(), mDesc.videoMode.getHeight(), &winWidth, &winHeight);
  122. // clamp window dimensions to screen size
  123. int outerw = (int(winWidth) < screenw)? int(winWidth) : screenw;
  124. int outerh = (int(winHeight) < screenh)? int(winHeight) : screenh;
  125. if (left == -1)
  126. left = monitorInfoEx.rcWork.left + (screenw - outerw) / 2;
  127. else if (hMonitor != NULL)
  128. left += monitorInfoEx.rcWork.left;
  129. if (top == -1)
  130. top = monitorInfoEx.rcWork.top + (screenh - outerh) / 2;
  131. else if (hMonitor != NULL)
  132. top += monitorInfoEx.rcWork.top;
  133. }
  134. else if (hMonitor != NULL)
  135. {
  136. left += monitorInfoEx.rcWork.left;
  137. top += monitorInfoEx.rcWork.top;
  138. }
  139. mWidth = mDesc.videoMode.getWidth();
  140. mHeight = mDesc.videoMode.getHeight();
  141. mTop = top;
  142. mLeft = left;
  143. if (mIsFullScreen)
  144. {
  145. dwStyle |= WS_POPUP;
  146. dwStyleEx |= WS_EX_TOPMOST;
  147. mTop = monitorInfoEx.rcMonitor.top;
  148. mLeft = monitorInfoEx.rcMonitor.left;
  149. }
  150. else
  151. {
  152. if (parent)
  153. {
  154. if(mDesc.toolWindow)
  155. dwStyleEx = WS_EX_TOOLWINDOW;
  156. else
  157. dwStyle |= WS_CHILD;
  158. }
  159. if (!parent || mDesc.toolWindow)
  160. {
  161. if (mDesc.border == WindowBorder::None)
  162. dwStyle |= WS_POPUP;
  163. else if (mDesc.border == WindowBorder::Fixed)
  164. dwStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
  165. WS_SYSMENU | WS_MINIMIZEBOX;
  166. else
  167. dwStyle |= WS_OVERLAPPEDWINDOW;
  168. }
  169. int screenw = GetSystemMetrics(SM_CXSCREEN);
  170. int screenh = GetSystemMetrics(SM_CYSCREEN);
  171. if (!mDesc.outerDimensions)
  172. {
  173. // Calculate window dimensions required
  174. // to get the requested client area
  175. SetRect(&rc, 0, 0, mWidth, mHeight);
  176. AdjustWindowRect(&rc, dwStyle, false);
  177. mWidth = rc.right - rc.left;
  178. mHeight = rc.bottom - rc.top;
  179. // Clamp window rect to the nearest display monitor.
  180. if (mLeft < monitorInfoEx.rcWork.left)
  181. mLeft = monitorInfoEx.rcWork.left;
  182. if (mTop < monitorInfoEx.rcWork.top)
  183. mTop = monitorInfoEx.rcWork.top;
  184. if ((int)mWidth > monitorInfoEx.rcWork.right - mLeft)
  185. mWidth = monitorInfoEx.rcWork.right - mLeft;
  186. if ((int)mHeight > monitorInfoEx.rcWork.bottom - mTop)
  187. mHeight = monitorInfoEx.rcWork.bottom - mTop;
  188. }
  189. }
  190. // register class and create window
  191. WNDCLASS wc = { CS_OWNDC, PlatformWndProc::_win32WndProc, 0, 0, hInst,
  192. LoadIcon(NULL, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),
  193. (HBRUSH)GetStockObject(BLACK_BRUSH), NULL, "GLWindow" };
  194. RegisterClass(&wc);
  195. if (mIsFullScreen)
  196. {
  197. DEVMODE displayDeviceMode;
  198. memset(&displayDeviceMode, 0, sizeof(displayDeviceMode));
  199. displayDeviceMode.dmSize = sizeof(DEVMODE);
  200. displayDeviceMode.dmBitsPerPel = mColorDepth;
  201. displayDeviceMode.dmPelsWidth = mWidth;
  202. displayDeviceMode.dmPelsHeight = mHeight;
  203. displayDeviceMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
  204. if (mDisplayFrequency)
  205. {
  206. displayDeviceMode.dmDisplayFrequency = mDisplayFrequency;
  207. displayDeviceMode.dmFields |= DM_DISPLAYFREQUENCY;
  208. if (ChangeDisplaySettingsEx(mDeviceName, &displayDeviceMode, NULL, CDS_FULLSCREEN | CDS_TEST, NULL) != DISP_CHANGE_SUCCESSFUL)
  209. {
  210. CM_EXCEPT(RenderingAPIException, "ChangeDisplaySettings with user display frequency failed.");
  211. }
  212. }
  213. if (ChangeDisplaySettingsEx(mDeviceName, &displayDeviceMode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)
  214. {
  215. CM_EXCEPT(RenderingAPIException, "ChangeDisplaySettings failed.");
  216. }
  217. }
  218. // Pass pointer to self as WM_CREATE parameter
  219. mHWnd = CreateWindowEx(dwStyleEx, "GLWindow", mDesc.title.c_str(),
  220. dwStyle, mLeft, mTop, mWidth, mHeight, parent, 0, hInst, this);
  221. }
  222. RECT rc;
  223. GetWindowRect(mHWnd, &rc);
  224. mTop = rc.top;
  225. mLeft = rc.left;
  226. GetClientRect(mHWnd, &rc);
  227. mWidth = rc.right;
  228. mHeight = rc.bottom;
  229. mHDC = GetDC(mHWnd);
  230. if (!mIsExternalGLControl)
  231. {
  232. int testMultisample = mMultisampleCount;
  233. bool testHwGamma = mDesc.gamma;
  234. bool formatOk = mGLSupport.selectPixelFormat(mHDC, mColorDepth, testMultisample, testHwGamma);
  235. if (!formatOk)
  236. {
  237. if (mMultisampleCount > 0)
  238. {
  239. // Try without multisampling
  240. testMultisample = 0;
  241. formatOk = mGLSupport.selectPixelFormat(mHDC, mColorDepth, testMultisample, testHwGamma);
  242. }
  243. if (!formatOk && mDesc.gamma)
  244. {
  245. // Try without sRGB
  246. testHwGamma = false;
  247. testMultisample = mMultisampleCount;
  248. formatOk = mGLSupport.selectPixelFormat(mHDC, mColorDepth, testMultisample, testHwGamma);
  249. }
  250. if (!formatOk && mDesc.gamma && (mMultisampleCount > 0))
  251. {
  252. // Try without both
  253. testHwGamma = false;
  254. testMultisample = 0;
  255. formatOk = mGLSupport.selectPixelFormat(mHDC, mColorDepth, testMultisample, testHwGamma);
  256. }
  257. if (!formatOk)
  258. CM_EXCEPT(RenderingAPIException, "Failed selecting pixel format.");
  259. }
  260. // Record what gamma option we used in the end
  261. // this will control enabling of sRGB state flags when used
  262. mHwGamma = testHwGamma;
  263. mMultisampleCount = testMultisample;
  264. }
  265. mActive = true;
  266. mContext = mGLSupport.createContext(mHDC, glrc);
  267. RenderWindow::initialize_internal();
  268. }
  269. void Win32Window::destroy_internal()
  270. {
  271. if (!mHWnd)
  272. return;
  273. // Unregister and destroy GLContext
  274. cm_delete(mContext);
  275. if (!mIsExternal)
  276. {
  277. if (mIsFullScreen)
  278. ChangeDisplaySettingsEx(mDeviceName, NULL, NULL, 0, NULL);
  279. DestroyWindow(mHWnd);
  280. }
  281. else
  282. {
  283. // just release the DC
  284. ReleaseDC(mHWnd, mHDC);
  285. }
  286. mActive = false;
  287. mClosed = true;
  288. mHDC = 0; // no release thanks to CS_OWNDC wndclass style
  289. mHWnd = 0;
  290. if (mDeviceName != NULL)
  291. {
  292. cm_free<ScratchAlloc>(mDeviceName);
  293. mDeviceName = NULL;
  294. }
  295. RenderWindow::destroy_internal();
  296. }
  297. void Win32Window::setFullscreen(UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
  298. {
  299. THROW_IF_NOT_CORE_THREAD;
  300. if (mIsChild)
  301. return;
  302. const Win32VideoModeInfo& videoModeInfo = static_cast<const Win32VideoModeInfo&>(RenderSystem::instance().getVideoModeInfo());
  303. UINT32 numOutputs = videoModeInfo.getNumOutputs();
  304. if (numOutputs == 0)
  305. return;
  306. UINT32 actualMonitorIdx = std::min(monitorIdx, numOutputs - 1);
  307. const Win32VideoOutputInfo& outputInfo = static_cast<const Win32VideoOutputInfo&>(videoModeInfo.getOutputInfo(actualMonitorIdx));
  308. bool oldFullscreen = mIsFullScreen;
  309. DWORD style = WS_VISIBLE | WS_CLIPCHILDREN | WS_POPUP;
  310. mDisplayFrequency = Math::roundToInt(refreshRate);
  311. mIsFullScreen = true;
  312. DEVMODE displayDeviceMode;
  313. memset(&displayDeviceMode, 0, sizeof(displayDeviceMode));
  314. displayDeviceMode.dmSize = sizeof(DEVMODE);
  315. displayDeviceMode.dmBitsPerPel = mColorDepth;
  316. displayDeviceMode.dmPelsWidth = width;
  317. displayDeviceMode.dmPelsHeight = height;
  318. displayDeviceMode.dmDisplayFrequency = mDisplayFrequency;
  319. displayDeviceMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
  320. HMONITOR hMonitor = outputInfo.getMonitorHandle();
  321. MONITORINFOEX monitorInfo;
  322. memset(&monitorInfo, 0, sizeof(MONITORINFOEX));
  323. monitorInfo.cbSize = sizeof(MONITORINFOEX);
  324. GetMonitorInfo(hMonitor, &monitorInfo);
  325. // Move window to 0, 0 before display switch
  326. SetWindowPos(mHWnd, HWND_TOPMOST, 0, 0, mWidth, mHeight, SWP_NOACTIVATE);
  327. if (ChangeDisplaySettingsEx(monitorInfo.szDevice, &displayDeviceMode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)
  328. {
  329. CM_EXCEPT(RenderingAPIException, "ChangeDisplaySettings failed");
  330. }
  331. mTop = monitorInfo.rcMonitor.top;
  332. mLeft = monitorInfo.rcMonitor.left;
  333. mWidth = width;
  334. mHeight = height;
  335. SetWindowLong(mHWnd, GWL_STYLE, style);
  336. SetWindowPos(mHWnd, HWND_TOPMOST, mLeft, mTop, width, height, SWP_NOACTIVATE);
  337. }
  338. void Win32Window::setFullscreen(const VideoMode& mode)
  339. {
  340. THROW_IF_NOT_CORE_THREAD;
  341. setFullscreen(mode.getWidth(), mode.getHeight(), mode.getRefreshRate(), mode.getOutputIdx());
  342. }
  343. void Win32Window::setWindowed()
  344. {
  345. THROW_IF_NOT_CORE_THREAD;
  346. if (!mIsFullScreen)
  347. return;
  348. mIsFullScreen = false;
  349. DWORD style = WS_VISIBLE | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW;
  350. // Drop out of fullscreen
  351. ChangeDisplaySettingsEx(mDeviceName, NULL, NULL, 0, NULL);
  352. // Calculate overall dimensions for requested client area
  353. unsigned int winWidth, winHeight;
  354. _adjustWindow(mWidth, mHeight, &winWidth, &winHeight);
  355. // Deal with centering when switching down to smaller resolution
  356. HMONITOR hMonitor = MonitorFromWindow(mHWnd, MONITOR_DEFAULTTONEAREST);
  357. MONITORINFO monitorInfo;
  358. memset(&monitorInfo, 0, sizeof(MONITORINFO));
  359. monitorInfo.cbSize = sizeof(MONITORINFO);
  360. GetMonitorInfo(hMonitor, &monitorInfo);
  361. LONG screenw = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
  362. LONG screenh = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
  363. int left = screenw > int(winWidth) ? ((screenw - int(winWidth)) / 2) : 0;
  364. int top = screenh > int(winHeight) ? ((screenh - int(winHeight)) / 2) : 0;
  365. SetWindowLong(mHWnd, GWL_STYLE, style);
  366. SetWindowPos(mHWnd, HWND_NOTOPMOST, left, top, winWidth, winHeight,
  367. SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOACTIVATE);
  368. _windowMovedOrResized();
  369. }
  370. bool Win32Window::isActive(void) const
  371. {
  372. if (isFullScreen())
  373. return isVisible();
  374. return mActive && isVisible();
  375. }
  376. bool Win32Window::isVisible() const
  377. {
  378. return (mHWnd && !IsIconic(mHWnd));
  379. }
  380. bool Win32Window::isClosed() const
  381. {
  382. return mClosed;
  383. }
  384. void Win32Window::move(INT32 left, INT32 top)
  385. {
  386. THROW_IF_NOT_CORE_THREAD;
  387. if (mHWnd && !mIsFullScreen)
  388. {
  389. mLeft = left;
  390. mTop = top;
  391. SetWindowPos(mHWnd, 0, left, top, 0, 0,
  392. SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  393. }
  394. }
  395. void Win32Window::resize(UINT32 width, UINT32 height)
  396. {
  397. THROW_IF_NOT_CORE_THREAD;
  398. if (mHWnd && !mIsFullScreen)
  399. {
  400. mWidth = width;
  401. mHeight = height;
  402. RECT rc = { 0, 0, width, height };
  403. AdjustWindowRect(&rc, GetWindowLong(mHWnd, GWL_STYLE), false);
  404. width = rc.right - rc.left;
  405. height = rc.bottom - rc.top;
  406. SetWindowPos(mHWnd, 0, 0, 0, width, height,
  407. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  408. }
  409. }
  410. void Win32Window::swapBuffers()
  411. {
  412. THROW_IF_NOT_CORE_THREAD;
  413. if (!mIsExternalGLControl) {
  414. SwapBuffers(mHDC);
  415. }
  416. }
  417. void Win32Window::copyToMemory(const PixelData &dst, FrameBuffer buffer)
  418. {
  419. THROW_IF_NOT_CORE_THREAD;
  420. if ((dst.getLeft() < 0) || (dst.getRight() > mWidth) ||
  421. (dst.getTop() < 0) || (dst.getBottom() > mHeight) ||
  422. (dst.getFront() != 0) || (dst.getBack() != 1))
  423. {
  424. CM_EXCEPT(InvalidParametersException, "Invalid box.");
  425. }
  426. if (buffer == FB_AUTO)
  427. {
  428. buffer = mIsFullScreen? FB_FRONT : FB_BACK;
  429. }
  430. GLenum format = BansheeEngine::GLPixelUtil::getGLOriginFormat(dst.getFormat());
  431. GLenum type = BansheeEngine::GLPixelUtil::getGLOriginDataType(dst.getFormat());
  432. if ((format == GL_NONE) || (type == 0))
  433. {
  434. CM_EXCEPT(InvalidParametersException, "Unsupported format.");
  435. }
  436. // Must change the packing to ensure no overruns!
  437. glPixelStorei(GL_PACK_ALIGNMENT, 1);
  438. glReadBuffer((buffer == FB_FRONT)? GL_FRONT : GL_BACK);
  439. glReadPixels((GLint)dst.getLeft(), (GLint)dst.getTop(),
  440. (GLsizei)dst.getWidth(), (GLsizei)dst.getHeight(),
  441. format, type, dst.getData());
  442. // restore default alignment
  443. glPixelStorei(GL_PACK_ALIGNMENT, 4);
  444. //vertical flip
  445. {
  446. size_t rowSpan = dst.getWidth() * PixelUtil::getNumElemBytes(dst.getFormat());
  447. size_t height = dst.getHeight();
  448. UINT8 *tmpData = (UINT8*)cm_alloc<ScratchAlloc>((UINT32)(rowSpan * height));
  449. UINT8 *srcRow = (UINT8 *)dst.getData(), *tmpRow = tmpData + (height - 1) * rowSpan;
  450. while (tmpRow >= tmpData)
  451. {
  452. memcpy(tmpRow, srcRow, rowSpan);
  453. srcRow += rowSpan;
  454. tmpRow -= rowSpan;
  455. }
  456. memcpy(dst.getData(), tmpData, rowSpan * height);
  457. cm_free<ScratchAlloc>(tmpData);
  458. }
  459. }
  460. Vector2I Win32Window::screenToWindowPos(const Vector2I& screenPos) const
  461. {
  462. POINT pos;
  463. pos.x = screenPos.x;
  464. pos.y = screenPos.y;
  465. ScreenToClient(mHWnd, &pos);
  466. return Vector2I(pos.x, pos.y);
  467. }
  468. Vector2I Win32Window::windowToScreenPos(const Vector2I& windowPos) const
  469. {
  470. POINT pos;
  471. pos.x = windowPos.x;
  472. pos.y = windowPos.y;
  473. ClientToScreen(mHWnd, &pos);
  474. return Vector2I(pos.x, pos.y);
  475. }
  476. void Win32Window::getCustomAttribute(const String& name, void* pData) const
  477. {
  478. if(name == "GLCONTEXT")
  479. {
  480. *static_cast<GLContext**>(pData) = mContext;
  481. return;
  482. }
  483. else if(name == "WINDOW")
  484. {
  485. HWND *pHwnd = (HWND*)pData;
  486. *pHwnd = _getWindowHandle();
  487. return;
  488. }
  489. }
  490. void Win32Window::setActive(bool state)
  491. {
  492. THROW_IF_NOT_CORE_THREAD;
  493. if (mDeviceName != NULL && state == false)
  494. {
  495. HWND hActiveWindow = GetActiveWindow();
  496. char classNameSrc[_MAX_CLASS_NAME_ + 1];
  497. char classNameDst[_MAX_CLASS_NAME_ + 1];
  498. GetClassName(mHWnd, classNameSrc, _MAX_CLASS_NAME_);
  499. GetClassName(hActiveWindow, classNameDst, _MAX_CLASS_NAME_);
  500. if (strcmp(classNameDst, classNameSrc) == 0)
  501. {
  502. state = true;
  503. }
  504. }
  505. mActive = state;
  506. if( mIsFullScreen )
  507. {
  508. if( state == false )
  509. { //Restore Desktop
  510. ChangeDisplaySettingsEx(mDeviceName, NULL, NULL, 0, NULL);
  511. ShowWindow(mHWnd, SW_SHOWMINNOACTIVE);
  512. }
  513. else
  514. { //Restore App
  515. ShowWindow(mHWnd, SW_SHOWNORMAL);
  516. DEVMODE displayDeviceMode;
  517. memset(&displayDeviceMode, 0, sizeof(displayDeviceMode));
  518. displayDeviceMode.dmSize = sizeof(DEVMODE);
  519. displayDeviceMode.dmBitsPerPel = mColorDepth;
  520. displayDeviceMode.dmPelsWidth = mWidth;
  521. displayDeviceMode.dmPelsHeight = mHeight;
  522. displayDeviceMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
  523. if (mDisplayFrequency)
  524. {
  525. displayDeviceMode.dmDisplayFrequency = mDisplayFrequency;
  526. displayDeviceMode.dmFields |= DM_DISPLAYFREQUENCY;
  527. }
  528. ChangeDisplaySettingsEx(mDeviceName, &displayDeviceMode, NULL, CDS_FULLSCREEN, NULL);
  529. }
  530. }
  531. }
  532. void Win32Window::setHidden(bool hidden)
  533. {
  534. THROW_IF_NOT_CORE_THREAD;
  535. mHidden = hidden;
  536. if (!mIsExternal)
  537. {
  538. if (hidden)
  539. ShowWindow(mHWnd, SW_HIDE);
  540. else
  541. ShowWindow(mHWnd, SW_SHOWNORMAL);
  542. }
  543. }
  544. void Win32Window::_windowMovedOrResized()
  545. {
  546. if (!mHWnd || IsIconic(mHWnd))
  547. return;
  548. RECT rc;
  549. GetWindowRect(mHWnd, &rc);
  550. mTop = rc.top;
  551. mLeft = rc.left;
  552. GetClientRect(mHWnd, &rc);
  553. mWidth = rc.right - rc.left;
  554. mHeight = rc.bottom - rc.top;
  555. RenderWindow::_windowMovedOrResized();
  556. }
  557. void Win32Window::_adjustWindow(unsigned int clientWidth, unsigned int clientHeight,
  558. unsigned int* winWidth, unsigned int* winHeight)
  559. {
  560. // NB only call this for non full screen
  561. RECT rc;
  562. SetRect(&rc, 0, 0, clientWidth, clientHeight);
  563. AdjustWindowRect(&rc, WS_VISIBLE | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW, false);
  564. *winWidth = rc.right - rc.left;
  565. *winHeight = rc.bottom - rc.top;
  566. // adjust to monitor
  567. HMONITOR hMonitor = MonitorFromWindow(mHWnd, MONITOR_DEFAULTTONEAREST);
  568. // Get monitor info
  569. MONITORINFO monitorInfo;
  570. memset(&monitorInfo, 0, sizeof(MONITORINFO));
  571. monitorInfo.cbSize = sizeof(MONITORINFO);
  572. GetMonitorInfo(hMonitor, &monitorInfo);
  573. LONG maxW = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
  574. LONG maxH = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
  575. if (*winWidth > (unsigned int)maxW)
  576. *winWidth = maxW;
  577. if (*winHeight > (unsigned int)maxH)
  578. *winHeight = maxH;
  579. }
  580. }