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.

2719 lines
79 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #if !defined( _GAMECONSOLE )
  8. #include <windows.h>
  9. #include <imm.h>
  10. #endif
  11. #include <string.h>
  12. #include "inputgameui.h"
  13. #include "tier0/icommandline.h"
  14. #include "gameuisystemmgr.h"
  15. #include "inputsystem/analogcode.h"
  16. #include "inputsystem/iinputstacksystem.h"
  17. #if defined( _GAMECONSOLE )
  18. #include "xbox/xbox_win32stubs.h"
  19. #endif
  20. // memdbgon must be the last include file in a .cpp file!!!
  21. #include "tier0/memdbgon.h"
  22. SHORT System_GetKeyState( int virtualKeyCode ); // in System.cpp, a hack to only have g_pVCR in system.cpp
  23. CInputGameUI g_InputGameUI;
  24. CInputGameUI *g_pInputGameUI = &g_InputGameUI;
  25. //-----------------------------------------------------------------------------
  26. // Construct, destruct
  27. //-----------------------------------------------------------------------------
  28. CInputGameUI::CInputGameUI()
  29. {
  30. m_nDebugMessages = -1;
  31. #ifndef _GAMECONSOLE
  32. _imeWnd = 0;
  33. _imeCandidates = 0;
  34. #endif
  35. InitInputContext( &m_DefaultInputContext );
  36. m_hContext = DEFAULT_INPUT_CONTEXT;
  37. m_nWindowWidth = 0;
  38. m_nWindowHeight = 0;
  39. // build key to text translation table
  40. // first byte unshifted key
  41. // second byte shifted key
  42. // the rest is the name of the key
  43. _keyTrans[KEY_0] ="0)KEY_0";
  44. _keyTrans[KEY_1] ="1!KEY_1";
  45. _keyTrans[KEY_2] ="2@KEY_2";
  46. _keyTrans[KEY_3] ="3#KEY_3";
  47. _keyTrans[KEY_4] ="4$KEY_4";
  48. _keyTrans[KEY_5] ="5%KEY_5";
  49. _keyTrans[KEY_6] ="6^KEY_6";
  50. _keyTrans[KEY_7] ="7&KEY_7";
  51. _keyTrans[KEY_8] ="8*KEY_8";
  52. _keyTrans[KEY_9] ="9(KEY_9";
  53. _keyTrans[KEY_A] ="aAKEY_A";
  54. _keyTrans[KEY_B] ="bBKEY_B";
  55. _keyTrans[KEY_C] ="cCKEY_C";
  56. _keyTrans[KEY_D] ="dDKEY_D";
  57. _keyTrans[KEY_E] ="eEKEY_E";
  58. _keyTrans[KEY_F] ="fFKEY_F";
  59. _keyTrans[KEY_G] ="gGKEY_G";
  60. _keyTrans[KEY_H] ="hHKEY_H";
  61. _keyTrans[KEY_I] ="iIKEY_I";
  62. _keyTrans[KEY_J] ="jJKEY_J";
  63. _keyTrans[KEY_K] ="kKKEY_K";
  64. _keyTrans[KEY_L] ="lLKEY_L"", L";
  65. _keyTrans[KEY_M] ="mMKEY_M";
  66. _keyTrans[KEY_N] ="nNKEY_N";
  67. _keyTrans[KEY_O] ="oOKEY_O";
  68. _keyTrans[KEY_P] ="pPKEY_P";
  69. _keyTrans[KEY_Q] ="qQKEY_Q";
  70. _keyTrans[KEY_R] ="rRKEY_R";
  71. _keyTrans[KEY_S] ="sSKEY_S";
  72. _keyTrans[KEY_T] ="tTKEY_T";
  73. _keyTrans[KEY_U] ="uUKEY_U";
  74. _keyTrans[KEY_V] ="vVKEY_V";
  75. _keyTrans[KEY_W] ="wWKEY_W";
  76. _keyTrans[KEY_X] ="xXKEY_X";
  77. _keyTrans[KEY_Y] ="yYKEY_Y";
  78. _keyTrans[KEY_Z] ="zZKEY_Z";
  79. _keyTrans[KEY_PAD_0] ="0\0KEY_PAD_0";
  80. _keyTrans[KEY_PAD_1] ="1\0KEY_PAD_1";
  81. _keyTrans[KEY_PAD_2] ="2\0KEY_PAD_2";
  82. _keyTrans[KEY_PAD_3] ="3\0KEY_PAD_3";
  83. _keyTrans[KEY_PAD_4] ="4\0KEY_PAD_4";
  84. _keyTrans[KEY_PAD_5] ="5\0KEY_PAD_5";
  85. _keyTrans[KEY_PAD_6] ="6\0KEY_PAD_6";
  86. _keyTrans[KEY_PAD_7] ="7\0KEY_PAD_7";
  87. _keyTrans[KEY_PAD_8] ="8\0KEY_PAD_8";
  88. _keyTrans[KEY_PAD_9] ="9\0KEY_PAD_9";
  89. _keyTrans[KEY_PAD_DIVIDE] ="//KEY_PAD_DIVIDE";
  90. _keyTrans[KEY_PAD_MULTIPLY] ="**KEY_PAD_MULTIPLY";
  91. _keyTrans[KEY_PAD_MINUS] ="--KEY_PAD_MINUS";
  92. _keyTrans[KEY_PAD_PLUS] ="++KEY_PAD_PLUS";
  93. _keyTrans[KEY_PAD_ENTER] ="\0\0KEY_PAD_ENTER";
  94. _keyTrans[KEY_PAD_DECIMAL] =".\0KEY_PAD_DECIMAL"", L";
  95. _keyTrans[KEY_LBRACKET] ="[{KEY_LBRACKET";
  96. _keyTrans[KEY_RBRACKET] ="]}KEY_RBRACKET";
  97. _keyTrans[KEY_SEMICOLON] =";:KEY_SEMICOLON";
  98. _keyTrans[KEY_APOSTROPHE] ="'\"KEY_APOSTROPHE";
  99. _keyTrans[KEY_BACKQUOTE] ="`~KEY_BACKQUOTE";
  100. _keyTrans[KEY_COMMA] =",<KEY_COMMA";
  101. _keyTrans[KEY_PERIOD] =".>KEY_PERIOD";
  102. _keyTrans[KEY_SLASH] ="/?KEY_SLASH";
  103. _keyTrans[KEY_BACKSLASH] ="\\|KEY_BACKSLASH";
  104. _keyTrans[KEY_MINUS] ="-_KEY_MINUS";
  105. _keyTrans[KEY_EQUAL] ="=+KEY_EQUAL"", L";
  106. _keyTrans[KEY_ENTER] ="\0\0KEY_ENTER";
  107. _keyTrans[KEY_SPACE] =" KEY_SPACE";
  108. _keyTrans[KEY_BACKSPACE] ="\0\0KEY_BACKSPACE";
  109. _keyTrans[KEY_TAB] ="\0\0KEY_TAB";
  110. _keyTrans[KEY_CAPSLOCK] ="\0\0KEY_CAPSLOCK";
  111. _keyTrans[KEY_NUMLOCK] ="\0\0KEY_NUMLOCK";
  112. _keyTrans[KEY_ESCAPE] ="\0\0KEY_ESCAPE";
  113. _keyTrans[KEY_SCROLLLOCK] ="\0\0KEY_SCROLLLOCK";
  114. _keyTrans[KEY_INSERT] ="\0\0KEY_INSERT";
  115. _keyTrans[KEY_DELETE] ="\0\0KEY_DELETE";
  116. _keyTrans[KEY_HOME] ="\0\0KEY_HOME";
  117. _keyTrans[KEY_END] ="\0\0KEY_END";
  118. _keyTrans[KEY_PAGEUP] ="\0\0KEY_PAGEUP";
  119. _keyTrans[KEY_PAGEDOWN] ="\0\0KEY_PAGEDOWN";
  120. _keyTrans[KEY_BREAK] ="\0\0KEY_BREAK";
  121. _keyTrans[KEY_LSHIFT] ="\0\0KEY_LSHIFT";
  122. _keyTrans[KEY_RSHIFT] ="\0\0KEY_RSHIFT";
  123. _keyTrans[KEY_LALT] ="\0\0KEY_LALT";
  124. _keyTrans[KEY_RALT] ="\0\0KEY_RALT";
  125. _keyTrans[KEY_LCONTROL] ="\0\0KEY_LCONTROL"", L";
  126. _keyTrans[KEY_RCONTROL] ="\0\0KEY_RCONTROL"", L";
  127. _keyTrans[KEY_LWIN] ="\0\0KEY_LWIN";
  128. _keyTrans[KEY_RWIN] ="\0\0KEY_RWIN";
  129. _keyTrans[KEY_APP] ="\0\0KEY_APP";
  130. _keyTrans[KEY_UP] ="\0\0KEY_UP";
  131. _keyTrans[KEY_LEFT] ="\0\0KEY_LEFT";
  132. _keyTrans[KEY_DOWN] ="\0\0KEY_DOWN";
  133. _keyTrans[KEY_RIGHT] ="\0\0KEY_RIGHT";
  134. _keyTrans[KEY_F1] ="\0\0KEY_F1";
  135. _keyTrans[KEY_F2] ="\0\0KEY_F2";
  136. _keyTrans[KEY_F3] ="\0\0KEY_F3";
  137. _keyTrans[KEY_F4] ="\0\0KEY_F4";
  138. _keyTrans[KEY_F5] ="\0\0KEY_F5";
  139. _keyTrans[KEY_F6] ="\0\0KEY_F6";
  140. _keyTrans[KEY_F7] ="\0\0KEY_F7";
  141. _keyTrans[KEY_F8] ="\0\0KEY_F8";
  142. _keyTrans[KEY_F9] ="\0\0KEY_F9";
  143. _keyTrans[KEY_F10] ="\0\0KEY_F10";
  144. _keyTrans[KEY_F11] ="\0\0KEY_F11";
  145. _keyTrans[KEY_F12] ="\0\0KEY_F12";
  146. }
  147. CInputGameUI::~CInputGameUI()
  148. {
  149. DestroyCandidateList();
  150. }
  151. //-----------------------------------------------------------------------------
  152. // Init, shutdown
  153. //-----------------------------------------------------------------------------
  154. void CInputGameUI::Init()
  155. {
  156. m_hEventChannel = g_pEventSystem->CreateEventQueue();
  157. CursorEnterEvent::RegisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnCursorEnter );
  158. CursorExitEvent::RegisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnCursorExit );
  159. CursorMoveEvent::RegisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnCursorMove );
  160. InternalCursorMoveEvent::RegisterMemberFunc( m_hEventChannel, this, &CInputGameUI::UpdateCursorPosInternal );
  161. MouseDownEvent::RegisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnMouseDown );
  162. MouseUpEvent::RegisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnMouseUp );
  163. MouseDoubleClickEvent::RegisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnMouseDoubleClick );
  164. MouseWheelEvent::RegisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnMouseWheel );
  165. KeyDownEvent::RegisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnKeyDown );
  166. KeyUpEvent::RegisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnKeyUp );
  167. KeyCodeTypedEvent::RegisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnKeyCodeTyped );
  168. KeyTypedEvent::RegisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnKeyTyped );
  169. LoseKeyFocusEvent::RegisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnLoseKeyFocus );
  170. GainKeyFocusEvent::RegisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnGainKeyFocus );
  171. }
  172. void CInputGameUI::Shutdown()
  173. {
  174. CursorEnterEvent::UnregisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnCursorEnter );
  175. CursorExitEvent::UnregisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnCursorExit );
  176. CursorMoveEvent::UnregisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnCursorMove );
  177. InternalCursorMoveEvent::UnregisterMemberFunc( m_hEventChannel, this, &CInputGameUI::UpdateCursorPosInternal );
  178. MouseDownEvent::UnregisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnMouseDown );
  179. MouseUpEvent::UnregisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnMouseUp );
  180. MouseDoubleClickEvent::UnregisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnMouseDoubleClick );
  181. MouseWheelEvent::UnregisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnMouseWheel );
  182. KeyDownEvent::UnregisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnKeyDown );
  183. KeyUpEvent::UnregisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnKeyUp );
  184. KeyCodeTypedEvent::UnregisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnKeyCodeTyped );
  185. KeyTypedEvent::UnregisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnKeyTyped );
  186. LoseKeyFocusEvent::UnregisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnLoseKeyFocus );
  187. GainKeyFocusEvent::UnregisterMemberFunc( m_hEventChannel, this, &CInputGameUI::OnGainKeyFocus );
  188. g_pEventSystem->DestroyEventQueue( m_hEventChannel );
  189. }
  190. //-----------------------------------------------------------------------------
  191. // Resets an input context
  192. //-----------------------------------------------------------------------------
  193. void CInputGameUI::InitInputContext( InputContext_t *pContext )
  194. {
  195. pContext->_keyFocus = NULL;
  196. pContext->_bKeyTrap = false;
  197. pContext->_oldMouseFocus = NULL;
  198. pContext->_mouseFocus = NULL;
  199. pContext->_mouseOver = NULL;
  200. pContext->_mouseCapture = NULL;
  201. pContext->_mouseLeftTrap = NULL;
  202. pContext->_mouseMiddleTrap = NULL;
  203. pContext->_mouseRightTrap = NULL;
  204. pContext->m_nCursorX = pContext->m_nCursorY = 0;
  205. pContext->m_nLastPostedCursorX = pContext->m_nLastPostedCursorY = -9999;
  206. pContext->m_nExternallySetCursorX = pContext->m_nExternallySetCursorY = 0;
  207. pContext->m_bSetCursorExplicitly = false;
  208. // zero mouse and keys
  209. memset(pContext->_mousePressed, 0, sizeof(pContext->_mousePressed));
  210. memset(pContext->_mouseDoublePressed, 0, sizeof(pContext->_mouseDoublePressed));
  211. memset(pContext->_mouseDown, 0, sizeof(pContext->_mouseDown));
  212. memset(pContext->_mouseReleased, 0, sizeof(pContext->_mouseReleased));
  213. memset(pContext->_keyPressed, 0, sizeof(pContext->_keyPressed));
  214. memset(pContext->_keyTyped, 0, sizeof(pContext->_keyTyped));
  215. memset(pContext->_keyDown, 0, sizeof(pContext->_keyDown));
  216. memset(pContext->_keyReleased, 0, sizeof(pContext->_keyReleased));
  217. pContext->m_MouseCaptureStartCode = (ButtonCode_t)-1;
  218. pContext->m_KeyCodeUnhandledListeners.RemoveAll();
  219. pContext->m_pUnhandledMouseClickListener = NULL;
  220. pContext->m_bRestrictMessagesToModalSubTree = false;
  221. }
  222. void CInputGameUI::ResetInputContext( vgui::HInputContext context )
  223. {
  224. // FIXME: Needs to release various keys, mouse buttons, etc...?
  225. // At least needs to cause things to lose focus
  226. InitInputContext( GetInputContext(context) );
  227. }
  228. //-----------------------------------------------------------------------------
  229. // Creates/ destroys "input" contexts, which contains information
  230. // about which controls have mouse + key focus, for example.
  231. //-----------------------------------------------------------------------------
  232. vgui::HInputContext CInputGameUI::CreateInputContext()
  233. {
  234. vgui::HInputContext i = m_Contexts.AddToTail();
  235. InitInputContext( &m_Contexts[i] );
  236. return i;
  237. }
  238. void CInputGameUI::DestroyInputContext( vgui::HInputContext context )
  239. {
  240. Assert( context != DEFAULT_INPUT_CONTEXT );
  241. if ( m_hContext == context )
  242. {
  243. ActivateInputContext( DEFAULT_INPUT_CONTEXT );
  244. }
  245. m_Contexts.Remove(context);
  246. }
  247. //-----------------------------------------------------------------------------
  248. // Returns the current input context
  249. //-----------------------------------------------------------------------------
  250. CInputGameUI::InputContext_t *CInputGameUI::GetInputContext( vgui::HInputContext context )
  251. {
  252. if (context == DEFAULT_INPUT_CONTEXT)
  253. {
  254. return &m_DefaultInputContext;
  255. }
  256. return &m_Contexts[context];
  257. }
  258. //-----------------------------------------------------------------------------
  259. // Activates a particular input context, use DEFAULT_INPUT_CONTEXT
  260. // to get the one normally used by VGUI
  261. //-----------------------------------------------------------------------------
  262. void CInputGameUI::ActivateInputContext( vgui::HInputContext context )
  263. {
  264. Assert( (context == DEFAULT_INPUT_CONTEXT) || m_Contexts.IsValidIndex(context) );
  265. m_hContext = context;
  266. }
  267. //-----------------------------------------------------------------------------
  268. // Used to know the dimensions of the window on screen.
  269. // Very important when viewport is not the same as the window.
  270. //-----------------------------------------------------------------------------
  271. void CInputGameUI::SetWindowSize( int width, int height )
  272. {
  273. g_pGameUISystemMgrImpl->SetWindowSize( width, height );
  274. }
  275. //-----------------------------------------------------------------------------
  276. // Purpose:
  277. //-----------------------------------------------------------------------------
  278. void CInputGameUI::RunFrame()
  279. {
  280. if ( m_nDebugMessages == -1 )
  281. {
  282. m_nDebugMessages = CommandLine()->FindParm( "-debuggameui" ) ? 1 : 0;
  283. }
  284. InputContext_t *pContext = GetInputContext(m_hContext);
  285. //clear mouse and key states
  286. int i;
  287. for ( i = 0; i < MOUSE_COUNT; i++ )
  288. {
  289. pContext->_mousePressed[i] = 0;
  290. pContext->_mouseDoublePressed[i] = 0;
  291. pContext->_mouseReleased[i] = 0;
  292. }
  293. for ( i = 0; i < BUTTON_CODE_COUNT; i++ )
  294. {
  295. pContext->_keyPressed[i] = 0;
  296. pContext->_keyTyped[i] = 0;
  297. pContext->_keyReleased[i] = 0;
  298. }
  299. CHitArea *wantedKeyFocus = CalculateNewKeyFocus();
  300. // make sure old and new focus get painted
  301. if ( pContext->_keyFocus != wantedKeyFocus )
  302. {
  303. if ( pContext->_keyFocus != NULL )
  304. {
  305. LoseKeyFocusEvent::Post( pContext->_keyFocus );
  306. }
  307. if ( wantedKeyFocus != NULL )
  308. {
  309. GainKeyFocusEvent::Post( wantedKeyFocus );
  310. }
  311. // accept the focus request
  312. pContext->_keyFocus = wantedKeyFocus;
  313. pContext->_bKeyTrap = false;
  314. }
  315. // Pump any key repeats
  316. ButtonCode_t repeatCode = pContext->m_keyRepeater.KeyRepeated();
  317. if (repeatCode)
  318. {
  319. InternalKeyCodePressed( repeatCode );
  320. }
  321. }
  322. //-----------------------------------------------------------------------------
  323. //
  324. //-----------------------------------------------------------------------------
  325. void CInputGameUI::ProcessEvents()
  326. {
  327. g_pEventSystem->ProcessEvents( m_hEventChannel );
  328. }
  329. //-----------------------------------------------------------------------------
  330. // Purpose: Calculate the new key focus
  331. //-----------------------------------------------------------------------------
  332. CHitArea *CInputGameUI::CalculateNewKeyFocus()
  333. {
  334. // get the top-order panel
  335. CHitArea *wantedKeyFocus = NULL;
  336. // ask the gameui for what it would like to be the current focus
  337. wantedKeyFocus = g_pGameUISystemMgrImpl->GetRequestedKeyFocus();
  338. if ( wantedKeyFocus == NULL )
  339. {
  340. InputContext_t *pContext = GetInputContext(m_hContext);
  341. return pContext->_keyFocus;
  342. }
  343. else
  344. {
  345. Assert( wantedKeyFocus->IsHitArea() );
  346. return wantedKeyFocus;
  347. }
  348. }
  349. //-----------------------------------------------------------------------------
  350. // Purpose: Graphic's visibility was set to false.
  351. //-----------------------------------------------------------------------------
  352. void CInputGameUI::GraphicHidden( CHitArea *focus, InputContext_t &context )
  353. {
  354. if ( context._keyFocus == focus )
  355. {
  356. context._keyFocus = NULL;
  357. context._bKeyTrap = false;
  358. }
  359. if (context._mouseOver == focus )
  360. {
  361. /*
  362. if ( m_nDebugMessages > 0 )
  363. {
  364. g_pIVgui->DPrintf2( "removing kb focus %s\n",
  365. context._keyFocus ? pcontext._keyFocus->GetName() : "(no name)" );
  366. }
  367. */
  368. context._mouseOver = NULL;
  369. }
  370. if ( context._oldMouseFocus == focus )
  371. {
  372. context._oldMouseFocus = NULL;
  373. }
  374. if ( context._mouseFocus == focus )
  375. {
  376. context._mouseFocus = NULL;
  377. }
  378. if ( context._mouseLeftTrap == focus )
  379. {
  380. context._mouseLeftTrap = NULL;
  381. }
  382. if ( context._mouseMiddleTrap == focus )
  383. {
  384. context._mouseMiddleTrap = NULL;
  385. }
  386. if ( context._mouseRightTrap == focus )
  387. {
  388. context._mouseRightTrap = NULL;
  389. }
  390. // NOTE: These two will only ever happen for the default context at the moment
  391. if ( context._mouseCapture == focus )
  392. {
  393. SetMouseCapture(NULL);
  394. context._mouseCapture = NULL;
  395. }
  396. if ( context.m_pUnhandledMouseClickListener == focus )
  397. {
  398. context.m_pUnhandledMouseClickListener = NULL;
  399. }
  400. //context.m_KeyCodeUnhandledListeners.FindAndRemove( focus );
  401. }
  402. //-----------------------------------------------------------------------------
  403. // Purpose:
  404. // Input : *focus -
  405. //-----------------------------------------------------------------------------
  406. void CInputGameUI::GraphicHidden( CHitArea *focus )
  407. {
  408. HInputContext i;
  409. for ( i = m_Contexts.Head(); i != m_Contexts.InvalidIndex(); i = m_Contexts.Next(i) )
  410. {
  411. GraphicHidden( focus, m_Contexts[i] );
  412. }
  413. GraphicHidden( focus, m_DefaultInputContext );
  414. }
  415. //-----------------------------------------------------------------------------
  416. // Purpose: An Input Graphic's visibility was set to true. Force focus update to occur with no mouse movement.
  417. //-----------------------------------------------------------------------------
  418. void CInputGameUI::ForceInputFocusUpdate()
  419. {
  420. // Force the focus to get updated.
  421. HInputContext i;
  422. for ( i = m_Contexts.Head(); i != m_Contexts.InvalidIndex(); i = m_Contexts.Next(i) )
  423. {
  424. InputContext_t *pContext = &m_Contexts[i];
  425. UpdateMouseFocus( pContext->m_nCursorX, pContext->m_nCursorY );
  426. }
  427. UpdateMouseFocus( m_DefaultInputContext.m_nCursorX, m_DefaultInputContext.m_nCursorY );
  428. }
  429. //-----------------------------------------------------------------------------
  430. // Purpose:
  431. //-----------------------------------------------------------------------------
  432. void CInputGameUI::PanelDeleted( CHitArea *focus, InputContext_t &context )
  433. {
  434. if (context._keyFocus == focus)
  435. {
  436. context._keyFocus = NULL;
  437. context._bKeyTrap = false;
  438. }
  439. if (context._mouseOver == focus)
  440. {
  441. /*
  442. if ( m_nDebugMessages > 0 )
  443. {
  444. g_pIVgui->DPrintf2( "removing kb focus %s\n",
  445. context._keyFocus ? pcontext._keyFocus->GetName() : "(no name)" );
  446. }
  447. */
  448. context._mouseOver = NULL;
  449. }
  450. if ( context._oldMouseFocus == focus )
  451. {
  452. context._oldMouseFocus = NULL;
  453. }
  454. if ( context._mouseFocus == focus )
  455. {
  456. context._mouseFocus = NULL;
  457. }
  458. if ( context._mouseLeftTrap == focus )
  459. {
  460. context._mouseLeftTrap = NULL;
  461. }
  462. if ( context._mouseMiddleTrap == focus )
  463. {
  464. context._mouseMiddleTrap = NULL;
  465. }
  466. if ( context._mouseRightTrap == focus )
  467. {
  468. context._mouseRightTrap = NULL;
  469. }
  470. // NOTE: These two will only ever happen for the default context at the moment
  471. if ( context._mouseCapture == focus )
  472. {
  473. SetMouseCapture(NULL);
  474. context._mouseCapture = NULL;
  475. }
  476. if ( context.m_pUnhandledMouseClickListener == focus )
  477. {
  478. context.m_pUnhandledMouseClickListener = NULL;
  479. }
  480. context.m_KeyCodeUnhandledListeners.FindAndRemove( focus );
  481. }
  482. //-----------------------------------------------------------------------------
  483. // Purpose:
  484. // Input : *focus -
  485. //-----------------------------------------------------------------------------
  486. void CInputGameUI::PanelDeleted( CHitArea *focus )
  487. {
  488. HInputContext i;
  489. for ( i = m_Contexts.Head(); i != m_Contexts.InvalidIndex(); i = m_Contexts.Next(i) )
  490. {
  491. PanelDeleted( focus, m_Contexts[i] );
  492. }
  493. PanelDeleted( focus, m_DefaultInputContext );
  494. }
  495. //-----------------------------------------------------------------------------
  496. // Purpose: Sets the new mouse focus
  497. // won't override _mouseCapture settings
  498. // Input : newMouseFocus -
  499. //-----------------------------------------------------------------------------
  500. void CInputGameUI::SetMouseFocus( CHitArea *newMouseFocus )
  501. {
  502. InputContext_t *pContext = GetInputContext( m_hContext );
  503. if ( pContext->_mouseOver != newMouseFocus || ( !pContext->_mouseCapture && pContext->_mouseFocus != newMouseFocus ) )
  504. {
  505. pContext->_oldMouseFocus = pContext->_mouseOver;
  506. pContext->_mouseOver = newMouseFocus;
  507. //tell the old panel with the mouseFocus that the cursor exited
  508. if ( pContext->_oldMouseFocus != NULL )
  509. {
  510. // only notify of entry if the mouse is not captured or we're the captured panel
  511. if ( !pContext->_mouseCapture || pContext->_oldMouseFocus == pContext->_mouseCapture )
  512. {
  513. CursorExitEvent::Post( pContext->_oldMouseFocus );
  514. }
  515. }
  516. //tell the new panel with the mouseFocus that the cursor entered
  517. if ( pContext->_mouseOver != NULL )
  518. {
  519. // only notify of entry if the mouse is not captured or we're the captured panel
  520. if ( !pContext->_mouseCapture || pContext->_mouseOver == pContext->_mouseCapture )
  521. {
  522. CursorEnterEvent::Post( pContext->_mouseOver );
  523. }
  524. }
  525. // set where the mouse is currently over
  526. // mouse capture overrides destination
  527. pContext->_mouseFocus = pContext->_mouseCapture ? pContext->_mouseCapture : pContext->_mouseOver;
  528. }
  529. }
  530. //-----------------------------------------------------------------------------
  531. // Purpose: Calculates which panel the cursor is currently over and sets it up
  532. // as the current mouse focus.
  533. //-----------------------------------------------------------------------------
  534. void CInputGameUI::UpdateMouseFocus( int x, int y )
  535. {
  536. //InputContext_t *pContext = GetInputContext( m_hContext );
  537. CHitArea *pFocus = NULL;
  538. //if ( g_pSurface->IsCursorVisible() && g_pSurface->IsWithin(x, y) )
  539. {
  540. if (!pFocus)
  541. {
  542. // find the panel that has the focus
  543. pFocus = g_pGameUISystemMgrImpl->GetMouseFocus( x, y );
  544. }
  545. }
  546. SetMouseFocus( pFocus );
  547. }
  548. //-----------------------------------------------------------------------------
  549. // Passes in a keycode which allows hitting other mouse buttons w/o cancelling capture mode
  550. //-----------------------------------------------------------------------------
  551. void CInputGameUI::SetMouseCaptureEx( CHitArea *panel, ButtonCode_t captureStartMouseCode )
  552. {
  553. // This sets m_MouseCaptureStartCode to -1, so we set the real value afterward
  554. SetMouseCapture( panel );
  555. InputContext_t *pContext = GetInputContext( m_hContext );
  556. Assert( pContext );
  557. pContext->m_MouseCaptureStartCode = captureStartMouseCode;
  558. }
  559. //-----------------------------------------------------------------------------
  560. // Passes in a keycode which allows hitting other mouse buttons w/o canceling capture mode
  561. // Purpose: Sets or releases the mouse capture
  562. // Input : panel - pointer to the panel to get mouse capture
  563. // a NULL panel means that you want to clear the mouseCapture
  564. //-----------------------------------------------------------------------------
  565. void CInputGameUI::SetMouseCapture( CHitArea *panel )
  566. {
  567. InputContext_t *pContext = GetInputContext( m_hContext );
  568. Assert( pContext );
  569. pContext->m_MouseCaptureStartCode = (ButtonCode_t)-1;
  570. pContext->_mouseCapture = panel;
  571. }
  572. CHitArea *CInputGameUI::GetMouseCapture()
  573. {
  574. InputContext_t *pContext = GetInputContext( m_hContext );
  575. return (CHitArea *)pContext->_mouseCapture;
  576. }
  577. void SetKeyFocus( CHitArea *pFocus ); // note this will not post any messages.
  578. //-----------------------------------------------------------------------------
  579. // Purpose: Used to set keyfocus to mousefocus when they are linked together.
  580. //
  581. // This will not post any messages. If it did anims would get played twice,
  582. // once for mouse focus gained/lost, once for key focus gained/lost
  583. //-----------------------------------------------------------------------------
  584. void CInputGameUI::SetKeyFocus( CHitArea *pFocus)
  585. {
  586. GetInputContext( m_hContext )->_keyFocus = pFocus;
  587. }
  588. //-----------------------------------------------------------------------------
  589. // Purpose:
  590. //-----------------------------------------------------------------------------
  591. CHitArea *CInputGameUI::GetKeyFocus()
  592. {
  593. return (CHitArea *)( GetInputContext( m_hContext )->_keyFocus );
  594. }
  595. //-----------------------------------------------------------------------------
  596. // Purpose:
  597. //-----------------------------------------------------------------------------
  598. CHitArea *CInputGameUI::GetCalculatedKeyFocus()
  599. {
  600. return (CHitArea *) CalculateNewKeyFocus();
  601. }
  602. //-----------------------------------------------------------------------------
  603. // Purpose:
  604. //-----------------------------------------------------------------------------
  605. CHitArea * CInputGameUI::GetMouseOver()
  606. {
  607. return (CHitArea *)( GetInputContext( m_hContext )->_mouseOver );
  608. }
  609. CHitArea * CInputGameUI::GetMouseFocus()
  610. {
  611. return (CHitArea *)( GetInputContext( m_hContext )->_mouseFocus );
  612. }
  613. bool CInputGameUI::WasMousePressed( ButtonCode_t code )
  614. {
  615. return GetInputContext( m_hContext )->_mousePressed[ code - MOUSE_FIRST ];
  616. }
  617. bool CInputGameUI::WasMouseDoublePressed( ButtonCode_t code )
  618. {
  619. return GetInputContext( m_hContext )->_mouseDoublePressed[ code - MOUSE_FIRST ];
  620. }
  621. bool CInputGameUI::IsMouseDown( ButtonCode_t code )
  622. {
  623. return GetInputContext( m_hContext )->_mouseDown[ code - MOUSE_FIRST ];
  624. }
  625. bool CInputGameUI::WasMouseReleased( ButtonCode_t code )
  626. {
  627. return GetInputContext( m_hContext )->_mouseReleased[ code - MOUSE_FIRST ];
  628. }
  629. //-----------------------------------------------------------------------------
  630. //
  631. //-----------------------------------------------------------------------------
  632. bool CInputGameUI::WasKeyPressed( ButtonCode_t code )
  633. {
  634. return GetInputContext( m_hContext )->_keyPressed[ code - KEY_FIRST ];
  635. }
  636. bool CInputGameUI::IsKeyDown( ButtonCode_t code )
  637. {
  638. return GetInputContext( m_hContext )->_keyDown[ code - KEY_FIRST ];
  639. }
  640. bool CInputGameUI::WasKeyTyped( ButtonCode_t code )
  641. {
  642. return GetInputContext( m_hContext )->_keyTyped[ code - KEY_FIRST ];
  643. }
  644. bool CInputGameUI::WasKeyReleased( ButtonCode_t code )
  645. {
  646. // changed from: only return true if the key was released and the passed in panel matches the keyFocus
  647. return GetInputContext( m_hContext )->_keyReleased[ code - KEY_FIRST ];
  648. }
  649. //-----------------------------------------------------------------------------
  650. // Cursor position; this is the current position read from the input queue.
  651. // We need to set it because client code may read this during Mouse Pressed
  652. // events, etc.
  653. //-----------------------------------------------------------------------------
  654. void CInputGameUI::UpdateCursorPosInternal( const int &x, const int &y )
  655. {
  656. // Windows sends a CursorMoved message even when you haven't actually
  657. // moved the cursor, this means we are going into this fxn just by clicking
  658. // in the window. We only want to execute this code if we have actually moved
  659. // the cursor while dragging. So this code has been added to check
  660. // if we have actually moved from our previous position.
  661. InputContext_t *pContext = GetInputContext( m_hContext );
  662. if ( pContext->m_nCursorX == x && pContext->m_nCursorY == y )
  663. return;
  664. pContext->m_nCursorX = x;
  665. pContext->m_nCursorY = y;
  666. // Rescale this accounting the window size being different from the viewport size.
  667. int windowWidth, windowHeight;
  668. g_pGameUISystemMgrImpl->GetWindowSize( windowWidth, windowHeight );
  669. int viewportWidth, viewportHeight;
  670. g_pGameUISystemMgrImpl->GetViewportSize( viewportWidth, viewportHeight );
  671. if ( windowHeight != 0 && viewportHeight != 0 )
  672. {
  673. if ( windowWidth != viewportWidth || windowHeight != viewportHeight )
  674. {
  675. pContext->m_nCursorX = x * viewportWidth/windowWidth;
  676. pContext->m_nCursorY = y * viewportHeight/windowHeight;
  677. }
  678. }
  679. // Cursor has moved, so make sure the mouseFocus is current
  680. UpdateMouseFocus( pContext->m_nCursorX, pContext->m_nCursorY );
  681. }
  682. //-----------------------------------------------------------------------------
  683. // This is called by panels to teleport the cursor
  684. //-----------------------------------------------------------------------------
  685. void CInputGameUI::SetCursorPos( int x, int y )
  686. {
  687. InputContext_t *pContext = GetInputContext( m_hContext );
  688. pContext->m_nExternallySetCursorX = x;
  689. pContext->m_nExternallySetCursorY = y;
  690. pContext->m_bSetCursorExplicitly = true;
  691. }
  692. //-----------------------------------------------------------------------------
  693. //
  694. //-----------------------------------------------------------------------------
  695. void CInputGameUI::GetCursorPos(int &x, int &y)
  696. {
  697. GetCursorPosition( x, y );
  698. }
  699. //-----------------------------------------------------------------------------
  700. // Here for backward compat
  701. //-----------------------------------------------------------------------------
  702. void CInputGameUI::GetCursorPosition( int &x, int &y )
  703. {
  704. InputContext_t *pContext = GetInputContext( m_hContext );
  705. x = pContext->m_nCursorX;
  706. y = pContext->m_nCursorY;
  707. }
  708. //-----------------------------------------------------------------------------
  709. // Purpose: Converts a key code into a full key name
  710. //-----------------------------------------------------------------------------
  711. void CInputGameUI::GetKeyCodeText(ButtonCode_t code, char *buf, int buflen)
  712. {
  713. if (!buf)
  714. return;
  715. // copy text into buf up to buflen in length
  716. // skip 2 in _keyTrans because the first two are for GetKeyCodeChar
  717. for (int i = 0; i < buflen; i++)
  718. {
  719. char ch = _keyTrans[code][i+2];
  720. buf[i] = ch;
  721. if (ch == 0)
  722. break;
  723. }
  724. }
  725. //-----------------------------------------------------------------------------
  726. // Low-level cursor getting/setting functions
  727. //-----------------------------------------------------------------------------
  728. void CInputGameUI::SurfaceSetCursorPos( int x, int y )
  729. {
  730. g_pInputStackSystem->SetCursorPosition( g_pGameUISystemMgrImpl->GetInputContext(), x, y );
  731. //if ( g_pSurface->HasCursorPosFunctions() ) // does the surface export cursor functions for us to use?
  732. {
  733. // g_pSurface->SurfaceSetCursorPos(x,y);
  734. }
  735. //else
  736. {
  737. // translate into coordinates relative to surface
  738. //int px, py. pw, pt;
  739. //g_pSurface->GetAbsoluteWindowBounds(px, py, pw, pt);
  740. //x += px;
  741. //y += py;
  742. // set windows cursor pos
  743. //::SetCursorPos(x, y);
  744. }
  745. }
  746. void CInputGameUI::SurfaceGetCursorPos( int &x, int &y )
  747. {
  748. #ifndef _GAMECONSOLE // X360TBD
  749. //if ( g_pSurface->HasCursorPosFunctions() ) // does the surface export cursor functions for us to use?
  750. {
  751. // g_pSurface->SurfaceGetCursorPos( x,y );
  752. }
  753. //else
  754. {
  755. // g_pInputSystem->GetCursorPosition( &x, &y );
  756. // get mouse position in windows
  757. POINT pnt;
  758. ::GetCursorPos(&pnt);
  759. x = pnt.x;
  760. y = pnt.y;
  761. // translate into coordinates relative to surface
  762. //int px, py, pw, pt;
  763. //g_pSurface->GetAbsoluteWindowBounds(px, py, pw, pt);
  764. //x -= px;
  765. //y -= py;
  766. }
  767. #else
  768. x = 0;
  769. y = 0;
  770. #endif
  771. }
  772. void CInputGameUI::SetCursorOveride( vgui::HCursor cursor )
  773. {
  774. _cursorOverride = cursor;
  775. }
  776. vgui::HCursor CInputGameUI::GetCursorOveride()
  777. {
  778. return _cursorOverride;
  779. }
  780. //-----------------------------------------------------------------------------
  781. // Called when we've detected cursor has moved via a windows message
  782. //-----------------------------------------------------------------------------
  783. bool CInputGameUI::InternalCursorMoved( int x, int y )
  784. {
  785. InternalCursorMoveEvent::Post( x, y );
  786. return true;
  787. }
  788. //-----------------------------------------------------------------------------
  789. // Makes sure the windows cursor is in the right place after processing input
  790. //-----------------------------------------------------------------------------
  791. void CInputGameUI::HandleExplicitSetCursor( )
  792. {
  793. InputContext_t *pContext = GetInputContext( m_hContext );
  794. if ( pContext->m_bSetCursorExplicitly )
  795. {
  796. pContext->m_nCursorX = pContext->m_nExternallySetCursorX;
  797. pContext->m_nCursorY = pContext->m_nExternallySetCursorY;
  798. pContext->m_bSetCursorExplicitly = false;
  799. // NOTE: This forces a cursor moved message to be posted next time
  800. pContext->m_nLastPostedCursorX = pContext->m_nLastPostedCursorY = -9999;
  801. SurfaceSetCursorPos( pContext->m_nCursorX, pContext->m_nCursorY );
  802. UpdateMouseFocus( pContext->m_nCursorX, pContext->m_nCursorY );
  803. }
  804. }
  805. //-----------------------------------------------------------------------------
  806. // Called when we've detected cursor has moved via a windows message
  807. //-----------------------------------------------------------------------------
  808. void CInputGameUI::PostCursorMessage( )
  809. {
  810. InputContext_t *pContext = GetInputContext( m_hContext );
  811. if ( pContext->m_bSetCursorExplicitly )
  812. {
  813. // NOTE m_bSetCursorExplicitly will be reset to false in HandleExplicitSetCursor
  814. pContext->m_nCursorX = pContext->m_nExternallySetCursorX;
  815. pContext->m_nCursorY = pContext->m_nExternallySetCursorY;
  816. }
  817. if ( pContext->m_nLastPostedCursorX == pContext->m_nCursorX && pContext->m_nLastPostedCursorY == pContext->m_nCursorY )
  818. return;
  819. pContext->m_nLastPostedCursorX = pContext->m_nCursorX;
  820. pContext->m_nLastPostedCursorY = pContext->m_nCursorY;
  821. if ( pContext->_mouseCapture )
  822. {
  823. // the panel with mouse capture gets all messages
  824. CursorMoveEvent::Post( pContext->_mouseCapture, pContext->m_nCursorX, pContext->m_nCursorY );
  825. }
  826. else if ( pContext->_mouseFocus != NULL)
  827. {
  828. // mouse focus is current from UpdateMouse focus
  829. // so the appmodal check has already been made.
  830. CursorMoveEvent::Post( pContext->_mouseFocus, pContext->m_nCursorX, pContext->m_nCursorY );
  831. }
  832. }
  833. bool CInputGameUI::InternalMousePressed( ButtonCode_t code )
  834. {
  835. // True means we've processed the message and other code shouldn't see this message
  836. bool bFilter = false;
  837. InputContext_t *pContext = GetInputContext( m_hContext );
  838. if ( pContext->_mouseCapture )
  839. {
  840. // The faked mouse wheel button messages are specifically ignored by vgui
  841. if ( code == MOUSE_WHEEL_DOWN || code == MOUSE_WHEEL_UP )
  842. return true;
  843. bool captureLost = code == pContext->m_MouseCaptureStartCode || pContext->m_MouseCaptureStartCode == (ButtonCode_t)-1;
  844. // the panel with mouse capture gets all messages
  845. MouseDownEvent::Post( pContext->_mouseCapture, code );
  846. if ( captureLost )
  847. {
  848. // this has to happen after MousePressed so the panel doesn't Think it got a mouse press after it lost capture
  849. SetMouseCapture(NULL);
  850. }
  851. bFilter = true;
  852. }
  853. else if ( pContext->_mouseFocus != NULL )
  854. {
  855. // The faked mouse wheel button messages are specifically ignored by vgui
  856. if ( code == MOUSE_WHEEL_DOWN || code == MOUSE_WHEEL_UP )
  857. return true;
  858. // tell the panel with the mouseFocus that the mouse was presssed
  859. //g_pIVgui->PostMessage((VPANEL)pContext->_mouseFocus, new KeyValues("MousePressed", "code", code), NULL);
  860. // g_pIVgui->DPrintf2("MousePressed: (%s, %s)\n", _mouseFocus->GetName(), _mouseFocus->GetClassName());
  861. MouseDownEvent::Post( pContext->_mouseFocus, code );
  862. if ( code == MOUSE_LEFT )
  863. {
  864. pContext->_mouseLeftTrap = pContext->_mouseFocus;
  865. }
  866. else if ( code == MOUSE_MIDDLE )
  867. {
  868. pContext->_mouseMiddleTrap = pContext->_mouseFocus;
  869. }
  870. else if ( code == MOUSE_RIGHT )
  871. {
  872. pContext->_mouseRightTrap = pContext->_mouseFocus;
  873. }
  874. bFilter = true;
  875. }
  876. return bFilter;
  877. }
  878. bool CInputGameUI::InternalMouseDoublePressed( ButtonCode_t code )
  879. {
  880. // True means we've processed the message and other code shouldn't see this message
  881. bool bFilter = false;
  882. InputContext_t *pContext = GetInputContext( m_hContext );
  883. if ( pContext->_mouseCapture )
  884. {
  885. // The faked mouse wheel button messages are specifically ignored by vgui
  886. if ( code == MOUSE_WHEEL_DOWN || code == MOUSE_WHEEL_UP )
  887. return true;
  888. // the panel with mouse capture gets all messages
  889. MouseDoubleClickEvent::Post( pContext->_mouseCapture, code );
  890. bFilter = true;
  891. }
  892. else if ( pContext->_mouseFocus != NULL )
  893. {
  894. // The faked mouse wheel button messages are specifically ignored by vgui
  895. if ( code == MOUSE_WHEEL_DOWN || code == MOUSE_WHEEL_UP )
  896. return true;
  897. // tell the panel with the mouseFocus that the mouse was double presssed
  898. MouseDoubleClickEvent::Post( pContext->_mouseFocus, code );
  899. bFilter = true;
  900. }
  901. return bFilter;
  902. }
  903. bool CInputGameUI::InternalMouseReleased( ButtonCode_t code )
  904. {
  905. // True means we've processed the message and other code shouldn't see this message
  906. bool bFilter = false;
  907. InputContext_t *pContext = GetInputContext( m_hContext );
  908. if ( pContext->_mouseCapture )
  909. {
  910. // The faked mouse wheel button messages are specifically ignored by vgui
  911. if ( code == MOUSE_WHEEL_DOWN || code == MOUSE_WHEEL_UP )
  912. return true;
  913. // the panel with mouse capture gets all messages
  914. MouseUpEvent::Post( pContext->_mouseCapture, pContext->_mouseCapture, code );
  915. bFilter = true;
  916. }
  917. else if ( pContext->_mouseLeftTrap )
  918. {
  919. MouseUpEvent::Post( pContext->_mouseLeftTrap, pContext->_mouseLeftTrap, code );
  920. pContext->_mouseLeftTrap = NULL;
  921. bFilter = true;
  922. }
  923. else if ( pContext->_mouseMiddleTrap )
  924. {
  925. MouseUpEvent::Post( pContext->_mouseMiddleTrap, pContext->_mouseLeftTrap, code );
  926. pContext->_mouseMiddleTrap = NULL;
  927. bFilter = true;
  928. }
  929. else if ( pContext->_mouseRightTrap )
  930. {
  931. MouseUpEvent::Post( pContext->_mouseRightTrap, pContext->_mouseLeftTrap, code );
  932. pContext->_mouseRightTrap = NULL;
  933. bFilter = true;
  934. }
  935. /* If the mouse was not trapped by a down, don't propagate this message.
  936. else if ( pContext->_mouseFocus != NULL )
  937. {
  938. // The faked mouse wheel button messages are specifically ignored by vgui
  939. if ( code == MOUSE_WHEEL_DOWN || code == MOUSE_WHEEL_UP )
  940. return true;
  941. MouseUpEvent::Post( pContext->_mouseFocus, code );
  942. bFilter = true;
  943. }
  944. */
  945. return bFilter;
  946. }
  947. bool CInputGameUI::InternalMouseWheeled(int delta)
  948. {
  949. // True means we've processed the message and other code shouldn't see this message
  950. bool bFilter = false;
  951. InputContext_t *pContext = GetInputContext( m_hContext );
  952. if ( pContext->_mouseFocus != NULL )
  953. {
  954. // the mouseWheel works with the mouseFocus, not the keyFocus
  955. MouseWheelEvent::Post( pContext->_mouseFocus, delta );
  956. bFilter = true;
  957. }
  958. return bFilter;
  959. }
  960. //-----------------------------------------------------------------------------
  961. // Updates the internal key/mouse state associated with the current input context without sending messages
  962. //-----------------------------------------------------------------------------
  963. void CInputGameUI::SetMouseCodeState( ButtonCode_t code, GameUIMouseCodeState_t state )
  964. {
  965. if ( !IsMouseCode( code ) )
  966. return;
  967. InputContext_t *pContext = GetInputContext( m_hContext );
  968. switch( state )
  969. {
  970. case BUTTON_RELEASED:
  971. pContext->_mouseReleased[ code - MOUSE_FIRST ] = 1;
  972. break;
  973. case BUTTON_PRESSED:
  974. pContext->_mousePressed[ code - MOUSE_FIRST ] = 1;
  975. break;
  976. case BUTTON_DOUBLECLICKED:
  977. pContext->_mouseDoublePressed[ code - MOUSE_FIRST ] = 1;
  978. break;
  979. }
  980. pContext->_mouseDown[ code - MOUSE_FIRST ] = ( state != BUTTON_RELEASED );
  981. }
  982. void CInputGameUI::SetKeyCodeState( ButtonCode_t code, bool bPressed )
  983. {
  984. if ( !IsKeyCode( code )
  985. #ifdef _GAMECONSOLE
  986. && !IsJoystickCode( code )
  987. #endif
  988. )
  989. return;
  990. InputContext_t *pContext = GetInputContext( m_hContext );
  991. if ( bPressed )
  992. {
  993. //set key state
  994. pContext->_keyPressed[ code - KEY_FIRST ] = 1;
  995. }
  996. else
  997. {
  998. // set key state
  999. pContext->_keyReleased[ code - KEY_FIRST ] = 1;
  1000. }
  1001. pContext->_keyDown[ code - KEY_FIRST ] = bPressed;
  1002. }
  1003. void CInputGameUI::UpdateButtonState( const InputEvent_t &event )
  1004. {
  1005. switch( event.m_nType )
  1006. {
  1007. case IE_ButtonPressed:
  1008. case IE_ButtonReleased:
  1009. case IE_ButtonDoubleClicked:
  1010. {
  1011. // NOTE: data2 is the virtual key code (data1 contains the scan-code one)
  1012. ButtonCode_t code = (ButtonCode_t)event.m_nData2;
  1013. // FIXME: Workaround hack
  1014. if ( IsKeyCode( code ) || IsJoystickCode( code ) )
  1015. {
  1016. SetKeyCodeState( code, ( event.m_nType != IE_ButtonReleased ) );
  1017. break;
  1018. }
  1019. if ( IsMouseCode( code ) )
  1020. {
  1021. GameUIMouseCodeState_t state;
  1022. state = ( event.m_nType == IE_ButtonReleased ) ? BUTTON_RELEASED : BUTTON_PRESSED;
  1023. if ( event.m_nType == IE_ButtonDoubleClicked )
  1024. {
  1025. state = BUTTON_DOUBLECLICKED;
  1026. }
  1027. SetMouseCodeState( code, state );
  1028. break;
  1029. }
  1030. }
  1031. break;
  1032. }
  1033. }
  1034. bool CInputGameUI::InternalKeyCodePressed( ButtonCode_t code )
  1035. {
  1036. InputContext_t *pContext = GetInputContext( m_hContext );
  1037. // mask out bogus keys
  1038. if ( !IsKeyCode( code ) && !IsJoystickCode( code ) )
  1039. return false;
  1040. bool bFilter = false;
  1041. if( pContext->_keyFocus!= NULL )
  1042. {
  1043. #ifdef _GAMECONSOLE
  1044. //g_pIVgui->PostMessage((VPANEL) MESSAGE_CURRENT_KEYFOCUS, message, NULL );
  1045. #else
  1046. //tell the current focused panel that a key was typed
  1047. KeyDownEvent::Post( pContext->_keyFocus, code );
  1048. pContext->_bKeyTrap = true;
  1049. #endif
  1050. bFilter = true;
  1051. }
  1052. if ( bFilter )
  1053. {
  1054. // Only notice the key down for repeating if we actually used the key
  1055. pContext->m_keyRepeater.KeyDown( code );
  1056. }
  1057. return bFilter;
  1058. }
  1059. void CInputGameUI::InternalKeyCodeTyped( ButtonCode_t code )
  1060. {
  1061. InputContext_t *pContext = GetInputContext( m_hContext );
  1062. // mask out bogus keys
  1063. if ( !IsKeyCode( code ) && !IsJoystickCode( code ) )
  1064. return;
  1065. // set key state
  1066. pContext->_keyTyped[ code - KEY_FIRST ] = 1;
  1067. if( pContext->_keyFocus!= NULL )
  1068. {
  1069. #ifdef _GAMECONSOLE
  1070. //g_pIVgui->PostMessage((VPANEL) MESSAGE_CURRENT_KEYFOCUS, message, NULL );
  1071. #else
  1072. //tell the current focused panel that a key was typed
  1073. KeyCodeTypedEvent::Post( pContext->_keyFocus, code );
  1074. g_pGameUISystemMgrImpl->OnKeyCodeTyped( code ); // FIXME, make work like mouse clicked.
  1075. #endif
  1076. }
  1077. }
  1078. void CInputGameUI::InternalKeyTyped( wchar_t unichar )
  1079. {
  1080. InputContext_t *pContext = GetInputContext( m_hContext );
  1081. // set key state
  1082. if( unichar <= KEY_LAST )
  1083. {
  1084. pContext->_keyTyped[unichar]=1;
  1085. }
  1086. if( pContext->_keyFocus!= NULL )
  1087. {
  1088. #ifdef _GAMECONSOLE
  1089. //g_pIVgui->PostMessage((VPANEL) MESSAGE_CURRENT_KEYFOCUS, message, NULL );
  1090. #else
  1091. //tell the current focused panel that a key was typed
  1092. KeyTypedEvent::Post( pContext->_keyFocus, unichar );
  1093. g_pGameUISystemMgrImpl->OnKeyTyped( unichar ); // FIXME, make work like mouse clicked.
  1094. #endif
  1095. }
  1096. }
  1097. bool CInputGameUI::InternalKeyCodeReleased( ButtonCode_t code )
  1098. {
  1099. InputContext_t *pContext = GetInputContext( m_hContext );
  1100. // mask out bogus keys
  1101. if ( !IsKeyCode( code ) && !IsJoystickCode( code ) )
  1102. return false;
  1103. pContext->m_keyRepeater.KeyUp( code );
  1104. if ( ( pContext->_keyFocus!= NULL ) && pContext->_bKeyTrap )
  1105. {
  1106. #ifdef _GAMECONSOLE
  1107. //g_pIVgui->PostMessage((VPANEL) MESSAGE_CURRENT_KEYFOCUS, message, NULL );
  1108. #else
  1109. //tell the current focused panel that a key was released
  1110. KeyUpEvent::Post( pContext->_keyFocus, code );
  1111. pContext->_bKeyTrap = false;
  1112. #endif
  1113. return true;
  1114. }
  1115. return false;
  1116. }
  1117. //-----------------------------------------------------------------------------
  1118. // Purpose: posts a message to the key focus if it's valid
  1119. //-----------------------------------------------------------------------------
  1120. bool CInputGameUI::PostKeyMessage(KeyValues *message)
  1121. {
  1122. InputContext_t *pContext = GetInputContext( m_hContext );
  1123. if( pContext->_keyFocus!= NULL )
  1124. {
  1125. #ifdef _GAMECONSOLE
  1126. //g_pIVgui->PostMessage((VPANEL) MESSAGE_CURRENT_KEYFOCUS, message, NULL );
  1127. #else
  1128. //tell the current focused panel that a key was released
  1129. //g_pIVgui->PostMessage((VPANEL)pContext->_keyFocus, message, NULL );
  1130. #endif
  1131. return true;
  1132. }
  1133. message->deleteThis();
  1134. return false;
  1135. }
  1136. enum LANGFLAG
  1137. {
  1138. ENGLISH,
  1139. TRADITIONAL_CHINESE,
  1140. JAPANESE,
  1141. KOREAN,
  1142. SIMPLIFIED_CHINESE,
  1143. UNKNOWN,
  1144. NUM_IMES_SUPPORTED
  1145. } LangFlag;
  1146. struct LanguageIds
  1147. {
  1148. // char const *idname;
  1149. unsigned short id;
  1150. int languageflag;
  1151. wchar_t const *shortcode;
  1152. wchar_t const *displayname;
  1153. bool invertcomposition;
  1154. };
  1155. LanguageIds g_LanguageIds[] =
  1156. {
  1157. { 0x0000, UNKNOWN, L"", L"Neutral" },
  1158. { 0x007f, UNKNOWN, L"", L"Invariant" },
  1159. { 0x0400, UNKNOWN, L"", L"User Default Language" },
  1160. { 0x0800, UNKNOWN, L"", L"System Default Language" },
  1161. { 0x0436, UNKNOWN, L"AF", L"Afrikaans" },
  1162. { 0x041c, UNKNOWN, L"SQ", L"Albanian" },
  1163. { 0x0401, UNKNOWN, L"AR", L"Arabic (Saudi Arabia)" },
  1164. { 0x0801, UNKNOWN, L"AR", L"Arabic (Iraq)" },
  1165. { 0x0c01, UNKNOWN, L"AR", L"Arabic (Egypt)" },
  1166. { 0x1001, UNKNOWN, L"AR", L"Arabic (Libya)" },
  1167. { 0x1401, UNKNOWN, L"AR", L"Arabic (Algeria)" },
  1168. { 0x1801, UNKNOWN, L"AR", L"Arabic (Morocco)" },
  1169. { 0x1c01, UNKNOWN, L"AR", L"Arabic (Tunisia)" },
  1170. { 0x2001, UNKNOWN, L"AR", L"Arabic (Oman)" },
  1171. { 0x2401, UNKNOWN, L"AR", L"Arabic (Yemen)" },
  1172. { 0x2801, UNKNOWN, L"AR", L"Arabic (Syria)" },
  1173. { 0x2c01, UNKNOWN, L"AR", L"Arabic (Jordan)" },
  1174. { 0x3001, UNKNOWN, L"AR", L"Arabic (Lebanon)" },
  1175. { 0x3401, UNKNOWN, L"AR", L"Arabic (Kuwait)" },
  1176. { 0x3801, UNKNOWN, L"AR", L"Arabic (U.A.E.)" },
  1177. { 0x3c01, UNKNOWN, L"AR", L"Arabic (Bahrain)" },
  1178. { 0x4001, UNKNOWN, L"AR", L"Arabic (Qatar)" },
  1179. { 0x042b, UNKNOWN, L"HY", L"Armenian" },
  1180. { 0x042c, UNKNOWN, L"AZ", L"Azeri (Latin)" },
  1181. { 0x082c, UNKNOWN, L"AZ", L"Azeri (Cyrillic)" },
  1182. { 0x042d, UNKNOWN, L"ES", L"Basque" },
  1183. { 0x0423, UNKNOWN, L"BE", L"Belarusian" },
  1184. { 0x0445, UNKNOWN, L"", L"Bengali (India)" },
  1185. { 0x141a, UNKNOWN, L"", L"Bosnian (Bosnia and Herzegovina)" },
  1186. { 0x0402, UNKNOWN, L"BG", L"Bulgarian" },
  1187. { 0x0455, UNKNOWN, L"", L"Burmese" },
  1188. { 0x0403, UNKNOWN, L"CA", L"Catalan" },
  1189. { 0x0404, TRADITIONAL_CHINESE, L"CHT", L"#IME_0404", true },
  1190. { 0x0804, SIMPLIFIED_CHINESE, L"CHS", L"#IME_0804", true },
  1191. { 0x0c04, UNKNOWN, L"CH", L"Chinese (Hong Kong SAR, PRC)" },
  1192. { 0x1004, UNKNOWN, L"CH", L"Chinese (Singapore)" },
  1193. { 0x1404, UNKNOWN, L"CH", L"Chinese (Macao SAR)" },
  1194. { 0x041a, UNKNOWN, L"HR", L"Croatian" },
  1195. { 0x101a, UNKNOWN, L"HR", L"Croatian (Bosnia and Herzegovina)" },
  1196. { 0x0405, UNKNOWN, L"CZ", L"Czech" },
  1197. { 0x0406, UNKNOWN, L"DK", L"Danish" },
  1198. { 0x0465, UNKNOWN, L"MV", L"Divehi" },
  1199. { 0x0413, UNKNOWN, L"NL", L"Dutch (Netherlands)" },
  1200. { 0x0813, UNKNOWN, L"BE", L"Dutch (Belgium)" },
  1201. { 0x0409, ENGLISH, L"EN", L"#IME_0409" },
  1202. { 0x0809, ENGLISH, L"EN", L"English (United Kingdom)" },
  1203. { 0x0c09, ENGLISH, L"EN", L"English (Australian)" },
  1204. { 0x1009, ENGLISH, L"EN", L"English (Canadian)" },
  1205. { 0x1409, ENGLISH, L"EN", L"English (New Zealand)" },
  1206. { 0x1809, ENGLISH, L"EN", L"English (Ireland)" },
  1207. { 0x1c09, ENGLISH, L"EN", L"English (South Africa)" },
  1208. { 0x2009, ENGLISH, L"EN", L"English (Jamaica)" },
  1209. { 0x2409, ENGLISH, L"EN", L"English (Caribbean)" },
  1210. { 0x2809, ENGLISH, L"EN", L"English (Belize)" },
  1211. { 0x2c09, ENGLISH, L"EN", L"English (Trinidad)" },
  1212. { 0x3009, ENGLISH, L"EN", L"English (Zimbabwe)" },
  1213. { 0x3409, ENGLISH, L"EN", L"English (Philippines)" },
  1214. { 0x0425, UNKNOWN, L"ET", L"Estonian" },
  1215. { 0x0438, UNKNOWN, L"FO", L"Faeroese" },
  1216. { 0x0429, UNKNOWN, L"FA", L"Farsi" },
  1217. { 0x040b, UNKNOWN, L"FI", L"Finnish" },
  1218. { 0x040c, UNKNOWN, L"FR", L"#IME_040c" },
  1219. { 0x080c, UNKNOWN, L"FR", L"French (Belgian)" },
  1220. { 0x0c0c, UNKNOWN, L"FR", L"French (Canadian)" },
  1221. { 0x100c, UNKNOWN, L"FR", L"French (Switzerland)" },
  1222. { 0x140c, UNKNOWN, L"FR", L"French (Luxembourg)" },
  1223. { 0x180c, UNKNOWN, L"FR", L"French (Monaco)" },
  1224. { 0x0456, UNKNOWN, L"GL", L"Galician" },
  1225. { 0x0437, UNKNOWN, L"KA", L"Georgian" },
  1226. { 0x0407, UNKNOWN, L"DE", L"#IME_0407" },
  1227. { 0x0807, UNKNOWN, L"DE", L"German (Switzerland)" },
  1228. { 0x0c07, UNKNOWN, L"DE", L"German (Austria)" },
  1229. { 0x1007, UNKNOWN, L"DE", L"German (Luxembourg)" },
  1230. { 0x1407, UNKNOWN, L"DE", L"German (Liechtenstein)" },
  1231. { 0x0408, UNKNOWN, L"GR", L"Greek" },
  1232. { 0x0447, UNKNOWN, L"IN", L"Gujarati" },
  1233. { 0x040d, UNKNOWN, L"HE", L"Hebrew" },
  1234. { 0x0439, UNKNOWN, L"HI", L"Hindi" },
  1235. { 0x040e, UNKNOWN, L"HU", L"Hungarian" },
  1236. { 0x040f, UNKNOWN, L"IS", L"Icelandic" },
  1237. { 0x0421, UNKNOWN, L"ID", L"Indonesian" },
  1238. { 0x0434, UNKNOWN, L"", L"isiXhosa/Xhosa (South Africa)" },
  1239. { 0x0435, UNKNOWN, L"", L"isiZulu/Zulu (South Africa)" },
  1240. { 0x0410, UNKNOWN, L"IT", L"#IME_0410" },
  1241. { 0x0810, UNKNOWN, L"IT", L"Italian (Switzerland)" },
  1242. { 0x0411, JAPANESE, L"JP", L"#IME_0411" },
  1243. { 0x044b, UNKNOWN, L"IN", L"Kannada" },
  1244. { 0x0457, UNKNOWN, L"IN", L"Konkani" },
  1245. { 0x0412, KOREAN, L"KR", L"#IME_0412" },
  1246. { 0x0812, UNKNOWN, L"KR", L"Korean (Johab)" },
  1247. { 0x0440, UNKNOWN, L"KZ", L"Kyrgyz." },
  1248. { 0x0426, UNKNOWN, L"LV", L"Latvian" },
  1249. { 0x0427, UNKNOWN, L"LT", L"Lithuanian" },
  1250. { 0x0827, UNKNOWN, L"LT", L"Lithuanian (Classic)" },
  1251. { 0x042f, UNKNOWN, L"MK", L"FYRO Macedonian" },
  1252. { 0x043e, UNKNOWN, L"MY", L"Malay (Malaysian)" },
  1253. { 0x083e, UNKNOWN, L"MY", L"Malay (Brunei Darussalam)" },
  1254. { 0x044c, UNKNOWN, L"IN", L"Malayalam (India)" },
  1255. { 0x0481, UNKNOWN, L"", L"Maori (New Zealand)" },
  1256. { 0x043a, UNKNOWN, L"", L"Maltese (Malta)" },
  1257. { 0x044e, UNKNOWN, L"IN", L"Marathi" },
  1258. { 0x0450, UNKNOWN, L"MN", L"Mongolian" },
  1259. { 0x0414, UNKNOWN, L"NO", L"Norwegian (Bokmal)" },
  1260. { 0x0814, UNKNOWN, L"NO", L"Norwegian (Nynorsk)" },
  1261. { 0x0415, UNKNOWN, L"PL", L"Polish" },
  1262. { 0x0416, UNKNOWN, L"PT", L"Portuguese (Brazil)" },
  1263. { 0x0816, UNKNOWN, L"PT", L"Portuguese (Portugal)" },
  1264. { 0x0446, UNKNOWN, L"IN", L"Punjabi" },
  1265. { 0x046b, UNKNOWN, L"", L"Quechua (Bolivia)" },
  1266. { 0x086b, UNKNOWN, L"", L"Quechua (Ecuador)" },
  1267. { 0x0c6b, UNKNOWN, L"", L"Quechua (Peru)" },
  1268. { 0x0418, UNKNOWN, L"RO", L"Romanian" },
  1269. { 0x0419, UNKNOWN, L"RU", L"#IME_0419" },
  1270. { 0x044f, UNKNOWN, L"IN", L"Sanskrit" },
  1271. { 0x043b, UNKNOWN, L"", L"Sami, Northern (Norway)" },
  1272. { 0x083b, UNKNOWN, L"", L"Sami, Northern (Sweden)" },
  1273. { 0x0c3b, UNKNOWN, L"", L"Sami, Northern (Finland)" },
  1274. { 0x103b, UNKNOWN, L"", L"Sami, Lule (Norway)" },
  1275. { 0x143b, UNKNOWN, L"", L"Sami, Lule (Sweden)" },
  1276. { 0x183b, UNKNOWN, L"", L"Sami, Southern (Norway)" },
  1277. { 0x1c3b, UNKNOWN, L"", L"Sami, Southern (Sweden)" },
  1278. { 0x203b, UNKNOWN, L"", L"Sami, Skolt (Finland)" },
  1279. { 0x243b, UNKNOWN, L"", L"Sami, Inari (Finland)" },
  1280. { 0x0c1a, UNKNOWN, L"SR", L"Serbian (Cyrillic)" },
  1281. { 0x1c1a, UNKNOWN, L"SR", L"Serbian (Cyrillic, Bosnia, and Herzegovina)" },
  1282. { 0x081a, UNKNOWN, L"SR", L"Serbian (Latin)" },
  1283. { 0x181a, UNKNOWN, L"SR", L"Serbian (Latin, Bosnia, and Herzegovina)" },
  1284. { 0x046c, UNKNOWN, L"", L"Sesotho sa Leboa/Northern Sotho (South Africa)" },
  1285. { 0x0432, UNKNOWN, L"", L"Setswana/Tswana (South Africa)" },
  1286. { 0x041b, UNKNOWN, L"SK", L"Slovak" },
  1287. { 0x0424, UNKNOWN, L"SI", L"Slovenian" },
  1288. { 0x040a, UNKNOWN, L"ES", L"#IME_040a" },
  1289. { 0x080a, UNKNOWN, L"ES", L"Spanish (Mexican)" },
  1290. { 0x0c0a, UNKNOWN, L"ES", L"Spanish (Spain, Modern Sort)" },
  1291. { 0x100a, UNKNOWN, L"ES", L"Spanish (Guatemala)" },
  1292. { 0x140a, UNKNOWN, L"ES", L"Spanish (Costa Rica)" },
  1293. { 0x180a, UNKNOWN, L"ES", L"Spanish (Panama)" },
  1294. { 0x1c0a, UNKNOWN, L"ES", L"Spanish (Dominican Republic)" },
  1295. { 0x200a, UNKNOWN, L"ES", L"Spanish (Venezuela)" },
  1296. { 0x240a, UNKNOWN, L"ES", L"Spanish (Colombia)" },
  1297. { 0x280a, UNKNOWN, L"ES", L"Spanish (Peru)" },
  1298. { 0x2c0a, UNKNOWN, L"ES", L"Spanish (Argentina)" },
  1299. { 0x300a, UNKNOWN, L"ES", L"Spanish (Ecuador)" },
  1300. { 0x340a, UNKNOWN, L"ES", L"Spanish (Chile)" },
  1301. { 0x380a, UNKNOWN, L"ES", L"Spanish (Uruguay)" },
  1302. { 0x3c0a, UNKNOWN, L"ES", L"Spanish (Paraguay)" },
  1303. { 0x400a, UNKNOWN, L"ES", L"Spanish (Bolivia)" },
  1304. { 0x440a, UNKNOWN, L"ES", L"Spanish (El Salvador)" },
  1305. { 0x480a, UNKNOWN, L"ES", L"Spanish (Honduras)" },
  1306. { 0x4c0a, UNKNOWN, L"ES", L"Spanish (Nicaragua)" },
  1307. { 0x500a, UNKNOWN, L"ES", L"Spanish (Puerto Rico)" },
  1308. { 0x0430, UNKNOWN, L"", L"Sutu" },
  1309. { 0x0441, UNKNOWN, L"KE", L"Swahili (Kenya)" },
  1310. { 0x041d, UNKNOWN, L"SV", L"Swedish" },
  1311. { 0x081d, UNKNOWN, L"SV", L"Swedish (Finland)" },
  1312. { 0x045a, UNKNOWN, L"SY", L"Syriac" },
  1313. { 0x0449, UNKNOWN, L"IN", L"Tamil" },
  1314. { 0x0444, UNKNOWN, L"RU", L"Tatar (Tatarstan)" },
  1315. { 0x044a, UNKNOWN, L"IN", L"Telugu" },
  1316. { 0x041e, UNKNOWN, L"TH", L"#IME_041e" },
  1317. { 0x041f, UNKNOWN, L"TR", L"Turkish" },
  1318. { 0x0422, UNKNOWN, L"UA", L"Ukrainian" },
  1319. { 0x0420, UNKNOWN, L"PK", L"Urdu (Pakistan)" },
  1320. { 0x0820, UNKNOWN, L"IN", L"Urdu (India)" },
  1321. { 0x0443, UNKNOWN, L"UZ", L"Uzbek (Latin)" },
  1322. { 0x0843, UNKNOWN, L"UZ", L"Uzbek (Cyrillic)" },
  1323. { 0x042a, UNKNOWN, L"VN", L"Vietnamese" },
  1324. { 0x0452, UNKNOWN, L"", L"Welsh (United Kingdom)" },
  1325. };
  1326. static LanguageIds *GetLanguageInfo( unsigned short id )
  1327. {
  1328. for ( int j = 0; j < sizeof( g_LanguageIds ) / sizeof( g_LanguageIds[ 0 ] ); ++j )
  1329. {
  1330. if ( g_LanguageIds[ j ].id == id )
  1331. {
  1332. return &g_LanguageIds[ j ];
  1333. break;
  1334. }
  1335. }
  1336. return NULL;
  1337. }
  1338. /////////////////////////////////////////////////////////////////////////////
  1339. // CIMEDlg message handlers
  1340. static bool IsIDInList( unsigned short id, int count, HKL *list )
  1341. {
  1342. for ( int i = 0; i < count; ++i )
  1343. {
  1344. if ( LOWORD( list[ i ] ) == id )
  1345. {
  1346. return true;
  1347. }
  1348. }
  1349. return false;
  1350. }
  1351. static const wchar_t *GetLanguageName( unsigned short id )
  1352. {
  1353. wchar_t const *name = L"???";
  1354. for ( int j = 0; j < sizeof( g_LanguageIds ) / sizeof( g_LanguageIds[ 0 ] ); ++j )
  1355. {
  1356. if ( g_LanguageIds[ j ].id == id )
  1357. {
  1358. name = g_LanguageIds[ j ].displayname;
  1359. break;
  1360. }
  1361. }
  1362. return name;
  1363. }
  1364. //-----------------------------------------------------------------------------
  1365. // Purpose:
  1366. // Input : *hwnd -
  1367. //-----------------------------------------------------------------------------
  1368. void CInputGameUI::SetIMEWindow( void *hwnd )
  1369. {
  1370. #ifndef _GAMECONSOLE
  1371. _imeWnd = hwnd;
  1372. #endif
  1373. }
  1374. //-----------------------------------------------------------------------------
  1375. // Purpose:
  1376. //-----------------------------------------------------------------------------
  1377. void *CInputGameUI::GetIMEWindow()
  1378. {
  1379. #ifndef _GAMECONSOLE
  1380. return _imeWnd;
  1381. #else
  1382. return NULL;
  1383. #endif
  1384. }
  1385. static void SpewIMEInfo( int langid )
  1386. {
  1387. LanguageIds *info = GetLanguageInfo( langid );
  1388. if ( info )
  1389. {
  1390. wchar_t const *name = info->shortcode ? info->shortcode : L"???";
  1391. wchar_t outstr[ 512 ];
  1392. _snwprintf( outstr, sizeof( outstr ) / sizeof( wchar_t ), L"IME language changed to: %s", name );
  1393. OutputDebugStringW( outstr );
  1394. OutputDebugStringW( L"\n" );
  1395. }
  1396. }
  1397. // Change keyboard layout type
  1398. void CInputGameUI::OnChangeIME( bool forward )
  1399. {
  1400. #ifndef _GAMECONSOLE
  1401. HKL currentKb = GetKeyboardLayout( 0 );
  1402. UINT numKBs = GetKeyboardLayoutList( 0, NULL );
  1403. if ( numKBs > 0 )
  1404. {
  1405. HKL *list = new HKL[ numKBs ];
  1406. GetKeyboardLayoutList( numKBs, list );
  1407. int oldKb = 0;
  1408. CUtlVector< HKL > selections;
  1409. for ( unsigned int i = 0; i < numKBs; ++i )
  1410. {
  1411. BOOL first = !IsIDInList( LOWORD( list[ i ] ), i, list );
  1412. if ( !first )
  1413. continue;
  1414. selections.AddToTail( list[ i ] );
  1415. if ( list[ i ] == currentKb )
  1416. {
  1417. oldKb = selections.Count() - 1;
  1418. }
  1419. }
  1420. oldKb += forward ? 1 : -1;
  1421. if ( oldKb < 0 )
  1422. {
  1423. oldKb = max( 0, selections.Count() - 1 );
  1424. }
  1425. else if ( oldKb >= selections.Count() )
  1426. {
  1427. oldKb = 0;
  1428. }
  1429. ActivateKeyboardLayout( selections[ oldKb ], 0 );
  1430. int langid = LOWORD( selections[ oldKb ] );
  1431. SpewIMEInfo( langid );
  1432. delete[] list;
  1433. }
  1434. #endif
  1435. }
  1436. int CInputGameUI::GetCurrentIMEHandle()
  1437. {
  1438. #ifndef _GAMECONSOLE
  1439. HKL hkl = (HKL)GetKeyboardLayout( 0 );
  1440. return (int)hkl;
  1441. #else
  1442. return 0;
  1443. #endif
  1444. }
  1445. int CInputGameUI::GetEnglishIMEHandle()
  1446. {
  1447. #ifndef _GAMECONSOLE
  1448. HKL hkl = (HKL)0x04090409;
  1449. return (int)hkl;
  1450. #else
  1451. return 0;
  1452. #endif
  1453. }
  1454. void CInputGameUI::OnChangeIMEByHandle( int handleValue )
  1455. {
  1456. #ifndef _GAMECONSOLE
  1457. HKL hkl = (HKL)handleValue;
  1458. ActivateKeyboardLayout( hkl, 0 );
  1459. int langid = LOWORD( hkl);
  1460. SpewIMEInfo( langid );
  1461. #endif
  1462. }
  1463. // Returns the Language Bar label (Chinese, Korean, Japanese, Russion, Thai, etc.)
  1464. void CInputGameUI::GetIMELanguageName( wchar_t *buf, int unicodeBufferSizeInBytes )
  1465. {
  1466. #ifndef _GAMECONSOLE
  1467. wchar_t const *name = GetLanguageName( LOWORD( GetKeyboardLayout( 0 ) ) );
  1468. wcsncpy( buf, name, unicodeBufferSizeInBytes / sizeof( wchar_t ) - 1 );
  1469. buf[ unicodeBufferSizeInBytes / sizeof( wchar_t ) - 1 ] = L'\0';
  1470. #else
  1471. buf[0] = L'\0';
  1472. #endif
  1473. }
  1474. // Returns the short code for the language (EN, CH, KO, JP, RU, TH, etc. ).
  1475. void CInputGameUI::GetIMELanguageShortCode( wchar_t *buf, int unicodeBufferSizeInBytes )
  1476. {
  1477. #ifndef _GAMECONSOLE
  1478. LanguageIds *info = GetLanguageInfo( LOWORD( GetKeyboardLayout( 0 ) ) );
  1479. if ( !info )
  1480. {
  1481. buf[ 0 ] = L'\0';
  1482. }
  1483. else
  1484. {
  1485. wcsncpy( buf, info->shortcode, unicodeBufferSizeInBytes / sizeof( wchar_t ) - 1 );
  1486. buf[ unicodeBufferSizeInBytes / sizeof( wchar_t ) - 1 ] = L'\0';
  1487. }
  1488. #else
  1489. buf[0] = L'\0';
  1490. #endif
  1491. }
  1492. // Call with NULL dest to get item count
  1493. int CInputGameUI::GetIMELanguageList( LanguageItem *dest, int destcount )
  1494. {
  1495. #ifndef _GAMECONSOLE
  1496. int iret = 0;
  1497. UINT numKBs = GetKeyboardLayoutList( 0, NULL );
  1498. if ( numKBs > 0 )
  1499. {
  1500. HKL *list = new HKL[ numKBs ];
  1501. GetKeyboardLayoutList( numKBs, list );
  1502. CUtlVector< HKL > selections;
  1503. for ( unsigned int i = 0; i < numKBs; ++i )
  1504. {
  1505. BOOL first = !IsIDInList( LOWORD( list[ i ] ), i, list );
  1506. if ( !first )
  1507. continue;
  1508. selections.AddToTail( list[ i ] );
  1509. }
  1510. iret = selections.Count();
  1511. if ( dest )
  1512. {
  1513. for ( int i = 0; i < min(iret,destcount); ++i )
  1514. {
  1515. HKL hkl = selections[ i ];
  1516. LanguageItem *p = &dest[ i ];
  1517. LanguageIds *info = GetLanguageInfo( LOWORD( hkl ) );
  1518. memset( p, 0, sizeof( IInput::LanguageItem ) );
  1519. wcsncpy( p->shortname, info->shortcode, sizeof( p->shortname ) / sizeof( wchar_t ) );
  1520. p->shortname[ sizeof( p->shortname ) / sizeof( wchar_t ) - 1 ] = L'\0';
  1521. wcsncpy( p->menuname, info->displayname, sizeof( p->menuname ) / sizeof( wchar_t ) );
  1522. p->menuname[ sizeof( p->menuname ) / sizeof( wchar_t ) - 1 ] = L'\0';
  1523. p->handleValue = (int)hkl;
  1524. p->active = ( hkl == GetKeyboardLayout( 0 ) ) ? true : false;
  1525. }
  1526. }
  1527. delete[] list;
  1528. }
  1529. return iret;
  1530. #else
  1531. return 0;
  1532. #endif
  1533. }
  1534. /*
  1535. // Flag for effective options in conversion mode
  1536. BOOL fConvMode[NUM_IMES_SUPPORTED][13] =
  1537. {
  1538. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // EN
  1539. {1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0}, // Trad CH
  1540. {1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1}, // Japanese
  1541. {1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, // Kor
  1542. {1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0}, // Simp CH
  1543. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // UNK(same as EN)
  1544. }
  1545. // Flag for effective options in sentence mode
  1546. BOOL fSentMode[NUM_IMES_SUPPORTED][6] =
  1547. {
  1548. {0, 0, 0, 0, 0, 0}, // EN
  1549. {0, 1, 0, 0, 0, 0}, // Trad CH
  1550. {1, 1, 1, 1, 1, 1}, // Japanese
  1551. {0, 0, 0, 0, 0, 0}, // Kor
  1552. {0, 0, 0, 0, 0, 0} // Simp CH
  1553. {0, 0, 0, 0, 0, 0}, // UNK(same as EN)
  1554. };
  1555. // Conversion mode message
  1556. DWORD dwConvModeMsg[13] = {
  1557. IME_CMODE_ALPHANUMERIC, IME_CMODE_NATIVE, IME_CMODE_KATAKANA,
  1558. IME_CMODE_LANGUAGE, IME_CMODE_FULLSHAPE, IME_CMODE_ROMAN,
  1559. IME_CMODE_CHARCODE, IME_CMODE_HANJACONVERT, IME_CMODE_SOFTKBD,
  1560. IME_CMODE_NOCONVERSION, IME_CMODE_EUDC, IME_CMODE_SYMBOL,
  1561. IME_CMODE_FIXED};
  1562. // Sentence mode message
  1563. DWORD dwSentModeMsg[6] = {
  1564. IME_SMODE_NONE, IME_SMODE_PLAURALCLAUSE, IME_SMODE_SINGLECONVERT,
  1565. IME_SMODE_AUTOMATIC, IME_SMODE_PHRASEPREDICT, IME_SMODE_CONVERSATION };
  1566. // ENGLISH,
  1567. // TRADITIONAL_CHINESE,
  1568. // JAPANESE,
  1569. // KOREAN,
  1570. // SIMPLIFIED_CHINESE,
  1571. // UNKNOWN,
  1572. */
  1573. #ifndef _GAMECONSOLE
  1574. struct IMESettingsTransform
  1575. {
  1576. IMESettingsTransform( unsigned int cmr, unsigned int cma, unsigned int smr, unsigned int sma ) :
  1577. cmode_remove( cmr ),
  1578. cmode_add( cma ),
  1579. smode_remove( smr ),
  1580. smode_add( sma )
  1581. {
  1582. }
  1583. void Apply( HWND hwnd )
  1584. {
  1585. HIMC hImc = ImmGetContext( hwnd );
  1586. if ( hImc )
  1587. {
  1588. DWORD dwConvMode, dwSentMode;
  1589. ImmGetConversionStatus( hImc, &dwConvMode, &dwSentMode );
  1590. dwConvMode &= ~cmode_remove;
  1591. dwSentMode &= ~smode_remove;
  1592. ImmSetConversionStatus( hImc, dwConvMode, dwSentMode );
  1593. dwConvMode |= cmode_add;
  1594. dwSentMode |= smode_add;
  1595. ImmSetConversionStatus( hImc, dwConvMode, dwSentMode );
  1596. ImmReleaseContext( hwnd, hImc );
  1597. }
  1598. }
  1599. bool ConvMatches( DWORD convFlags )
  1600. {
  1601. // To match, the active flags have to have none of the remove flags and have to have all of the "add" flags
  1602. if ( convFlags & cmode_remove )
  1603. return false;
  1604. if ( ( convFlags & cmode_add ) == cmode_add )
  1605. {
  1606. return true;
  1607. }
  1608. return false;
  1609. }
  1610. bool SentMatches( DWORD sentFlags )
  1611. {
  1612. // To match, the active flags have to have none of the remove flags and have to have all of the "add" flags
  1613. if ( sentFlags & smode_remove )
  1614. return false;
  1615. if ( ( sentFlags & smode_add ) == smode_add )
  1616. {
  1617. return true;
  1618. }
  1619. return false;
  1620. }
  1621. unsigned int cmode_remove;
  1622. unsigned int cmode_add;
  1623. unsigned int smode_remove;
  1624. unsigned int smode_add;
  1625. };
  1626. static IMESettingsTransform g_ConversionMode_CHT_ToChinese(
  1627. IME_CMODE_ALPHANUMERIC,
  1628. IME_CMODE_NATIVE | IME_CMODE_LANGUAGE,
  1629. 0,
  1630. 0 );
  1631. static IMESettingsTransform g_ConversionMode_CHT_ToEnglish(
  1632. IME_CMODE_NATIVE | IME_CMODE_LANGUAGE,
  1633. IME_CMODE_ALPHANUMERIC,
  1634. 0,
  1635. 0 );
  1636. static IMESettingsTransform g_ConversionMode_CHS_ToChinese(
  1637. IME_CMODE_ALPHANUMERIC,
  1638. IME_CMODE_NATIVE | IME_CMODE_LANGUAGE,
  1639. 0,
  1640. 0 );
  1641. static IMESettingsTransform g_ConversionMode_CHS_ToEnglish(
  1642. IME_CMODE_NATIVE | IME_CMODE_LANGUAGE,
  1643. IME_CMODE_ALPHANUMERIC,
  1644. 0,
  1645. 0 );
  1646. static IMESettingsTransform g_ConversionMode_KO_ToKorean(
  1647. IME_CMODE_ALPHANUMERIC,
  1648. IME_CMODE_NATIVE | IME_CMODE_LANGUAGE,
  1649. 0,
  1650. 0 );
  1651. static IMESettingsTransform g_ConversionMode_KO_ToEnglish(
  1652. IME_CMODE_NATIVE | IME_CMODE_LANGUAGE,
  1653. IME_CMODE_ALPHANUMERIC,
  1654. 0,
  1655. 0 );
  1656. static IMESettingsTransform g_ConversionMode_JP_Hiragana(
  1657. IME_CMODE_ALPHANUMERIC | IME_CMODE_KATAKANA,
  1658. IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE,
  1659. 0,
  1660. 0 );
  1661. static IMESettingsTransform g_ConversionMode_JP_DirectInput(
  1662. IME_CMODE_NATIVE | ( IME_CMODE_KATAKANA | IME_CMODE_LANGUAGE ) | IME_CMODE_FULLSHAPE | IME_CMODE_ROMAN,
  1663. IME_CMODE_ALPHANUMERIC,
  1664. 0,
  1665. 0 );
  1666. static IMESettingsTransform g_ConversionMode_JP_FullwidthKatakana(
  1667. IME_CMODE_ALPHANUMERIC,
  1668. IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE | IME_CMODE_ROMAN | IME_CMODE_KATAKANA | IME_CMODE_LANGUAGE,
  1669. 0,
  1670. 0 );
  1671. static IMESettingsTransform g_ConversionMode_JP_HalfwidthKatakana(
  1672. IME_CMODE_ALPHANUMERIC | IME_CMODE_FULLSHAPE,
  1673. IME_CMODE_NATIVE | IME_CMODE_ROMAN | ( IME_CMODE_KATAKANA | IME_CMODE_LANGUAGE ),
  1674. 0,
  1675. 0 );
  1676. static IMESettingsTransform g_ConversionMode_JP_FullwidthAlphanumeric(
  1677. IME_CMODE_NATIVE | ( IME_CMODE_KATAKANA | IME_CMODE_LANGUAGE ),
  1678. IME_CMODE_ALPHANUMERIC | IME_CMODE_FULLSHAPE | IME_CMODE_ROMAN,
  1679. 0,
  1680. 0 );
  1681. static IMESettingsTransform g_ConversionMode_JP_HalfwidthAlphanumeric(
  1682. IME_CMODE_NATIVE | ( IME_CMODE_KATAKANA | IME_CMODE_LANGUAGE ) | IME_CMODE_FULLSHAPE,
  1683. IME_CMODE_ALPHANUMERIC | IME_CMODE_ROMAN,
  1684. 0,
  1685. 0 );
  1686. #endif // _GAMECONSOLE
  1687. int CInputGameUI::GetIMEConversionModes( ConversionModeItem *dest, int destcount )
  1688. {
  1689. #ifndef _GAMECONSOLE
  1690. if ( dest )
  1691. {
  1692. memset( dest, 0, destcount * sizeof( ConversionModeItem ) );
  1693. }
  1694. DWORD dwConvMode = 0, dwSentMode = 0;
  1695. HIMC hImc = ImmGetContext( ( HWND )GetIMEWindow() );
  1696. if ( hImc )
  1697. {
  1698. ImmGetConversionStatus( hImc, &dwConvMode, &dwSentMode );
  1699. ImmReleaseContext( ( HWND )GetIMEWindow(), hImc );
  1700. }
  1701. LanguageIds *info = GetLanguageInfo( LOWORD( GetKeyboardLayout( 0 ) ) );
  1702. switch ( info->languageflag )
  1703. {
  1704. default:
  1705. return 0;
  1706. case TRADITIONAL_CHINESE:
  1707. // This is either native or alphanumeric
  1708. if ( dest )
  1709. {
  1710. ConversionModeItem *item;
  1711. int i = 0;
  1712. item = &dest[ i++ ];
  1713. wcsncpy( item->menuname, L"#IME_Chinese", sizeof( item->menuname ) / sizeof( wchar_t ) );
  1714. item->handleValue = (int)&g_ConversionMode_CHT_ToChinese;
  1715. item->active = g_ConversionMode_CHT_ToChinese.ConvMatches( dwConvMode );
  1716. item = &dest[ i++ ];
  1717. wcsncpy( item->menuname, L"#IME_English", sizeof( item->menuname ) / sizeof( wchar_t ) );
  1718. item->handleValue = (int)&g_ConversionMode_CHT_ToEnglish;
  1719. item->active = g_ConversionMode_CHT_ToEnglish.ConvMatches( dwConvMode );
  1720. }
  1721. return 2;
  1722. case JAPANESE:
  1723. // There are 6 Japanese modes
  1724. if ( dest )
  1725. {
  1726. ConversionModeItem *item;
  1727. int i = 0;
  1728. item = &dest[ i++ ];
  1729. wcsncpy( item->menuname, L"#IME_Hiragana", sizeof( item->menuname ) / sizeof( wchar_t ) );
  1730. item->handleValue = (int)&g_ConversionMode_JP_Hiragana;
  1731. item->active = g_ConversionMode_JP_Hiragana.ConvMatches( dwConvMode );
  1732. item = &dest[ i++ ];
  1733. wcsncpy( item->menuname, L"#IME_FullWidthKatakana", sizeof( item->menuname ) / sizeof( wchar_t ) );
  1734. item->handleValue = (int)&g_ConversionMode_JP_FullwidthKatakana;
  1735. item->active = g_ConversionMode_JP_FullwidthKatakana.ConvMatches( dwConvMode );
  1736. item = &dest[ i++ ];
  1737. wcsncpy( item->menuname, L"#IME_FullWidthAlphanumeric", sizeof( item->menuname ) / sizeof( wchar_t ) );
  1738. item->handleValue = (int)&g_ConversionMode_JP_FullwidthAlphanumeric;
  1739. item->active = g_ConversionMode_JP_FullwidthAlphanumeric.ConvMatches( dwConvMode );
  1740. item = &dest[ i++ ];
  1741. wcsncpy( item->menuname, L"#IME_HalfWidthKatakana", sizeof( item->menuname ) / sizeof( wchar_t ) );
  1742. item->handleValue = (int)&g_ConversionMode_JP_HalfwidthKatakana;
  1743. item->active = g_ConversionMode_JP_HalfwidthKatakana.ConvMatches( dwConvMode );
  1744. item = &dest[ i++ ];
  1745. wcsncpy( item->menuname, L"#IME_HalfWidthAlphanumeric", sizeof( item->menuname ) / sizeof( wchar_t ) );
  1746. item->handleValue = (int)&g_ConversionMode_JP_HalfwidthAlphanumeric;
  1747. item->active = g_ConversionMode_JP_HalfwidthAlphanumeric.ConvMatches( dwConvMode );
  1748. item = &dest[ i++ ];
  1749. wcsncpy( item->menuname, L"#IME_English", sizeof( item->menuname ) / sizeof( wchar_t ) );
  1750. item->handleValue = (int)&g_ConversionMode_JP_DirectInput;
  1751. item->active = g_ConversionMode_JP_DirectInput.ConvMatches( dwConvMode );
  1752. }
  1753. return 6;
  1754. case KOREAN:
  1755. // This is either native or alphanumeric
  1756. if ( dest )
  1757. {
  1758. ConversionModeItem *item;
  1759. int i = 0;
  1760. item = &dest[ i++ ];
  1761. wcsncpy( item->menuname, L"#IME_Korean", sizeof( item->menuname ) / sizeof( wchar_t ) );
  1762. item->handleValue = (int)&g_ConversionMode_KO_ToKorean;
  1763. item->active = g_ConversionMode_KO_ToKorean.ConvMatches( dwConvMode );
  1764. item = &dest[ i++ ];
  1765. wcsncpy( item->menuname, L"#IME_English", sizeof( item->menuname ) / sizeof( wchar_t ) );
  1766. item->handleValue = (int)&g_ConversionMode_KO_ToEnglish;
  1767. item->active = g_ConversionMode_KO_ToEnglish.ConvMatches( dwConvMode );
  1768. }
  1769. return 2;
  1770. case SIMPLIFIED_CHINESE:
  1771. // This is either native or alphanumeric
  1772. if ( dest )
  1773. {
  1774. ConversionModeItem *item;
  1775. int i = 0;
  1776. item = &dest[ i++ ];
  1777. wcsncpy( item->menuname, L"#IME_Chinese", sizeof( item->menuname ) / sizeof( wchar_t ) );
  1778. item->handleValue = (int)&g_ConversionMode_CHS_ToChinese;
  1779. item->active = g_ConversionMode_CHS_ToChinese.ConvMatches( dwConvMode );
  1780. item = &dest[ i++ ];
  1781. wcsncpy( item->menuname, L"#IME_English", sizeof( item->menuname ) / sizeof( wchar_t ) );
  1782. item->handleValue = (int)&g_ConversionMode_CHS_ToChinese;
  1783. item->active = g_ConversionMode_CHS_ToChinese.ConvMatches( dwConvMode );
  1784. }
  1785. return 2;
  1786. }
  1787. #endif
  1788. return 0;
  1789. }
  1790. #ifndef _GAMECONSOLE
  1791. static IMESettingsTransform g_SentenceMode_JP_None(
  1792. 0,
  1793. 0,
  1794. IME_SMODE_PLAURALCLAUSE | IME_SMODE_SINGLECONVERT | IME_SMODE_AUTOMATIC | IME_SMODE_PHRASEPREDICT | IME_SMODE_CONVERSATION,
  1795. IME_SMODE_NONE );
  1796. static IMESettingsTransform g_SentenceMode_JP_General(
  1797. 0,
  1798. 0,
  1799. IME_SMODE_NONE | IME_SMODE_PLAURALCLAUSE | IME_SMODE_SINGLECONVERT | IME_SMODE_AUTOMATIC | IME_SMODE_CONVERSATION,
  1800. IME_SMODE_PHRASEPREDICT
  1801. );
  1802. static IMESettingsTransform g_SentenceMode_JP_BiasNames(
  1803. 0,
  1804. 0,
  1805. IME_SMODE_NONE | IME_SMODE_PHRASEPREDICT | IME_SMODE_SINGLECONVERT | IME_SMODE_AUTOMATIC | IME_SMODE_CONVERSATION,
  1806. IME_SMODE_PLAURALCLAUSE
  1807. );
  1808. static IMESettingsTransform g_SentenceMode_JP_BiasSpeech(
  1809. 0,
  1810. 0,
  1811. IME_SMODE_NONE | IME_SMODE_PHRASEPREDICT | IME_SMODE_SINGLECONVERT | IME_SMODE_AUTOMATIC | IME_SMODE_PLAURALCLAUSE,
  1812. IME_SMODE_CONVERSATION
  1813. );
  1814. #endif // _GAMECONSOLE
  1815. int CInputGameUI::GetIMESentenceModes( SentenceModeItem *dest, int destcount )
  1816. {
  1817. #ifndef _GAMECONSOLE
  1818. if ( dest )
  1819. {
  1820. memset( dest, 0, destcount * sizeof( SentenceModeItem ) );
  1821. }
  1822. DWORD dwConvMode = 0, dwSentMode = 0;
  1823. HIMC hImc = ImmGetContext( ( HWND )GetIMEWindow() );
  1824. if ( hImc )
  1825. {
  1826. ImmGetConversionStatus( hImc, &dwConvMode, &dwSentMode );
  1827. ImmReleaseContext( ( HWND )GetIMEWindow(), hImc );
  1828. }
  1829. LanguageIds *info = GetLanguageInfo( LOWORD( GetKeyboardLayout( 0 ) ) );
  1830. switch ( info->languageflag )
  1831. {
  1832. default:
  1833. return 0;
  1834. // case TRADITIONAL_CHINESE:
  1835. // break;
  1836. case JAPANESE:
  1837. // There are 4 Japanese sentence modes
  1838. if ( dest )
  1839. {
  1840. SentenceModeItem *item;
  1841. int i = 0;
  1842. item = &dest[ i++ ];
  1843. wcsncpy( item->menuname, L"#IME_General", sizeof( item->menuname ) / sizeof( wchar_t ) );
  1844. item->handleValue = (int)&g_SentenceMode_JP_General;
  1845. item->active = g_SentenceMode_JP_General.SentMatches( dwSentMode );
  1846. item = &dest[ i++ ];
  1847. wcsncpy( item->menuname, L"#IME_BiasNames", sizeof( item->menuname ) / sizeof( wchar_t ) );
  1848. item->handleValue = (int)&g_SentenceMode_JP_BiasNames;
  1849. item->active = g_SentenceMode_JP_BiasNames.SentMatches( dwSentMode );
  1850. item = &dest[ i++ ];
  1851. wcsncpy( item->menuname, L"#IME_BiasSpeech", sizeof( item->menuname ) / sizeof( wchar_t ) );
  1852. item->handleValue = (int)&g_SentenceMode_JP_BiasSpeech;
  1853. item->active = g_SentenceMode_JP_BiasSpeech.SentMatches( dwSentMode );
  1854. item = &dest[ i++ ];
  1855. wcsncpy( item->menuname, L"#IME_NoConversion", sizeof( item->menuname ) / sizeof( wchar_t ) );
  1856. item->handleValue = (int)&g_SentenceMode_JP_None;
  1857. item->active = g_SentenceMode_JP_None.SentMatches( dwSentMode );
  1858. }
  1859. return 4;
  1860. }
  1861. #endif
  1862. return 0;
  1863. }
  1864. void CInputGameUI::OnChangeIMEConversionModeByHandle( int handleValue )
  1865. {
  1866. #ifndef _GAMECONSOLE
  1867. if ( handleValue == 0 )
  1868. return;
  1869. IMESettingsTransform *txform = ( IMESettingsTransform * )handleValue;
  1870. txform->Apply( (HWND)GetIMEWindow() );
  1871. #endif
  1872. }
  1873. void CInputGameUI::OnChangeIMESentenceModeByHandle( int handleValue )
  1874. {
  1875. }
  1876. void CInputGameUI::OnInputLanguageChanged()
  1877. {
  1878. }
  1879. void CInputGameUI::OnIMEStartComposition()
  1880. {
  1881. }
  1882. void DescribeIMEFlag( char const *string, bool value )
  1883. {
  1884. if ( value )
  1885. {
  1886. Msg( " %s\n", string );
  1887. }
  1888. }
  1889. #define IMEDesc( x ) DescribeIMEFlag( #x, flags & x );
  1890. void CInputGameUI::OnIMEComposition( int flags )
  1891. {
  1892. #ifndef _GAMECONSOLE
  1893. /*
  1894. Msg( "OnIMEComposition\n" );
  1895. IMEDesc( VGUI_GCS_COMPREADSTR );
  1896. IMEDesc( VGUI_GCS_COMPREADATTR );
  1897. IMEDesc( VGUI_GCS_COMPREADCLAUSE );
  1898. IMEDesc( VGUI_GCS_COMPSTR );
  1899. IMEDesc( VGUI_GCS_COMPATTR );
  1900. IMEDesc( VGUI_GCS_COMPCLAUSE );
  1901. IMEDesc( VGUI_GCS_CURSORPOS );
  1902. IMEDesc( VGUI_GCS_DELTASTART );
  1903. IMEDesc( VGUI_GCS_RESULTREADSTR );
  1904. IMEDesc( VGUI_GCS_RESULTREADCLAUSE );
  1905. IMEDesc( VGUI_GCS_RESULTSTR );
  1906. IMEDesc( VGUI_GCS_RESULTCLAUSE );
  1907. IMEDesc( VGUI_CS_INSERTCHAR );
  1908. IMEDesc( VGUI_CS_NOMOVECARET );
  1909. */
  1910. HIMC hIMC = ImmGetContext( ( HWND )GetIMEWindow() );
  1911. if ( hIMC )
  1912. {
  1913. if ( flags & VGUI_GCS_RESULTSTR )
  1914. {
  1915. wchar_t tempstr[ 32 ];
  1916. int len = ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, (LPVOID)tempstr, sizeof( tempstr ) );
  1917. if ( len > 0 )
  1918. {
  1919. if ((len % 2) != 0)
  1920. len++;
  1921. int numchars = len / sizeof( wchar_t );
  1922. for ( int i = 0; i < numchars; ++i )
  1923. {
  1924. InternalKeyTyped( tempstr[ i ] );
  1925. }
  1926. }
  1927. }
  1928. if ( flags & VGUI_GCS_COMPSTR )
  1929. {
  1930. wchar_t tempstr[ 256 ];
  1931. int len = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, (LPVOID)tempstr, sizeof( tempstr ) );
  1932. if ( len > 0 )
  1933. {
  1934. if ((len % 2) != 0)
  1935. len++;
  1936. int numchars = len / sizeof( wchar_t );
  1937. tempstr[ numchars ] = L'\0';
  1938. InternalSetCompositionString( tempstr );
  1939. }
  1940. }
  1941. ImmReleaseContext( ( HWND )GetIMEWindow(), hIMC );
  1942. }
  1943. #endif
  1944. }
  1945. void CInputGameUI::OnIMEEndComposition()
  1946. {
  1947. InputContext_t *pContext = GetInputContext( m_hContext );
  1948. if ( pContext )
  1949. {
  1950. // tell the current focused panel that a key was typed
  1951. PostKeyMessage( new KeyValues( "DoCompositionString", "string", L"" ) );
  1952. }
  1953. }
  1954. void CInputGameUI::DestroyCandidateList()
  1955. {
  1956. #ifndef _GAMECONSOLE
  1957. if ( _imeCandidates )
  1958. {
  1959. delete[] (char *)_imeCandidates;
  1960. _imeCandidates = 0;
  1961. }
  1962. #endif
  1963. }
  1964. void CInputGameUI::OnIMEShowCandidates()
  1965. {
  1966. #ifndef _GAMECONSOLE
  1967. DestroyCandidateList();
  1968. CreateNewCandidateList();
  1969. InternalShowCandidateWindow();
  1970. #endif
  1971. }
  1972. void CInputGameUI::OnIMECloseCandidates()
  1973. {
  1974. #ifndef _GAMECONSOLE
  1975. InternalHideCandidateWindow();
  1976. DestroyCandidateList();
  1977. #endif
  1978. }
  1979. void CInputGameUI::OnIMEChangeCandidates()
  1980. {
  1981. #ifndef _GAMECONSOLE
  1982. DestroyCandidateList();
  1983. CreateNewCandidateList();
  1984. InternalUpdateCandidateWindow();
  1985. #endif
  1986. }
  1987. void CInputGameUI::CreateNewCandidateList()
  1988. {
  1989. #ifndef _GAMECONSOLE
  1990. Assert( !_imeCandidates );
  1991. HIMC hImc = ImmGetContext( ( HWND )GetIMEWindow() );
  1992. if ( hImc )
  1993. {
  1994. DWORD numCandidates = 0;
  1995. DWORD bytes = ImmGetCandidateListCountW( hImc, &numCandidates );
  1996. if ( numCandidates > 0 )
  1997. {
  1998. DWORD buflen = bytes + 1;
  1999. char *buf = new char[ buflen ];
  2000. Q_memset( buf, 0, buflen );
  2001. CANDIDATELIST *list = ( CANDIDATELIST *)buf;
  2002. DWORD copyBytes = ImmGetCandidateListW( hImc, 0, list, buflen );
  2003. if ( copyBytes > 0 )
  2004. {
  2005. _imeCandidates = list;
  2006. }
  2007. else
  2008. {
  2009. delete[] buf;
  2010. }
  2011. }
  2012. ImmReleaseContext( ( HWND )GetIMEWindow(), hImc );
  2013. }
  2014. #endif
  2015. }
  2016. int CInputGameUI::GetCandidateListCount()
  2017. {
  2018. #ifndef _GAMECONSOLE
  2019. if ( !_imeCandidates )
  2020. return 0;
  2021. return (int)_imeCandidates->dwCount;
  2022. #else
  2023. return 0;
  2024. #endif
  2025. }
  2026. void CInputGameUI::GetCandidate( int num, wchar_t *dest, int destSizeBytes )
  2027. {
  2028. dest[ 0 ] = L'\0';
  2029. #ifndef _GAMECONSOLE
  2030. if ( num < 0 || num >= (int)_imeCandidates->dwCount )
  2031. {
  2032. return;
  2033. }
  2034. DWORD offset = *( DWORD *)( (char *)( _imeCandidates->dwOffset + num ) );
  2035. wchar_t *s = ( wchar_t *)( (char *)_imeCandidates + offset );
  2036. wcsncpy( dest, s, destSizeBytes / sizeof( wchar_t ) - 1 );
  2037. dest[ destSizeBytes / sizeof( wchar_t ) - 1 ] = L'\0';
  2038. #endif
  2039. }
  2040. int CInputGameUI::GetCandidateListSelectedItem()
  2041. {
  2042. #ifndef _GAMECONSOLE
  2043. if ( !_imeCandidates )
  2044. return 0;
  2045. return (int)_imeCandidates->dwSelection;
  2046. #else
  2047. return 0;
  2048. #endif
  2049. }
  2050. int CInputGameUI::GetCandidateListPageSize()
  2051. {
  2052. #ifndef _GAMECONSOLE
  2053. if ( !_imeCandidates )
  2054. return 0;
  2055. return (int)_imeCandidates->dwPageSize;
  2056. #else
  2057. return 0;
  2058. #endif
  2059. }
  2060. int CInputGameUI::GetCandidateListPageStart()
  2061. {
  2062. #ifndef _GAMECONSOLE
  2063. if ( !_imeCandidates )
  2064. return 0;
  2065. return (int)_imeCandidates->dwPageStart;
  2066. #else
  2067. return 0;
  2068. #endif
  2069. }
  2070. void CInputGameUI::SetCandidateListPageStart( int start )
  2071. {
  2072. #ifndef _GAMECONSOLE
  2073. HIMC hImc = ImmGetContext( ( HWND )GetIMEWindow() );
  2074. if ( hImc )
  2075. {
  2076. ImmNotifyIME( hImc, NI_SETCANDIDATE_PAGESTART, 0, start );
  2077. ImmReleaseContext( ( HWND )GetIMEWindow(), hImc );
  2078. }
  2079. #endif
  2080. }
  2081. void CInputGameUI::OnIMERecomputeModes()
  2082. {
  2083. }
  2084. //-----------------------------------------------------------------------------
  2085. // Purpose:
  2086. // Output : Returns true on success, false on failure.
  2087. //-----------------------------------------------------------------------------
  2088. bool CInputGameUI::CandidateListStartsAtOne()
  2089. {
  2090. #ifndef _GAMECONSOLE
  2091. DWORD prop = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_PROPERTY );
  2092. if ( prop & IME_PROP_CANDLIST_START_FROM_1 )
  2093. {
  2094. return true;
  2095. }
  2096. #endif
  2097. return false;
  2098. }
  2099. void CInputGameUI::SetCandidateWindowPos( int x, int y )
  2100. {
  2101. #ifndef _GAMECONSOLE
  2102. POINT point;
  2103. CANDIDATEFORM Candidate;
  2104. point.x = x;
  2105. point.y = y;
  2106. HIMC hIMC = ImmGetContext( ( HWND )GetIMEWindow() );
  2107. if ( hIMC )
  2108. {
  2109. // Set candidate window position near caret position
  2110. Candidate.dwIndex = 0;
  2111. Candidate.dwStyle = CFS_FORCE_POSITION;
  2112. Candidate.ptCurrentPos.x = point.x;
  2113. Candidate.ptCurrentPos.y = point.y;
  2114. ImmSetCandidateWindow( hIMC, &Candidate );
  2115. ImmReleaseContext( ( HWND )GetIMEWindow(),hIMC );
  2116. }
  2117. #endif
  2118. }
  2119. void CInputGameUI::InternalSetCompositionString( const wchar_t *compstr )
  2120. {
  2121. InputContext_t *pContext = GetInputContext( m_hContext );
  2122. if ( pContext )
  2123. {
  2124. // tell the current focused panel that a key was typed
  2125. PostKeyMessage( new KeyValues( "DoCompositionString", "string", compstr ) );
  2126. }
  2127. }
  2128. void CInputGameUI::InternalShowCandidateWindow()
  2129. {
  2130. InputContext_t *pContext = GetInputContext( m_hContext );
  2131. if ( pContext )
  2132. {
  2133. PostKeyMessage( new KeyValues( "DoShowIMECandidates" ) );
  2134. }
  2135. }
  2136. void CInputGameUI::InternalHideCandidateWindow()
  2137. {
  2138. InputContext_t *pContext = GetInputContext( m_hContext );
  2139. if ( pContext )
  2140. {
  2141. PostKeyMessage( new KeyValues( "DoHideIMECandidates" ) );
  2142. }
  2143. }
  2144. void CInputGameUI::InternalUpdateCandidateWindow()
  2145. {
  2146. InputContext_t *pContext = GetInputContext( m_hContext );
  2147. if ( pContext )
  2148. {
  2149. PostKeyMessage( new KeyValues( "DoUpdateIMECandidates" ) );
  2150. }
  2151. }
  2152. bool CInputGameUI::GetShouldInvertCompositionString()
  2153. {
  2154. #ifndef _GAMECONSOLE
  2155. LanguageIds *info = GetLanguageInfo( LOWORD( GetKeyboardLayout( 0 ) ) );
  2156. if ( !info )
  2157. return false;
  2158. // Only Chinese (simplified and traditional)
  2159. return info->invertcomposition;
  2160. #else
  2161. return false;
  2162. #endif
  2163. }
  2164. //-----------------------------------------------------------------------------
  2165. // Handles an input event, returns true if the event should be filtered
  2166. // from the rest of the game
  2167. //-----------------------------------------------------------------------------
  2168. bool InputGameUIHandleInputEvent( const InputEvent_t &event )
  2169. {
  2170. switch( event.m_nType )
  2171. {
  2172. case IE_ButtonPressed:
  2173. {
  2174. // NOTE: data2 is the virtual key code (data1 contains the scan-code one)
  2175. ButtonCode_t code = (ButtonCode_t)event.m_nData2;
  2176. if ( IsKeyCode( code ) || IsJoystickCode( code ) )
  2177. {
  2178. return g_pInputGameUI->InternalKeyCodePressed( code );
  2179. }
  2180. if ( IsJoystickCode( code ) )
  2181. {
  2182. return g_pInputGameUI->InternalKeyCodePressed( code );
  2183. }
  2184. if ( IsMouseCode( code ) )
  2185. {
  2186. return g_pInputGameUI->InternalMousePressed( code );
  2187. }
  2188. }
  2189. break;
  2190. case IE_ButtonReleased:
  2191. {
  2192. // NOTE: data2 is the virtual key code (data1 contains the scan-code one)
  2193. ButtonCode_t code = (ButtonCode_t)event.m_nData2;
  2194. if ( IsKeyCode( code ) || IsJoystickCode( code ) )
  2195. {
  2196. return g_pInputGameUI->InternalKeyCodeReleased( code );
  2197. }
  2198. if ( IsJoystickCode( code ) )
  2199. {
  2200. return g_pInputGameUI->InternalKeyCodeReleased( code );
  2201. }
  2202. if ( IsMouseCode( code ) )
  2203. {
  2204. return g_pInputGameUI->InternalMouseReleased( code );
  2205. }
  2206. }
  2207. break;
  2208. case IE_ButtonDoubleClicked:
  2209. {
  2210. // NOTE: data2 is the virtual key code (data1 contains the scan-code one)
  2211. ButtonCode_t code = (ButtonCode_t)event.m_nData2;
  2212. if ( IsMouseCode( code ) )
  2213. {
  2214. return g_pInputGameUI->InternalMouseDoublePressed( code );
  2215. }
  2216. }
  2217. break;
  2218. case IE_AnalogValueChanged:
  2219. {
  2220. if ( event.m_nData == MOUSE_WHEEL )
  2221. return g_pInputGameUI->InternalMouseWheeled( event.m_nData3 );
  2222. if ( event.m_nData == MOUSE_XY )
  2223. return g_pInputGameUI->InternalCursorMoved( event.m_nData2, event.m_nData3 );
  2224. }
  2225. break;
  2226. case IE_KeyCodeTyped:
  2227. {
  2228. ButtonCode_t code = (ButtonCode_t)event.m_nData;
  2229. g_pInputGameUI->InternalKeyCodeTyped( code );
  2230. }
  2231. return true;
  2232. case IE_KeyTyped:
  2233. {
  2234. ButtonCode_t code = (ButtonCode_t)event.m_nData;
  2235. g_pInputGameUI->InternalKeyTyped( code );
  2236. }
  2237. return true;
  2238. case IE_Quit:
  2239. return true;
  2240. case IE_Close:
  2241. return true;
  2242. case IE_SetCursor:
  2243. //ActivateCurrentCursor();
  2244. return true;
  2245. case IE_WindowSizeChanged:
  2246. {
  2247. g_pInputGameUI->SetWindowSize( event.m_nData, event.m_nData2 );
  2248. }
  2249. case IE_IMESetWindow:
  2250. g_pInputGameUI->SetIMEWindow( (void *)event.m_nData );
  2251. return true;
  2252. case IE_LocateMouseClick:
  2253. g_pInputGameUI->InternalCursorMoved( event.m_nData, event.m_nData2 );
  2254. return true;
  2255. case IE_InputLanguageChanged:
  2256. g_pInputGameUI->OnInputLanguageChanged();
  2257. return true;
  2258. case IE_IMEStartComposition:
  2259. g_pInputGameUI->OnIMEStartComposition();
  2260. return true;
  2261. case IE_IMEComposition:
  2262. g_pInputGameUI->OnIMEComposition( event.m_nData );
  2263. return true;
  2264. case IE_IMEEndComposition:
  2265. g_pInputGameUI->OnIMEEndComposition();
  2266. return true;
  2267. case IE_IMEShowCandidates:
  2268. g_pInputGameUI->OnIMEShowCandidates();
  2269. return true;
  2270. case IE_IMEChangeCandidates:
  2271. g_pInputGameUI->OnIMEChangeCandidates();
  2272. return true;
  2273. case IE_IMECloseCandidates:
  2274. g_pInputGameUI->OnIMECloseCandidates();
  2275. return true;
  2276. case IE_IMERecomputeModes:
  2277. g_pInputGameUI->OnIMERecomputeModes();
  2278. return true;
  2279. }
  2280. return false;
  2281. }
  2282. void CInputGameUI::OnCursorEnter( CHitArea* const & pTarget )
  2283. {
  2284. Assert( pTarget );
  2285. pTarget->OnCursorEnter();
  2286. }
  2287. void CInputGameUI::OnCursorExit( CHitArea * const & pTarget )
  2288. {
  2289. Assert( pTarget );
  2290. pTarget->OnCursorExit();
  2291. }
  2292. void CInputGameUI::OnCursorMove( CHitArea * const & pTarget, const int &x, const int &y )
  2293. {
  2294. Assert( pTarget );
  2295. pTarget->OnCursorMove( x, y );
  2296. }
  2297. void CInputGameUI::OnMouseDown( CHitArea * const & pTarget, const ButtonCode_t &code )
  2298. {
  2299. Assert( pTarget );
  2300. pTarget->OnMouseDown( code );
  2301. }
  2302. // Traps get nulled out when the up event is recieved so it is passed in here.
  2303. void CInputGameUI::OnMouseUp( CHitArea * const & pTarget, CHitArea * const & pTrap, const ButtonCode_t &code )
  2304. {
  2305. Assert( pTarget );
  2306. InputContext_t *pContext = GetInputContext( m_hContext );
  2307. // Scripts are only run if the current mouse focus is the same as the trap.
  2308. // If they aren't the same, then the user moved the mouse off the target area.
  2309. if ( code == MOUSE_LEFT )
  2310. {
  2311. pTarget->OnMouseUp( code, ( pTrap == pContext->_mouseFocus ) );
  2312. }
  2313. else if ( code == MOUSE_MIDDLE )
  2314. {
  2315. pTarget->OnMouseUp( code, ( pTrap == pContext->_mouseFocus ) );
  2316. }
  2317. else if ( code == MOUSE_RIGHT )
  2318. {
  2319. pTarget->OnMouseUp( code, ( pTrap == pContext->_mouseFocus ) );
  2320. }
  2321. }
  2322. void CInputGameUI::OnMouseDoubleClick( CHitArea * const & pTarget, const ButtonCode_t &code )
  2323. {
  2324. Assert( pTarget );
  2325. pTarget->OnMouseDoubleClick( code );
  2326. }
  2327. void CInputGameUI::OnMouseWheel( CHitArea * const & pTarget, const int &delta )
  2328. {
  2329. Assert( pTarget );
  2330. pTarget->OnMouseWheel( delta );
  2331. }
  2332. void CInputGameUI::OnKeyDown( CHitArea * const & pTarget, const ButtonCode_t &code )
  2333. {
  2334. Assert( pTarget );
  2335. pTarget->OnKeyDown( code );
  2336. }
  2337. void CInputGameUI::OnKeyUp( CHitArea * const & pTarget, const ButtonCode_t &code )
  2338. {
  2339. Assert( pTarget );
  2340. pTarget->OnKeyUp( code );
  2341. }
  2342. void CInputGameUI::OnKeyCodeTyped( CHitArea * const & pTarget, const ButtonCode_t &code )
  2343. {
  2344. Assert( pTarget );
  2345. pTarget->OnKeyCodeTyped( code );
  2346. }
  2347. void CInputGameUI::OnKeyTyped( CHitArea * const & pTarget, const wchar_t &unichar )
  2348. {
  2349. Assert( pTarget );
  2350. pTarget->OnKeyTyped( unichar );
  2351. }
  2352. void CInputGameUI::OnLoseKeyFocus( CHitArea * const & pTarget )
  2353. {
  2354. Assert( pTarget );
  2355. pTarget->OnLoseKeyFocus();
  2356. }
  2357. void CInputGameUI::OnGainKeyFocus( CHitArea * const & pTarget )
  2358. {
  2359. Assert( pTarget );
  2360. pTarget->OnGainKeyFocus();
  2361. }