Counter Strike : Global Offensive Source Code
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.

544 lines
14 KiB

  1. //===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: Methods associated with the cursor
  4. //
  5. // $Revision: $
  6. // $NoKeywords: $
  7. //===========================================================================//
  8. #if !defined( _X360 )
  9. #define OEMRESOURCE //for OCR_* cursor junk
  10. #include "winlite.h"
  11. #endif
  12. #include "tier0/dbg.h"
  13. #include "tier1/utldict.h"
  14. #include "Cursor.h"
  15. #include "vguimatsurface.h"
  16. #include "filesystem.h"
  17. #if defined( PLATFORM_OSX )
  18. #include <Carbon/Carbon.h>
  19. #endif
  20. #include <appframework/ilaunchermgr.h>
  21. #if (USE_SDL)
  22. #include "SDL.h"
  23. #endif
  24. #if defined( DX_TO_GL_ABSTRACTION )
  25. #include "materialsystem/imaterialsystem.h"
  26. #endif
  27. #include "inputsystem/iinputsystem.h"
  28. #include "inputsystem/iinputstacksystem.h"
  29. // memdbgon must be the last include file in a .cpp file!!!
  30. #include "tier0/memdbgon.h"
  31. using namespace vgui;
  32. #if defined( USE_SDL )
  33. static SDL_Cursor *s_pDefaultCursor[ dc_last ];
  34. static SDL_Cursor *s_hCurrentCursor = NULL;
  35. static SDL_Cursor *s_hCurrentlySetCursor = NULL;
  36. #elif defined( WIN32 )
  37. static InputCursorHandle_t s_pDefaultCursor[20];
  38. static InputCursorHandle_t s_hCurrentCursor = NULL;
  39. #endif
  40. static bool s_bCursorLocked = false;
  41. static bool s_bCursorVisible = true;
  42. //-----------------------------------------------------------------------------
  43. // Initializes cursors
  44. //-----------------------------------------------------------------------------
  45. void InitCursors()
  46. {
  47. // load up all default cursors
  48. #if defined( USE_SDL )
  49. s_pDefaultCursor[ dc_none ] = NULL;
  50. s_pDefaultCursor[ dc_arrow ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_ARROW );
  51. s_pDefaultCursor[ dc_ibeam ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_IBEAM );
  52. s_pDefaultCursor[ dc_hourglass ]= SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_WAIT );
  53. s_pDefaultCursor[ dc_crosshair ]= SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_CROSSHAIR );
  54. s_pDefaultCursor[ dc_waitarrow ]= SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_WAITARROW );
  55. s_pDefaultCursor[ dc_sizenwse ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_SIZENWSE );
  56. s_pDefaultCursor[ dc_sizenesw ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_SIZENESW );
  57. s_pDefaultCursor[ dc_sizewe ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_SIZEWE );
  58. s_pDefaultCursor[ dc_sizens ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_SIZENS );
  59. s_pDefaultCursor[ dc_sizeall ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_SIZEALL );
  60. s_pDefaultCursor[ dc_no ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_NO );
  61. s_pDefaultCursor[ dc_hand ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_HAND );
  62. s_hCurrentCursor = s_pDefaultCursor[ dc_arrow ];
  63. #elif defined( WIN32 )
  64. s_pDefaultCursor[dc_none] = INPUT_CURSOR_HANDLE_INVALID;
  65. s_pDefaultCursor[dc_arrow] = g_pInputSystem->GetStandardCursor( INPUT_CURSOR_ARROW );
  66. s_pDefaultCursor[dc_ibeam] = g_pInputSystem->GetStandardCursor( INPUT_CURSOR_IBEAM );
  67. s_pDefaultCursor[dc_hourglass]= g_pInputSystem->GetStandardCursor( INPUT_CURSOR_HOURGLASS );
  68. s_pDefaultCursor[dc_crosshair]= g_pInputSystem->GetStandardCursor( INPUT_CURSOR_CROSSHAIR );
  69. s_pDefaultCursor[dc_waitarrow]= g_pInputSystem->GetStandardCursor( INPUT_CURSOR_WAITARROW );
  70. s_pDefaultCursor[dc_up] = g_pInputSystem->GetStandardCursor( INPUT_CURSOR_UP );
  71. s_pDefaultCursor[dc_sizenwse] = g_pInputSystem->GetStandardCursor( INPUT_CURSOR_SIZE_NW_SE );
  72. s_pDefaultCursor[dc_sizenesw] = g_pInputSystem->GetStandardCursor( INPUT_CURSOR_SIZE_NE_SW );
  73. s_pDefaultCursor[dc_sizewe] = g_pInputSystem->GetStandardCursor( INPUT_CURSOR_SIZE_W_E );
  74. s_pDefaultCursor[dc_sizens] = g_pInputSystem->GetStandardCursor( INPUT_CURSOR_SIZE_N_S );
  75. s_pDefaultCursor[dc_sizeall] = g_pInputSystem->GetStandardCursor( INPUT_CURSOR_SIZE_ALL );
  76. s_pDefaultCursor[dc_no] = g_pInputSystem->GetStandardCursor( INPUT_CURSOR_NO );
  77. s_pDefaultCursor[dc_hand] = g_pInputSystem->GetStandardCursor( INPUT_CURSOR_HAND );
  78. s_hCurrentCursor = s_pDefaultCursor[dc_arrow];
  79. #endif
  80. s_bCursorLocked = false;
  81. s_bCursorVisible = true;
  82. }
  83. #define USER_CURSOR_MASK 0x80000000
  84. #ifdef WIN32
  85. //-----------------------------------------------------------------------------
  86. // Purpose: Simple manager for user loaded windows cursors in vgui
  87. //-----------------------------------------------------------------------------
  88. class CUserCursorManager
  89. {
  90. public:
  91. void Shutdown();
  92. vgui::HCursor CreateCursorFromFile( char const *curOrAniFile, char const *pPathID );
  93. bool LookupCursor( vgui::HCursor cursor, InputCursorHandle_t& handle );
  94. private:
  95. CUtlDict< InputCursorHandle_t, int > m_UserCursors;
  96. };
  97. void CUserCursorManager::Shutdown()
  98. {
  99. m_UserCursors.RemoveAll();
  100. }
  101. vgui::HCursor CUserCursorManager::CreateCursorFromFile( char const *curOrAniFile, char const *pPathID )
  102. {
  103. char fn[ 512 ];
  104. Q_strncpy( fn, curOrAniFile, sizeof( fn ) );
  105. Q_strlower( fn );
  106. Q_FixSlashes( fn );
  107. int cursorIndex = m_UserCursors.Find( fn );
  108. if ( cursorIndex != m_UserCursors.InvalidIndex() )
  109. {
  110. return cursorIndex | USER_CURSOR_MASK;
  111. }
  112. InputCursorHandle_t newCursor = g_pInputSystem->LoadCursorFromFile( fn, pPathID );
  113. cursorIndex = m_UserCursors.Insert( fn, newCursor );
  114. return cursorIndex | USER_CURSOR_MASK;
  115. }
  116. bool CUserCursorManager::LookupCursor( vgui::HCursor cursor, InputCursorHandle_t& handle )
  117. {
  118. if ( !( (int)cursor & USER_CURSOR_MASK ) )
  119. {
  120. handle = 0;
  121. return false;
  122. }
  123. int cursorIndex = (int)cursor & ~USER_CURSOR_MASK;
  124. if ( !m_UserCursors.IsValidIndex( cursorIndex ) )
  125. {
  126. handle = 0;
  127. return false;
  128. }
  129. handle = m_UserCursors[ cursorIndex ];
  130. return true;
  131. }
  132. static CUserCursorManager g_UserCursors;
  133. #endif
  134. vgui::HCursor Cursor_CreateCursorFromFile( char const *curOrAniFile, char const *pPathID )
  135. {
  136. #ifdef WIN32
  137. return g_UserCursors.CreateCursorFromFile( curOrAniFile, pPathID );
  138. #else
  139. return dc_user;
  140. #endif
  141. }
  142. void Cursor_ClearUserCursors()
  143. {
  144. }
  145. #ifdef OSX
  146. static HCursor s_hCursor = dc_arrow;
  147. #if defined( PLATFORM_64BITS )
  148. // MCCLEANUP
  149. OSStatus SetThemeCursor(ThemeCursor inCursor)
  150. {
  151. return OSStatus(0);
  152. }
  153. #endif
  154. #endif
  155. //-----------------------------------------------------------------------------
  156. // Selects a cursor
  157. //-----------------------------------------------------------------------------
  158. void CursorSelect( InputContextHandle_t hContext, HCursor hCursor )
  159. {
  160. if ( s_bCursorLocked )
  161. return;
  162. static ConVarRef cv_vguipanel_active( "vgui_panel_active" );
  163. #if defined( USE_SDL )
  164. switch (hCursor)
  165. {
  166. case dc_user:
  167. case dc_none:
  168. case dc_blank:
  169. // Make sure we have the latest blank cursor handle.
  170. // s_pDefaultCursor[dc_none] = (Cursor) g_pLauncherMgr->GetBlankCursor();
  171. s_bCursorVisible = false;
  172. break;
  173. case dc_arrow:
  174. case dc_waitarrow:
  175. case dc_ibeam:
  176. case dc_hourglass:
  177. case dc_crosshair:
  178. case dc_up:
  179. case dc_sizenwse:
  180. case dc_sizenesw:
  181. case dc_sizewe:
  182. case dc_sizens:
  183. case dc_sizeall:
  184. case dc_no:
  185. case dc_hand:
  186. s_bCursorVisible = true;
  187. s_hCurrentCursor = s_pDefaultCursor[hCursor];
  188. break;
  189. default:
  190. s_bCursorVisible = false; // we don't support custom cursors at the moment (but could, if necessary).
  191. Assert(0);
  192. break;
  193. }
  194. ActivateCurrentCursor( hContext );
  195. #elif defined( WIN32 )
  196. // [jason] When the console window is raised, keep the cursor active even if the mouse focus is not on the console window.
  197. // This makes it easier track where the cursor is on-screen when the user moves off of the console.
  198. if ( cv_vguipanel_active.GetBool() == true && hCursor == dc_none )
  199. {
  200. hCursor = dc_arrow;
  201. }
  202. s_bCursorVisible = true;
  203. switch ( hCursor )
  204. {
  205. case dc_user:
  206. case dc_none:
  207. case dc_blank:
  208. s_bCursorVisible = false;
  209. break;
  210. case dc_arrow:
  211. case dc_waitarrow:
  212. case dc_ibeam:
  213. case dc_hourglass:
  214. case dc_crosshair:
  215. case dc_up:
  216. case dc_sizenwse:
  217. case dc_sizenesw:
  218. case dc_sizewe:
  219. case dc_sizens:
  220. case dc_sizeall:
  221. case dc_no:
  222. case dc_hand:
  223. s_hCurrentCursor = s_pDefaultCursor[hCursor];
  224. break;
  225. default:
  226. {
  227. InputCursorHandle_t custom = 0;
  228. #ifdef WIN32
  229. if ( g_UserCursors.LookupCursor( hCursor, custom ) && custom != 0 )
  230. {
  231. s_hCurrentCursor = custom;
  232. }
  233. else
  234. #endif // WIN32
  235. {
  236. s_bCursorVisible = false;
  237. Assert(0);
  238. }
  239. }
  240. break;
  241. }
  242. ActivateCurrentCursor( hContext );
  243. g_pInputSystem->SetMouseCursorVisible( s_bCursorVisible );
  244. #elif defined( PLATFORM_OSX )
  245. // @wge: Copied from window's section above
  246. // [jason] When the console window is raised, keep the cursor active even if the mouse focus is not on the console window.
  247. // This makes it easier track where the cursor is on-screen when the user moves off of the console.
  248. if ( cv_vguipanel_active.GetBool() == true && hCursor == dc_none )
  249. {
  250. if (!CommandLine()->FindParm("-keepmousehooked"))
  251. {
  252. CGAssociateMouseAndMouseCursorPosition( false );
  253. if ( CGCursorIsVisible() )
  254. {
  255. CGDisplayHideCursor(kCGDirectMainDisplay);
  256. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  257. int rx, ry, width, height;
  258. pRenderContext->GetViewport( rx, ry, width, height );
  259. CursorSetPos( NULL, width/2, height/2 ); // we are hiding the cursor so move it to the middle of our window
  260. }
  261. }
  262. s_bCursorVisible = false;
  263. }
  264. else
  265. {
  266. if (!CommandLine()->FindParm("-keepmousehooked"))
  267. {
  268. CGAssociateMouseAndMouseCursorPosition( true );
  269. if ( !CGCursorIsVisible() )
  270. {
  271. CGDisplayShowCursor(kCGDirectMainDisplay);
  272. }
  273. }
  274. s_bCursorVisible = true;
  275. }
  276. s_hCursor = hCursor;
  277. s_bCursorVisible = true;
  278. switch (hCursor)
  279. {
  280. case dc_none:
  281. case dc_user:
  282. case dc_blank:
  283. s_bCursorVisible = false;
  284. break;
  285. case dc_arrow:
  286. SetThemeCursor( kThemeArrowCursor );
  287. break;
  288. case dc_ibeam:
  289. SetThemeCursor( kThemeIBeamCursor );
  290. break;
  291. case dc_hourglass:
  292. SetThemeCursor( kThemeSpinningCursor );
  293. break;
  294. case dc_waitarrow:
  295. SetThemeCursor( kThemeSpinningCursor );
  296. break;
  297. case dc_crosshair:
  298. SetThemeCursor( kThemeCrossCursor );
  299. break;
  300. case dc_up:
  301. SetThemeCursor( kThemeResizeUpCursor );
  302. break;
  303. case dc_sizenwse:
  304. SetThemeCursor( kThemeCountingUpAndDownHandCursor );
  305. break;
  306. case dc_sizenesw:
  307. SetThemeCursor( kThemeResizeUpDownCursor );
  308. break;
  309. case dc_sizewe:
  310. SetThemeCursor( kThemeResizeLeftRightCursor );
  311. break;
  312. case dc_sizens:
  313. SetThemeCursor( kThemeResizeUpDownCursor );
  314. break;
  315. case dc_sizeall:
  316. SetThemeCursor( kThemeContextualMenuArrowCursor );
  317. break;
  318. case dc_no:
  319. SetThemeCursor( kThemeNotAllowedCursor );
  320. break;
  321. case dc_hand:
  322. SetThemeCursor( kThemePointingHandCursor );
  323. break;
  324. };
  325. g_pInputSystem->SetMouseCursorVisible( s_bCursorVisible );
  326. #elif defined( _PS3 )
  327. #elif defined( LINUX )
  328. #error
  329. #else
  330. #error
  331. #endif
  332. }
  333. //-----------------------------------------------------------------------------
  334. // Activates the current cursor
  335. //-----------------------------------------------------------------------------
  336. void ActivateCurrentCursor( InputContextHandle_t hContext )
  337. {
  338. if (s_bCursorVisible)
  339. {
  340. #if defined( USE_SDL )
  341. if (s_hCurrentlySetCursor != s_hCurrentCursor)
  342. {
  343. s_hCurrentlySetCursor = s_hCurrentCursor;
  344. g_pLauncherMgr->SetMouseCursor( s_hCurrentlySetCursor );
  345. g_pLauncherMgr->SetMouseVisible( true );
  346. }
  347. #elif defined( WIN32 )
  348. g_pInputStackSystem->SetCursorIcon( hContext, s_hCurrentCursor );
  349. #elif defined( OSX )
  350. if ( !CGCursorIsVisible() && !CommandLine()->FindParm("-keepmousehooked") )
  351. {
  352. CGDisplayShowCursor(kCGDirectMainDisplay);
  353. }
  354. #else
  355. #error
  356. #endif
  357. }
  358. else
  359. {
  360. #if defined( USE_SDL )
  361. if (s_hCurrentlySetCursor != s_pDefaultCursor[dc_none])
  362. {
  363. s_hCurrentlySetCursor = s_pDefaultCursor[dc_none];
  364. g_pLauncherMgr->SetMouseCursor( s_hCurrentlySetCursor );
  365. g_pLauncherMgr->SetMouseVisible( false );
  366. }
  367. #elif defined( WIN32 )
  368. g_pInputStackSystem->SetCursorIcon( hContext, INPUT_CURSOR_HANDLE_INVALID );
  369. #elif defined( OSX )
  370. if ( CGCursorIsVisible() && !CommandLine()->FindParm("-keepmousehooked") )
  371. {
  372. CGDisplayHideCursor(kCGDirectMainDisplay);
  373. }
  374. #else
  375. #error
  376. #endif
  377. }
  378. }
  379. //-----------------------------------------------------------------------------
  380. // Purpose: prevents vgui from changing the cursor
  381. //-----------------------------------------------------------------------------
  382. void LockCursor( InputContextHandle_t hContext, bool bEnable )
  383. {
  384. s_bCursorLocked = bEnable;
  385. ActivateCurrentCursor( hContext );
  386. }
  387. //-----------------------------------------------------------------------------
  388. // Purpose: unlocks the cursor state
  389. //-----------------------------------------------------------------------------
  390. bool IsCursorLocked()
  391. {
  392. return s_bCursorLocked;
  393. }
  394. //-----------------------------------------------------------------------------
  395. // handles mouse movement
  396. //-----------------------------------------------------------------------------
  397. void CursorSetPos( InputContextHandle_t hContext, int x, int y )
  398. {
  399. Assert( hContext != INPUT_CONTEXT_HANDLE_INVALID );
  400. #if defined( DX_TO_GL_ABSTRACTION )
  401. if ( s_bCursorVisible )
  402. #endif
  403. g_pInputStackSystem->SetCursorPosition( hContext, x, y );
  404. }
  405. void CursorGetPos( InputContextHandle_t hContext, int &x, int &y )
  406. {
  407. // Should I add GetCursorPosition to InputStackSystem?
  408. Assert( hContext != INPUT_CONTEXT_HANDLE_INVALID );
  409. g_pInputSystem->GetCursorPosition( &x, &y );
  410. }
  411. #ifdef OSX
  412. void CursorRunFrame()
  413. {
  414. static HCursor hCursorLast = dc_none;
  415. if ( hCursorLast == s_hCursor )
  416. return;
  417. hCursorLast = s_hCursor;
  418. if ( s_hCursor == dc_none || s_hCursor == dc_user || s_hCursor == dc_blank )
  419. {
  420. if (!CommandLine()->FindParm("-keepmousehooked"))
  421. {
  422. // @wge Removed. After this is called, all mouse coordinates will be locked (returning only delta). We need coordinates for Scaleform.
  423. //CGAssociateMouseAndMouseCursorPosition( false );
  424. if ( CGCursorIsVisible() )
  425. CGDisplayHideCursor(kCGDirectMainDisplay);
  426. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  427. int rx, ry, width, height;
  428. pRenderContext->GetViewport( rx, ry, width, height );
  429. // we are hiding the cursor so move it to the middle of our window
  430. g_pInputSystem->SetCursorPosition( width/2, height/2 );
  431. }
  432. s_bCursorVisible = false;
  433. }
  434. else
  435. {
  436. if (!CommandLine()->FindParm("-keepmousehooked"))
  437. {
  438. // @wge Removed, see above comment.
  439. //CGAssociateMouseAndMouseCursorPosition( true );
  440. if ( !CGCursorIsVisible() )
  441. {
  442. CGDisplayShowCursor( kCGDirectMainDisplay );
  443. }
  444. }
  445. s_bCursorVisible = true;
  446. }
  447. }
  448. #endif