input.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095
  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. #if PAL_HAS_NATIVEMIDI
  886. MIDI_CheckLoop();
  887. #endif
  888. while (PAL_PollEvent(NULL));
  889. }
  890. int
  891. PAL_PollEvent(
  892. SDL_Event *event
  893. )
  894. /*++
  895. Purpose:
  896. Poll and process one event.
  897. Parameters:
  898. [OUT] event - Events polled from SDL.
  899. Return value:
  900. Return value of PAL_PollEvent.
  901. --*/
  902. {
  903. SDL_Event evt;
  904. int ret = SDL_PollEvent(&evt);
  905. if (ret != 0 && !input_event_filter(&evt, &g_InputState))
  906. {
  907. PAL_EventFilter(&evt);
  908. }
  909. if (event != NULL)
  910. {
  911. *event = evt;
  912. }
  913. return ret;
  914. }
  915. VOID
  916. PAL_RegisterInputFilter(
  917. void (*init_filter)(),
  918. int (*event_filter)(const SDL_Event *, volatile PALINPUTSTATE *),
  919. void (*shutdown_filter)()
  920. )
  921. /*++
  922. Purpose:
  923. Register caller-defined input event filter.
  924. Parameters:
  925. [IN] init_filter - Filter that will be called inside PAL_InitInput
  926. [IN] event_filter - Filter that will be called inside PAL_PollEvent,
  927. return non-zero value from this filter disables
  928. further internal event processing.
  929. [IN] shutdown_filter - Filter that will be called inside PAL_ShutdownInput
  930. Passing NULL to either parameter means the caller does not provide such filter.
  931. Return value:
  932. None.
  933. --*/
  934. {
  935. if (init_filter)
  936. input_init_filter = init_filter;
  937. if (event_filter)
  938. input_event_filter = event_filter;
  939. if (shutdown_filter)
  940. input_shutdown_filter = shutdown_filter;
  941. }