Event.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  1. /**
  2. * Copyright (c) 2006-2022 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. #include "Event.h"
  21. #include "filesystem/DroppedFile.h"
  22. #include "filesystem/Filesystem.h"
  23. #include "keyboard/sdl/Keyboard.h"
  24. #include "joystick/JoystickModule.h"
  25. #include "joystick/sdl/Joystick.h"
  26. #include "touch/sdl/Touch.h"
  27. #include "graphics/Graphics.h"
  28. #include "window/Window.h"
  29. #include "common/Exception.h"
  30. #include "audio/Audio.h"
  31. #include "common/config.h"
  32. #include "timer/Timer.h"
  33. #include <cmath>
  34. namespace love
  35. {
  36. namespace event
  37. {
  38. namespace sdl
  39. {
  40. // SDL reports mouse coordinates in the window coordinate system in OS X, but
  41. // we want them in pixel coordinates (may be different with high-DPI enabled.)
  42. static void windowToDPICoords(double *x, double *y)
  43. {
  44. auto window = Module::getInstance<window::Window>(Module::M_WINDOW);
  45. if (window)
  46. window->windowToDPICoords(x, y);
  47. }
  48. #ifndef LOVE_MACOSX
  49. static void normalizedToDPICoords(double *x, double *y)
  50. {
  51. double w = 1.0, h = 1.0;
  52. auto window = Module::getInstance<window::Window>(Module::M_WINDOW);
  53. if (window)
  54. {
  55. w = window->getWidth();
  56. h = window->getHeight();
  57. window->windowToDPICoords(&w, &h);
  58. }
  59. if (x)
  60. *x = ((*x) * w);
  61. if (y)
  62. *y = ((*y) * h);
  63. }
  64. #endif
  65. // SDL's event watch callbacks trigger when the event is actually posted inside
  66. // SDL, unlike with SDL_PollEvents. This is useful for some events which require
  67. // handling inside the function which triggered them on some backends.
  68. static int SDLCALL watchAppEvents(void * /*udata*/, SDL_Event *event)
  69. {
  70. auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
  71. switch (event->type)
  72. {
  73. // On iOS, calling any OpenGL ES function after the function which triggers
  74. // SDL_APP_DIDENTERBACKGROUND is called will kill the app, so we handle it
  75. // with an event watch callback, which will be called inside that function.
  76. case SDL_APP_DIDENTERBACKGROUND:
  77. case SDL_APP_WILLENTERFOREGROUND:
  78. if (gfx)
  79. gfx->setActive(event->type == SDL_APP_WILLENTERFOREGROUND);
  80. break;
  81. default:
  82. break;
  83. }
  84. return 1;
  85. }
  86. const char *Event::getName() const
  87. {
  88. return "love.event.sdl";
  89. }
  90. Event::Event()
  91. {
  92. if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0)
  93. throw love::Exception("Could not initialize SDL events subsystem (%s)", SDL_GetError());
  94. SDL_AddEventWatch(watchAppEvents, this);
  95. }
  96. Event::~Event()
  97. {
  98. SDL_DelEventWatch(watchAppEvents, this);
  99. SDL_QuitSubSystem(SDL_INIT_EVENTS);
  100. }
  101. void Event::pump()
  102. {
  103. exceptionIfInRenderPass("love.event.pump");
  104. SDL_Event e;
  105. while (SDL_PollEvent(&e))
  106. {
  107. Message *msg = convert(e);
  108. if (msg)
  109. {
  110. push(msg);
  111. msg->release();
  112. }
  113. }
  114. }
  115. Message *Event::wait()
  116. {
  117. exceptionIfInRenderPass("love.event.wait");
  118. SDL_Event e;
  119. if (SDL_WaitEvent(&e) != 1)
  120. return nullptr;
  121. return convert(e);
  122. }
  123. void Event::clear()
  124. {
  125. exceptionIfInRenderPass("love.event.clear");
  126. SDL_Event e;
  127. while (SDL_PollEvent(&e))
  128. {
  129. // Do nothing with 'e' ...
  130. }
  131. love::event::Event::clear();
  132. }
  133. void Event::exceptionIfInRenderPass(const char *name)
  134. {
  135. // Some core OS graphics functionality (e.g. swap buffers on some platforms)
  136. // happens inside SDL_PumpEvents - which is called by SDL_PollEvent and
  137. // friends. It's probably a bad idea to call those functions while a Canvas
  138. // is active.
  139. auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
  140. if (gfx != nullptr && gfx->isCanvasActive())
  141. throw love::Exception("%s cannot be called while a Canvas is active in love.graphics.", name);
  142. }
  143. Message *Event::convert(const SDL_Event &e)
  144. {
  145. Message *msg = nullptr;
  146. std::vector<Variant> vargs;
  147. vargs.reserve(4);
  148. love::filesystem::Filesystem *filesystem = nullptr;
  149. love::keyboard::Keyboard::Key key = love::keyboard::Keyboard::KEY_UNKNOWN;
  150. love::keyboard::Keyboard::Scancode scancode = love::keyboard::Keyboard::SCANCODE_UNKNOWN;
  151. const char *txt;
  152. const char *txt2;
  153. std::map<SDL_Keycode, love::keyboard::Keyboard::Key>::const_iterator keyit;
  154. #ifndef LOVE_MACOSX
  155. love::touch::sdl::Touch *touchmodule = nullptr;
  156. love::touch::Touch::TouchInfo touchinfo;
  157. #endif
  158. #ifdef LOVE_LINUX
  159. static bool touchNormalizationBug = false;
  160. #endif
  161. switch (e.type)
  162. {
  163. case SDL_KEYDOWN:
  164. if (e.key.repeat)
  165. {
  166. auto kb = Module::getInstance<love::keyboard::Keyboard>(Module::M_KEYBOARD);
  167. if (kb && !kb->hasKeyRepeat())
  168. break;
  169. }
  170. keyit = keys.find(e.key.keysym.sym);
  171. if (keyit != keys.end())
  172. key = keyit->second;
  173. if (!love::keyboard::Keyboard::getConstant(key, txt))
  174. txt = "unknown";
  175. love::keyboard::sdl::Keyboard::getConstant(e.key.keysym.scancode, scancode);
  176. if (!love::keyboard::Keyboard::getConstant(scancode, txt2))
  177. txt2 = "unknown";
  178. vargs.emplace_back(txt, strlen(txt));
  179. vargs.emplace_back(txt2, strlen(txt2));
  180. vargs.emplace_back(e.key.repeat != 0);
  181. msg = new Message("keypressed", vargs);
  182. break;
  183. case SDL_KEYUP:
  184. keyit = keys.find(e.key.keysym.sym);
  185. if (keyit != keys.end())
  186. key = keyit->second;
  187. if (!love::keyboard::Keyboard::getConstant(key, txt))
  188. txt = "unknown";
  189. love::keyboard::sdl::Keyboard::getConstant(e.key.keysym.scancode, scancode);
  190. if (!love::keyboard::Keyboard::getConstant(scancode, txt2))
  191. txt2 = "unknown";
  192. vargs.emplace_back(txt, strlen(txt));
  193. vargs.emplace_back(txt2, strlen(txt2));
  194. msg = new Message("keyreleased", vargs);
  195. break;
  196. case SDL_TEXTINPUT:
  197. txt = e.text.text;
  198. vargs.emplace_back(txt, strlen(txt));
  199. msg = new Message("textinput", vargs);
  200. break;
  201. case SDL_TEXTEDITING:
  202. txt = e.edit.text;
  203. vargs.emplace_back(txt, strlen(txt));
  204. vargs.emplace_back((double) e.edit.start);
  205. vargs.emplace_back((double) e.edit.length);
  206. msg = new Message("textedited", vargs);
  207. break;
  208. case SDL_MOUSEMOTION:
  209. {
  210. double x = (double) e.motion.x;
  211. double y = (double) e.motion.y;
  212. double xrel = (double) e.motion.xrel;
  213. double yrel = (double) e.motion.yrel;
  214. windowToDPICoords(&x, &y);
  215. windowToDPICoords(&xrel, &yrel);
  216. vargs.emplace_back(x);
  217. vargs.emplace_back(y);
  218. vargs.emplace_back(xrel);
  219. vargs.emplace_back(yrel);
  220. vargs.emplace_back(e.motion.which == SDL_TOUCH_MOUSEID);
  221. msg = new Message("mousemoved", vargs);
  222. }
  223. break;
  224. case SDL_MOUSEBUTTONDOWN:
  225. case SDL_MOUSEBUTTONUP:
  226. {
  227. // SDL uses button 3 for the right mouse button, but we use button 2
  228. int button = e.button.button;
  229. switch (button)
  230. {
  231. case SDL_BUTTON_RIGHT:
  232. button = 2;
  233. break;
  234. case SDL_BUTTON_MIDDLE:
  235. button = 3;
  236. break;
  237. }
  238. double px = (double) e.button.x;
  239. double py = (double) e.button.y;
  240. windowToDPICoords(&px, &py);
  241. vargs.emplace_back(px);
  242. vargs.emplace_back(py);
  243. vargs.emplace_back((double) button);
  244. vargs.emplace_back(e.button.which == SDL_TOUCH_MOUSEID);
  245. vargs.emplace_back((double) e.button.clicks);
  246. bool down = e.type == SDL_MOUSEBUTTONDOWN;
  247. msg = new Message(down ? "mousepressed" : "mousereleased", vargs);
  248. }
  249. break;
  250. case SDL_MOUSEWHEEL:
  251. vargs.emplace_back((double) e.wheel.x);
  252. vargs.emplace_back((double) e.wheel.y);
  253. msg = new Message("wheelmoved", vargs);
  254. break;
  255. case SDL_FINGERDOWN:
  256. case SDL_FINGERUP:
  257. case SDL_FINGERMOTION:
  258. // Touch events are disabled in OS X because we only actually want touch
  259. // screen events, but most touch devices in OS X aren't touch screens
  260. // (and SDL doesn't differentiate.) Non-screen touch devices like Mac
  261. // trackpads won't give touch coords in the window's coordinate-space.
  262. #ifndef LOVE_MACOSX
  263. touchinfo.id = (int64) e.tfinger.fingerId;
  264. touchinfo.x = e.tfinger.x;
  265. touchinfo.y = e.tfinger.y;
  266. touchinfo.dx = e.tfinger.dx;
  267. touchinfo.dy = e.tfinger.dy;
  268. touchinfo.pressure = e.tfinger.pressure;
  269. #ifdef LOVE_LINUX
  270. // FIXME: hacky workaround for SDL not normalizing touch coordinates in
  271. // its X11 backend: https://bugzilla.libsdl.org/show_bug.cgi?id=2307
  272. if (touchNormalizationBug || fabs(touchinfo.x) >= 1.5 || fabs(touchinfo.y) >= 1.5 || fabs(touchinfo.dx) >= 1.5 || fabs(touchinfo.dy) >= 1.5)
  273. {
  274. touchNormalizationBug = true;
  275. windowToDPICoords(&touchinfo.x, &touchinfo.y);
  276. windowToDPICoords(&touchinfo.dx, &touchinfo.dy);
  277. }
  278. else
  279. #endif
  280. {
  281. // SDL's coords are normalized to [0, 1], but we want screen coords.
  282. normalizedToDPICoords(&touchinfo.x, &touchinfo.y);
  283. normalizedToDPICoords(&touchinfo.dx, &touchinfo.dy);
  284. }
  285. // We need to update the love.touch.sdl internal state from here.
  286. touchmodule = (touch::sdl::Touch *) Module::getInstance("love.touch.sdl");
  287. if (touchmodule)
  288. touchmodule->onEvent(e.type, touchinfo);
  289. // This is a bit hackish and we lose the higher 32 bits of the id on
  290. // 32-bit systems, but SDL only ever gives id's that at most use as many
  291. // bits as can fit in a pointer (for now.)
  292. // We use lightuserdata instead of a lua_Number (double) because doubles
  293. // can't represent all possible id values on 64-bit systems.
  294. vargs.emplace_back((void *) (intptr_t) touchinfo.id);
  295. vargs.emplace_back(touchinfo.x);
  296. vargs.emplace_back(touchinfo.y);
  297. vargs.emplace_back(touchinfo.dx);
  298. vargs.emplace_back(touchinfo.dy);
  299. vargs.emplace_back(touchinfo.pressure);
  300. if (e.type == SDL_FINGERDOWN)
  301. txt = "touchpressed";
  302. else if (e.type == SDL_FINGERUP)
  303. txt = "touchreleased";
  304. else
  305. txt = "touchmoved";
  306. msg = new Message(txt, vargs);
  307. #endif
  308. break;
  309. case SDL_JOYBUTTONDOWN:
  310. case SDL_JOYBUTTONUP:
  311. case SDL_JOYAXISMOTION:
  312. case SDL_JOYBALLMOTION:
  313. case SDL_JOYHATMOTION:
  314. case SDL_JOYDEVICEADDED:
  315. case SDL_JOYDEVICEREMOVED:
  316. case SDL_CONTROLLERBUTTONDOWN:
  317. case SDL_CONTROLLERBUTTONUP:
  318. case SDL_CONTROLLERAXISMOTION:
  319. msg = convertJoystickEvent(e);
  320. break;
  321. case SDL_WINDOWEVENT:
  322. msg = convertWindowEvent(e);
  323. break;
  324. #if SDL_VERSION_ATLEAST(2, 0, 9)
  325. case SDL_DISPLAYEVENT:
  326. if (e.display.event == SDL_DISPLAYEVENT_ORIENTATION)
  327. {
  328. auto orientation = window::Window::ORIENTATION_UNKNOWN;
  329. switch ((SDL_DisplayOrientation) e.display.data1)
  330. {
  331. case SDL_ORIENTATION_UNKNOWN:
  332. default:
  333. orientation = window::Window::ORIENTATION_UNKNOWN;
  334. break;
  335. case SDL_ORIENTATION_LANDSCAPE:
  336. orientation = window::Window::ORIENTATION_LANDSCAPE;
  337. break;
  338. case SDL_ORIENTATION_LANDSCAPE_FLIPPED:
  339. orientation = window::Window::ORIENTATION_LANDSCAPE_FLIPPED;
  340. break;
  341. case SDL_ORIENTATION_PORTRAIT:
  342. orientation = window::Window::ORIENTATION_PORTRAIT;
  343. break;
  344. case SDL_ORIENTATION_PORTRAIT_FLIPPED:
  345. orientation = window::Window::ORIENTATION_PORTRAIT_FLIPPED;
  346. break;
  347. }
  348. if (!window::Window::getConstant(orientation, txt))
  349. txt = "unknown";
  350. vargs.emplace_back((double)(e.display.display + 1));
  351. vargs.emplace_back(txt, strlen(txt));
  352. msg = new Message("displayrotated", vargs);
  353. }
  354. break;
  355. #endif
  356. case SDL_DROPFILE:
  357. filesystem = Module::getInstance<filesystem::Filesystem>(Module::M_FILESYSTEM);
  358. if (filesystem != nullptr)
  359. {
  360. // Allow mounting any dropped path, so zips or dirs can be mounted.
  361. filesystem->allowMountingForPath(e.drop.file);
  362. if (filesystem->isRealDirectory(e.drop.file))
  363. {
  364. vargs.emplace_back(e.drop.file, strlen(e.drop.file));
  365. msg = new Message("directorydropped", vargs);
  366. }
  367. else
  368. {
  369. auto *file = new love::filesystem::DroppedFile(e.drop.file);
  370. vargs.emplace_back(&love::filesystem::DroppedFile::type, file);
  371. msg = new Message("filedropped", vargs);
  372. file->release();
  373. }
  374. }
  375. SDL_free(e.drop.file);
  376. break;
  377. case SDL_QUIT:
  378. case SDL_APP_TERMINATING:
  379. msg = new Message("quit");
  380. break;
  381. case SDL_APP_LOWMEMORY:
  382. msg = new Message("lowmemory");
  383. break;
  384. default:
  385. break;
  386. }
  387. return msg;
  388. }
  389. Message *Event::convertJoystickEvent(const SDL_Event &e) const
  390. {
  391. auto joymodule = Module::getInstance<joystick::JoystickModule>(Module::M_JOYSTICK);
  392. if (!joymodule)
  393. return nullptr;
  394. Message *msg = nullptr;
  395. std::vector<Variant> vargs;
  396. vargs.reserve(4);
  397. love::Type *joysticktype = &love::joystick::Joystick::type;
  398. love::joystick::Joystick *stick = nullptr;
  399. love::joystick::Joystick::Hat hat;
  400. love::joystick::Joystick::GamepadButton padbutton;
  401. love::joystick::Joystick::GamepadAxis padaxis;
  402. const char *txt;
  403. switch (e.type)
  404. {
  405. case SDL_JOYBUTTONDOWN:
  406. case SDL_JOYBUTTONUP:
  407. stick = joymodule->getJoystickFromID(e.jbutton.which);
  408. if (!stick)
  409. break;
  410. vargs.emplace_back(joysticktype, stick);
  411. vargs.emplace_back((double)(e.jbutton.button+1));
  412. msg = new Message((e.type == SDL_JOYBUTTONDOWN) ?
  413. "joystickpressed" : "joystickreleased",
  414. vargs);
  415. break;
  416. case SDL_JOYAXISMOTION:
  417. {
  418. stick = joymodule->getJoystickFromID(e.jaxis.which);
  419. if (!stick)
  420. break;
  421. vargs.emplace_back(joysticktype, stick);
  422. vargs.emplace_back((double)(e.jaxis.axis+1));
  423. float value = joystick::Joystick::clampval(e.jaxis.value / 32768.0f);
  424. vargs.emplace_back((double) value);
  425. msg = new Message("joystickaxis", vargs);
  426. }
  427. break;
  428. case SDL_JOYHATMOTION:
  429. if (!joystick::sdl::Joystick::getConstant(e.jhat.value, hat) || !joystick::Joystick::getConstant(hat, txt))
  430. break;
  431. stick = joymodule->getJoystickFromID(e.jhat.which);
  432. if (!stick)
  433. break;
  434. vargs.emplace_back(joysticktype, stick);
  435. vargs.emplace_back((double)(e.jhat.hat+1));
  436. vargs.emplace_back(txt, strlen(txt));
  437. msg = new Message("joystickhat", vargs);
  438. break;
  439. case SDL_CONTROLLERBUTTONDOWN:
  440. case SDL_CONTROLLERBUTTONUP:
  441. if (!joystick::sdl::Joystick::getConstant((SDL_GameControllerButton) e.cbutton.button, padbutton))
  442. break;
  443. if (!joystick::Joystick::getConstant(padbutton, txt))
  444. break;
  445. stick = joymodule->getJoystickFromID(e.cbutton.which);
  446. if (!stick)
  447. break;
  448. vargs.emplace_back(joysticktype, stick);
  449. vargs.emplace_back(txt, strlen(txt));
  450. msg = new Message(e.type == SDL_CONTROLLERBUTTONDOWN ?
  451. "gamepadpressed" : "gamepadreleased", vargs);
  452. break;
  453. case SDL_CONTROLLERAXISMOTION:
  454. if (joystick::sdl::Joystick::getConstant((SDL_GameControllerAxis) e.caxis.axis, padaxis))
  455. {
  456. if (!joystick::Joystick::getConstant(padaxis, txt))
  457. break;
  458. stick = joymodule->getJoystickFromID(e.caxis.which);
  459. if (!stick)
  460. break;
  461. vargs.emplace_back(joysticktype, stick);
  462. vargs.emplace_back(txt, strlen(txt));
  463. float value = joystick::Joystick::clampval(e.caxis.value / 32768.0f);
  464. vargs.emplace_back((double) value);
  465. msg = new Message("gamepadaxis", vargs);
  466. }
  467. break;
  468. case SDL_JOYDEVICEADDED:
  469. // jdevice.which is the joystick device index.
  470. stick = joymodule->addJoystick(e.jdevice.which);
  471. if (stick)
  472. {
  473. vargs.emplace_back(joysticktype, stick);
  474. msg = new Message("joystickadded", vargs);
  475. }
  476. break;
  477. case SDL_JOYDEVICEREMOVED:
  478. // jdevice.which is the joystick instance ID now.
  479. stick = joymodule->getJoystickFromID(e.jdevice.which);
  480. if (stick)
  481. {
  482. joymodule->removeJoystick(stick);
  483. vargs.emplace_back(joysticktype, stick);
  484. msg = new Message("joystickremoved", vargs);
  485. }
  486. break;
  487. default:
  488. break;
  489. }
  490. return msg;
  491. }
  492. Message *Event::convertWindowEvent(const SDL_Event &e)
  493. {
  494. Message *msg = nullptr;
  495. std::vector<Variant> vargs;
  496. vargs.reserve(4);
  497. window::Window *win = nullptr;
  498. graphics::Graphics *gfx = nullptr;
  499. if (e.type != SDL_WINDOWEVENT)
  500. return nullptr;
  501. switch (e.window.event)
  502. {
  503. case SDL_WINDOWEVENT_FOCUS_GAINED:
  504. case SDL_WINDOWEVENT_FOCUS_LOST:
  505. vargs.emplace_back(e.window.event == SDL_WINDOWEVENT_FOCUS_GAINED);
  506. msg = new Message("focus", vargs);
  507. break;
  508. case SDL_WINDOWEVENT_ENTER:
  509. case SDL_WINDOWEVENT_LEAVE:
  510. vargs.emplace_back(e.window.event == SDL_WINDOWEVENT_ENTER);
  511. msg = new Message("mousefocus", vargs);
  512. break;
  513. case SDL_WINDOWEVENT_SHOWN:
  514. case SDL_WINDOWEVENT_HIDDEN:
  515. vargs.emplace_back(e.window.event == SDL_WINDOWEVENT_SHOWN);
  516. msg = new Message("visible", vargs);
  517. break;
  518. case SDL_WINDOWEVENT_RESIZED:
  519. {
  520. double width = e.window.data1;
  521. double height = e.window.data2;
  522. gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
  523. win = Module::getInstance<window::Window>(Module::M_WINDOW);
  524. // WINDOWEVENT_SIZE_CHANGED will always occur before RESIZED.
  525. // The size values in the Window aren't necessarily the same as the
  526. // graphics size, which is what we want to output.
  527. if (gfx)
  528. {
  529. width = gfx->getWidth();
  530. height = gfx->getHeight();
  531. }
  532. else if (win)
  533. {
  534. width = win->getWidth();
  535. height = win->getHeight();
  536. windowToDPICoords(&width, &height);
  537. }
  538. vargs.emplace_back(width);
  539. vargs.emplace_back(height);
  540. msg = new Message("resize", vargs);
  541. }
  542. break;
  543. case SDL_WINDOWEVENT_SIZE_CHANGED:
  544. win = Module::getInstance<window::Window>(Module::M_WINDOW);
  545. if (win)
  546. win->onSizeChanged(e.window.data1, e.window.data2);
  547. break;
  548. case SDL_WINDOWEVENT_MINIMIZED:
  549. case SDL_WINDOWEVENT_RESTORED:
  550. #ifdef LOVE_ANDROID
  551. if (auto audio = Module::getInstance<audio::Audio>(Module::M_AUDIO))
  552. {
  553. if (e.window.event == SDL_WINDOWEVENT_MINIMIZED)
  554. {
  555. for (auto &src : pausedSources)
  556. src->release();
  557. pausedSources = audio->pause();
  558. for (auto &src : pausedSources)
  559. src->retain();
  560. }
  561. else if (e.window.event == SDL_WINDOWEVENT_RESTORED)
  562. {
  563. audio->play(pausedSources);
  564. for (auto &src : pausedSources)
  565. src->release();
  566. pausedSources.resize(0);
  567. }
  568. }
  569. #endif
  570. break;
  571. }
  572. return msg;
  573. }
  574. std::map<SDL_Keycode, love::keyboard::Keyboard::Key> Event::createKeyMap()
  575. {
  576. using love::keyboard::Keyboard;
  577. std::map<SDL_Keycode, Keyboard::Key> k;
  578. k[SDLK_UNKNOWN] = Keyboard::KEY_UNKNOWN;
  579. k[SDLK_RETURN] = Keyboard::KEY_RETURN;
  580. k[SDLK_ESCAPE] = Keyboard::KEY_ESCAPE;
  581. k[SDLK_BACKSPACE] = Keyboard::KEY_BACKSPACE;
  582. k[SDLK_TAB] = Keyboard::KEY_TAB;
  583. k[SDLK_SPACE] = Keyboard::KEY_SPACE;
  584. k[SDLK_EXCLAIM] = Keyboard::KEY_EXCLAIM;
  585. k[SDLK_QUOTEDBL] = Keyboard::KEY_QUOTEDBL;
  586. k[SDLK_HASH] = Keyboard::KEY_HASH;
  587. k[SDLK_PERCENT] = Keyboard::KEY_PERCENT;
  588. k[SDLK_DOLLAR] = Keyboard::KEY_DOLLAR;
  589. k[SDLK_AMPERSAND] = Keyboard::KEY_AMPERSAND;
  590. k[SDLK_QUOTE] = Keyboard::KEY_QUOTE;
  591. k[SDLK_LEFTPAREN] = Keyboard::KEY_LEFTPAREN;
  592. k[SDLK_RIGHTPAREN] = Keyboard::KEY_RIGHTPAREN;
  593. k[SDLK_ASTERISK] = Keyboard::KEY_ASTERISK;
  594. k[SDLK_PLUS] = Keyboard::KEY_PLUS;
  595. k[SDLK_COMMA] = Keyboard::KEY_COMMA;
  596. k[SDLK_MINUS] = Keyboard::KEY_MINUS;
  597. k[SDLK_PERIOD] = Keyboard::KEY_PERIOD;
  598. k[SDLK_SLASH] = Keyboard::KEY_SLASH;
  599. k[SDLK_0] = Keyboard::KEY_0;
  600. k[SDLK_1] = Keyboard::KEY_1;
  601. k[SDLK_2] = Keyboard::KEY_2;
  602. k[SDLK_3] = Keyboard::KEY_3;
  603. k[SDLK_4] = Keyboard::KEY_4;
  604. k[SDLK_5] = Keyboard::KEY_5;
  605. k[SDLK_6] = Keyboard::KEY_6;
  606. k[SDLK_7] = Keyboard::KEY_7;
  607. k[SDLK_8] = Keyboard::KEY_8;
  608. k[SDLK_9] = Keyboard::KEY_9;
  609. k[SDLK_COLON] = Keyboard::KEY_COLON;
  610. k[SDLK_SEMICOLON] = Keyboard::KEY_SEMICOLON;
  611. k[SDLK_LESS] = Keyboard::KEY_LESS;
  612. k[SDLK_EQUALS] = Keyboard::KEY_EQUALS;
  613. k[SDLK_GREATER] = Keyboard::KEY_GREATER;
  614. k[SDLK_QUESTION] = Keyboard::KEY_QUESTION;
  615. k[SDLK_AT] = Keyboard::KEY_AT;
  616. k[SDLK_LEFTBRACKET] = Keyboard::KEY_LEFTBRACKET;
  617. k[SDLK_BACKSLASH] = Keyboard::KEY_BACKSLASH;
  618. k[SDLK_RIGHTBRACKET] = Keyboard::KEY_RIGHTBRACKET;
  619. k[SDLK_CARET] = Keyboard::KEY_CARET;
  620. k[SDLK_UNDERSCORE] = Keyboard::KEY_UNDERSCORE;
  621. k[SDLK_BACKQUOTE] = Keyboard::KEY_BACKQUOTE;
  622. k[SDLK_a] = Keyboard::KEY_A;
  623. k[SDLK_b] = Keyboard::KEY_B;
  624. k[SDLK_c] = Keyboard::KEY_C;
  625. k[SDLK_d] = Keyboard::KEY_D;
  626. k[SDLK_e] = Keyboard::KEY_E;
  627. k[SDLK_f] = Keyboard::KEY_F;
  628. k[SDLK_g] = Keyboard::KEY_G;
  629. k[SDLK_h] = Keyboard::KEY_H;
  630. k[SDLK_i] = Keyboard::KEY_I;
  631. k[SDLK_j] = Keyboard::KEY_J;
  632. k[SDLK_k] = Keyboard::KEY_K;
  633. k[SDLK_l] = Keyboard::KEY_L;
  634. k[SDLK_m] = Keyboard::KEY_M;
  635. k[SDLK_n] = Keyboard::KEY_N;
  636. k[SDLK_o] = Keyboard::KEY_O;
  637. k[SDLK_p] = Keyboard::KEY_P;
  638. k[SDLK_q] = Keyboard::KEY_Q;
  639. k[SDLK_r] = Keyboard::KEY_R;
  640. k[SDLK_s] = Keyboard::KEY_S;
  641. k[SDLK_t] = Keyboard::KEY_T;
  642. k[SDLK_u] = Keyboard::KEY_U;
  643. k[SDLK_v] = Keyboard::KEY_V;
  644. k[SDLK_w] = Keyboard::KEY_W;
  645. k[SDLK_x] = Keyboard::KEY_X;
  646. k[SDLK_y] = Keyboard::KEY_Y;
  647. k[SDLK_z] = Keyboard::KEY_Z;
  648. k[SDLK_CAPSLOCK] = Keyboard::KEY_CAPSLOCK;
  649. k[SDLK_F1] = Keyboard::KEY_F1;
  650. k[SDLK_F2] = Keyboard::KEY_F2;
  651. k[SDLK_F3] = Keyboard::KEY_F3;
  652. k[SDLK_F4] = Keyboard::KEY_F4;
  653. k[SDLK_F5] = Keyboard::KEY_F5;
  654. k[SDLK_F6] = Keyboard::KEY_F6;
  655. k[SDLK_F7] = Keyboard::KEY_F7;
  656. k[SDLK_F8] = Keyboard::KEY_F8;
  657. k[SDLK_F9] = Keyboard::KEY_F9;
  658. k[SDLK_F10] = Keyboard::KEY_F10;
  659. k[SDLK_F11] = Keyboard::KEY_F11;
  660. k[SDLK_F12] = Keyboard::KEY_F12;
  661. k[SDLK_PRINTSCREEN] = Keyboard::KEY_PRINTSCREEN;
  662. k[SDLK_SCROLLLOCK] = Keyboard::KEY_SCROLLLOCK;
  663. k[SDLK_PAUSE] = Keyboard::KEY_PAUSE;
  664. k[SDLK_INSERT] = Keyboard::KEY_INSERT;
  665. k[SDLK_HOME] = Keyboard::KEY_HOME;
  666. k[SDLK_PAGEUP] = Keyboard::KEY_PAGEUP;
  667. k[SDLK_DELETE] = Keyboard::KEY_DELETE;
  668. k[SDLK_END] = Keyboard::KEY_END;
  669. k[SDLK_PAGEDOWN] = Keyboard::KEY_PAGEDOWN;
  670. k[SDLK_RIGHT] = Keyboard::KEY_RIGHT;
  671. k[SDLK_LEFT] = Keyboard::KEY_LEFT;
  672. k[SDLK_DOWN] = Keyboard::KEY_DOWN;
  673. k[SDLK_UP] = Keyboard::KEY_UP;
  674. k[SDLK_NUMLOCKCLEAR] = Keyboard::KEY_NUMLOCKCLEAR;
  675. k[SDLK_KP_DIVIDE] = Keyboard::KEY_KP_DIVIDE;
  676. k[SDLK_KP_MULTIPLY] = Keyboard::KEY_KP_MULTIPLY;
  677. k[SDLK_KP_MINUS] = Keyboard::KEY_KP_MINUS;
  678. k[SDLK_KP_PLUS] = Keyboard::KEY_KP_PLUS;
  679. k[SDLK_KP_ENTER] = Keyboard::KEY_KP_ENTER;
  680. k[SDLK_KP_0] = Keyboard::KEY_KP_0;
  681. k[SDLK_KP_1] = Keyboard::KEY_KP_1;
  682. k[SDLK_KP_2] = Keyboard::KEY_KP_2;
  683. k[SDLK_KP_3] = Keyboard::KEY_KP_3;
  684. k[SDLK_KP_4] = Keyboard::KEY_KP_4;
  685. k[SDLK_KP_5] = Keyboard::KEY_KP_5;
  686. k[SDLK_KP_6] = Keyboard::KEY_KP_6;
  687. k[SDLK_KP_7] = Keyboard::KEY_KP_7;
  688. k[SDLK_KP_8] = Keyboard::KEY_KP_8;
  689. k[SDLK_KP_9] = Keyboard::KEY_KP_9;
  690. k[SDLK_KP_PERIOD] = Keyboard::KEY_KP_PERIOD;
  691. k[SDLK_KP_COMMA] = Keyboard::KEY_KP_COMMA;
  692. k[SDLK_KP_EQUALS] = Keyboard::KEY_KP_EQUALS;
  693. k[SDLK_APPLICATION] = Keyboard::KEY_APPLICATION;
  694. k[SDLK_POWER] = Keyboard::KEY_POWER;
  695. k[SDLK_F13] = Keyboard::KEY_F13;
  696. k[SDLK_F14] = Keyboard::KEY_F14;
  697. k[SDLK_F15] = Keyboard::KEY_F15;
  698. k[SDLK_F16] = Keyboard::KEY_F16;
  699. k[SDLK_F17] = Keyboard::KEY_F17;
  700. k[SDLK_F18] = Keyboard::KEY_F18;
  701. k[SDLK_F19] = Keyboard::KEY_F19;
  702. k[SDLK_F20] = Keyboard::KEY_F20;
  703. k[SDLK_F21] = Keyboard::KEY_F21;
  704. k[SDLK_F22] = Keyboard::KEY_F22;
  705. k[SDLK_F23] = Keyboard::KEY_F23;
  706. k[SDLK_F24] = Keyboard::KEY_F24;
  707. k[SDLK_EXECUTE] = Keyboard::KEY_EXECUTE;
  708. k[SDLK_HELP] = Keyboard::KEY_HELP;
  709. k[SDLK_MENU] = Keyboard::KEY_MENU;
  710. k[SDLK_SELECT] = Keyboard::KEY_SELECT;
  711. k[SDLK_STOP] = Keyboard::KEY_STOP;
  712. k[SDLK_AGAIN] = Keyboard::KEY_AGAIN;
  713. k[SDLK_UNDO] = Keyboard::KEY_UNDO;
  714. k[SDLK_CUT] = Keyboard::KEY_CUT;
  715. k[SDLK_COPY] = Keyboard::KEY_COPY;
  716. k[SDLK_PASTE] = Keyboard::KEY_PASTE;
  717. k[SDLK_FIND] = Keyboard::KEY_FIND;
  718. k[SDLK_MUTE] = Keyboard::KEY_MUTE;
  719. k[SDLK_VOLUMEUP] = Keyboard::KEY_VOLUMEUP;
  720. k[SDLK_VOLUMEDOWN] = Keyboard::KEY_VOLUMEDOWN;
  721. k[SDLK_ALTERASE] = Keyboard::KEY_ALTERASE;
  722. k[SDLK_SYSREQ] = Keyboard::KEY_SYSREQ;
  723. k[SDLK_CANCEL] = Keyboard::KEY_CANCEL;
  724. k[SDLK_CLEAR] = Keyboard::KEY_CLEAR;
  725. k[SDLK_PRIOR] = Keyboard::KEY_PRIOR;
  726. k[SDLK_RETURN2] = Keyboard::KEY_RETURN2;
  727. k[SDLK_SEPARATOR] = Keyboard::KEY_SEPARATOR;
  728. k[SDLK_OUT] = Keyboard::KEY_OUT;
  729. k[SDLK_OPER] = Keyboard::KEY_OPER;
  730. k[SDLK_CLEARAGAIN] = Keyboard::KEY_CLEARAGAIN;
  731. k[SDLK_THOUSANDSSEPARATOR] = Keyboard::KEY_THOUSANDSSEPARATOR;
  732. k[SDLK_DECIMALSEPARATOR] = Keyboard::KEY_DECIMALSEPARATOR;
  733. k[SDLK_CURRENCYUNIT] = Keyboard::KEY_CURRENCYUNIT;
  734. k[SDLK_CURRENCYSUBUNIT] = Keyboard::KEY_CURRENCYSUBUNIT;
  735. k[SDLK_LCTRL] = Keyboard::KEY_LCTRL;
  736. k[SDLK_LSHIFT] = Keyboard::KEY_LSHIFT;
  737. k[SDLK_LALT] = Keyboard::KEY_LALT;
  738. k[SDLK_LGUI] = Keyboard::KEY_LGUI;
  739. k[SDLK_RCTRL] = Keyboard::KEY_RCTRL;
  740. k[SDLK_RSHIFT] = Keyboard::KEY_RSHIFT;
  741. k[SDLK_RALT] = Keyboard::KEY_RALT;
  742. k[SDLK_RGUI] = Keyboard::KEY_RGUI;
  743. k[SDLK_MODE] = Keyboard::KEY_MODE;
  744. k[SDLK_AUDIONEXT] = Keyboard::KEY_AUDIONEXT;
  745. k[SDLK_AUDIOPREV] = Keyboard::KEY_AUDIOPREV;
  746. k[SDLK_AUDIOSTOP] = Keyboard::KEY_AUDIOSTOP;
  747. k[SDLK_AUDIOPLAY] = Keyboard::KEY_AUDIOPLAY;
  748. k[SDLK_AUDIOMUTE] = Keyboard::KEY_AUDIOMUTE;
  749. k[SDLK_MEDIASELECT] = Keyboard::KEY_MEDIASELECT;
  750. k[SDLK_WWW] = Keyboard::KEY_WWW;
  751. k[SDLK_MAIL] = Keyboard::KEY_MAIL;
  752. k[SDLK_CALCULATOR] = Keyboard::KEY_CALCULATOR;
  753. k[SDLK_COMPUTER] = Keyboard::KEY_COMPUTER;
  754. k[SDLK_AC_SEARCH] = Keyboard::KEY_APP_SEARCH;
  755. k[SDLK_AC_HOME] = Keyboard::KEY_APP_HOME;
  756. k[SDLK_AC_BACK] = Keyboard::KEY_APP_BACK;
  757. k[SDLK_AC_FORWARD] = Keyboard::KEY_APP_FORWARD;
  758. k[SDLK_AC_STOP] = Keyboard::KEY_APP_STOP;
  759. k[SDLK_AC_REFRESH] = Keyboard::KEY_APP_REFRESH;
  760. k[SDLK_AC_BOOKMARKS] = Keyboard::KEY_APP_BOOKMARKS;
  761. k[SDLK_BRIGHTNESSDOWN] = Keyboard::KEY_BRIGHTNESSDOWN;
  762. k[SDLK_BRIGHTNESSUP] = Keyboard::KEY_BRIGHTNESSUP;
  763. k[SDLK_DISPLAYSWITCH] = Keyboard::KEY_DISPLAYSWITCH;
  764. k[SDLK_KBDILLUMTOGGLE] = Keyboard::KEY_KBDILLUMTOGGLE;
  765. k[SDLK_KBDILLUMDOWN] = Keyboard::KEY_KBDILLUMDOWN;
  766. k[SDLK_KBDILLUMUP] = Keyboard::KEY_KBDILLUMUP;
  767. k[SDLK_EJECT] = Keyboard::KEY_EJECT;
  768. k[SDLK_SLEEP] = Keyboard::KEY_SLEEP;
  769. #ifdef LOVE_ANDROID
  770. k[SDLK_AC_BACK] = Keyboard::KEY_ESCAPE;
  771. #endif
  772. return k;
  773. }
  774. std::map<SDL_Keycode, love::keyboard::Keyboard::Key> Event::keys = Event::createKeyMap();
  775. } // sdl
  776. } // event
  777. } // love