Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

870 lines
26 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dwinproc.cpp
  6. * Content: DirectDraw processing of Window messages
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 27-Jan-00 kanqiu initial implementation
  11. ***************************************************************************/
  12. #include "ddrawpr.h"
  13. #include "swapchan.hpp"
  14. #include "resource.inl"
  15. #ifdef WINNT
  16. #define USESHOWWINDOW
  17. // WindowInfo structure
  18. typedef struct _D3DWINDOWINFO
  19. {
  20. DWORD dwMagic;
  21. HWND hWnd;
  22. WNDPROC lpWndProc;
  23. DWORD dwFlags;
  24. CEnum *pEnum;
  25. DWORD dwDDFlags;
  26. } D3DWINDOWINFO;
  27. // WindowInfo for our single hooked winproc
  28. // This global variable should never never be accessed outside
  29. // of this file.
  30. D3DWINDOWINFO g_WindowInfo = {0, 0, 0, 0, 0, 0};
  31. #undef DPF_MODNAME
  32. #define DPF_MODNAME "CSwapChain::HIDESHOW_IME"
  33. // IME hide/show function
  34. void CSwapChain::HIDESHOW_IME()
  35. {
  36. if (m_lSetIME)
  37. {
  38. SystemParametersInfo(
  39. SPI_SETSHOWIMEUI, m_lSetIME - 1, NULL, 0);
  40. InterlockedExchange(&m_lSetIME, 0);
  41. }
  42. } // HIDESHOW_IME
  43. #undef DPF_MODNAME
  44. #define DPF_MODNAME "CSwapChain::IsWinProcDeactivated"
  45. BOOL CSwapChain::IsWinProcDeactivated() const
  46. {
  47. // Do we even have our own win-proc?
  48. if (g_WindowInfo.hWnd != Device()->FocusWindow())
  49. {
  50. return FALSE;
  51. }
  52. // Check to see if our win-proc is deactivated then
  53. if (DDRAWILCL_ACTIVENO & g_WindowInfo.dwDDFlags)
  54. {
  55. return TRUE;
  56. }
  57. else
  58. {
  59. return FALSE;
  60. }
  61. } // IsWinProcActive
  62. #undef DPF_MODNAME
  63. #define DPF_MODNAME "CSwapChain::MakeFullscreen"
  64. //
  65. // make the passed window fullscreen and topmost and set a timer
  66. // to make the window topmost again, what a hack.
  67. //
  68. void CSwapChain::MakeFullscreen()
  69. {
  70. // We need to make sure that we don't send this
  71. // size message to the app
  72. g_WindowInfo.dwFlags |= WININFO_SELFSIZE;
  73. // Do the processing
  74. MONITORINFO MonInfo;
  75. MonInfo.rcMonitor.top = MonInfo.rcMonitor.left = 0;
  76. if (1 < Device()->Enum()->GetAdapterCount())
  77. {
  78. HMONITOR hMonitor = Device()->Enum()->
  79. GetAdapterMonitor(Device()->AdapterIndex());
  80. MonInfo.cbSize = sizeof(MONITORINFO);
  81. if (hMonitor)
  82. InternalGetMonitorInfo(hMonitor, &MonInfo);
  83. }
  84. SetWindowPos(m_PresentationData.hDeviceWindow, NULL,
  85. MonInfo.rcMonitor.left,
  86. MonInfo.rcMonitor.top,
  87. Width(),
  88. Height(),
  89. SWP_NOZORDER | SWP_NOACTIVATE);
  90. if (GetForegroundWindow() == Device()->FocusWindow())
  91. {
  92. // If the exclusive mode window is not visible, make it so.
  93. if (!IsWindowVisible(m_PresentationData.hDeviceWindow))
  94. {
  95. ShowWindow(m_PresentationData.hDeviceWindow, SW_SHOW);
  96. }
  97. SetWindowPos(m_PresentationData.hDeviceWindow, HWND_TOPMOST, 0, 0, 0, 0,
  98. SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  99. // If the exclusive mode window is maximized, restore it.
  100. if (IsZoomed(m_PresentationData.hDeviceWindow))
  101. {
  102. ShowWindow(m_PresentationData.hDeviceWindow, SW_RESTORE);
  103. }
  104. }
  105. // We're done; so undo the self-size flag
  106. g_WindowInfo.dwFlags &= ~WININFO_SELFSIZE;
  107. } // CSwapChain::MakeFullscreen
  108. #undef DPF_MODNAME
  109. #define DPF_MODNAME "handleActivateApp"
  110. HRESULT handleActivateApp(BOOL is_active)
  111. {
  112. // We are going to start touching some internal
  113. // data structures of the device and/or enum objects
  114. // so we have to take the critical section for the device
  115. #ifdef DEBUG
  116. CLockD3D _lock(g_WindowInfo.pEnum, DPF_MODNAME, __FILE__);
  117. #else
  118. CLockD3D _lock(g_WindowInfo.pEnum);
  119. #endif
  120. HRESULT ddrval;
  121. BOOL has_excl;
  122. CEnum *pEnum = g_WindowInfo.pEnum;
  123. #ifdef WINNT
  124. if (pEnum->CheckExclusiveMode(NULL, &has_excl, is_active)
  125. && !has_excl && is_active)
  126. {
  127. // If we didn't get exclusive mode, for example, a different thread came in
  128. DPF_ERR("Could not get exclusive mode when we thought we could");
  129. return E_FAIL;
  130. }
  131. #endif //WINNT
  132. /*
  133. * stuff to do before the mode set if deactivating
  134. */
  135. if (is_active)
  136. {
  137. /*
  138. * restore exclusive mode. Here we don't release the ref we took on the exclusive mode mutex,
  139. * since we want to keep the exclusive mode mutex.
  140. */
  141. pEnum->StartExclusiveMode();
  142. }
  143. else
  144. {
  145. /*
  146. * restore the mode
  147. */
  148. pEnum->DoneExclusiveMode();
  149. }
  150. return S_OK;
  151. } /* handleActivateApp */
  152. #undef DPF_MODNAME
  153. #define DPF_MODNAME "WindowProc"
  154. /*
  155. * WindowProc
  156. */
  157. LRESULT WINAPI WindowProc(
  158. HWND hWnd,
  159. UINT uMsg,
  160. WPARAM wParam,
  161. LPARAM lParam)
  162. {
  163. BOOL is_active;
  164. WNDPROC proc;
  165. BOOL get_away;
  166. LRESULT rc;
  167. /*
  168. * Check the window proc
  169. */
  170. if (g_WindowInfo.hWnd != hWnd || g_WindowInfo.dwMagic != WININFO_MAGIC)
  171. {
  172. DPF(4, "FATAL ERROR! Window Proc Called for hWnd %08lx, but not in list!", hWnd);
  173. DEBUG_BREAK();
  174. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  175. }
  176. if (g_WindowInfo.dwFlags & WININFO_SELFSIZE)
  177. {
  178. return 0L; // don't send to app, it's caused by MakeFullscreen
  179. }
  180. /*
  181. * unhook at destroy (or if the WININFO_UNHOOK bit is set)
  182. */
  183. proc = g_WindowInfo.lpWndProc;
  184. if (uMsg == WM_NCDESTROY)
  185. {
  186. DPF (4, "*** WM_NCDESTROY unhooking window ***");
  187. g_WindowInfo.dwFlags |= WININFO_UNHOOK;
  188. }
  189. if (g_WindowInfo.dwFlags & WININFO_UNHOOK)
  190. {
  191. DPF (4, "*** Unhooking window proc");
  192. if (g_WindowInfo.dwFlags & WININFO_ZOMBIE)
  193. {
  194. DPF (4, "*** Freeing ZOMBIE WININFO ***");
  195. ZeroMemory(&g_WindowInfo, sizeof(g_WindowInfo));
  196. }
  197. SetWindowLongPtr(hWnd, GWLP_WNDPROC, (INT_PTR) proc);
  198. rc = CallWindowProc(proc, hWnd, uMsg, wParam, lParam);
  199. return rc;
  200. }
  201. /*
  202. * Code to defer app activation of minimized app until it is restored.
  203. */
  204. switch(uMsg)
  205. {
  206. #ifdef WIN95
  207. case WM_POWERBROADCAST:
  208. if ((wParam == PBT_APMSUSPEND) || (wParam == PBT_APMSTANDBY))
  209. #else
  210. //winnt doesn't know about standby vs suspend
  211. case WM_POWER:
  212. if (wParam == PWR_SUSPENDREQUEST)
  213. #endif
  214. {
  215. DPF(4, "WM_POWERBROADCAST: deactivating application");
  216. SendMessage(hWnd, WM_ACTIVATEAPP, 0, GetCurrentThreadId());
  217. }
  218. break;
  219. case WM_SIZE:
  220. DPF(4, "WM_SIZE hWnd=%X wp=%04X, lp=%08X dwFlags=%08lx", hWnd, wParam,
  221. lParam, g_WindowInfo.dwFlags);
  222. if (!(g_WindowInfo.dwFlags & WININFO_INACTIVATEAPP)
  223. && ((wParam == SIZE_RESTORED) || (wParam == SIZE_MAXIMIZED))
  224. && (GetForegroundWindow() == hWnd))
  225. {
  226. #ifdef WINNT
  227. //
  228. // Wouldncha know it, but NT's messaging order is HUGELY different when alt-tabbing
  229. // between two exclusive mode apps. The first WM_SIZE sent to the activating app is
  230. // sent BEFORE the deactivating app loses FSE. This WM_SIZE is totally necessary to
  231. // reactivate the activating app, but it has to wait until the app loses FSE.
  232. // So, we simply wait on the exclusive mode mutex. This seems to work!
  233. //
  234. {
  235. DWORD dwWaitResult;
  236. dwWaitResult = WaitForSingleObject(hExclusiveModeMutex, INFINITE);
  237. switch (dwWaitResult)
  238. {
  239. case WAIT_OBJECT_0:
  240. case WAIT_ABANDONED:
  241. ReleaseMutex(hExclusiveModeMutex);
  242. break;
  243. case WAIT_TIMEOUT:
  244. default:
  245. DDASSERT(!"Unexpected return value from WaitForSingleObject");
  246. }
  247. }
  248. #endif
  249. DPF(4, "WM_SIZE: Window restored, sending WM_ACTIVATEAPP");
  250. PostMessage(hWnd, WM_ACTIVATEAPP, 1, GetCurrentThreadId());
  251. }
  252. else
  253. {
  254. DPF(4, "WM_SIZE: Window restored, NOT sending WM_ACTIVATEAPP");
  255. }
  256. break;
  257. case WM_ACTIVATEAPP:
  258. if (IsIconic(hWnd) && wParam)
  259. {
  260. DPF(4, "WM_ACTIVATEAPP: Ignoring while minimized");
  261. return 0;
  262. }
  263. else
  264. {
  265. g_WindowInfo.dwFlags |= WININFO_INACTIVATEAPP;
  266. }
  267. break;
  268. }
  269. /*
  270. * is directdraw involved here?
  271. */
  272. if (!(g_WindowInfo.dwFlags & WININFO_DDRAWHOOKED))
  273. {
  274. rc = CallWindowProc(proc, hWnd, uMsg, wParam, lParam);
  275. // clear the WININFO_INACTIVATEAPP bit, but make sure to make sure
  276. // we are still hooked!
  277. if (uMsg == WM_ACTIVATEAPP && (g_WindowInfo.hWnd == hWnd))
  278. {
  279. g_WindowInfo.dwFlags &= ~WININFO_INACTIVATEAPP;
  280. }
  281. return rc;
  282. }
  283. #ifdef DEBUG
  284. if (!IsIconic(hWnd))
  285. {
  286. if (GetForegroundWindow() == hWnd)
  287. {
  288. HWND hwndT;
  289. RECT rc,rcT;
  290. GetWindowRect(hWnd, &rc);
  291. for (hwndT = GetWindow(hWnd, GW_HWNDFIRST);
  292. hwndT && hwndT != hWnd;
  293. hwndT = GetWindow(hwndT, GW_HWNDNEXT))
  294. {
  295. if (IsWindowVisible(hwndT))
  296. {
  297. GetWindowRect(hwndT, &rcT);
  298. if (IntersectRect(&rcT, &rcT, &rc))
  299. {
  300. DPF(4, "Window %08x is on top of us!!", hwndT);
  301. }
  302. }
  303. }
  304. }
  305. }
  306. #endif
  307. /*
  308. * NOTE: we don't take the DLL csect here. By not doing this, we can
  309. * up the performance here. However, this means that the application
  310. * could have a separate thread kill exclusive mode while window
  311. * messages were being processed. This could cause our death.
  312. * Is this OK?
  313. */
  314. switch(uMsg)
  315. {
  316. /*
  317. * WM_SYSKEYUP
  318. *
  319. * watch for system keys of app trying to switch away from us...
  320. *
  321. * we only need to do this on Win95 because we have disabled all
  322. * the task-switching hot keys. on NT we will get switched
  323. * away from normaly by the system.
  324. */
  325. case WM_SYSKEYUP:
  326. DPF(4, "WM_SYSKEYUP: wParam=%08lx lParam=%08lx", wParam, lParam);
  327. get_away = FALSE;
  328. if (wParam == VK_TAB)
  329. {
  330. if (lParam & 0x20000000l)
  331. {
  332. if (g_WindowInfo.dwFlags & WININFO_IGNORENEXTALTTAB)
  333. {
  334. DPF(4, "AHHHHHHHHHHHH Ignoring AltTab");
  335. }
  336. else
  337. {
  338. get_away = TRUE;
  339. }
  340. }
  341. }
  342. else if (wParam == VK_ESCAPE)
  343. {
  344. get_away = TRUE;
  345. }
  346. g_WindowInfo.dwFlags &= ~WININFO_IGNORENEXTALTTAB;
  347. if (get_away)
  348. {
  349. DPF(4, "Hot key pressed, switching away from app");
  350. PostMessage(hWnd, WM_ACTIVATEAPP, 0, GetCurrentThreadId());
  351. }
  352. break;
  353. /*
  354. * WM_SYSCOMMAND
  355. *
  356. * watch for screen savers, and don't allow them!
  357. *
  358. */
  359. case WM_SYSCOMMAND:
  360. switch(wParam)
  361. {
  362. case SC_SCREENSAVE:
  363. DPF(4, "Ignoring screen saver!");
  364. return 1;
  365. // allow window to be restored even if it has popup(s)
  366. case SC_RESTORE:
  367. ShowWindow(hWnd, SW_RESTORE);
  368. break;
  369. }
  370. break;
  371. #ifdef USESHOWWINDOW
  372. case WM_DISPLAYCHANGE:
  373. DPF(4, "WM_DISPLAYCHANGE: %dx%dx%d", LOWORD(lParam), HIWORD(lParam), wParam);
  374. //
  375. // WM_DISPLAYCHANGE is *sent* to the thread that called
  376. // change display settings, we will most likely have the
  377. // direct draw lock, make sure we set the WININFO_SELFSIZE
  378. // bit while calling down the chain to prevent deadlock
  379. //
  380. g_WindowInfo.dwFlags |= WININFO_SELFSIZE;
  381. rc = CallWindowProc(proc, hWnd, uMsg, wParam, lParam);
  382. g_WindowInfo.dwFlags &= ~WININFO_SELFSIZE;
  383. return rc;
  384. #endif
  385. /*
  386. * WM_ACTIVATEAPP
  387. *
  388. * the application has been reactivated. In this case, we need to
  389. * reset the mode
  390. *
  391. */
  392. case WM_ACTIVATEAPP:
  393. is_active = (BOOL)wParam && GetForegroundWindow() == hWnd && !IsIconic(hWnd);
  394. if (!is_active && wParam != 0)
  395. {
  396. DPF(4, "WM_ACTIVATEAPP: setting wParam to 0, not realy active");
  397. wParam = 0;
  398. }
  399. if (is_active)
  400. {
  401. DPF(4, "WM_ACTIVATEAPP: BEGIN Activating app pid=%08lx, tid=%08lx",
  402. GetCurrentProcessId(), GetCurrentThreadId());
  403. }
  404. else
  405. {
  406. DPF(4, "WM_ACTIVATEAPP: BEGIN Deactivating app pid=%08lx, tid=%08lx",
  407. GetCurrentProcessId(), GetCurrentThreadId());
  408. }
  409. if (is_active && (g_WindowInfo.dwDDFlags & DDRAWILCL_ACTIVEYES))
  410. {
  411. DPF(4, "*** Already activated");
  412. }
  413. else
  414. if (!is_active && (g_WindowInfo.dwDDFlags & DDRAWILCL_ACTIVENO))
  415. {
  416. DPF(4, "*** Already deactivated");
  417. }
  418. else
  419. {
  420. if (FAILED(handleActivateApp(is_active)))
  421. break;
  422. DPF(4, "*** Active state changing");
  423. if (is_active)
  424. {
  425. #ifdef DEBUG
  426. if (GetAsyncKeyState(VK_MENU) < 0)
  427. DPF(4, "ALT key is DOWN");
  428. if (GetKeyState(VK_MENU) < 0)
  429. DPF(4, "we think the ALT key is DOWN");
  430. #endif DEBUG
  431. if (GetAsyncKeyState(VK_MENU) < 0)
  432. {
  433. g_WindowInfo.dwFlags |= WININFO_IGNORENEXTALTTAB;
  434. DPF(4, "AHHHHHHH Setting to ignore next alt tab");
  435. }
  436. else
  437. {
  438. g_WindowInfo.dwFlags &= ~WININFO_IGNORENEXTALTTAB;
  439. }
  440. }
  441. /*
  442. * In the multi-mon scenario, it's possible that multiple
  443. * devices are using this same window, so we need to do
  444. * the following for each device.
  445. */
  446. g_WindowInfo.dwDDFlags &= ~(DDRAWILCL_ACTIVEYES|DDRAWILCL_ACTIVENO);
  447. if (is_active)
  448. {
  449. g_WindowInfo.dwDDFlags |= DDRAWILCL_ACTIVEYES;
  450. }
  451. else
  452. {
  453. g_WindowInfo.dwDDFlags |= DDRAWILCL_ACTIVENO;
  454. }
  455. }
  456. #ifdef DEBUG
  457. if (is_active)
  458. {
  459. DPF(4, "WM_ACTIVATEAPP: DONE Activating app pid=%08lx, tid=%08lx",
  460. GetCurrentProcessId(), GetCurrentThreadId());
  461. }
  462. else
  463. {
  464. DPF(4, "WM_ACTIVATEAPP: DONE Deactivating app pid=%08lx, tid=%08lx",
  465. GetCurrentProcessId(), GetCurrentThreadId());
  466. }
  467. #endif
  468. rc = CallWindowProc(proc, hWnd, uMsg, wParam, lParam);
  469. // clear the WININFO_INACTIVATEAPP bit, but make sure to make sure
  470. // we are still hooked!
  471. if (g_WindowInfo.hWnd == hWnd)
  472. {
  473. g_WindowInfo.dwFlags &= ~WININFO_INACTIVATEAPP;
  474. }
  475. return rc;
  476. break;
  477. }
  478. rc = CallWindowProc(proc, hWnd, uMsg, wParam, lParam);
  479. return rc;
  480. } /* WindowProc */
  481. #undef DPF_MODNAME
  482. #define DPF_MODNAME "CSwapChain::SetAppHWnd"
  483. /*
  484. * SetAppHWnd
  485. *
  486. * Set the WindowList struct up with the app's hwnd info
  487. * Must be called with Device crit-sec taken and with the
  488. * Global Exclusive Mode Mutex
  489. */
  490. HRESULT
  491. CSwapChain::SetAppHWnd()
  492. {
  493. HWND hWnd, hEnumWnd;
  494. if (m_PresentationData.Windowed)
  495. hWnd = NULL;
  496. else
  497. hWnd = Device()->FocusWindow();
  498. hEnumWnd = Device()->Enum()->ExclusiveOwnerWindow();
  499. if (hEnumWnd)
  500. {
  501. if (hEnumWnd == Device()->FocusWindow())
  502. {
  503. if (m_PresentationData.Windowed)
  504. {
  505. Device()->Enum()->SetFullScreenDevice(
  506. Device()->AdapterIndex(), NULL);
  507. // If our enum still has a focus-
  508. // window then that means another
  509. // device has gone FS with the same
  510. // focus-window; so do nothing
  511. if (Device()->Enum()->ExclusiveOwnerWindow())
  512. return DD_OK;
  513. // Else, fall through so that
  514. // we tear down the winproc.
  515. }
  516. else
  517. {
  518. Device()->Enum()->SetFullScreenDevice(
  519. Device()->AdapterIndex(), Device());
  520. // Already hooked - no need to do more
  521. return DD_OK;
  522. }
  523. }
  524. }
  525. /*
  526. * check if this isn't doing anything
  527. */
  528. if (hWnd == NULL && g_WindowInfo.hWnd == NULL)
  529. {
  530. return S_OK;
  531. }
  532. // Check if we have a case of different HWND trying to be hooked
  533. if (hWnd && g_WindowInfo.hWnd && g_WindowInfo.hWnd != hWnd)
  534. {
  535. DPF(1, "Hwnd %08lx no good: Different Hwnd (%08lx) already set for Device",
  536. hWnd, g_WindowInfo.hWnd);
  537. return D3DERR_INVALIDCALL;
  538. }
  539. /*
  540. * are we shutting an HWND down?
  541. */
  542. if (hWnd == NULL)
  543. {
  544. if (IsWindow(g_WindowInfo.hWnd))
  545. {
  546. WNDPROC proc;
  547. proc = (WNDPROC) GetWindowLongPtr(g_WindowInfo.hWnd, GWLP_WNDPROC);
  548. if (proc != (WNDPROC) WindowProc &&
  549. proc != (WNDPROC) g_WindowInfo.lpWndProc)
  550. {
  551. DPF(3, "Window has been subclassed; cannot restore!");
  552. g_WindowInfo.dwFlags |= WININFO_ZOMBIE;
  553. }
  554. else if (GetWindowThreadProcessId(g_WindowInfo.hWnd, NULL) !=
  555. GetCurrentThreadId())
  556. {
  557. DPF(3, "intra-thread window unhook, letting window proc do it");
  558. g_WindowInfo.dwFlags |= WININFO_UNHOOK;
  559. g_WindowInfo.dwFlags |= WININFO_ZOMBIE;
  560. PostMessage(g_WindowInfo.hWnd, WM_NULL, 0, 0);
  561. }
  562. else
  563. {
  564. DPF(4, "Unsubclassing window %08lx", g_WindowInfo.hWnd);
  565. SetWindowLongPtr(g_WindowInfo.hWnd, GWLP_WNDPROC,
  566. (INT_PTR) g_WindowInfo.lpWndProc);
  567. ZeroMemory(&g_WindowInfo, sizeof(g_WindowInfo));
  568. }
  569. }
  570. else
  571. {
  572. ZeroMemory(&g_WindowInfo, sizeof(g_WindowInfo));
  573. }
  574. Device()->Enum()->SetFullScreenDevice(
  575. Device()->AdapterIndex(), NULL);
  576. }
  577. /*
  578. * changing or adding an hwnd then...
  579. */
  580. else
  581. {
  582. /*
  583. * brand new object...
  584. */
  585. if (g_WindowInfo.dwMagic == 0)
  586. {
  587. g_WindowInfo.dwMagic = WININFO_MAGIC;
  588. g_WindowInfo.hWnd = hWnd;
  589. g_WindowInfo.lpWndProc = (WNDPROC) GetWindowLongPtr(hWnd, GWLP_WNDPROC);
  590. SetWindowLongPtr(hWnd, GWLP_WNDPROC, (INT_PTR) WindowProc);
  591. }
  592. g_WindowInfo.pEnum = Device()->Enum();
  593. g_WindowInfo.dwFlags |= WININFO_DDRAWHOOKED;
  594. // Sanity check
  595. DXGASSERT(Device()->Enum()->ExclusiveOwnerWindow() == NULL);
  596. Device()->Enum()->SetFullScreenDevice(
  597. Device()->AdapterIndex(), Device());
  598. DPF(4, "Subclassing window %08lx", g_WindowInfo.hWnd);
  599. }
  600. return S_OK;
  601. } /* SetAppHWnd */
  602. extern "C" void ResetUniqueness( HANDLE hDD );
  603. #undef DPF_MODNAME
  604. #define DPF_MODNAME "CSwapChain::DoneExclusiveMode"
  605. /*
  606. * DoneExclusiveMode
  607. */
  608. void
  609. CSwapChain::DoneExclusiveMode(BOOL bChangeWindow)
  610. {
  611. HRESULT hr = S_OK;
  612. BOOL bMinimize = TRUE;
  613. DPF(4, "DoneExclusiveMode");
  614. if (m_bExclusiveMode)
  615. {
  616. D3D8_SETMODEDATA SetModeData;
  617. m_bExclusiveMode = FALSE;
  618. DPF(4, "INACTIVE: %08lx: Restoring original mode (%dx%dx%dx%d)",
  619. GetCurrentProcessId(), Device()->DesktopMode().Width,
  620. Device()->DesktopMode().Height,Device()->DesktopMode().Format,
  621. Device()->DesktopMode().RefreshRate);
  622. SetModeData.hDD = Device()->GetHandle();
  623. SetModeData.dwWidth = Device()->DesktopMode().Width;
  624. SetModeData.dwHeight = Device()->DesktopMode().Height;
  625. SetModeData.Format = Device()->DesktopMode().Format;
  626. SetModeData.dwRefreshRate = Device()->DesktopMode().RefreshRate;
  627. SetModeData.bRestore = TRUE;
  628. Device()->GetHalCallbacks()->SetMode(&SetModeData);
  629. if (SetModeData.ddRVal != S_OK)
  630. {
  631. DPF_ERR("Unable to restore to original desktop mode");
  632. // return SetModeData.ddRVal;
  633. }
  634. // some part of the runtime count on that SetMode cause device
  635. // lost, that's not true for whistler anymore if this fullscreen
  636. // mode happens to be the same as the original desktop mode.
  637. // so we ResetUniqueness to force the device to get lost.
  638. if (Device()->DesktopMode().Width == Width() &&
  639. Device()->DesktopMode().Height == Height() &&
  640. Device()->DesktopMode().Format == BackBufferFormat())
  641. ResetUniqueness(Device()->GetHandle());
  642. DPF(4, "Enabling error mode, hotkeys");
  643. SetErrorMode(m_uiErrorMode);
  644. #ifdef WINNT
  645. // Restore cursor shadow coming out of fullscreen
  646. SystemParametersInfo(SPI_SETCURSORSHADOW, 0, (LPVOID)m_pCursorShadow, 0);
  647. #endif
  648. // Restore reactive menus coming out of fullscreen:
  649. SystemParametersInfo(SPI_SETHOTTRACKING, 0, (LPVOID)m_pHotTracking, 0);
  650. InterlockedExchange(&m_lSetIME, m_lIMEState + 1);
  651. #ifdef WINNT
  652. // Notify the display driver that we are chaning cooperative level
  653. D3D8_SETEXCLUSIVEMODEDATA ExclusiveData;
  654. ExclusiveData.hDD = Device()->GetHandle();
  655. ExclusiveData.dwEnterExcl = FALSE;
  656. Device()->GetHalCallbacks()->SetExclusiveMode(&ExclusiveData);
  657. /*
  658. * If RestoreDisplayMode failed, we are probably on a different desktop. In this case,
  659. * we should not minimize the window or else things won't work right when we switch
  660. * back to the original desktop.
  661. */
  662. if (SetModeData.ddRVal != S_OK)
  663. {
  664. HDESK hDesktop;
  665. static BYTE szName1[256];
  666. static BYTE szName2[256];
  667. DWORD dwTemp;
  668. // Get the name of the current desktop
  669. hDesktop = OpenInputDesktop( 0, FALSE, DESKTOP_READOBJECTS );
  670. GetUserObjectInformation( hDesktop, UOI_NAME, szName1, sizeof( szName1 ), &dwTemp );
  671. CloseDesktop( hDesktop );
  672. // Get the name of the apps' desktop
  673. hDesktop = GetThreadDesktop( GetCurrentThreadId() );
  674. GetUserObjectInformation( hDesktop, UOI_NAME, szName2, sizeof( szName2 ), &dwTemp );
  675. if( lstrcmp( (const LPCSTR)szName1, (const LPCSTR)szName2 ) )
  676. {
  677. bMinimize = FALSE;
  678. }
  679. }
  680. #endif
  681. if (bChangeWindow)
  682. {
  683. HIDESHOW_IME();
  684. /*
  685. * minimize window if deactivating
  686. */
  687. if (IsWindowVisible(m_PresentationData.hDeviceWindow) && bMinimize)
  688. {
  689. g_WindowInfo.dwFlags |= WININFO_SELFSIZE;
  690. #ifdef USESHOWWINDOW
  691. ShowWindow(m_PresentationData.hDeviceWindow, SW_SHOWMINNOACTIVE);
  692. #else
  693. SetWindowPos(m_PresentationData.hDeviceWindow, NULL, 0, 0, 0, 0,
  694. SWP_NOZORDER | SWP_NOACTIVATE);
  695. #endif
  696. g_WindowInfo.dwFlags &= ~WININFO_SELFSIZE;
  697. }
  698. }
  699. }
  700. } /* DoneExclusiveMode */
  701. #undef DPF_MODNAME
  702. #define DPF_MODNAME "CSwapChain::StartExclusiveMode"
  703. /*
  704. * StartExclusiveMode
  705. */
  706. void
  707. CSwapChain::StartExclusiveMode(BOOL bChangeWindow)
  708. {
  709. DWORD dwWaitResult;
  710. DPF(4, "StartExclusiveMode");
  711. /*
  712. * Preceeding code should have taken this mutex already.
  713. */
  714. if (!m_bExclusiveMode)
  715. {
  716. m_bExclusiveMode = TRUE;
  717. #if defined(WINNT) && defined(DEBUG)
  718. dwWaitResult = WaitForSingleObject(hExclusiveModeMutex, 0);
  719. DDASSERT(dwWaitResult == WAIT_OBJECT_0);
  720. ReleaseMutex(hExclusiveModeMutex);
  721. #endif
  722. m_uiErrorMode = SetErrorMode(SEM_NOGPFAULTERRORBOX |
  723. SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  724. #ifdef WINNT
  725. // Save current cursor shadow setting
  726. SystemParametersInfo(SPI_GETCURSORSHADOW, 0, (LPVOID) &(m_pCursorShadow), 0);
  727. SystemParametersInfo(SPI_SETCURSORSHADOW, 0, 0, 0);
  728. #endif
  729. // Save current hot-tracking setting
  730. SystemParametersInfo(SPI_GETHOTTRACKING, 0, (LPVOID) &(m_pHotTracking), 0);
  731. SystemParametersInfo(SPI_GETSHOWIMEUI, 0, (LPVOID) &(m_lIMEState), 0);
  732. //And turn it off as we go into exclusive mode
  733. SystemParametersInfo(SPI_SETHOTTRACKING, 0, 0, 0);
  734. InterlockedExchange(&m_lSetIME, FALSE + 1);
  735. #ifdef WINNT
  736. // Notify the display driver that we are chaning cooperative level
  737. D3D8_SETEXCLUSIVEMODEDATA ExclusiveData;
  738. ExclusiveData.hDD = Device()->GetHandle();
  739. ExclusiveData.dwEnterExcl = TRUE;
  740. Device()->GetHalCallbacks()->SetExclusiveMode(&ExclusiveData);
  741. #endif
  742. if (bChangeWindow)
  743. {
  744. MakeFullscreen();
  745. HIDESHOW_IME();
  746. if (IsWindowVisible(m_PresentationData.hDeviceWindow))
  747. {
  748. g_WindowInfo.dwFlags |= WININFO_SELFSIZE;
  749. #ifdef USESHOWWINDOW
  750. ShowWindow(m_PresentationData.hDeviceWindow, SW_SHOWNOACTIVATE);
  751. #else
  752. {
  753. RECT rc;
  754. SetRect(&rc,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));
  755. SetWindowPos(g_WindowInfo.hWnd, NULL,rc.left, rc.top,
  756. rc.right - rc.left,rc.bottom - rc.top,
  757. SWP_NOZORDER | SWP_NOACTIVATE);
  758. }
  759. #endif
  760. g_WindowInfo.dwFlags &= ~WININFO_SELFSIZE;
  761. }
  762. }
  763. }
  764. } /* StartExclusiveMode */
  765. #endif //WINNT
  766. // End of file : dwinproc.cpp