123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768 |
- /**
- * Copyright (c) 2006-2024 LOVE Development Team
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- **/
- #include "Event.h"
- #include "common/int.h"
- #include "filesystem/NativeFile.h"
- #include "filesystem/Filesystem.h"
- #include "keyboard/sdl/Keyboard.h"
- #include "joystick/JoystickModule.h"
- #include "touch/sdl/Touch.h"
- #include "graphics/Graphics.h"
- #include "window/Window.h"
- #include "common/Exception.h"
- #include "audio/Audio.h"
- #include "common/config.h"
- #include "timer/Timer.h"
- #include "sensor/sdl/Sensor.h"
- #include <cmath>
- #include "joystick/sdl/Joystick.h"
- namespace love
- {
- namespace event
- {
- namespace sdl
- {
- // SDL reports mouse coordinates in the window coordinate system in OS X, but
- // we want them in pixel coordinates (may be different with high-DPI enabled.)
- static void windowToDPICoords(double *x, double *y)
- {
- auto window = Module::getInstance<window::Window>(Module::M_WINDOW);
- if (window)
- window->windowToDPICoords(x, y);
- }
- static void clampToWindow(double *x, double *y)
- {
- auto window = Module::getInstance<window::Window>(Module::M_WINDOW);
- if (window)
- window->clampPositionInWindow(x, y);
- }
- static void normalizedToDPICoords(double *x, double *y)
- {
- double w = 1.0, h = 1.0;
- auto window = Module::getInstance<window::Window>(Module::M_WINDOW);
- if (window)
- {
- w = window->getWidth();
- h = window->getHeight();
- window->windowToDPICoords(&w, &h);
- }
- if (x)
- *x = ((*x) * w);
- if (y)
- *y = ((*y) * h);
- }
- // SDL's event watch callbacks trigger when the event is actually posted inside
- // SDL, unlike with SDL_PollEvents. This is useful for some events which require
- // handling inside the function which triggered them on some backends.
- static bool SDLCALL watchAppEvents(void * /*udata*/, SDL_Event *event)
- {
- auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
- switch (event->type)
- {
- // On iOS, calling any OpenGL ES function after the function which triggers
- // SDL_APP_DIDENTERBACKGROUND is called will kill the app, so we handle it
- // with an event watch callback, which will be called inside that function.
- case SDL_EVENT_DID_ENTER_BACKGROUND:
- case SDL_EVENT_WILL_ENTER_FOREGROUND:
- if (gfx)
- gfx->setActive(event->type == SDL_EVENT_WILL_ENTER_FOREGROUND);
- break;
- default:
- break;
- }
- return 1;
- }
- Event::Event()
- : love::event::Event("love.event.sdl")
- {
- if (!SDL_InitSubSystem(SDL_INIT_EVENTS))
- throw love::Exception("Could not initialize SDL events subsystem (%s)", SDL_GetError());
- SDL_AddEventWatch(watchAppEvents, this);
- }
- Event::~Event()
- {
- SDL_RemoveEventWatch(watchAppEvents, this);
- SDL_QuitSubSystem(SDL_INIT_EVENTS);
- }
- void Event::pump(float waitTimeout)
- {
- exceptionIfInRenderPass("love.event.pump");
- int waitTimeoutMS = 0;
- if (std::isinf(waitTimeout) || waitTimeout < 0.0f)
- waitTimeoutMS = -1; // Wait forever.
- else if (waitTimeout > 0.0f)
- waitTimeoutMS = (int)std::min<int64>(LOVE_INT32_MAX, 1000LL * waitTimeout);
- // Wait for the first event, if requested.
- SDL_Event e;
- if (SDL_WaitEventTimeout(&e, waitTimeoutMS))
- {
- StrongRef<Message> msg(convert(e), Acquire::NORETAIN);
- if (msg)
- push(msg);
- // Fetch any extra events that came in during WaitEvent.
- while (SDL_PollEvent(&e))
- {
- msg.set(convert(e), Acquire::NORETAIN);
- if (msg)
- push(msg);
- }
- }
- }
- Message *Event::wait()
- {
- exceptionIfInRenderPass("love.event.wait");
- SDL_Event e;
- if (!SDL_WaitEvent(&e))
- return nullptr;
- return convert(e);
- }
- void Event::clear()
- {
- exceptionIfInRenderPass("love.event.clear");
- SDL_Event e;
- while (SDL_PollEvent(&e))
- {
- // Do nothing with 'e' ...
- }
- love::event::Event::clear();
- }
- void Event::exceptionIfInRenderPass(const char *name)
- {
- // Some core OS graphics functionality (e.g. swap buffers on some platforms)
- // happens inside SDL_PumpEvents - which is called by SDL_PollEvent and
- // friends. It's probably a bad idea to call those functions while a RT
- // is active.
- auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
- if (gfx != nullptr && gfx->isRenderTargetActive())
- throw love::Exception("%s cannot be called while a render target is active in love.graphics.", name);
- }
- Message *Event::convert(const SDL_Event &e)
- {
- Message *msg = nullptr;
- std::vector<Variant> vargs;
- vargs.reserve(4);
- love::filesystem::Filesystem *filesystem = nullptr;
- love::sensor::Sensor *sensorInstance = nullptr;
- love::keyboard::Keyboard::Key key = love::keyboard::Keyboard::KEY_UNKNOWN;
- love::keyboard::Keyboard::Scancode scancode = love::keyboard::Keyboard::SCANCODE_UNKNOWN;
- const char *txt;
- const char *txt2;
- love::touch::sdl::Touch *touchmodule = nullptr;
- love::touch::Touch::TouchInfo touchinfo = {};
- switch (e.type)
- {
- case SDL_EVENT_KEY_DOWN:
- if (e.key.repeat)
- {
- auto kb = Module::getInstance<love::keyboard::Keyboard>(Module::M_KEYBOARD);
- if (kb && !kb->hasKeyRepeat())
- break;
- }
- love::keyboard::sdl::Keyboard::getConstant(e.key.key, key);
- if (!love::keyboard::Keyboard::getConstant(key, txt))
- txt = "unknown";
- love::keyboard::sdl::Keyboard::getConstant(e.key.scancode, scancode);
- if (!love::keyboard::Keyboard::getConstant(scancode, txt2))
- txt2 = "unknown";
- vargs.emplace_back(txt, strlen(txt));
- vargs.emplace_back(txt2, strlen(txt2));
- vargs.emplace_back(e.key.repeat != 0);
- msg = new Message("keypressed", vargs);
- break;
- case SDL_EVENT_KEY_UP:
- love::keyboard::sdl::Keyboard::getConstant(e.key.key, key);
- if (!love::keyboard::Keyboard::getConstant(key, txt))
- txt = "unknown";
- love::keyboard::sdl::Keyboard::getConstant(e.key.scancode, scancode);
- if (!love::keyboard::Keyboard::getConstant(scancode, txt2))
- txt2 = "unknown";
- vargs.emplace_back(txt, strlen(txt));
- vargs.emplace_back(txt2, strlen(txt2));
- msg = new Message("keyreleased", vargs);
- break;
- case SDL_EVENT_TEXT_INPUT:
- txt = e.text.text;
- vargs.emplace_back(txt, strlen(txt));
- msg = new Message("textinput", vargs);
- break;
- case SDL_EVENT_TEXT_EDITING:
- txt = e.edit.text;
- vargs.emplace_back(txt, strlen(txt));
- vargs.emplace_back((double) e.edit.start);
- vargs.emplace_back((double) e.edit.length);
- msg = new Message("textedited", vargs);
- break;
- case SDL_EVENT_MOUSE_MOTION:
- {
- double x = (double) e.motion.x;
- double y = (double) e.motion.y;
- double xrel = (double) e.motion.xrel;
- double yrel = (double) e.motion.yrel;
- // SDL reports mouse coordinates outside the window bounds when click-and-
- // dragging. For compatibility we clamp instead since user code may not be
- // able to handle out-of-bounds coordinates. SDL has a hint to turn off
- // auto capture, but it doesn't report the mouse's position at the edge of
- // the window if the mouse moves fast enough when it's off.
- clampToWindow(&x, &y);
- windowToDPICoords(&x, &y);
- windowToDPICoords(&xrel, &yrel);
- vargs.emplace_back(x);
- vargs.emplace_back(y);
- vargs.emplace_back(xrel);
- vargs.emplace_back(yrel);
- vargs.emplace_back(e.motion.which == SDL_TOUCH_MOUSEID);
- msg = new Message("mousemoved", vargs);
- }
- break;
- case SDL_EVENT_MOUSE_BUTTON_DOWN:
- case SDL_EVENT_MOUSE_BUTTON_UP:
- {
- // SDL uses button 3 for the right mouse button, but we use button 2
- int button = e.button.button;
- switch (button)
- {
- case SDL_BUTTON_RIGHT:
- button = 2;
- break;
- case SDL_BUTTON_MIDDLE:
- button = 3;
- break;
- }
- double px = (double) e.button.x;
- double py = (double) e.button.y;
- clampToWindow(&px, &py);
- windowToDPICoords(&px, &py);
- vargs.emplace_back(px);
- vargs.emplace_back(py);
- vargs.emplace_back((double) button);
- vargs.emplace_back(e.button.which == SDL_TOUCH_MOUSEID);
- vargs.emplace_back((double) e.button.clicks);
- bool down = e.type == SDL_EVENT_MOUSE_BUTTON_DOWN;
- msg = new Message(down ? "mousepressed" : "mousereleased", vargs);
- }
- break;
- case SDL_EVENT_MOUSE_WHEEL:
- vargs.emplace_back((double) e.wheel.x);
- vargs.emplace_back((double) e.wheel.y);
- txt = e.wheel.direction == SDL_MOUSEWHEEL_FLIPPED ? "flipped" : "standard";
- vargs.emplace_back(txt, strlen(txt));
- msg = new Message("wheelmoved", vargs);
- break;
- case SDL_EVENT_FINGER_DOWN:
- case SDL_EVENT_FINGER_UP:
- case SDL_EVENT_FINGER_MOTION:
- touchinfo.id = (int64)e.tfinger.fingerID;
- touchinfo.x = e.tfinger.x;
- touchinfo.y = e.tfinger.y;
- touchinfo.dx = e.tfinger.dx;
- touchinfo.dy = e.tfinger.dy;
- touchinfo.pressure = e.tfinger.pressure;
- touchinfo.deviceType = love::touch::sdl::Touch::getDeviceType(SDL_GetTouchDeviceType(e.tfinger.touchID));
- touchinfo.mouse = e.tfinger.touchID == SDL_MOUSE_TOUCHID;
- // SDL's coords are normalized to [0, 1], but we want screen coords for direct touches.
- if (touchinfo.deviceType == love::touch::Touch::DEVICE_TOUCHSCREEN)
- {
- normalizedToDPICoords(&touchinfo.x, &touchinfo.y);
- normalizedToDPICoords(&touchinfo.dx, &touchinfo.dy);
- }
- // We need to update the love.touch.sdl internal state from here.
- touchmodule = (touch::sdl::Touch *) Module::getInstance("love.touch.sdl");
- if (touchmodule)
- touchmodule->onEvent(e.type, touchinfo);
- if (!love::touch::Touch::getConstant(touchinfo.deviceType, txt))
- txt = "unknown";
- // This is a bit hackish and we lose the higher 32 bits of the id on
- // 32-bit systems, but SDL only ever gives id's that at most use as many
- // bits as can fit in a pointer (for now.)
- // We use lightuserdata instead of a lua_Number (double) because doubles
- // can't represent all possible id values on 64-bit systems.
- vargs.emplace_back((void *)(intptr_t)touchinfo.id);
- vargs.emplace_back(touchinfo.x);
- vargs.emplace_back(touchinfo.y);
- vargs.emplace_back(touchinfo.dx);
- vargs.emplace_back(touchinfo.dy);
- vargs.emplace_back(touchinfo.pressure);
- vargs.emplace_back(txt, strlen(txt));
- vargs.emplace_back(touchinfo.mouse);
- if (e.type == SDL_EVENT_FINGER_DOWN)
- txt = "touchpressed";
- else if (e.type == SDL_EVENT_FINGER_UP)
- txt = "touchreleased";
- else
- txt = "touchmoved";
- msg = new Message(txt, vargs);
- break;
- case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
- case SDL_EVENT_JOYSTICK_BUTTON_UP:
- case SDL_EVENT_JOYSTICK_AXIS_MOTION:
- case SDL_EVENT_JOYSTICK_HAT_MOTION:
- case SDL_EVENT_JOYSTICK_ADDED:
- case SDL_EVENT_JOYSTICK_REMOVED:
- case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
- case SDL_EVENT_GAMEPAD_BUTTON_UP:
- case SDL_EVENT_GAMEPAD_AXIS_MOTION:
- case SDL_EVENT_GAMEPAD_SENSOR_UPDATE:
- msg = convertJoystickEvent(e);
- break;
- case SDL_EVENT_WINDOW_FOCUS_GAINED:
- case SDL_EVENT_WINDOW_FOCUS_LOST:
- case SDL_EVENT_WINDOW_MOUSE_ENTER:
- case SDL_EVENT_WINDOW_MOUSE_LEAVE:
- case SDL_EVENT_WINDOW_SHOWN:
- case SDL_EVENT_WINDOW_HIDDEN:
- case SDL_EVENT_WINDOW_RESIZED:
- case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
- case SDL_EVENT_WINDOW_MINIMIZED:
- case SDL_EVENT_WINDOW_RESTORED:
- case SDL_EVENT_WINDOW_EXPOSED:
- case SDL_EVENT_WINDOW_OCCLUDED:
- msg = convertWindowEvent(e);
- break;
- case SDL_EVENT_DISPLAY_ORIENTATION:
- {
- auto orientation = window::Window::ORIENTATION_UNKNOWN;
- switch ((SDL_DisplayOrientation) e.display.data1)
- {
- case SDL_ORIENTATION_UNKNOWN:
- default:
- orientation = window::Window::ORIENTATION_UNKNOWN;
- break;
- case SDL_ORIENTATION_LANDSCAPE:
- orientation = window::Window::ORIENTATION_LANDSCAPE;
- break;
- case SDL_ORIENTATION_LANDSCAPE_FLIPPED:
- orientation = window::Window::ORIENTATION_LANDSCAPE_FLIPPED;
- break;
- case SDL_ORIENTATION_PORTRAIT:
- orientation = window::Window::ORIENTATION_PORTRAIT;
- break;
- case SDL_ORIENTATION_PORTRAIT_FLIPPED:
- orientation = window::Window::ORIENTATION_PORTRAIT_FLIPPED;
- break;
- }
- if (!window::Window::getConstant(orientation, txt))
- txt = "unknown";
- int count = 0;
- int displayindex = 0;
- SDL_DisplayID *displays = SDL_GetDisplays(&count);
- for (int i = 0; i < count; i++)
- {
- if (displays[i] == e.display.displayID)
- {
- displayindex = i;
- break;
- }
- }
- SDL_free(displays);
- vargs.emplace_back((double)(displayindex + 1));
- vargs.emplace_back(txt, strlen(txt));
- msg = new Message("displayrotated", vargs);
- }
- break;
- case SDL_EVENT_DROP_BEGIN:
- msg = new Message("dropbegan", vargs);
- break;
- case SDL_EVENT_DROP_COMPLETE:
- {
- double x = e.drop.x;
- double y = e.drop.y;
- windowToDPICoords(&x, &y);
- vargs.emplace_back(x);
- vargs.emplace_back(y);
- msg = new Message("dropcompleted", vargs);
- }
- break;
- case SDL_EVENT_DROP_POSITION:
- {
- double x = e.drop.x;
- double y = e.drop.y;
- windowToDPICoords(&x, &y);
- vargs.emplace_back(x);
- vargs.emplace_back(y);
- msg = new Message("dropmoved", vargs);
- }
- break;
- case SDL_EVENT_DROP_FILE:
- filesystem = Module::getInstance<filesystem::Filesystem>(Module::M_FILESYSTEM);
- if (filesystem != nullptr)
- {
- const char *filepath = e.drop.data;
- // Allow mounting any dropped path, so zips or dirs can be mounted.
- filesystem->allowMountingForPath(filepath);
- double x = e.drop.x;
- double y = e.drop.y;
- windowToDPICoords(&x, &y);
- if (filesystem->isRealDirectory(filepath))
- {
- vargs.emplace_back(filepath, strlen(filepath));
- vargs.emplace_back(x);
- vargs.emplace_back(y);
- msg = new Message("directorydropped", vargs);
- }
- else
- {
- auto *file = new love::filesystem::NativeFile(filepath, love::filesystem::File::MODE_CLOSED);
- vargs.emplace_back(&love::filesystem::NativeFile::type, file);
- vargs.emplace_back(x);
- vargs.emplace_back(y);
- msg = new Message("filedropped", vargs);
- file->release();
- }
- }
- break;
- case SDL_EVENT_QUIT:
- case SDL_EVENT_TERMINATING:
- msg = new Message("quit");
- break;
- case SDL_EVENT_LOW_MEMORY:
- msg = new Message("lowmemory");
- break;
- case SDL_EVENT_LOCALE_CHANGED:
- msg = new Message("localechanged");
- break;
- case SDL_EVENT_SENSOR_UPDATE:
- sensorInstance = Module::getInstance<sensor::Sensor>(M_SENSOR);
- if (sensorInstance)
- {
- std::vector<void*> sensors = sensorInstance->getHandles();
- for (void *s: sensors)
- {
- SDL_Sensor *sensor = (SDL_Sensor *) s;
- SDL_SensorID id = SDL_GetSensorID(sensor);
- if (e.sensor.which == id)
- {
- // Found sensor
- const char *sensorType;
- auto sdltype = SDL_GetSensorType(sensor);
- if (!sensor::Sensor::getConstant(sensor::sdl::Sensor::convert(sdltype), sensorType))
- sensorType = "unknown";
- vargs.emplace_back(sensorType, strlen(sensorType));
- // Both accelerometer and gyroscope only pass up to 3 values.
- // https://github.com/libsdl-org/SDL/blob/SDL2/include/SDL_sensor.h#L81-L127
- vargs.emplace_back(e.sensor.data[0]);
- vargs.emplace_back(e.sensor.data[1]);
- vargs.emplace_back(e.sensor.data[2]);
- msg = new Message("sensorupdated", vargs);
- break;
- }
- }
- }
- break;
- default:
- break;
- }
- return msg;
- }
- Message *Event::convertJoystickEvent(const SDL_Event &e) const
- {
- auto joymodule = Module::getInstance<joystick::JoystickModule>(Module::M_JOYSTICK);
- if (!joymodule)
- return nullptr;
- Message *msg = nullptr;
- std::vector<Variant> vargs;
- vargs.reserve(4);
- love::Type *joysticktype = &love::joystick::Joystick::type;
- love::joystick::Joystick *stick = nullptr;
- love::joystick::Joystick::Hat hat;
- love::joystick::Joystick::GamepadButton padbutton;
- love::joystick::Joystick::GamepadAxis padaxis;
- const char *txt;
- switch (e.type)
- {
- case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
- case SDL_EVENT_JOYSTICK_BUTTON_UP:
- stick = joymodule->getJoystickFromID(e.jbutton.which);
- if (!stick)
- break;
- vargs.emplace_back(joysticktype, stick);
- vargs.emplace_back((double)(e.jbutton.button+1));
- msg = new Message((e.type == SDL_EVENT_JOYSTICK_BUTTON_DOWN) ?
- "joystickpressed" : "joystickreleased",
- vargs);
- break;
- case SDL_EVENT_JOYSTICK_AXIS_MOTION:
- {
- stick = joymodule->getJoystickFromID(e.jaxis.which);
- if (!stick)
- break;
- vargs.emplace_back(joysticktype, stick);
- vargs.emplace_back((double)(e.jaxis.axis+1));
- float value = joystick::Joystick::clampval(e.jaxis.value / 32768.0f);
- vargs.emplace_back((double) value);
- msg = new Message("joystickaxis", vargs);
- }
- break;
- case SDL_EVENT_JOYSTICK_HAT_MOTION:
- if (!joystick::sdl::Joystick::getConstant(e.jhat.value, hat) || !joystick::Joystick::getConstant(hat, txt))
- break;
- stick = joymodule->getJoystickFromID(e.jhat.which);
- if (!stick)
- break;
- vargs.emplace_back(joysticktype, stick);
- vargs.emplace_back((double)(e.jhat.hat+1));
- vargs.emplace_back(txt, strlen(txt));
- msg = new Message("joystickhat", vargs);
- break;
- case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
- case SDL_EVENT_GAMEPAD_BUTTON_UP:
- {
- const auto &b = e.gbutton;
- if (!joystick::sdl::Joystick::getConstant((SDL_GamepadButton) b.button, padbutton))
- break;
- if (!joystick::Joystick::getConstant(padbutton, txt))
- break;
- stick = joymodule->getJoystickFromID(b.which);
- if (!stick)
- break;
- vargs.emplace_back(joysticktype, stick);
- vargs.emplace_back(txt, strlen(txt));
- msg = new Message(e.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN ?
- "gamepadpressed" : "gamepadreleased", vargs);
- }
- break;
- case SDL_EVENT_GAMEPAD_AXIS_MOTION:
- if (joystick::sdl::Joystick::getConstant((SDL_GamepadAxis) e.gaxis.axis, padaxis))
- {
- if (!joystick::Joystick::getConstant(padaxis, txt))
- break;
- const auto &a = e.gaxis;
- stick = joymodule->getJoystickFromID(a.which);
- if (!stick)
- break;
- vargs.emplace_back(joysticktype, stick);
- vargs.emplace_back(txt, strlen(txt));
- float value = joystick::Joystick::clampval(a.value / 32768.0f);
- vargs.emplace_back((double) value);
- msg = new Message("gamepadaxis", vargs);
- }
- break;
- case SDL_EVENT_JOYSTICK_ADDED:
- // jdevice.which is the joystick device index.
- stick = joymodule->addJoystick(e.jdevice.which);
- if (stick)
- {
- vargs.emplace_back(joysticktype, stick);
- msg = new Message("joystickadded", vargs);
- }
- break;
- case SDL_EVENT_JOYSTICK_REMOVED:
- // jdevice.which is the joystick instance ID now.
- stick = joymodule->getJoystickFromID(e.jdevice.which);
- if (stick)
- {
- joymodule->removeJoystick(stick);
- vargs.emplace_back(joysticktype, stick);
- msg = new Message("joystickremoved", vargs);
- }
- break;
- #if defined(LOVE_ENABLE_SENSOR)
- case SDL_EVENT_GAMEPAD_SENSOR_UPDATE:
- {
- const auto &sens = e.gsensor;
- stick = joymodule->getJoystickFromID(sens.which);
- if (stick)
- {
- using Sensor = love::sensor::Sensor;
- const char *sensorName;
- Sensor::SensorType sensorType = love::sensor::sdl::Sensor::convert((SDL_SensorType) sens.sensor);
- if (!Sensor::getConstant(sensorType, sensorName))
- sensorName = "unknown";
- vargs.emplace_back(joysticktype, stick);
- vargs.emplace_back(sensorName, strlen(sensorName));
- vargs.emplace_back(sens.data[0]);
- vargs.emplace_back(sens.data[1]);
- vargs.emplace_back(sens.data[2]);
- msg = new Message("joysticksensorupdated", vargs);
- }
- }
- break;
- #endif // defined(LOVE_ENABLE_SENSOR)
- default:
- break;
- }
- return msg;
- }
- Message *Event::convertWindowEvent(const SDL_Event &e)
- {
- Message *msg = nullptr;
- std::vector<Variant> vargs;
- vargs.reserve(4);
- window::Window *win = nullptr;
- graphics::Graphics *gfx = nullptr;
- auto event = e.type;
- switch (event)
- {
- case SDL_EVENT_WINDOW_FOCUS_GAINED:
- case SDL_EVENT_WINDOW_FOCUS_LOST:
- vargs.emplace_back(event == SDL_EVENT_WINDOW_FOCUS_GAINED);
- msg = new Message("focus", vargs);
- break;
- case SDL_EVENT_WINDOW_MOUSE_ENTER:
- case SDL_EVENT_WINDOW_MOUSE_LEAVE:
- vargs.emplace_back(event == SDL_EVENT_WINDOW_MOUSE_ENTER);
- msg = new Message("mousefocus", vargs);
- break;
- case SDL_EVENT_WINDOW_SHOWN:
- case SDL_EVENT_WINDOW_HIDDEN:
- case SDL_EVENT_WINDOW_MINIMIZED:
- case SDL_EVENT_WINDOW_RESTORED:
- #ifdef LOVE_ANDROID
- if (auto audio = Module::getInstance<audio::Audio>(Module::M_AUDIO))
- {
- if (event == SDL_EVENT_WINDOW_MINIMIZED)
- audio->pauseContext();
- else if (event == SDL_EVENT_WINDOW_RESTORED)
- audio->resumeContext();
- }
- #endif
- // WINDOW_RESTORED can also happen when going from maximized -> unmaximized,
- // but there isn't a nice way to avoid sending our event in that situation.
- vargs.emplace_back(event == SDL_EVENT_WINDOW_SHOWN || event == SDL_EVENT_WINDOW_RESTORED);
- msg = new Message("visible", vargs);
- break;
- case SDL_EVENT_WINDOW_EXPOSED:
- msg = new Message("exposed");
- break;
- case SDL_EVENT_WINDOW_OCCLUDED:
- msg = new Message("occluded");
- break;
- case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
- {
- double width = e.window.data1;
- double height = e.window.data2;
- gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
- win = Module::getInstance<window::Window>(Module::M_WINDOW);
- if (win)
- win->onSizeChanged(e.window.data1, e.window.data2);
- // The size values in the Window aren't necessarily the same as the
- // graphics size, which is what we want to output.
- if (gfx)
- {
- width = gfx->getWidth();
- height = gfx->getHeight();
- }
- else if (win)
- {
- width = win->getWidth();
- height = win->getHeight();
- windowToDPICoords(&width, &height);
- }
- vargs.emplace_back(width);
- vargs.emplace_back(height);
- msg = new Message("resize", vargs);
- }
- break;
- }
- return msg;
- }
- } // sdl
- } // event
- } // love
|