From 962bc38a08eff50513e6f474d786813e1b32172d Mon Sep 17 00:00:00 2001 From: Chris Sarbora Date: Wed, 21 Jan 2026 00:20:18 -0600 Subject: [PATCH] Use SDL_PollEvent instead of Event Filters SDL EventFilters were *always* the incorrect way to handle input, but now in SDL3 are even more incorrect as they run on the thread that accepts the input, not the thread that's intended to handle it. (This is a significant difference on Android and iOS.) The fix is surprisingly simple: Just poll for input in the OS defer handler. This is already called at the start of every type of every frame, so it is the perfect place to grab input. --- Descent3/sdlmain.cpp | 33 --------------------------------- ddio/ddio.cpp | 42 +++++++++++++++++++++++++++++++++++++++++- ddio/ddio_lnx.h | 6 ++++++ ddio/lnxio.cpp | 13 +++++++++++++ ddio/lnxkey.cpp | 36 ++++++++++-------------------------- ddio/lnxkey_sdl.cpp | 14 ++++++-------- ddio/lnxmouse.cpp | 22 +++++----------------- ddio/sdljoy.cpp | 4 +--- 8 files changed, 82 insertions(+), 88 deletions(-) diff --git a/Descent3/sdlmain.cpp b/Descent3/sdlmain.cpp index 92974f5d1..4813bface 100644 --- a/Descent3/sdlmain.cpp +++ b/Descent3/sdlmain.cpp @@ -176,37 +176,6 @@ class oeD3LnxDatabase final : public oeLnxAppDatabase { } }; -bool sdlKeyFilter(const SDL_Event *event); -bool sdlMouseButtonUpFilter(const SDL_Event *event); -bool sdlMouseButtonDownFilter(const SDL_Event *event); -bool sdlMouseWheelFilter(const SDL_Event *event); -bool sdlMouseMotionFilter(const SDL_Event *event); - -bool SDLCALL d3SDLEventFilter(void *userdata, SDL_Event *event) { - switch (event->type) { - case SDL_EVENT_KEY_UP: - case SDL_EVENT_KEY_DOWN: - return (sdlKeyFilter(event)); - case SDL_EVENT_JOYSTICK_BALL_MOTION: - case SDL_EVENT_MOUSE_MOTION: - return (sdlMouseMotionFilter(event)); - case SDL_EVENT_MOUSE_BUTTON_UP: - return (sdlMouseButtonUpFilter(event)); - case SDL_EVENT_MOUSE_BUTTON_DOWN: - return (sdlMouseButtonDownFilter(event)); - case SDL_EVENT_MOUSE_WHEEL: - return (sdlMouseWheelFilter(event)); - case SDL_EVENT_QUIT: - SDL_Quit(); - _exit(0); - break; - default: - break; - } // switch - - return (1); -} - // --------------------------------------------------------------------------- // Main // creates all the OS objects and then runs Descent 3. @@ -250,8 +219,6 @@ int main(int argc, char *argv[]) { return (0); } - // !!! FIXME: Don't use an event filter! - SDL_SetEventFilter(d3SDLEventFilter, nullptr); install_signal_handlers(); // Initialize our OS Object. This could be a game dependant OS object, or a default OS object. diff --git a/ddio/ddio.cpp b/ddio/ddio.cpp index 78b3d3d96..9a061e71a 100644 --- a/ddio/ddio.cpp +++ b/ddio/ddio.cpp @@ -90,7 +90,10 @@ #include +#include + #include "ddio.h" +#include "ddio_lnx.h" #include "joystick.h" #include "log.h" #include "pserror.h" @@ -140,9 +143,46 @@ void ddio_Resume() { ddio_InternalKeyResume(); ddio_InternalMouseResume(); } + // handles buffered input from devices once per frame. +void sdlKeyEvent(const SDL_Event *event); +void sdlMouseButtonUpEvent(const SDL_Event *event); +void sdlMouseButtonDownEvent(const SDL_Event *event); +void sdlMouseWheelEvent(const SDL_Event *event); +void sdlMouseMotionEvent(const SDL_Event *event); void ddio_Frame() { + if (Input_mode == Input_sdl) { + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_EVENT_KEY_UP: + case SDL_EVENT_KEY_DOWN: + sdlKeyEvent(&event); + break; + case SDL_EVENT_JOYSTICK_BALL_MOTION: + case SDL_EVENT_MOUSE_MOTION: + sdlMouseMotionEvent(&event); + break; + case SDL_EVENT_MOUSE_BUTTON_UP: + sdlMouseButtonUpEvent(&event); + break; + case SDL_EVENT_MOUSE_BUTTON_DOWN: + sdlMouseButtonDownEvent(&event); + break; + case SDL_EVENT_MOUSE_WHEEL: + sdlMouseWheelEvent(&event); + break; + case SDL_EVENT_QUIT: + SDL_Quit(); + _exit(0); + break; + default: + break; + } + } + } + ddio_InternalKeyFrame(); ddio_InternalMouseFrame(); ddio_InternalJoyFrame(); -} \ No newline at end of file +} diff --git a/ddio/ddio_lnx.h b/ddio/ddio_lnx.h index 8e96b1d80..ca22e679e 100644 --- a/ddio/ddio_lnx.h +++ b/ddio/ddio_lnx.h @@ -28,4 +28,10 @@ extern oeLnxApplication *Lnx_app_obj; +enum input_mode_t { + Input_null, + Input_sdl, +}; +extern enum input_mode_t Input_mode; + #endif diff --git a/ddio/lnxio.cpp b/ddio/lnxio.cpp index c96173b2b..d8b410b7f 100644 --- a/ddio/lnxio.cpp +++ b/ddio/lnxio.cpp @@ -69,9 +69,11 @@ #include "application.h" #include "ddio.h" #include "log.h" +#include "ddio_lnx.h" bool DDIO_init = false; oeLnxApplication *Lnx_app_obj = NULL; +enum input_mode_t Input_mode; // ---------------------------------------------------------------------------- // Initialization and destruction functions @@ -80,6 +82,17 @@ oeLnxApplication *Lnx_app_obj = NULL; bool ddio_InternalInit(ddio_init_info *init_info) { LOG_DEBUG << "DDIO: ddio_InternalInit() called."; Lnx_app_obj = (oeLnxApplication *)init_info->obj; + + if (!Lnx_app_obj) { + return false; + } + + tLnxAppInfo app_info; + Lnx_app_obj->get_info(&app_info); + + // determine if we are to use SDL or null mode + Input_mode = (app_info.flags & APPFLAG_USESERVICE) ? Input_null : Input_sdl; + DDIO_init = true; return true; } diff --git a/ddio/lnxkey.cpp b/ddio/lnxkey.cpp index c6abbe368..f4f23cb4a 100644 --- a/ddio/lnxkey.cpp +++ b/ddio/lnxkey.cpp @@ -52,6 +52,7 @@ #include "application.h" #include "ddio.h" #include "mono.h" +#include "ddio_lnx.h" volatile struct tLnxKeys { union { @@ -87,29 +88,12 @@ void ddio_sdl_InternalResetKey(uint8_t key); bool ddio_sdl_KeyFrame(); void ddio_sdl_InternalKeyFrame(void); -enum { - Input_null, - Input_sdl // Input_svga,Input_xwin -} Keyboard_mode; - // ---------------------------------------------------------------------------- // Initialization of keyboard device. // ---------------------------------------------------------------------------- bool ddio_InternalKeyInit(ddio_init_info *init_info) { - oeLnxApplication *app = (oeLnxApplication *)init_info->obj; - tLnxAppInfo app_info; - - if (!app) { - return false; - } - - app->get_info(&app_info); - - // determine if we are to use SDL or null mode - Keyboard_mode = (app_info.flags & APPFLAG_USESERVICE) ? Input_null : Input_sdl; - - switch (Keyboard_mode) { + switch (Input_mode) { case Input_null: return ddio_null_InternalKeyInit(init_info); case Input_sdl: @@ -120,7 +104,7 @@ bool ddio_InternalKeyInit(ddio_init_info *init_info) { } void ddio_InternalKeyClose() { - switch (Keyboard_mode) { + switch (Input_mode) { case Input_null: return ddio_null_InternalKeyClose(); case Input_sdl: @@ -129,7 +113,7 @@ void ddio_InternalKeyClose() { } bool ddio_InternalKeyState(uint8_t key) { - switch (Keyboard_mode) { + switch (Input_mode) { case Input_null: return ddio_null_InternalKeyState(key); case Input_sdl: @@ -140,7 +124,7 @@ bool ddio_InternalKeyState(uint8_t key) { } void ddio_InternalKeySuspend() { - switch (Keyboard_mode) { + switch (Input_mode) { case Input_null: ddio_null_InternalKeySuspend(); break; @@ -150,7 +134,7 @@ void ddio_InternalKeySuspend() { } void ddio_InternalKeyResume() { - switch (Keyboard_mode) { + switch (Input_mode) { case Input_null: ddio_null_InternalKeyResume(); break; @@ -160,7 +144,7 @@ void ddio_InternalKeyResume() { } float ddio_InternalKeyDownTime(uint8_t key) { - switch (Keyboard_mode) { + switch (Input_mode) { case Input_null: return ddio_null_InternalKeyDownTime(key); case Input_sdl: @@ -171,7 +155,7 @@ float ddio_InternalKeyDownTime(uint8_t key) { } void ddio_InternalResetKey(uint8_t key) { - switch (Keyboard_mode) { + switch (Input_mode) { case Input_null: ddio_null_InternalResetKey(key); break; @@ -181,7 +165,7 @@ void ddio_InternalResetKey(uint8_t key) { } bool ddio_KeyFrame() { - switch (Keyboard_mode) { + switch (Input_mode) { case Input_sdl: break; case Input_null: @@ -192,7 +176,7 @@ bool ddio_KeyFrame() { } void ddio_InternalKeyFrame(void) { - switch (Keyboard_mode) { + switch (Input_mode) { case Input_null: ddio_null_InternalKeyFrame(); break; diff --git a/ddio/lnxkey_sdl.cpp b/ddio/lnxkey_sdl.cpp index c8888747f..fe8db2ad4 100644 --- a/ddio/lnxkey_sdl.cpp +++ b/ddio/lnxkey_sdl.cpp @@ -340,15 +340,15 @@ static inline uint8_t sdlkeycode_to_keycode(uint32_t sdlkeycode) { return (uint8_t)rc; } -bool sdlKeyFilter(const SDL_Event *event) { +void sdlKeyEvent(const SDL_Event *event) { uint8_t kc = 0; if ((event->type != SDL_EVENT_KEY_UP) && (event->type != SDL_EVENT_KEY_DOWN)) - return true; + return; if (event->key.down) { if (event->key.repeat) { - return false; // ignore these, we only want to know if it's a first time pressed, not a key-repeat. + return; // ignore these, we only want to know if it's a first time pressed, not a key-repeat. } kc = sdlkeycode_to_keycode(event->key.key); if (event->key.mod & SDL_KMOD_CTRL) { @@ -358,7 +358,7 @@ bool sdlKeyFilter(const SDL_Event *event) { bool grab = !ddio_MouseGetGrab(); ddio_MouseSetGrab(grab); SDL_SetWindowRelativeMouseMode(GSDLWindow, grab); - return false; + return; } // switch } // if @@ -366,7 +366,7 @@ bool sdlKeyFilter(const SDL_Event *event) { if ((kc == KEY_ENTER) || (kc == KEY_PADENTER)) { Game_fullscreen = !Game_fullscreen; rend_SetFullScreen(Game_fullscreen); - return false; + return; } // if } // else if @@ -382,9 +382,7 @@ bool sdlKeyFilter(const SDL_Event *event) { ddio_UpdateKeyState(kc, false); } // if } - - return false; -} // sdlKeyFilter +} bool ddio_sdl_InternalKeyInit(ddio_init_info *init_info) { // reset key list diff --git a/ddio/lnxmouse.cpp b/ddio/lnxmouse.cpp index 12c0121db..649427f00 100644 --- a/ddio/lnxmouse.cpp +++ b/ddio/lnxmouse.cpp @@ -190,7 +190,7 @@ void ddio_MouseMode(int mode) { Mouse_mode = mode; } // virtual coordinate system for mouse (match to video resolution set for optimal mouse usage. void ddio_MouseSetVCoords(int width, int height) { ddio_MouseSetLimits(0, 0, width, height); } -bool sdlMouseButtonDownFilter(SDL_Event const *event) { +void sdlMouseButtonDownEvent(SDL_Event const *event) { ASSERT(event->type == SDL_EVENT_MOUSE_BUTTON_DOWN); const SDL_MouseButtonEvent *ev = &event->button; @@ -258,11 +258,9 @@ bool sdlMouseButtonDownFilter(SDL_Event const *event) { MB_queue.send(mevt); // mprintf(0, "MOUSE Button 7: Down\n"); } - - return false; } -bool sdlMouseButtonUpFilter(SDL_Event const *event) { +void sdlMouseButtonUpEvent(SDL_Event const *event) { ASSERT(event->type == SDL_EVENT_MOUSE_BUTTON_UP); const SDL_MouseButtonEvent *ev = &event->button; @@ -332,11 +330,9 @@ bool sdlMouseButtonUpFilter(SDL_Event const *event) { MB_queue.send(mevt); // mprintf(0, "MOUSE Button 7: Up\n"); } - - return false; } -bool sdlMouseWheelFilter(SDL_Event const *event) { +void sdlMouseWheelEvent(SDL_Event const *event) { ASSERT(event->type == SDL_EVENT_MOUSE_WHEEL); const SDL_MouseWheelEvent *ev = &event->wheel; @@ -383,11 +379,9 @@ bool sdlMouseWheelFilter(SDL_Event const *event) { MB_queue.send(mevt); // mprintf(0, "MOUSE Scrollwheel: Rolled Down\n"); } - - return false; } -bool sdlMouseMotionFilter(SDL_Event const *event) { +void sdlMouseMotionEvent(SDL_Event const *event) { if (event->type == SDL_EVENT_JOYSTICK_BALL_MOTION) { DDIO_mouse_state.dx = event->jball.xrel / 100.0f; DDIO_mouse_state.dy = event->jball.yrel / 100.0f; @@ -408,16 +402,10 @@ bool sdlMouseMotionFilter(SDL_Event const *event) { DDIO_mouse_state.y = DDIO_mouse_state.t; if (DDIO_mouse_state.y >= DDIO_mouse_state.b) DDIO_mouse_state.y = DDIO_mouse_state.b - 1; - - return false; } // This function will handle all mouse events. -void ddio_InternalMouseFrame(void) { - static unsigned frame_count = 0; - SDL_PumpEvents(); - frame_count++; -} +void ddio_InternalMouseFrame(void) {} /* x, y = absolute mouse position dx, dy = mouse deltas since last call diff --git a/ddio/sdljoy.cpp b/ddio/sdljoy.cpp index 5c0d79ea2..713652213 100644 --- a/ddio/sdljoy.cpp +++ b/ddio/sdljoy.cpp @@ -341,6 +341,4 @@ static int joyGetNumDevs(void) { return found; } -void ddio_InternalJoyFrame(void) { - // All the work is done already in SDL_PumpEvents() -} +void ddio_InternalJoyFrame(void) {}