#include "engine/events.hpp" #include #ifdef USE_SDL3 #include #include #else #include #ifdef USE_SDL1 #include "utils/sdl2_to_1_2_backports.h" #endif #endif #include "controls/input.h" #include "controls/padmapper.hpp" #include "engine/demomode.h" #include "engine/render/primitive_render.hpp" #include "interfac.h" #include "movie.h" #include "options.h" #include "panels/console.hpp" #include "utils/display.h" #include "utils/is_of.hpp" #include "utils/log.hpp" #include "utils/sdl_compat.h" #ifndef USE_SDL1 #include "controls/touch/event_handlers.h" #endif #ifdef __vita__ #include "diablo.h" #include "platform/vita/touch.h" #endif #ifdef __SWITCH__ #include "platform/switch/docking.h" #include #endif namespace devilution { namespace { bool FalseAvail(const char *name, int value) { LogVerbose("Unhandled SDL event: {} {}", name, value); return true; } bool FetchMessage_Real(SDL_Event *event, uint16_t *modState) { #ifdef __SWITCH__ HandleDocking(); #endif SDL_Event e; if (!PollEvent(&e)) return false; event->type = static_cast(0); *modState = SDL_GetModState(); #ifdef __vita__ HandleTouchEvent(&e, MousePosition); #elif !defined(USE_SDL1) HandleTouchEvent(e); #endif if (e.type == SDL_EVENT_QUIT || IsCustomEvent(e.type)) { *event = e; return true; } // Erroneous events generated by RG350 kernel. if (IsAnyOf(e.type, SDL_EVENT_KEY_DOWN, SDL_EVENT_KEY_UP) && SDLC_EventKey(e) == SDLK_UNKNOWN) return true; #if !defined(USE_SDL1) && !defined(__vita__) if (!movie_playing) { // SDL generates mouse events from touch-based inputs to provide basic // touchscreeen support for apps that don't explicitly handle touch events if (IsAnyOf(e.type, SDL_EVENT_MOUSE_BUTTON_DOWN, SDL_EVENT_MOUSE_BUTTON_UP) && e.button.which == SDL_TOUCH_MOUSEID) { return true; } if (e.type == SDL_EVENT_MOUSE_MOTION && e.motion.which == SDL_TOUCH_MOUSEID) { return true; } if (e.type == SDL_EVENT_MOUSE_WHEEL && e.wheel.which == SDL_TOUCH_MOUSEID) { return true; } } #endif if (!SDLC_ConvertEventToRenderCoordinates(renderer, &e)) { LogWarn(LogCategory::Application, "SDL_ConvertEventToRenderCoordinates: {}", SDL_GetError()); SDL_ClearError(); } if (HandleControllerAddedOrRemovedEvent(e)) return true; switch (e.type) { #ifdef USE_SDL3 case SDL_EVENT_GAMEPAD_AXIS_MOTION: case SDL_EVENT_GAMEPAD_BUTTON_DOWN: case SDL_EVENT_GAMEPAD_BUTTON_UP: case SDL_EVENT_FINGER_DOWN: case SDL_EVENT_FINGER_UP: case SDL_EVENT_TEXT_EDITING: case SDL_EVENT_TEXT_INPUT: case SDL_EVENT_WINDOW_RESIZED: case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: case SDL_EVENT_WINDOW_SHOWN: case SDL_EVENT_WINDOW_MINIMIZED: case SDL_EVENT_WINDOW_MAXIMIZED: case SDL_EVENT_WINDOW_RESTORED: case SDL_EVENT_WINDOW_HDR_STATE_CHANGED: case SDL_EVENT_WINDOW_FOCUS_GAINED: case SDL_EVENT_WINDOW_FOCUS_LOST: case SDL_EVENT_MOUSE_WHEEL: case SDL_EVENT_JOYSTICK_AXIS_MOTION: case SDL_EVENT_JOYSTICK_HAT_MOTION: case SDL_EVENT_JOYSTICK_BUTTON_DOWN: case SDL_EVENT_JOYSTICK_BUTTON_UP: case SDL_EVENT_MOUSE_MOTION: case SDL_EVENT_MOUSE_BUTTON_DOWN: case SDL_EVENT_MOUSE_BUTTON_UP: *event = e; break; case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_UP: if (e.key.key == SDLK_UNKNOWN) { return FalseAvail(e.key.down ? "SDL_EVENT_KEY_DOWN" : "SDL_EVENT_KEY_UP", e.key.key); } *event = e; break; case SDL_EVENT_AUDIO_DEVICE_ADDED: return FalseAvail("SDL_EVENT_AUDIO_DEVICE_ADDED", e.adevice.which); case SDL_EVENT_AUDIO_DEVICE_REMOVED: return FalseAvail("SDL_EVENT_AUDIO_DEVICE_REMOVED", e.adevice.which); case SDL_EVENT_KEYMAP_CHANGED: return FalseAvail("SDL_EVENT_KEYMAP_CHANGED", 0); #else #if SDL_VERSION_ATLEAST(2, 0, 0) case SDL_CONTROLLERAXISMOTION: case SDL_CONTROLLERBUTTONDOWN: case SDL_CONTROLLERBUTTONUP: case SDL_FINGERDOWN: case SDL_FINGERUP: case SDL_TEXTEDITING: case SDL_TEXTINPUT: case SDL_WINDOWEVENT: case SDL_MOUSEWHEEL: #else case SDL_ACTIVEEVENT: #endif case SDL_JOYAXISMOTION: case SDL_JOYHATMOTION: case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: case SDL_MOUSEMOTION: case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: *event = e; break; case SDL_KEYDOWN: case SDL_KEYUP: if (e.key.keysym.sym == -1) return FalseAvail(e.type == SDL_KEYDOWN ? "SDL_KEYDOWN" : "SDL_KEYUP", e.key.keysym.sym); *event = e; break; #ifndef USE_SDL1 #if SDL_VERSION_ATLEAST(2, 0, 4) case SDL_AUDIODEVICEADDED: return FalseAvail("SDL_AUDIODEVICEADDED", e.adevice.which); case SDL_AUDIODEVICEREMOVED: return FalseAvail("SDL_AUDIODEVICEREMOVED", e.adevice.which); case SDL_KEYMAPCHANGED: return FalseAvail("SDL_KEYMAPCHANGED", 0); #endif #endif #endif default: return FalseAvail("unknown", e.type); } return true; } } // namespace EventHandler CurrentEventHandler; EventHandler SetEventHandler(EventHandler eventHandler) { PadmapperReleaseAllActiveButtons(); EventHandler previousHandler = CurrentEventHandler; CurrentEventHandler = eventHandler; return previousHandler; } bool FetchMessage(SDL_Event *event, uint16_t *modState) { const bool available = demo::IsRunning() ? demo::FetchMessage(event, modState) : FetchMessage_Real(event, modState); if (available && demo::IsRecording()) demo::RecordMessage(*event, *modState); return available; } void HandleMessage(const SDL_Event &event, uint16_t modState) { assert(CurrentEventHandler != nullptr); CurrentEventHandler(event, modState); } } // namespace devilution