2
0

BsWin32Window.cpp 19 KB

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