input.c 23 KB

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