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.

991 lines
30 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: sswproc.cxx
  3. *
  4. * Window procedure functions.
  5. *
  6. * Copyright (c) 1996 Microsoft Corporation
  7. \**************************************************************************/
  8. #include <windows.h>
  9. #include <commdlg.h>
  10. #include <scrnsave.h>
  11. #include <GL\gl.h>
  12. #include "tk.h"
  13. #include <math.h>
  14. #include <memory.h>
  15. #include <string.h>
  16. #include <stdarg.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <malloc.h>
  20. #include <time.h>
  21. #include "ssintrnl.hxx"
  22. #include "sswproc.hxx"
  23. #include "palette.hxx"
  24. #include "clear.hxx"
  25. // forward declarations of internal functions
  26. static void ss_TimerProc();
  27. LRESULT SS_ScreenSaverProc(HWND, UINT, WPARAM, LPARAM);
  28. LONG
  29. FullScreenPaletteManageProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  30. static void
  31. ssw_RelayMessageToChildren( PSSW pssw, UINT msg, WPARAM wParam, LPARAM lParam);
  32. static void ssw_RealizePalette( PSSW pssw, BOOL bBackground );
  33. static void ssw_DeletePalette( PSSW pssw );
  34. /**************************************************************************\
  35. * ScreenSaverProc
  36. *
  37. * Processes messages for the top level screen saver window.
  38. *
  39. * Unhandled msgs are sent to DefScreenSaverProc
  40. \**************************************************************************/
  41. LRESULT
  42. ScreenSaverProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  43. {
  44. HDC hdc;
  45. PAINTSTRUCT ps;
  46. static BOOL bInited = FALSE;
  47. static UINT idTimer = 0;
  48. // Draw timer time-out interval
  49. #ifdef SS_DEBUG
  50. static UINT uiTimeOut = 2; // Let it rip !
  51. #else
  52. static UINT uiTimeOut = 16; // Cap at ~60 fps
  53. #endif
  54. static BOOL bSuspend = FALSE;
  55. #ifdef SS_WIN95_TIMER_HACK
  56. static BOOL bIdle = FALSE;
  57. #endif
  58. PSSW pssw;
  59. switch (message)
  60. {
  61. case WM_CREATE:
  62. case WM_ERASEBKGND:
  63. case SS_WM_INITGL:
  64. return SS_ScreenSaverProc( hwnd, message, wParam, lParam);
  65. case WM_ACTIVATE:
  66. if ( LOWORD(wParam) == WA_INACTIVE ) {
  67. SS_DBGMSG( "Main_Proc: WM_ACTIVATE inactive\n" );
  68. gpss->bInForeground = FALSE;
  69. } else {
  70. SS_DBGMSG( "Main_Proc: WM_ACTIVATE active\n" );
  71. gpss->bInForeground = TRUE;
  72. }
  73. // fall thru
  74. case WM_QUERYNEWPALETTE:
  75. case WM_PALETTECHANGED:
  76. case WM_SYSCOLORCHANGE:
  77. case SS_WM_PALETTE:
  78. return( MainPaletteManageProc( hwnd, message, wParam, lParam ) );
  79. case SS_WM_START:
  80. SS_DBGMSG( "Main_Proc: SS_WM_START\n" );
  81. // This is the main GL startup point. The global animation timer
  82. // is started, and SS_WM_START is relayed to the window chain.
  83. //mf: kluge for 'delayed background paint' problem in preview mode - in
  84. // floater type ss's, the main window gets this delayed bg paint thing that
  85. // makes the floater obvious. By relenquishing our time slice here, the
  86. // problem goes away...
  87. #if 1
  88. if( gpss->type == SS_TYPE_PREVIEW ) {
  89. Sleep(0);
  90. }
  91. #endif
  92. // Initialize the animation timer - it should start up once we
  93. // return from here
  94. idTimer = 1;
  95. SetTimer(hwnd, idTimer, uiTimeOut, 0);
  96. #ifdef SS_DEBUG
  97. // Start timer for calculating update rate
  98. gpss->timer.Start();
  99. #endif
  100. if( !bInited )
  101. bInited = TRUE;
  102. // Process SS_WM_START for the window chain
  103. return SS_ScreenSaverProc( hwnd, message, wParam, lParam);
  104. #ifdef SS_WIN95_TIMER_HACK
  105. case SS_WM_IDLE :
  106. if( wParam == SS_IDLE_ON )
  107. bIdle = TRUE;
  108. else if( wParam == SS_IDLE_OFF )
  109. bIdle = FALSE;
  110. break;
  111. #endif
  112. case WM_DESTROY:
  113. if (idTimer) {
  114. KillTimer(hwnd, idTimer);
  115. idTimer = 0;
  116. }
  117. // Destroy any children of the top level window
  118. pssw = gpss->sswTable.PsswFromHwnd( hwnd );
  119. PSSW psswChild;
  120. psswChild = pssw == NULL ? NULL : pssw->psswChildren;
  121. while( psswChild ) {
  122. if( psswChild->hwnd )
  123. DestroyWindow( psswChild->hwnd );
  124. psswChild = pssw->psswSibling;
  125. }
  126. // Handle any palette stuff
  127. //mf: Before deleting this top level window, we need to use its
  128. // still-valid dc to things like restore SystemPaletteUse mode. Ideally this
  129. // should be done after ~SSW has dumped GL, but ~SSW also releases the DC.
  130. // If this is a problem, we can create a new function SSW::DeleteGL that just
  131. // gets rid of the GL part
  132. if( gpss->pssPal && pssw)
  133. ssw_DeletePalette( pssw );
  134. // Dump the main pssw
  135. delete pssw;
  136. // All pssw's have now been deleted - remove global ptr to top of
  137. // window chain.
  138. gpss->psswMain = NULL;
  139. PostQuitMessage(0);
  140. return 0;
  141. case SS_WM_CLOSING:
  142. // mf:This message is sent when the screen saver receives a WM_CLOSE
  143. // msg, *after* any password protection routines.
  144. // For now, only sent in /s mode
  145. SS_DBGMSG( "Main_Proc: SS_WM_CLOSING\n" );
  146. if( gpss->bResSwitch ) {
  147. // pssw->GdiClear();
  148. // mf: untested for child window case
  149. // Restore previous display settings
  150. // Note that this is also checked for in ~SCRNSAVE, in
  151. // case this message is not hit.
  152. ChangeDisplaySettings(NULL, CDS_FULLSCREEN);
  153. gpss->bResSwitch = FALSE;
  154. }
  155. return 0;
  156. case WM_SETFOCUS:
  157. SS_DBGMSG( "Main_Proc: WM_FOCUS\n" );
  158. //mf: this catches some of the win95 passwd dialog problems, where
  159. // we don't get repaint msgs when dialogs end
  160. if( ss_fOnWin95() && ss_fFullScreenMode() ) {
  161. pssw = gpss->sswTable.PsswFromHwnd( hwnd );
  162. if (pssw != NULL)
  163. pssw->Repaint( FALSE );
  164. }
  165. break;
  166. #if DBG
  167. case WM_SHOWWINDOW:
  168. SS_DBGMSG( "Main_Proc: WM_SHOWWINDOW\n" );
  169. break;
  170. #endif
  171. case WM_PAINT:
  172. SS_DBGMSG( "Main_Proc: WM_PAINT\n" );
  173. pssw = gpss->sswTable.PsswFromHwnd( hwnd );
  174. if (pssw != NULL)
  175. pssw->Repaint( TRUE );
  176. #ifdef SS_DO_PAINT
  177. // We do the painting rather than letting the system do it
  178. hdc = BeginPaint(hwnd, &ps);
  179. // This is case where bg brush is NULL and we have to do repaint
  180. // We only do it after bInited, as this will avoid the first
  181. // WM_PAINT for the entire window.
  182. if( bInited )
  183. DrawGdiRect( hdc, gpss->hbrBg, &ps.rcPaint );
  184. EndPaint(hwnd, &ps);
  185. #endif // SS_DO_PAINT
  186. #ifdef SS_DELAYED_START_KLUGE
  187. if( !bInited && SS_DELAY_START(gpss->type) ) {
  188. bInited = TRUE;
  189. // Do initial GL configuration
  190. PostMessage( hwnd, SS_WM_INITGL, 0, 0 );
  191. // Start drawing
  192. PostMessage( hwnd, SS_WM_START, 0, 0 );
  193. }
  194. #endif // SS_DELAYED_START_KLUGE
  195. if( pssw->iSubWindow ) {
  196. // If this window has sub windows, mark the bg for validation,
  197. // since for hardware double buffered schemes, Swapbuffers
  198. // may swap in ugly garbage.
  199. pssw->bValidateBg = TRUE;
  200. }
  201. #ifdef SS_DO_PAINT
  202. return 0; // painting has been handled by us
  203. #endif // SS_DO_PAINT
  204. break;
  205. case WM_SIZE:
  206. // Suspend drawing if minimized
  207. if( wParam == SIZE_MINIMIZED )
  208. bSuspend = TRUE;
  209. else // either SIZE_RESTORED or SIZE_MAXIMIZED
  210. bSuspend = FALSE;
  211. return SS_ScreenSaverProc( hwnd, message, wParam, lParam);
  212. case WM_MOVE:
  213. SS_DBGMSG( "Main_Proc: WM_MOVE\n" );
  214. // See note for WM_PAINT for subWindows
  215. pssw = gpss->sswTable.PsswFromHwnd( hwnd );
  216. if (pssw == NULL)
  217. break;
  218. //mf: kluge for non-floater workaround : see above
  219. if( pssw->iSubWindow )
  220. pssw->bValidateBg = TRUE;
  221. break;
  222. case WM_TIMER:
  223. if( bSuspend )
  224. return 0;
  225. #ifdef SS_WIN95_TIMER_HACK
  226. if( bIdle ) {
  227. // We are in an idle state, and don't want to flood the queue
  228. // with WM_TIMER mesages. So we kill the timer, do our
  229. // drawing, then start another timer.
  230. // Kill current timer
  231. if (idTimer)
  232. KillTimer(hwnd, idTimer);
  233. else
  234. // unlikely, but what the hay
  235. return 0;
  236. }
  237. #endif
  238. ss_TimerProc();
  239. #ifdef SS_WIN95_TIMER_HACK
  240. if( bIdle ) {
  241. // Start another animation timer after we've done drawing
  242. SetTimer(hwnd, idTimer, uiTimeOut, 0);
  243. }
  244. #endif
  245. return 0;
  246. }
  247. return DefScreenSaverProc(hwnd, message, wParam, lParam);
  248. }
  249. /**************************************************************************\
  250. * SS_ScreenSaverProc
  251. *
  252. * Wndproc for child windows, and some messages from top-level window
  253. *
  254. * Unhandled msgs are sent to DefWindowProc
  255. \**************************************************************************/
  256. LRESULT
  257. SS_ScreenSaverProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  258. {
  259. HDC hdc;
  260. PAINTSTRUCT ps;
  261. int i;
  262. int retVal;
  263. PSSW pssw;
  264. switch (message)
  265. {
  266. case WM_CREATE:
  267. SS_DBGMSG1( "SS_Proc: WM_CREATE for 0x%x\n", hwnd );
  268. pssw = (PSSW) ( ((LPCREATESTRUCT)lParam)->lpCreateParams );
  269. gpss->sswTable.Register( hwnd, pssw );
  270. pssw->size.width = ((LPCREATESTRUCT)lParam)->cx;
  271. pssw->size.height = ((LPCREATESTRUCT)lParam)->cy;
  272. pssw->hwnd = hwnd;
  273. break;
  274. case SS_WM_INITGL:
  275. SS_DBGMSG1( "SS_Proc: SS_WM_INITGL for 0x%x\n", hwnd );
  276. pssw = gpss->sswTable.PsswFromHwnd( hwnd );
  277. pssw->InitGL();
  278. break;
  279. #ifdef SS_MULTI_WINDOW_TIMERS
  280. // Enable this section and fill it in if windows start their own animation
  281. // timers. For now, there is just one timer on the main window.
  282. case SS_WM_START:
  283. SS_DBGMSG1( "SS_Proc: SS_WM_START for 0x%x\n", hwnd );
  284. pssw = gpss->sswTable.PsswFromHwnd( hwnd );
  285. // Send SS_WM_START to any children of this window
  286. ssw_RelayMessageToChildren( pssw, SS_WM_START, 0, 0 );
  287. // Nothing really to do here yet...
  288. break;
  289. #endif
  290. case SS_WM_PALETTE:
  291. return( MainPaletteManageProc( hwnd, message, wParam, lParam ) );
  292. case WM_DESTROY:
  293. pssw = gpss->sswTable.PsswFromHwnd( hwnd );
  294. SS_DBGMSG1( "SS_Proc: WM_DESTROY for 0x%x\n", hwnd );
  295. // Kill off any children of this window first
  296. PSSW psswChild;
  297. psswChild = pssw == NULL ? NULL : pssw->psswChildren;
  298. while( psswChild ) {
  299. if( psswChild->hwnd )
  300. DestroyWindow( psswChild->hwnd );
  301. else
  302. delete psswChild;
  303. psswChild = pssw->psswSibling;
  304. }
  305. // Delete the pssw - this does all necessary cleanup
  306. delete pssw;
  307. break;
  308. case WM_ERASEBKGND:
  309. SS_DBGMSG1( "SS_Proc: WM_ERASEBKGRND for 0x%x\n", hwnd );
  310. #if 0
  311. // If eventually we want to control bg erasing...
  312. {
  313. BOOL bEraseNow = TRUE; // ! 0 or 1 have same effect !
  314. if( bEraseNow ) {
  315. // If bg for the window is NULL, ? should erase here ?
  316. return TRUE;
  317. }
  318. else
  319. return 0; // window remains marked for erasing
  320. }
  321. #else
  322. pssw = gpss->sswTable.PsswFromHwnd( hwnd );
  323. if (pssw != NULL)
  324. pssw->Repaint( FALSE );
  325. // Don't process this message
  326. return DefWindowProc(hwnd, message, wParam, lParam);
  327. #endif
  328. case WM_PAINT:
  329. // We get this msg every time window moves, since SWP_NOCOPYBITS is
  330. // specified with the window move.
  331. hdc = BeginPaint(hwnd, &ps);
  332. EndPaint(hwnd, &ps);
  333. break;
  334. case WM_SIZE:
  335. pssw = gpss->sswTable.PsswFromHwnd( hwnd );
  336. if (pssw != NULL)
  337. pssw->Resize( LOWORD(lParam), HIWORD(lParam) );
  338. break;
  339. // these msg's are never received by the child window ?
  340. case WM_ACTIVATE:
  341. case WM_QUERYNEWPALETTE:
  342. case WM_PALETTECHANGED:
  343. return( MainPaletteManageProc( hwnd, message, wParam, lParam ) );
  344. case WM_SYSCOMMAND:
  345. case WM_SETCURSOR:
  346. case WM_ACTIVATEAPP:
  347. case WM_MOUSEMOVE:
  348. case WM_LBUTTONDOWN:
  349. case WM_MBUTTONDOWN:
  350. case WM_RBUTTONDOWN:
  351. case WM_KEYDOWN:
  352. case WM_SYSKEYDOWN:
  353. case WM_POWERBROADCAST:
  354. case WM_POWER:
  355. pssw = gpss->sswTable.PsswFromHwnd( hwnd );
  356. if (pssw == NULL)
  357. return DefScreenSaverProc(hwnd, message, wParam, lParam);
  358. else
  359. return DefScreenSaverProc(pssw->psswParent->hwnd, message, wParam, lParam);
  360. default:
  361. return DefWindowProc(hwnd, message, wParam, lParam);
  362. }
  363. return 0;
  364. }
  365. #ifdef SS_DEBUG
  366. /**************************************************************************\
  367. * PrintUpdateRate
  368. *
  369. * Print number of updates per second in the title bar
  370. *
  371. \**************************************************************************/
  372. static void
  373. PrintUpdateRate( double elapsed, long updateCount )
  374. {
  375. char buf[100];
  376. double updateRate;
  377. if( elapsed == 0.0 )
  378. updateRate = 0.0;
  379. else
  380. updateRate = updateCount / elapsed;
  381. sprintf( buf, "Updates per second = %4.1f", updateRate );
  382. SendMessage(gpss->psswMain->hwnd, WM_SETTEXT, 0, (LPARAM)buf);
  383. }
  384. #endif
  385. /**************************************************************************\
  386. * ss_TimerProc
  387. *
  388. * Every time a timer event fires off, update all active windows
  389. *
  390. \**************************************************************************/
  391. static void
  392. ss_TimerProc()
  393. {
  394. static int busy = FALSE;
  395. int i;
  396. #ifdef SS_DEBUG
  397. static long updateCount = 0;
  398. static double updateInterval = 2.0;
  399. SS_TIMER *pTimer = &gpss->timer;
  400. #endif
  401. if (busy)
  402. return;
  403. busy = TRUE;
  404. gpss->psswMain->UpdateWindow();
  405. #ifdef SS_DEBUG
  406. updateCount++;
  407. if( gpss->bDoTiming &&
  408. (( (double) pTimer->ElapsedTime() ) >= updateInterval) )
  409. {
  410. double elapsed = pTimer->Stop();
  411. PrintUpdateRate( elapsed, updateCount );
  412. updateCount = 0;
  413. pTimer->Start();
  414. }
  415. #endif
  416. busy = FALSE;
  417. }
  418. /**************************************************************************\
  419. * RelayMessageToChildren
  420. *
  421. * Pass along the message to any child windows
  422. \**************************************************************************/
  423. static void
  424. ssw_RelayMessageToChildren( PSSW pssw, UINT msg, WPARAM wParam, LPARAM lParam)
  425. {
  426. PSSW psswChild = pssw->psswChildren;
  427. while( psswChild ) {
  428. if( psswChild->hwnd )
  429. SendMessage( psswChild->hwnd, msg, wParam, lParam );
  430. psswChild = psswChild->psswSibling;
  431. }
  432. }
  433. /**************************************************************************\
  434. * UpdateDIBColorTable
  435. *
  436. * Wrapper for SSDIB_UpdateColorTable.
  437. *
  438. * This controls the hPal parameter for SSDIB_UpdateColorTable.
  439. *
  440. \**************************************************************************/
  441. void
  442. ssw_UpdateDIBColorTable( HDC hdcbm, HDC hdcwin )
  443. {
  444. SS_PAL *pssPal = gpss->pssPal;
  445. if( !pssPal )
  446. return;
  447. #if 0
  448. HPALETTE hpal = pssPal->bTakeOver ? pssPal->hPal : NULL;
  449. #else
  450. HPALETTE hpal = pssPal->hPal;
  451. #endif
  452. SSDIB_UpdateColorTable( hdcbm, hdcwin, hpal );
  453. }
  454. /**************************************************************************\
  455. * RealizePalette
  456. *
  457. \**************************************************************************/
  458. static void
  459. ssw_RealizePalette( PSSW pssw, BOOL bBackground )
  460. {
  461. // assumed pssPal valid if get here
  462. SS_PAL *pssPal = gpss->pssPal;
  463. if( !pssw->hrc ) {
  464. // Can assume this window doesn't need to worry about palettes, but
  465. // if any of its children are subWindows, it will have to take care
  466. // of it *for* them.
  467. if( ! pssw->iSubWindow )
  468. return; // no hrc and no subWindow children
  469. }
  470. pssPal->Realize( pssw->hwnd, pssw->hdc, bBackground );
  471. if( pssw->pStretch && pssw->pStretch->ssbm.hdc ) {
  472. SS_BITMAP *pssbm = &pssw->pStretch->ssbm;
  473. ssw_UpdateDIBColorTable( pssbm->hdc, pssw->hdc );
  474. }
  475. }
  476. /**************************************************************************\
  477. * ssw_DeletePalette
  478. *
  479. \**************************************************************************/
  480. static void
  481. ssw_DeletePalette( PSSW pssw )
  482. {
  483. SS_PAL *pssPal = gpss->pssPal;
  484. if( pssPal->bTakeOver ) {
  485. // We took over the system palette - make a note of this
  486. // for any special ss termination conditions.
  487. gpss->flags |= SS_PALETTE_TAKEOVER;
  488. }
  489. pssPal->SetDC( pssw->hdc );
  490. delete pssPal;
  491. gpss->pssPal = NULL;
  492. }
  493. /**************************************************************************\
  494. * PaletteManage Procs
  495. \**************************************************************************/
  496. /* palette related msgs's:
  497. - WM_ACTIVATE:
  498. The WM_ACTIVATE message is sent when a window is being activated or
  499. deactivated. This message is sent first to the window procedure of
  500. the top-level window being deactivated; it is then sent to the
  501. window procedure of the top-level window being activated.
  502. - WM_QUERYNEWPALETTE:
  503. The WM_QUERYNEWPALETTE message informs a window that it is about
  504. to receive the keyboard focus, giving the window the opportunity
  505. to realize its logical palette when it receives the focus.
  506. If the window realizes its logical palette, it must return TRUE;
  507. otherwise, it must return FALSE.
  508. - WM_PALETTECHANGED:
  509. The WM_PALETTECHANGED message is sent to all top-level and overlapped
  510. windows after the window with the keyboard focus has realized its
  511. logical palette, thereby changing the system palette. This message
  512. enables a window that uses a color palette but does not have the
  513. keyboard focus to realize its logical palette and update its client
  514. area.
  515. This message must be sent to all top-level and overlapped windows,
  516. including the one that changed the system palette. If any child
  517. windows use a color palette, this message must be passed on to them
  518. as well.
  519. To avoid creating an infinite loop, a window that receives this
  520. message must not realize its palette, unless it determines that
  521. wParam does not contain its own window handle.
  522. - WM_SYSCOLORCHANGE:
  523. The WM_SYSCOLORCHANGE message is sent to all top-level windows when
  524. a change is made to a system color setting.
  525. - SS_WM_PALETTE:
  526. Internal msg. Uses:
  527. - In fullscreen mode, we send this from Main wndproc to main
  528. window's children on WM_ACTIVATE.
  529. - When this is received in SS_ScreenSaverProc, if fullscreen,
  530. it does:
  531. UnrealizeObject( pssPal->hPal );
  532. RealizePalette( hdc );
  533. otherwise, it is passed to PaletteManageProc, where
  534. Realize is called (for 'floater' windows to realize
  535. their palettes).
  536. - It is also sent by DelayPaletteRealization() when it can't get
  537. the system palette.
  538. */
  539. /**************************************************************************\
  540. * MainPaletteManageProc
  541. *
  542. * Top-level palette management proc.
  543. * Returns immediately if no palette set - otherwise calls through
  544. * paletteManageProc function pointer
  545. *
  546. \**************************************************************************/
  547. LONG
  548. MainPaletteManageProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  549. {
  550. if( !gpss->pssPal )
  551. // No palette management required
  552. return 0;
  553. // else call approppriate palette manage proc
  554. return (*gpss->pssPal->paletteManageProc)(hwnd, message, wParam, lParam);
  555. }
  556. LONG
  557. NullPaletteManageProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  558. {
  559. return 0;
  560. }
  561. /**************************************************************************\
  562. * FullScreenPaletteManageProc
  563. *
  564. * Processes messages relating to palette management in full screen mode.
  565. *
  566. \**************************************************************************/
  567. LONG
  568. FullScreenPaletteManageProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  569. {
  570. SS_PAL *pssPal;
  571. PSSW pssw;
  572. switch (message)
  573. {
  574. case WM_ACTIVATE:
  575. #if SS_DEBUG
  576. if ( LOWORD(wParam) == WA_INACTIVE )
  577. SS_DBGMSG1( "FullScreen_PMProc: WM_ACTIVATE : inactive for 0x%x\n",
  578. hwnd );
  579. else
  580. SS_DBGMSG1( "FullScreen_PMProc: WM_ACTIVATE : active for 0x%x\n",
  581. hwnd );
  582. #endif
  583. // !! This msg is only sent to main top level window
  584. pssw = gpss->sswTable.PsswFromHwnd( hwnd );
  585. pssPal = gpss->pssPal;
  586. if ( pssPal->bUseStatic ) {
  587. HDC hdc = pssw->hdc; // hdc *always* valid for top-level pssw
  588. // Note: wParam = 0 when window going *inactive*
  589. SetSystemPaletteUse( hdc, wParam ? SYSPAL_NOSTATIC
  590. : pssPal->uiOldStaticUse);
  591. }
  592. // Send SS_WM_PALETTE msg to main window
  593. SendMessage( hwnd, SS_WM_PALETTE, wParam, 0);
  594. break;
  595. case SS_WM_PALETTE:
  596. SS_DBGMSG1( "FullScreen_PMProc: SS_WM_PALETTE for 0x%x\n", hwnd );
  597. pssw = gpss->sswTable.PsswFromHwnd( hwnd );
  598. ssw_RelayMessageToChildren( pssw, SS_WM_PALETTE, wParam, 0 );
  599. HDC hdc;
  600. if( hdc = pssw->hdc )
  601. {
  602. pssPal = gpss->pssPal;
  603. //mf: this should call thru ssw_RealizePalette for bitmap case ? (for now
  604. // don't need to, since we take over palette...)
  605. // This resets the logical palette, causing remapping of
  606. // logical palette to system palette
  607. // mf: !!! ?? how come no dc with UnrealizeObject ? does that
  608. // mean its done once per app, not per child window ?
  609. // yeah, we should move this up...
  610. UnrealizeObject( pssPal->hPal );
  611. RealizePalette( hdc );
  612. }
  613. break;
  614. }
  615. return 0;
  616. }
  617. /**************************************************************************\
  618. * PaletteManageProc
  619. *
  620. * Processes messages relating to palette management for the general case.
  621. *
  622. * Note: this msg handling strategy is based loosely on the tk, so any changes
  623. * there should be reflected here
  624. \**************************************************************************/
  625. LONG
  626. PaletteManageProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  627. {
  628. // One global palette for all windows
  629. if( !gpss->pssPal )
  630. return 0;
  631. switch (message)
  632. {
  633. case WM_ACTIVATE:
  634. SendMessage( hwnd, SS_WM_PALETTE, gpss->bInBackground(), 0);
  635. // Allow DefWindowProc() to finish the default processing (which
  636. // includes changing the keyboard focus).
  637. break;
  638. case WM_QUERYNEWPALETTE:
  639. SS_DBGMSG1( "Palette_Proc: WM_QUERYNEWPALETTE for 0x%x\n", hwnd );
  640. // We don't actually realize palette here (we do it at WM_ACTIVATE
  641. // time), but we need the system to think that we have so that a
  642. // WM_PALETTECHANGED message is generated.
  643. //mf: why can't we just realize here ? and who wants even more messages to
  644. // be generated !!! :)
  645. // This is the only msg preview mode gets wrt palettes !
  646. if( !ss_fPreviewMode() )
  647. return (1);
  648. // We are in preview mode - realize the palette
  649. SendMessage( hwnd, SS_WM_PALETTE, gpss->bInBackground(), 0);
  650. break;
  651. case WM_PALETTECHANGED:
  652. SS_DBGMSG1( "Palette_Proc: WM_PALETTECHANGED for 0x%x\n", hwnd );
  653. // Respond to this message only if the window that changed the palette
  654. // is not this app's window.
  655. // We are not the foreground window, so realize palette in the
  656. // background. We cannot call Realize to do this because
  657. // we should not do any of the gbUseStaticColors processing while
  658. // in background.
  659. // Actually, we *can* be the fg window, so don't realize if
  660. // we're in foreground
  661. if( (hwnd != (HWND) wParam) && gpss->bInBackground() )
  662. SendMessage( hwnd, SS_WM_PALETTE, TRUE, 0);
  663. break;
  664. case WM_SYSCOLORCHANGE:
  665. // If the system colors have changed and we have a palette
  666. // for an RGB surface then we need to recompute the static
  667. // color mapping because they might have been changed in
  668. // the process of changing the system colors.
  669. SS_DBGMSG1( "Palette_Proc: WM_SYSCOLORCHANGE for 0x%x\n", hwnd );
  670. gpss->pssPal->ReCreateRGBPalette();
  671. SendMessage( hwnd, SS_WM_PALETTE, gpss->bInBackground(), 0);
  672. break;
  673. case SS_WM_PALETTE:
  674. SS_DBGMSG2( "Palette_Proc: SS_WM_PALETTE for 0x%x, bg = %d\n",
  675. hwnd, wParam );
  676. // Realize palette for this window and its children
  677. // wParam = TRUE if realize as bg
  678. PSSW pssw = gpss->sswTable.PsswFromHwnd( hwnd );
  679. ssw_RelayMessageToChildren( pssw, message, wParam, lParam );
  680. ssw_RealizePalette( pssw, (BOOL)wParam );
  681. break;
  682. }
  683. return 0;
  684. }
  685. /******************************Public*Routine******************************\
  686. * GLScreenSaverConfigureDialog
  687. *
  688. * This is a wrapper for ScreenSaverConfigureDialog, which is the main dialog
  689. * proc for all the GL screen savers in config mode.
  690. *
  691. * We call the client's ss_ConfigInit() routine on the first WM_PAINT, since
  692. * the dialog will have focus at this point (can realize palette) and all
  693. * buttons should have been created.
  694. \**************************************************************************/
  695. BOOL
  696. GLScreenSaverConfigureDialog( HWND hDlg, UINT msg, WPARAM wParam,
  697. LPARAM lParam )
  698. {
  699. static BOOL bInited = 0;
  700. switch( msg ) {
  701. case WM_INITDIALOG :
  702. {
  703. SS_DBGMSG( "GLScreenSaverConfigureDialog: WM_INITDIALOG\n" );
  704. // Create wrapper pssw for the dialog box
  705. PSSW pssw;
  706. pssw = new SSW( NULL, // ssw parent
  707. hDlg
  708. );
  709. SS_ASSERT( pssw, "GLScreenSaverConfigureDialog : alloc failure for psswMain\n" );
  710. gpss->psswMain = pssw;
  711. // Load any resource strings common to all the dialogs
  712. BOOL bStringsLoaded = ss_LoadTextureResourceStrings();
  713. // If this doesn't work, things are seriously wrong and we
  714. // shouldn't continue
  715. SS_ASSERT( bStringsLoaded, "GLScreenSaverConfigureDialog : failure loading common resource strings\n" );
  716. }
  717. break;
  718. case WM_PAINT:
  719. if( !bInited ) {
  720. // Call client's ss_ConfigInit()
  721. if( !ss_ConfigInit( hDlg ) ) {
  722. SS_WARNING( "ConfigInit failed\n" );
  723. // Send WM_CLOSE to the dialog - this will enable any
  724. // cleanup code to be called by the client
  725. SendMessage( hDlg, WM_CLOSE, 0, 0l );
  726. }
  727. bInited = TRUE;
  728. }
  729. break;
  730. case WM_ACTIVATE:
  731. case WM_QUERYNEWPALETTE:
  732. case WM_PALETTECHANGED:
  733. case SS_WM_PALETTE:
  734. return( MainPaletteManageProc( hDlg, msg, wParam, lParam ) );
  735. }
  736. return ScreenSaverConfigureDialog( hDlg, msg, wParam, lParam );
  737. }
  738. /******************************Public*Routine******************************\
  739. * SSW_TABLE constructor
  740. *
  741. \**************************************************************************/
  742. SSW_TABLE::SSW_TABLE()
  743. {
  744. nEntries = 0;
  745. }
  746. /******************************Public*Routine******************************\
  747. * Register
  748. *
  749. * Register a HWND/PSSW pair.
  750. \**************************************************************************/
  751. void
  752. SSW_TABLE::Register( HWND hwnd, PSSW pssw )
  753. {
  754. SSW_TABLE_ENTRY *pEntry;
  755. // Check if already in table
  756. if( PsswFromHwnd( hwnd ) )
  757. return;
  758. // put hwnd/pssw pair in the table
  759. pEntry = &sswTable[nEntries];
  760. pEntry->hwnd = hwnd;
  761. pEntry->pssw = pssw;
  762. nEntries++;
  763. }
  764. /******************************Public*Routine******************************\
  765. * PsswFromHwnd
  766. *
  767. * Return PSSW for the HWND
  768. \**************************************************************************/
  769. PSSW
  770. SSW_TABLE::PsswFromHwnd( HWND hwnd )
  771. {
  772. int count = nEntries;
  773. SSW_TABLE_ENTRY *pEntry = sswTable;
  774. while( count-- ) {
  775. if( pEntry->hwnd == hwnd )
  776. return pEntry->pssw;
  777. pEntry++;
  778. }
  779. return NULL;
  780. }
  781. /******************************Public*Routine******************************\
  782. * Remove
  783. *
  784. * Remove HWND/PSSW entry from table
  785. \**************************************************************************/
  786. BOOL
  787. SSW_TABLE::Remove( HWND hwnd )
  788. {
  789. SSW_TABLE_ENTRY *pEntry = sswTable;
  790. // Locate the hwnd/pssw pair
  791. for( int count = 0 ; count < nEntries ; count++, pEntry++ ) {
  792. if( pEntry->hwnd == hwnd )
  793. break;
  794. }
  795. if( count == nEntries )
  796. // couldn't find it in the table
  797. return FALSE;
  798. // Remove entry / shuffle up other entries
  799. for( int i = count; i < nEntries-1; i ++ ) {
  800. sswTable[i] = sswTable[i+1];
  801. }
  802. nEntries--;
  803. return TRUE;
  804. }