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.

619 lines
15 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: logon.cxx
  3. *
  4. * Copyright (c) 1997 Microsoft Corporation
  5. *
  6. \**************************************************************************/
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <math.h>
  10. #include <sys/types.h>
  11. #include <stdlib.h>
  12. #include <time.h>
  13. #include "uidemo.hxx"
  14. #include "logon.hxx"
  15. #include "logobj.hxx"
  16. //#define TEST_BITMAP 1
  17. //#define UIDEMO_SWITCH_RES 1
  18. MTKWIN *mtkWin; // the main window
  19. ISIZE winSize; // main window cached size and position
  20. IPOINT2D winPos;
  21. BOOL bSwapHintsEnabled; // global swap hints
  22. BOOL bSwapHints; // local use
  23. HCURSOR hNormalCursor, hHotCursor;
  24. HINSTANCE hLogonInstance;
  25. BOOL bDebugMode;
  26. BOOL bRunAgain;
  27. #if 0
  28. BOOL bFlyWithContext = TRUE;
  29. #else
  30. BOOL bFlyWithContext = FALSE;
  31. #endif
  32. // Stuff for the banner
  33. HDC hdcMem;
  34. HBITMAP hBanner;
  35. ISIZE bannerSize = { 0, 0 };
  36. RGBA bgColor = {0.16f, 0.234f, 0.32f, 0.0f}; // ok
  37. int nLogObj;
  38. LOG_OBJECT **pLogObj;
  39. static LOG_OBJECT *pHotObj; // currently hot object
  40. BOOL bLighting, bDepth;
  41. VIEW view;
  42. static BOOL bResSwitch;
  43. // Timing stuff
  44. AVG_UPDATE_TIMER frameRateTimer( 1.0f, 4 );
  45. TIMER transitionTimer;
  46. // Forwards
  47. static void CleanUp();
  48. static void GLFinish();
  49. /**************************************************************************\
  50. *
  51. \**************************************************************************/
  52. float Clamp(int iters_left, float t)
  53. {
  54. if (iters_left < 3) {
  55. return 0.0f;
  56. }
  57. return (float) (iters_left-2)*t/iters_left;
  58. }
  59. void ClearWindow()
  60. {
  61. int clearMask = GL_COLOR_BUFFER_BIT;
  62. if( bDepth )
  63. clearMask |= GL_DEPTH_BUFFER_BIT;
  64. if( !bSwapHints ) {
  65. glClear( clearMask );
  66. return;
  67. }
  68. GLIRECT rect, *pRect;
  69. pRect = &rect;
  70. for( int i = 0; i < nLogObj; i++ ) {
  71. pLogObj[i]->GetRect( pRect );
  72. glScissor( pRect->x, pRect->y, pRect->width, pRect->height );
  73. glClear( clearMask );
  74. AddSwapHintRect( pRect );
  75. }
  76. // restore full scissor (mf : ? or just disable,since this only place used ?
  77. glScissor( 0, 0, winSize.width, winSize.height );
  78. }
  79. void ClearAll()
  80. {
  81. static GLIRECT rect = {0};
  82. int clearMask = GL_COLOR_BUFFER_BIT;
  83. if( bDepth )
  84. clearMask |= GL_DEPTH_BUFFER_BIT;
  85. glScissor( 0, 0, winSize.width, winSize.height );
  86. glClear( clearMask );
  87. if( bSwapHints ) {
  88. rect.width = winSize.width;
  89. rect.height = winSize.height;
  90. AddSwapHintRect( &rect );
  91. }
  92. }
  93. void ClearRect( GLIRECT *pRect, BOOL bResetScissor )
  94. {
  95. int clearMask = GL_COLOR_BUFFER_BIT;
  96. if( bDepth )
  97. clearMask |= GL_DEPTH_BUFFER_BIT;
  98. glScissor( pRect->x, pRect->y, pRect->width, pRect->height );
  99. glClear( clearMask );
  100. if( bResetScissor )
  101. glScissor( 0, 0, winSize.width, winSize.height );
  102. }
  103. void DrawObjects( BOOL bCalcUpdateRect )
  104. {
  105. // Draws objects in their current positions
  106. for( int i = 0; i < nLogObj; i++ ) {
  107. pLogObj[i]->Draw( bCalcUpdateRect );
  108. }
  109. }
  110. void Flush()
  111. {
  112. // glFlush, SwapBuffers (if doubleBuf)
  113. mtkWin->Flush();
  114. }
  115. float MyRand(void)
  116. {
  117. return 10.0f * ( ((float) rand())/((float) RAND_MAX) - 0.5f);
  118. }
  119. static void
  120. SetDepthMode()
  121. {
  122. if( bDepth )
  123. glEnable(GL_DEPTH_TEST);
  124. else
  125. glDisable(GL_DEPTH_TEST);
  126. }
  127. static void
  128. SetTextureMode()
  129. {
  130. int mode;
  131. if( bLighting )
  132. mode = GL_MODULATE;
  133. else
  134. mode = GL_DECAL;
  135. glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode );
  136. }
  137. static void
  138. SetLightingMode()
  139. {
  140. if( bLighting )
  141. glEnable( GL_LIGHTING );
  142. else
  143. glDisable( GL_LIGHTING );
  144. SetTextureMode();
  145. }
  146. void
  147. CalcObjectWindowRects()
  148. {
  149. for( int i = 0; i < nLogObj; i++ ) {
  150. pLogObj[i]->CalcWinRect();
  151. }
  152. }
  153. //mf: VIEW class member
  154. static void
  155. SetView( ISIZE *pWinSize )
  156. {
  157. glViewport(0, 0, pWinSize->width, pWinSize->height);
  158. view.fViewDist = 10.0f; // viewing distance
  159. view.fovy = 45.0f; // field of view in y direction (degrees)
  160. view.fAspect = (float) pWinSize->width / (float) pWinSize->height;
  161. // We'll assume width >= height
  162. glMatrixMode(GL_PROJECTION);
  163. glLoadIdentity();
  164. gluPerspective(view.fovy, view.fAspect, 0.1, 100.0);
  165. // glOrtho( -5.0, 5.0, -5.0, 5.0, 0.0, 100.0 ); no look as good
  166. glMatrixMode(GL_MODELVIEW);
  167. glLoadIdentity();
  168. gluLookAt(0,0,view.fViewDist, 0,0,0, 0,1,0); // from, to, up...
  169. }
  170. void Reshape(int width, int height)
  171. {
  172. // Need to update main window info
  173. ISIZE *pSize = &winSize;
  174. pSize->width = width;
  175. pSize->height = height;
  176. if( !width || !height )
  177. return;
  178. SetView( pSize );
  179. UpdateLocalTransforms( UPDATE_ALL );
  180. CalcObjectWindowRects();
  181. // mf: this is kind of a hack, need a different mechanism, since get repaints
  182. // from resizes and window expose (an argument for msg loops even in mtk
  183. // programs. Of course, there's also tkDisplayFunc, which is called on PAINT,
  184. // as opposed to IdleFunc...
  185. ClearAll();
  186. }
  187. BOOL EscKey(int key, GLenum mask)
  188. {
  189. if( bDebugMode && (key == TK_ESCAPE) )
  190. Quit();
  191. return FALSE;
  192. }
  193. BOOL Key(int key, GLenum mask)
  194. {
  195. if( !bDebugMode )
  196. return FALSE;
  197. switch (key) {
  198. case TK_ESCAPE:
  199. Quit();
  200. break;
  201. default:
  202. return AttributeKey( key, mask );
  203. }
  204. return TRUE;
  205. }
  206. BOOL AttributeKey(int key, GLenum mask)
  207. {
  208. switch (key) {
  209. case TK_c :
  210. bFlyWithContext = !bFlyWithContext;
  211. break;
  212. case TK_d :
  213. bDepth = !bDepth;
  214. SetDepthMode();
  215. break;
  216. case TK_l :
  217. bLighting = !bLighting;
  218. // This affects texturing mode
  219. SetLightingMode();
  220. break;
  221. case TK_s :
  222. if( mtk_bAddSwapHintRect() )
  223. bSwapHintsEnabled = !bSwapHintsEnabled;
  224. break;
  225. default:
  226. return FALSE;
  227. }
  228. return TRUE;
  229. }
  230. static void LoadCursors()
  231. {
  232. hNormalCursor = LoadCursor( NULL, IDC_ARROW );
  233. hHotCursor = LoadCursor( hLogonInstance, MAKEINTRESOURCE( IDC_HOT_CURSOR ) );
  234. }
  235. /******************** MAIN LOGON SEQUENCE *********************************\
  236. *
  237. \**************************************************************************/
  238. static MTKWIN *CreateLogonWindow()
  239. {
  240. MTKWIN *win;
  241. // Set window size and position
  242. bResSwitch = FALSE;
  243. UINT winConfig = 0;
  244. // Have to intially create window without cursor, so can change it later
  245. winConfig |= MTK_NOCURSOR;
  246. if( bDebugMode ) {
  247. winPos.x = 10;
  248. winPos.y = 30;
  249. #if 0
  250. winSize.width = 400;
  251. winSize.height = 300;
  252. #else
  253. winSize.width = 800;
  254. winSize.height = 600;
  255. #endif
  256. } else {
  257. #if UIDEMO_SWITCH_RES
  258. if( mtk_ChangeDisplaySettings( 800, 600, NULL ) ) {
  259. bResSwitch = TRUE;
  260. }
  261. #endif
  262. winConfig |= MTK_FULLSCREEN | MTK_NOBORDER;
  263. winPos.x = 0;
  264. winPos.y = 0;
  265. winSize.width = GetSystemMetrics( SM_CXSCREEN );
  266. winSize.height = GetSystemMetrics( SM_CYSCREEN );
  267. #if 0
  268. // debugging full screen ...
  269. winSize.width /= 4;
  270. winSize.height /= 4;
  271. #endif
  272. }
  273. win = new MTKWIN();
  274. if( !win )
  275. return NULL;
  276. // Configure and create the window (mf: this 2 step process of constructor
  277. // and create will allow creating 'NULL' windows
  278. #ifdef TEST_BITMAP
  279. UINT glConfig = MTK_RGB | MTK_DOUBLE | MTK_BITMAP | MTK_DEPTH16;
  280. #else
  281. UINT glConfig = MTK_RGB | MTK_DOUBLE | MTK_DEPTH16;
  282. #endif
  283. if( !bDebugMode )
  284. glConfig |= MTK_NOBORDER;
  285. // Create the window
  286. if( ! win->Create( "Demo", &winSize, &winPos, winConfig, NULL ) ) {
  287. delete win;
  288. return NULL;
  289. }
  290. // Configure the window for OpenGL, setting ReshapeFunc to catch the
  291. // resize (can't set it before in this case, since we do various gl
  292. // calculations in the Reshape func.
  293. win->SetReshapeFunc(Reshape);
  294. win->SetFinishFunc(GLFinish);
  295. if( ! win->Config( glConfig ) )
  296. {
  297. delete win;
  298. return NULL;
  299. }
  300. return win;
  301. }
  302. static void InitGL(void)
  303. {
  304. #if 0
  305. static float lmodel_ambient[] = {0.0f, 0.0f, 0.0f, 0.0f};
  306. #else
  307. static float lmodel_ambient[] = {0.2f, 0.2f, 0.2f, 0.0f};
  308. #endif
  309. //mf: change to one sided lighting if object is closed
  310. static float lmodel_twoside[] = {(float)GL_TRUE};
  311. static float lmodel_local[] = {(float)GL_FALSE};
  312. static float light0_ambient[] = {0.1f, 0.1f, 0.1f, 1.0f};
  313. static float light0_diffuse[] = {1.0f, 1.0f, 1.0f, 0.0f};
  314. #if 1
  315. // static float light0_position[] = {-1.0f, 1.0f, 1.0f, 0.0f};
  316. static float light0_position[] = {-1.0f, 0.8f, 4.0f, 0.0f};
  317. #else
  318. static float light0_position[] = {-1.0f, 1.0f, 1.0f, 0.0f};
  319. #endif
  320. static float light0_specular[] = {1.0f, 1.0f, 1.0f, 0.0f};
  321. static float bevel_mat_ambient[] = {0.0f, 0.0f, 0.0f, 1.0f};
  322. static float bevel_mat_shininess[] = {40.0f};
  323. static float bevel_mat_specular[] = {1.0f, 1.0f, 1.0f, 0.0f};
  324. static float bevel_mat_diffuse[] = {1.0f, 1.0f, 1.0f, 0.0f};
  325. // Set GL attributes
  326. // glEnable(GL_CULL_FACE);
  327. glEnable( GL_SCISSOR_TEST );
  328. glCullFace(GL_BACK);
  329. glClearDepth(1.0f);
  330. glClearColor( bgColor.r, bgColor.g, bgColor.b, bgColor.a );
  331. glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
  332. glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
  333. glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
  334. glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
  335. glEnable(GL_LIGHT0);
  336. glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_local);
  337. glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
  338. glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
  339. glEnable(GL_LIGHTING);
  340. glMaterialfv(GL_FRONT, GL_AMBIENT, bevel_mat_ambient);
  341. glMaterialfv(GL_FRONT, GL_SHININESS, bevel_mat_shininess);
  342. glMaterialfv(GL_FRONT, GL_SPECULAR, bevel_mat_specular);
  343. glMaterialfv(GL_FRONT, GL_DIFFUSE, bevel_mat_diffuse);
  344. glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
  345. glEnable(GL_COLOR_MATERIAL);
  346. glEnable( GL_TEXTURE_2D );
  347. // Setup viewing parameters
  348. SetView( &winSize );
  349. // Rendering attributes
  350. bDepth = FALSE;
  351. SetDepthMode();
  352. bLighting = FALSE;
  353. SetLightingMode();
  354. #if 0
  355. glShadeModel(GL_SMOOTH);
  356. #else
  357. glShadeModel(GL_FLAT);
  358. #endif
  359. #ifdef TEST_BITMAP
  360. bSwapHintsEnabled = FALSE;
  361. #else
  362. bSwapHintsEnabled = mtk_bAddSwapHintRect();
  363. #endif
  364. // Update local copies of transforms, so we can calc 2D update rects
  365. //mf: ? protect with bSwapHints ?
  366. UpdateLocalTransforms( UPDATE_ALL );
  367. }
  368. static HBITMAP LoadBanner()
  369. {
  370. hdcMem = CreateCompatibleDC( NULL );
  371. HBITMAP hBanner = LoadBitmap( hLogonInstance,
  372. MAKEINTRESOURCE( IDB_BANNER ) );
  373. BITMAPINFO bmi = {0};
  374. bmi.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
  375. if( ! GetDIBits( hdcMem, hBanner, 0, 0, NULL, &bmi, DIB_RGB_COLORS ) ) {
  376. SS_WARNING( "Couldn't get banner bitmap dimensions\n" );
  377. } else {
  378. bannerSize.width = bmi.bmiHeader.biWidth;
  379. bannerSize.height = bmi.bmiHeader.biHeight;
  380. }
  381. if( !SelectObject( hdcMem, hBanner ) ) {
  382. SS_ERROR( "Couldn't select banner into DC\n" );
  383. return 0;
  384. }
  385. return hBanner;
  386. //mf: make hdcMem global, so it and hBanner can be deleted
  387. }
  388. BOOL LoadUserTextures( TEX_RES *pUserTexRes )
  389. {
  390. SetWindowText( mtkWin->GetHWND(), "Loading textures..." );
  391. for (int i = 0; i < nLogObj; i++) {
  392. pLogObj[i]->SetTexture( new TEXTURE( &pUserTexRes[i],
  393. hLogonInstance ) );
  394. //mf: also validate the textures...
  395. }
  396. glFinish();
  397. SetWindowText( mtkWin->GetHWND(), "" );
  398. return TRUE;
  399. }
  400. /******************** RunLogonSequence ************************************\
  401. *
  402. \**************************************************************************/
  403. BOOL RunLogonSequence( ENV *pEnv )
  404. {
  405. BOOL bRet;
  406. LOG_OBJECT *pSelectedLogObj;
  407. // Create table of ptrs to LOGOBJ's, which are wrappers around the list of
  408. // users. The list of users and their bitmaps, etc, should eventually be
  409. // a parameter to this function.
  410. bDebugMode = pEnv->bDebugMode;
  411. nLogObj = pEnv->nUsers;
  412. hLogonInstance = pEnv->hInstance;
  413. pLogObj = (LOG_OBJECT **) malloc( nLogObj * sizeof(LOG_OBJECT *) );
  414. for( int i = 0; i < nLogObj; i ++ ) {
  415. pLogObj[i] = new LOG_OBJECT();
  416. }
  417. // Create a window to run the logon sequence in
  418. mtkWin = CreateLogonWindow();
  419. if( !mtkWin )
  420. return FALSE;
  421. // Do any GL init for the window
  422. InitGL();
  423. LoadBanner();
  424. LoadUserTextures( pEnv->pUserTexRes );
  425. SetCursor( NULL );
  426. LoadCursors();
  427. mtkWin->SetReshapeFunc( Reshape );
  428. if( bDebugMode ) {
  429. // The sequences can repeat ad infinitum
  430. //mf: pretty crazy logic
  431. while( 1 ) {
  432. if( !RunLogonInitSequence() )
  433. // fatal
  434. break;
  435. run_hot_sequence:
  436. bRunAgain = FALSE;
  437. pSelectedLogObj = RunLogonHotSequence();
  438. if( bRunAgain ) {
  439. continue;
  440. }
  441. if( pSelectedLogObj == NULL )
  442. // fatal, no obect selected or window was closed
  443. break;
  444. if( ! RunLogonEndSequence( pSelectedLogObj ) )
  445. // fatal
  446. break;
  447. if( bRunAgain ) {
  448. goto run_hot_sequence;
  449. }
  450. break;
  451. }
  452. } else
  453. {
  454. // Normal operation...
  455. //mf: ? check for fatal errors ? or if !debugMode, call Quit whenever
  456. // Exec returns false
  457. RunLogonInitSequence();
  458. // Run 'hot' sequence, where user selects object
  459. if( !(pSelectedLogObj = RunLogonHotSequence()) ) {
  460. // No user selected, fatal
  461. CleanUp();
  462. return FALSE;
  463. }
  464. // Set the selected user index
  465. for( i = 0; i < nLogObj; i ++ ) {
  466. if( pSelectedLogObj == pLogObj[i] )
  467. pEnv->iSelectedUser = i;
  468. }
  469. // Run final sequence
  470. RunLogonEndSequence( pSelectedLogObj );
  471. }
  472. // Do various clean-up
  473. CleanUp();
  474. return TRUE;
  475. }
  476. void CleanUp()
  477. {
  478. if( mtkWin )
  479. mtkWin->Close(); // this will call destructor for mtkWin
  480. if( bResSwitch )
  481. mtk_RestoreDisplaySettings();
  482. }
  483. // This function is the FinishFunc callback, and should not be called directly
  484. static void GLFinish()
  485. {
  486. // Delete textures
  487. //mf: may want to keep the selected one... , depending on what the caller wants
  488. // returned. Maybe could keep the image data around, and then create a new
  489. // TEXTURE ctor that uses this data...
  490. for( int i = 0; i < nLogObj; i++ ) {
  491. if( pLogObj[i]->pTex ) {
  492. delete pLogObj[i]->pTex;
  493. pLogObj[i]->pTex = NULL;
  494. }
  495. }
  496. }
  497. //mf: this can be called during debug mode, to terminate prematurely
  498. void Quit()
  499. {
  500. CleanUp();
  501. mtkQuit();
  502. }