input.c 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093
  1. /* -*- mode: c; tab-width: 4; c-basic-offset: 4; c-file-style: "linux" -*- */
  2. //
  3. // Copyright (c) 2009-2011, Wei Mingzhi <whistler_wmz@users.sf.net>.
  4. // Copyright (c) 2011-2017, SDLPAL development team.
  5. // All rights reserved.
  6. //
  7. // This file is part of SDLPAL.
  8. //
  9. // SDLPAL is free software: you can redistribute it and/or modify
  10. // it under the terms of the GNU General Public License as published by
  11. // the Free Software Foundation, either version 3 of the License, or
  12. // (at your option) any later version.
  13. //
  14. // This program is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. // GNU General Public License for more details.
  18. //
  19. // You should have received a copy of the GNU General Public License
  20. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. //
  22. #include "main.h"
  23. #include <math.h>
  24. volatile PALINPUTSTATE g_InputState;
  25. #if PAL_HAS_JOYSTICKS
  26. static SDL_Joystick *g_pJoy = NULL;
  27. #endif
  28. #if !SDL_VERSION_ATLEAST(2,0,0)
  29. # define SDLK_KP_1 SDLK_KP1
  30. # define SDLK_KP_2 SDLK_KP2
  31. # define SDLK_KP_3 SDLK_KP3
  32. # define SDLK_KP_4 SDLK_KP4
  33. # define SDLK_KP_5 SDLK_KP5
  34. # define SDLK_KP_6 SDLK_KP6
  35. # define SDLK_KP_7 SDLK_KP7
  36. # define SDLK_KP_8 SDLK_KP8
  37. # define SDLK_KP_9 SDLK_KP9
  38. # define SDLK_KP_0 SDLK_KP0
  39. # define SDL_JoystickNameForIndex SDL_JoystickName
  40. #endif
  41. BOOL g_fUseJoystick = TRUE;
  42. static void _default_init_filter() {}
  43. static int _default_input_event_filter(const SDL_Event *event, volatile PALINPUTSTATE *state) { return 0; }
  44. static void _default_input_shutdown_filter() {}
  45. static void (*input_init_filter)() = _default_init_filter;
  46. static int (*input_event_filter)(const SDL_Event *, volatile PALINPUTSTATE *) = _default_input_event_filter;
  47. static void (*input_shutdown_filter)() = _default_input_shutdown_filter;
  48. static VOID
  49. PAL_KeyboardEventFilter(
  50. const SDL_Event *lpEvent
  51. )
  52. /*++
  53. Purpose:
  54. Handle keyboard events.
  55. Parameters:
  56. [IN] lpEvent - pointer to the event.
  57. Return value:
  58. None.
  59. --*/
  60. {
  61. switch (lpEvent->type)
  62. {
  63. case SDL_KEYDOWN:
  64. //
  65. // Pressed a key
  66. //
  67. if (lpEvent->key.keysym.mod & KMOD_ALT)
  68. {
  69. if (lpEvent->key.keysym.sym == SDLK_RETURN)
  70. {
  71. //
  72. // Pressed Alt+Enter (toggle fullscreen)...
  73. //
  74. VIDEO_ToggleFullscreen();
  75. return;
  76. }
  77. else if (lpEvent->key.keysym.sym == SDLK_F4)
  78. {
  79. //
  80. // Pressed Alt+F4 (Exit program)...
  81. //
  82. PAL_Shutdown(0);
  83. }
  84. }
  85. switch (lpEvent->key.keysym.sym)
  86. {
  87. case SDLK_UP:
  88. case SDLK_KP_8:
  89. if (gpGlobals->fInBattle || g_InputState.dir != kDirNorth)
  90. {
  91. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  92. g_InputState.dir = kDirNorth;
  93. g_InputState.dwKeyPress |= kKeyUp;
  94. }
  95. break;
  96. case SDLK_DOWN:
  97. case SDLK_KP_2:
  98. if (gpGlobals->fInBattle || g_InputState.dir != kDirSouth)
  99. {
  100. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  101. g_InputState.dir = kDirSouth;
  102. g_InputState.dwKeyPress |= kKeyDown;
  103. }
  104. break;
  105. case SDLK_LEFT:
  106. case SDLK_KP_4:
  107. if (gpGlobals->fInBattle || g_InputState.dir != kDirWest)
  108. {
  109. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  110. g_InputState.dir = kDirWest;
  111. g_InputState.dwKeyPress |= kKeyLeft;
  112. }
  113. break;
  114. case SDLK_RIGHT:
  115. case SDLK_KP_6:
  116. if (gpGlobals->fInBattle || g_InputState.dir != kDirEast)
  117. {
  118. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  119. g_InputState.dir = kDirEast;
  120. g_InputState.dwKeyPress |= kKeyRight;
  121. }
  122. break;
  123. case SDLK_ESCAPE:
  124. case SDLK_INSERT:
  125. case SDLK_LALT:
  126. case SDLK_RALT:
  127. case SDLK_KP_0:
  128. g_InputState.dwKeyPress |= kKeyMenu;
  129. break;
  130. case SDLK_RETURN:
  131. case SDLK_SPACE:
  132. case SDLK_KP_ENTER:
  133. case SDLK_LCTRL:
  134. g_InputState.dwKeyPress |= kKeySearch;
  135. break;
  136. case SDLK_PAGEUP:
  137. case SDLK_KP_9:
  138. g_InputState.dwKeyPress |= kKeyPgUp;
  139. break;
  140. case SDLK_PAGEDOWN:
  141. case SDLK_KP_3:
  142. g_InputState.dwKeyPress |= kKeyPgDn;
  143. break;
  144. case SDLK_HOME:
  145. g_InputState.dwKeyPress |= kKeyHome;
  146. break;
  147. case SDLK_END:
  148. g_InputState.dwKeyPress |= kKeyEnd;
  149. break;
  150. case SDLK_7: //7 for mobile device
  151. case SDLK_r:
  152. g_InputState.dwKeyPress |= kKeyRepeat;
  153. break;
  154. case SDLK_2: //2 for mobile device
  155. case SDLK_a:
  156. g_InputState.dwKeyPress |= kKeyAuto;
  157. break;
  158. case SDLK_d:
  159. g_InputState.dwKeyPress |= kKeyDefend;
  160. break;
  161. case SDLK_e:
  162. g_InputState.dwKeyPress |= kKeyUseItem;
  163. break;
  164. case SDLK_w:
  165. g_InputState.dwKeyPress |= kKeyThrowItem;
  166. break;
  167. case SDLK_q:
  168. g_InputState.dwKeyPress |= kKeyFlee;
  169. break;
  170. case SDLK_s:
  171. g_InputState.dwKeyPress |= kKeyStatus;
  172. break;
  173. case SDLK_f:
  174. case SDLK_5: // 5 for mobile device
  175. g_InputState.dwKeyPress |= kKeyForce;
  176. break;
  177. case SDLK_HASH: //# for mobile device
  178. case SDLK_p:
  179. VIDEO_SaveScreenshot();
  180. break;
  181. default:
  182. break;
  183. }
  184. break;
  185. case SDL_KEYUP:
  186. //
  187. // Released a key
  188. //
  189. switch (lpEvent->key.keysym.sym)
  190. {
  191. case SDLK_UP:
  192. case SDLK_KP_8:
  193. if (g_InputState.dir == kDirNorth)
  194. {
  195. g_InputState.dir = g_InputState.prevdir;
  196. }
  197. g_InputState.prevdir = kDirUnknown;
  198. break;
  199. case SDLK_DOWN:
  200. case SDLK_KP_2:
  201. if (g_InputState.dir == kDirSouth)
  202. {
  203. g_InputState.dir = g_InputState.prevdir;
  204. }
  205. g_InputState.prevdir = kDirUnknown;
  206. break;
  207. case SDLK_LEFT:
  208. case SDLK_KP_4:
  209. if (g_InputState.dir == kDirWest)
  210. {
  211. g_InputState.dir = g_InputState.prevdir;
  212. }
  213. g_InputState.prevdir = kDirUnknown;
  214. break;
  215. case SDLK_RIGHT:
  216. case SDLK_KP_6:
  217. if (g_InputState.dir == kDirEast)
  218. {
  219. g_InputState.dir = g_InputState.prevdir;
  220. }
  221. g_InputState.prevdir = kDirUnknown;
  222. break;
  223. default:
  224. break;
  225. }
  226. break;
  227. }
  228. }
  229. static VOID
  230. PAL_MouseEventFilter(
  231. const SDL_Event *lpEvent
  232. )
  233. /*++
  234. Purpose:
  235. Handle mouse events.
  236. Parameters:
  237. [IN] lpEvent - pointer to the event.
  238. Return value:
  239. None.
  240. --*/
  241. {
  242. #if PAL_HAS_MOUSE
  243. static short hitTest = 0; // Double click detect;
  244. const SDL_VideoInfo *vi;
  245. double screenWidth, gridWidth;
  246. double screenHeight, gridHeight;
  247. double mx, my;
  248. double thumbx;
  249. double thumby;
  250. INT gridIndex;
  251. BOOL isLeftMouseDBClick = FALSE;
  252. BOOL isLeftMouseClick = FALSE;
  253. BOOL isRightMouseClick = FALSE;
  254. static INT lastReleaseButtonTime, lastPressButtonTime, betweenTime;
  255. static INT lastPressx = 0;
  256. static INT lastPressy = 0;
  257. static INT lastReleasex = 0;
  258. static INT lastReleasey = 0;
  259. if (lpEvent->type!= SDL_MOUSEBUTTONDOWN && lpEvent->type != SDL_MOUSEBUTTONUP)
  260. return;
  261. vi = SDL_GetVideoInfo();
  262. screenWidth = vi->current_w;
  263. screenHeight = vi->current_h;
  264. gridWidth = screenWidth / 3;
  265. gridHeight = screenHeight / 3;
  266. mx = lpEvent->button.x;
  267. my = lpEvent->button.y;
  268. thumbx = ceil(mx / gridWidth);
  269. thumby = floor(my / gridHeight);
  270. gridIndex = thumbx + thumby * 3 - 1;
  271. switch (lpEvent->type)
  272. {
  273. case SDL_MOUSEBUTTONDOWN:
  274. lastPressButtonTime = SDL_GetTicks();
  275. lastPressx = lpEvent->button.x;
  276. lastPressy = lpEvent->button.y;
  277. switch (gridIndex)
  278. {
  279. case 2:
  280. g_InputState.prevdir = g_InputState.dir;
  281. g_InputState.dir = kDirNorth;
  282. break;
  283. case 6:
  284. g_InputState.prevdir = g_InputState.dir;
  285. g_InputState.dir = kDirSouth;
  286. break;
  287. case 0:
  288. g_InputState.prevdir = g_InputState.dir;
  289. g_InputState.dir = kDirWest;
  290. break;
  291. case 8:
  292. g_InputState.prevdir = g_InputState.dir;
  293. g_InputState.dir = kDirEast;
  294. break;
  295. case 1:
  296. //g_InputState.prevdir = g_InputState.dir;
  297. //g_InputState.dir = kDirNorth;
  298. g_InputState.dwKeyPress |= kKeyUp;
  299. break;
  300. case 7:
  301. //g_InputState.prevdir = g_InputState.dir;
  302. //g_InputState.dir = kDirSouth;
  303. g_InputState.dwKeyPress |= kKeyDown;
  304. break;
  305. case 3:
  306. //g_InputState.prevdir = g_InputState.dir;
  307. //g_InputState.dir = kDirWest;
  308. g_InputState.dwKeyPress |= kKeyLeft;
  309. break;
  310. case 5:
  311. //g_InputState.prevdir = g_InputState.dir;
  312. //g_InputState.dir = kDirEast;
  313. g_InputState.dwKeyPress |= kKeyRight;
  314. break;
  315. }
  316. break;
  317. case SDL_MOUSEBUTTONUP:
  318. lastReleaseButtonTime = SDL_GetTicks();
  319. lastReleasex = lpEvent->button.x;
  320. lastReleasey = lpEvent->button.y;
  321. hitTest ++;
  322. if (abs(lastPressx - lastReleasex) < 25 &&
  323. abs(lastPressy - lastReleasey) < 25)
  324. {
  325. betweenTime = lastReleaseButtonTime - lastPressButtonTime;
  326. if (betweenTime >500)
  327. {
  328. isRightMouseClick = TRUE;
  329. }
  330. else if (betweenTime >=0)
  331. {
  332. if((betweenTime < 100) && (hitTest >= 2))
  333. {
  334. isLeftMouseClick = TRUE;
  335. hitTest = 0;
  336. }
  337. else
  338. {
  339. isLeftMouseClick = TRUE;
  340. if(betweenTime > 100)
  341. {
  342. hitTest = 0;
  343. }
  344. }
  345. }
  346. }
  347. switch (gridIndex)
  348. {
  349. case 2:
  350. if( isLeftMouseDBClick )
  351. {
  352. AUDIO_IncreaseVolume();
  353. break;
  354. }
  355. case 6:
  356. case 0:
  357. if( isLeftMouseDBClick )
  358. {
  359. AUDIO_DecreaseVolume();
  360. break;
  361. }
  362. case 7:
  363. if (isRightMouseClick) //repeat attack
  364. {
  365. g_InputState.dwKeyPress |= kKeyRepeat;
  366. break;
  367. }
  368. case 8:
  369. g_InputState.dir = kDirUnknown;
  370. g_InputState.prevdir = kDirUnknown;
  371. break;
  372. case 1:
  373. if( isRightMouseClick )
  374. {
  375. g_InputState.dwKeyPress |= kKeyForce;
  376. }
  377. break;
  378. case 3:
  379. if( isRightMouseClick )
  380. {
  381. g_InputState.dwKeyPress |= kKeyAuto;
  382. }
  383. break;
  384. case 5:
  385. if( isRightMouseClick )
  386. {
  387. g_InputState.dwKeyPress |= kKeyDefend;
  388. }
  389. break;
  390. case 4:
  391. if (isRightMouseClick) // menu
  392. {
  393. g_InputState.dwKeyPress |= kKeyMenu;
  394. }
  395. else if (isLeftMouseClick) // search
  396. {
  397. g_InputState.dwKeyPress |= kKeySearch;
  398. }
  399. break;
  400. }
  401. break;
  402. }
  403. #endif
  404. }
  405. static VOID
  406. PAL_JoystickEventFilter(
  407. const SDL_Event *lpEvent
  408. )
  409. /*++
  410. Purpose:
  411. Handle joystick events.
  412. Parameters:
  413. [IN] lpEvent - pointer to the event.
  414. Return value:
  415. None.
  416. --*/
  417. {
  418. #if PAL_HAS_JOYSTICKS
  419. switch (lpEvent->type)
  420. {
  421. case SDL_JOYAXISMOTION:
  422. //
  423. // Moved an axis on joystick
  424. //
  425. switch (lpEvent->jaxis.axis)
  426. {
  427. case 0:
  428. //
  429. // X axis
  430. //
  431. if (lpEvent->jaxis.value > 20000)
  432. {
  433. if (g_InputState.dir != kDirEast)
  434. {
  435. g_InputState.dwKeyPress |= kKeyRight;
  436. }
  437. g_InputState.prevdir = g_InputState.dir;
  438. g_InputState.dir = kDirEast;
  439. }
  440. else if (lpEvent->jaxis.value < -20000)
  441. {
  442. if (g_InputState.dir != kDirWest)
  443. {
  444. g_InputState.dwKeyPress |= kKeyLeft;
  445. }
  446. g_InputState.prevdir = g_InputState.dir;
  447. g_InputState.dir = kDirWest;
  448. }
  449. else
  450. {
  451. if (g_InputState.prevdir != kDirEast &&
  452. g_InputState.prevdir != kDirWest)
  453. {
  454. g_InputState.dir = g_InputState.prevdir;
  455. }
  456. g_InputState.prevdir = kDirUnknown;
  457. }
  458. break;
  459. case 1:
  460. //
  461. // Y axis
  462. //
  463. if (lpEvent->jaxis.value > 20000)
  464. {
  465. if (g_InputState.dir != kDirSouth)
  466. {
  467. g_InputState.dwKeyPress |= kKeyDown;
  468. }
  469. g_InputState.prevdir = g_InputState.dir;
  470. g_InputState.dir = kDirSouth;
  471. }
  472. else if (lpEvent->jaxis.value < -20000)
  473. {
  474. if (g_InputState.dir != kDirNorth)
  475. {
  476. g_InputState.dwKeyPress |= kKeyUp;
  477. }
  478. g_InputState.prevdir = g_InputState.dir;
  479. g_InputState.dir = kDirNorth;
  480. }
  481. else
  482. {
  483. if (g_InputState.prevdir != kDirNorth &&
  484. g_InputState.prevdir != kDirSouth)
  485. {
  486. g_InputState.dir = g_InputState.prevdir;
  487. }
  488. g_InputState.prevdir = kDirUnknown;
  489. }
  490. break;
  491. }
  492. break;
  493. case SDL_JOYBUTTONDOWN:
  494. //
  495. // Pressed the joystick button
  496. //
  497. switch (lpEvent->jbutton.button & 1)
  498. {
  499. case 0:
  500. g_InputState.dwKeyPress |= kKeyMenu;
  501. break;
  502. case 1:
  503. g_InputState.dwKeyPress |= kKeySearch;
  504. break;
  505. }
  506. break;
  507. }
  508. #endif
  509. }
  510. #if PAL_HAS_TOUCH
  511. #define TOUCH_NONE 0
  512. #define TOUCH_UP 1
  513. #define TOUCH_DOWN 2
  514. #define TOUCH_LEFT 3
  515. #define TOUCH_RIGHT 4
  516. #define TOUCH_BUTTON1 5
  517. #define TOUCH_BUTTON2 6
  518. #define TOUCH_BUTTON3 7
  519. #define TOUCH_BUTTON4 8
  520. static float gfTouchXMin = 0.0f;
  521. static float gfTouchXMax = 1.0f;
  522. static float gfTouchYMin = 0.0f;
  523. static float gfTouchYMax = 1.0f;
  524. VOID
  525. PAL_SetTouchBounds(
  526. DWORD dwScreenWidth,
  527. DWORD dwScreenHeight,
  528. SDL_Rect renderRect
  529. )
  530. {
  531. gfTouchXMin = (float)renderRect.x / dwScreenWidth;
  532. gfTouchXMax = (float)(renderRect.x + renderRect.w) / dwScreenWidth;
  533. gfTouchYMin = (float)renderRect.y / dwScreenHeight;
  534. gfTouchYMax = (float)(renderRect.y + renderRect.h) / dwScreenHeight;
  535. }
  536. static int
  537. PAL_GetTouchArea(
  538. float X,
  539. float Y
  540. )
  541. {
  542. if (X < gfTouchXMin || X > gfTouchXMax || Y < 0.5f || Y > gfTouchYMax)
  543. {
  544. //
  545. // Upper area or cropped area
  546. //
  547. return TOUCH_NONE;
  548. }
  549. else
  550. {
  551. X = (X - gfTouchXMin) / (gfTouchXMax - gfTouchXMin);
  552. Y = (Y - gfTouchYMin) / (gfTouchYMax - gfTouchYMin);
  553. }
  554. if (X < 1.0f / 3)
  555. {
  556. if (Y - 0.5f < (1.0f / 6 - fabsf(X - 1.0f / 3 / 2)) * (0.5f / (1.0f / 3)))
  557. {
  558. return TOUCH_UP;
  559. }
  560. else if (Y - 0.75f > fabsf(X - 1.0f / 3 / 2) * (0.5f / (1.0f / 3)))
  561. {
  562. return TOUCH_DOWN;
  563. }
  564. else if (X < 1.0f / 3 / 2 && fabsf(Y - 0.75f) < 0.25f - X * (0.5f / (1.0f / 3)))
  565. {
  566. return TOUCH_LEFT;
  567. }
  568. else
  569. {
  570. return TOUCH_RIGHT;
  571. }
  572. }
  573. else if (X > 1.0f - 1.0f / 3)
  574. {
  575. if (X < 1.0f - (1.0f / 3 / 2))
  576. {
  577. if (Y < 0.75f)
  578. {
  579. return TOUCH_BUTTON1;
  580. }
  581. else
  582. {
  583. return TOUCH_BUTTON3;
  584. }
  585. }
  586. else
  587. {
  588. if (Y < 0.75f)
  589. {
  590. return TOUCH_BUTTON2;
  591. }
  592. else
  593. {
  594. return TOUCH_BUTTON4;
  595. }
  596. }
  597. }
  598. else
  599. {
  600. return TOUCH_NONE;
  601. }
  602. }
  603. static VOID
  604. PAL_SetTouchAction(
  605. int area
  606. )
  607. {
  608. switch (area)
  609. {
  610. case TOUCH_UP:
  611. g_InputState.dir = kDirNorth;
  612. g_InputState.dwKeyPress |= kKeyUp;
  613. break;
  614. case TOUCH_DOWN:
  615. g_InputState.dir = kDirSouth;
  616. g_InputState.dwKeyPress |= kKeyDown;
  617. break;
  618. case TOUCH_LEFT:
  619. g_InputState.dir = kDirWest;
  620. g_InputState.dwKeyPress |= kKeyLeft;
  621. break;
  622. case TOUCH_RIGHT:
  623. g_InputState.dir = kDirEast;
  624. g_InputState.dwKeyPress |= kKeyRight;
  625. break;
  626. case TOUCH_BUTTON1:
  627. if (gpGlobals->fInBattle)
  628. {
  629. g_InputState.dwKeyPress |= kKeyRepeat;
  630. }
  631. else
  632. {
  633. g_InputState.dwKeyPress |= kKeyForce;
  634. }
  635. break;
  636. case TOUCH_BUTTON2:
  637. g_InputState.dwKeyPress |= kKeyMenu;
  638. break;
  639. case TOUCH_BUTTON3:
  640. g_InputState.dwKeyPress |= kKeyUseItem;
  641. break;
  642. case TOUCH_BUTTON4:
  643. g_InputState.dwKeyPress |= kKeySearch;
  644. break;
  645. }
  646. }
  647. static VOID
  648. PAL_UnsetTouchAction(
  649. int area
  650. )
  651. {
  652. switch (area)
  653. {
  654. case TOUCH_UP:
  655. case TOUCH_DOWN:
  656. case TOUCH_LEFT:
  657. case TOUCH_RIGHT:
  658. g_InputState.dir = kDirUnknown;
  659. break;
  660. }
  661. }
  662. #endif
  663. static VOID
  664. PAL_TouchEventFilter(
  665. const SDL_Event *lpEvent
  666. )
  667. /*++
  668. Purpose:
  669. Handle touch events.
  670. Parameters:
  671. [IN] lpEvent - pointer to the event.
  672. Return value:
  673. None.
  674. --*/
  675. {
  676. #if PAL_HAS_TOUCH
  677. static SDL_TouchID finger1 = -1, finger2 = -1;
  678. static int prev_touch1 = TOUCH_NONE;
  679. static int prev_touch2 = TOUCH_NONE;
  680. switch (lpEvent->type)
  681. {
  682. case SDL_FINGERDOWN:
  683. if (finger1 == -1)
  684. {
  685. int area = PAL_GetTouchArea(lpEvent->tfinger.x, lpEvent->tfinger.y);
  686. finger1 = lpEvent->tfinger.fingerId;
  687. prev_touch1 = area;
  688. PAL_SetTouchAction(area);
  689. }
  690. else if (finger2 == -1)
  691. {
  692. int area = PAL_GetTouchArea(lpEvent->tfinger.x, lpEvent->tfinger.y);
  693. finger2 = lpEvent->tfinger.fingerId;
  694. prev_touch2 = area;
  695. PAL_SetTouchAction(area);
  696. }
  697. break;
  698. case SDL_FINGERUP:
  699. if (lpEvent->tfinger.fingerId == finger1)
  700. {
  701. PAL_UnsetTouchAction(prev_touch1);
  702. finger1 = -1;
  703. prev_touch1 = TOUCH_NONE;
  704. }
  705. else if (lpEvent->tfinger.fingerId == finger2)
  706. {
  707. PAL_UnsetTouchAction(prev_touch2);
  708. finger2 = -1;
  709. prev_touch2 = TOUCH_NONE;
  710. }
  711. break;
  712. case SDL_FINGERMOTION:
  713. if (lpEvent->tfinger.fingerId == finger1)
  714. {
  715. int area = PAL_GetTouchArea(lpEvent->tfinger.x, lpEvent->tfinger.y);
  716. if (prev_touch1 != area && area != TOUCH_NONE)
  717. {
  718. PAL_UnsetTouchAction(prev_touch1);
  719. prev_touch1 = area;
  720. PAL_SetTouchAction(area);
  721. }
  722. }
  723. else if (lpEvent->tfinger.fingerId == finger2)
  724. {
  725. int area = PAL_GetTouchArea(lpEvent->tfinger.x, lpEvent->tfinger.y);
  726. if (prev_touch2 != area && area != TOUCH_NONE)
  727. {
  728. PAL_UnsetTouchAction(prev_touch2);
  729. prev_touch2 = area;
  730. PAL_SetTouchAction(area);
  731. }
  732. }
  733. break;
  734. }
  735. #endif
  736. }
  737. static int SDLCALL
  738. PAL_EventFilter(
  739. const SDL_Event *lpEvent
  740. )
  741. /*++
  742. Purpose:
  743. SDL event filter function. A filter to process all events.
  744. Parameters:
  745. [IN] lpEvent - pointer to the event.
  746. Return value:
  747. 1 = the event will be added to the internal queue.
  748. 0 = the event will be dropped from the queue.
  749. --*/
  750. {
  751. switch (lpEvent->type)
  752. {
  753. #if SDL_VERSION_ATLEAST(2,0,0)
  754. case SDL_WINDOWEVENT:
  755. if (lpEvent->window.event == SDL_WINDOWEVENT_RESIZED)
  756. {
  757. //
  758. // resized the window
  759. //
  760. VIDEO_Resize(lpEvent->window.data1, lpEvent->window.data2);
  761. }
  762. break;
  763. case SDL_APP_WILLENTERBACKGROUND:
  764. g_bRenderPaused = TRUE;
  765. break;
  766. case SDL_APP_DIDENTERFOREGROUND:
  767. g_bRenderPaused = FALSE;
  768. VIDEO_UpdateScreen(NULL);
  769. break;
  770. #else
  771. case SDL_VIDEORESIZE:
  772. //
  773. // resized the window
  774. //
  775. VIDEO_Resize(lpEvent->resize.w, lpEvent->resize.h);
  776. break;
  777. #endif
  778. case SDL_QUIT:
  779. //
  780. // clicked on the close button of the window. Quit immediately.
  781. //
  782. PAL_Shutdown(0);
  783. }
  784. PAL_KeyboardEventFilter(lpEvent);
  785. PAL_MouseEventFilter(lpEvent);
  786. PAL_JoystickEventFilter(lpEvent);
  787. PAL_TouchEventFilter(lpEvent);
  788. //
  789. // All events are handled here; don't put anything to the internal queue
  790. //
  791. return 0;
  792. }
  793. VOID
  794. PAL_ClearKeyState(
  795. VOID
  796. )
  797. /*++
  798. Purpose:
  799. Clear the record of pressed keys.
  800. Parameters:
  801. None.
  802. Return value:
  803. None.
  804. --*/
  805. {
  806. g_InputState.dwKeyPress = 0;
  807. }
  808. VOID
  809. PAL_InitInput(
  810. VOID
  811. )
  812. /*++
  813. Purpose:
  814. Initialize the input subsystem.
  815. Parameters:
  816. None.
  817. Return value:
  818. None.
  819. --*/
  820. {
  821. memset((void *)&g_InputState, 0, sizeof(g_InputState));
  822. g_InputState.dir = kDirUnknown;
  823. g_InputState.prevdir = kDirUnknown;
  824. //
  825. // Check for joystick
  826. //
  827. #if PAL_HAS_JOYSTICKS
  828. if (SDL_NumJoysticks() > 0 && g_fUseJoystick)
  829. {
  830. int i;
  831. for (i = 0; i < SDL_NumJoysticks(); i++)
  832. {
  833. if (PAL_IS_VALID_JOYSTICK(SDL_JoystickNameForIndex(i)))
  834. {
  835. g_pJoy = SDL_JoystickOpen(i);
  836. break;
  837. }
  838. }
  839. if (g_pJoy != NULL)
  840. {
  841. SDL_JoystickEventState(SDL_ENABLE);
  842. }
  843. }
  844. #endif
  845. #ifdef PAL_ALLOW_KEYREPEAT
  846. SDL_EnableKeyRepeat(0, 0);
  847. #endif
  848. input_init_filter();
  849. }
  850. VOID
  851. PAL_ShutdownInput(
  852. VOID
  853. )
  854. /*++
  855. Purpose:
  856. Shutdown the input subsystem.
  857. Parameters:
  858. None.
  859. Return value:
  860. None.
  861. --*/
  862. {
  863. #if PAL_HAS_JOYSTICKS
  864. if (g_pJoy != NULL)
  865. {
  866. SDL_JoystickClose(g_pJoy);
  867. g_pJoy = NULL;
  868. }
  869. #endif
  870. input_shutdown_filter();
  871. }
  872. VOID
  873. PAL_ProcessEvent(
  874. VOID
  875. )
  876. /*++
  877. Purpose:
  878. Process all events.
  879. Parameters:
  880. None.
  881. Return value:
  882. None.
  883. --*/
  884. {
  885. MIDI_CheckLoop();
  886. while (PAL_PollEvent(NULL));
  887. }
  888. int
  889. PAL_PollEvent(
  890. SDL_Event *event
  891. )
  892. /*++
  893. Purpose:
  894. Poll and process one event.
  895. Parameters:
  896. [OUT] event - Events polled from SDL.
  897. Return value:
  898. Return value of PAL_PollEvent.
  899. --*/
  900. {
  901. SDL_Event evt;
  902. int ret = SDL_PollEvent(&evt);
  903. if (ret != 0 && !input_event_filter(&evt, &g_InputState))
  904. {
  905. PAL_EventFilter(&evt);
  906. }
  907. if (event != NULL)
  908. {
  909. *event = evt;
  910. }
  911. return ret;
  912. }
  913. VOID
  914. PAL_RegisterInputFilter(
  915. void (*init_filter)(),
  916. int (*event_filter)(const SDL_Event *, volatile PALINPUTSTATE *),
  917. void (*shutdown_filter)()
  918. )
  919. /*++
  920. Purpose:
  921. Register caller-defined input event filter.
  922. Parameters:
  923. [IN] init_filter - Filter that will be called inside PAL_InitInput
  924. [IN] event_filter - Filter that will be called inside PAL_PollEvent,
  925. return non-zero value from this filter disables
  926. further internal event processing.
  927. [IN] shutdown_filter - Filter that will be called inside PAL_ShutdownInput
  928. Passing NULL to either parameter means the caller does not provide such filter.
  929. Return value:
  930. None.
  931. --*/
  932. {
  933. if (init_filter)
  934. input_init_filter = init_filter;
  935. if (event_filter)
  936. input_event_filter = event_filter;
  937. if (shutdown_filter)
  938. input_shutdown_filter = shutdown_filter;
  939. }