|
|
|
|
#include "engine/events.hpp"
|
|
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
|
|
|
|
|
#ifdef USE_SDL3
|
|
|
|
|
#include <SDL3/SDL_error.h>
|
|
|
|
|
#include <SDL3/SDL_events.h>
|
|
|
|
|
#else
|
|
|
|
|
#include <SDL.h>
|
|
|
|
|
|
|
|
|
|
#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 <switch.h>
|
|
|
|
|
#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<SDL_EventType>(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
|