From 8e4eb47925648cd84d134dfe05ca7fb30727dc24 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Thu, 4 Apr 2019 23:15:20 +0200 Subject: [PATCH] added SDL event filter to track mouse position from mouse motion events This (re-)adds a mouse motion event filter to update the current mouse position for "pointer" class global animations, even if no events were handled before, which improves smoothness of mouse pointer movement. --- src/events.c | 28 +++++++++++++++++++++++++--- src/events.h | 1 + src/init.c | 2 ++ src/libgame/sdl.c | 21 +++++++++++++++++++++ src/libgame/sdl.h | 3 +++ src/libgame/system.c | 5 +++++ src/libgame/system.h | 1 + 7 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/events.c b/src/events.c index 3a22c742..bd82a609 100644 --- a/src/events.c +++ b/src/events.c @@ -47,6 +47,31 @@ static void HandleNoEvent(void); static void HandleEventActions(void); +// event filter to set mouse x/y position (for pointer class global animations) +// (this is especially required to ensure smooth global animation mouse pointer +// movement when the screen is updated without handling events; this can happen +// when drawing door/envelope request animations, for example) + +int FilterMouseMotionEvents(void *userdata, Event *event) +{ + if (event->type != EVENT_MOTIONNOTIFY) + return 1; + + int mouse_x = ((MotionEvent *)event)->x; + int mouse_y = ((MotionEvent *)event)->y; + + // mouse events do not contain logical screen size corrections at this stage + SDLCorrectMouseEventXY(&mouse_x, &mouse_y); + + mouse_x -= video.screen_xoffset; + mouse_y -= video.screen_yoffset; + + gfx.mouse_x = mouse_x; + gfx.mouse_y = mouse_y; + + return 1; +} + // event filter especially needed for SDL event filtering due to // delay problems with lots of mouse motion events when mouse button // not pressed (X11 can handle this with 'PointerMotionHintMask') @@ -74,9 +99,6 @@ static int FilterEvents(const Event *event) { ((MotionEvent *)event)->x -= video.screen_xoffset; ((MotionEvent *)event)->y -= video.screen_yoffset; - - gfx.mouse_x = ((MotionEvent *)event)->x; - gfx.mouse_y = ((MotionEvent *)event)->y; } // non-motion events are directly passed to event handler functions diff --git a/src/events.h b/src/events.h index 823670bc..3467e767 100644 --- a/src/events.h +++ b/src/events.h @@ -20,6 +20,7 @@ #define USEREVENT_ANIM_EVENT_ACTION 2 +int FilterMouseMotionEvents(void *, Event *); boolean NextValidEvent(Event *); void EventLoop(void); diff --git a/src/init.c b/src/init.c index 2bbc6238..1d4243db 100644 --- a/src/init.c +++ b/src/init.c @@ -6108,6 +6108,8 @@ void OpenAll(void) InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen); InitVideoOverlay(); + InitEventFilter(FilterMouseMotionEvents); + print_timestamp_time("[init video stuff]"); InitElementPropertiesStatic(); diff --git a/src/libgame/sdl.c b/src/libgame/sdl.c index 4bd19873..45f7f2ce 100644 --- a/src/libgame/sdl.c +++ b/src/libgame/sdl.c @@ -2362,6 +2362,27 @@ void SDLWaitEvent(Event *event) SDL_WaitEvent(event); } +void SDLCorrectMouseEventXY(int *x, int *y) +{ + if (sdl_renderer == NULL) + return; + + // this corrects the raw mouse position for logical screen size within event + // filters (correction done later by SDL library when handling mouse events) + + SDL_Rect viewport; + float scale_x, scale_y; + + SDL_RenderGetViewport(sdl_renderer, &viewport); + SDL_RenderGetScale(sdl_renderer, &scale_x, &scale_y); + + *x = (int)(*x / scale_x); + *y = (int)(*y / scale_y); + + *x -= viewport.x; + *y -= viewport.y; +} + // ============================================================================ // joystick functions diff --git a/src/libgame/sdl.h b/src/libgame/sdl.h index e4b2b684..35d6a241 100644 --- a/src/libgame/sdl.h +++ b/src/libgame/sdl.h @@ -65,6 +65,8 @@ typedef SDL_Event PauseResumeEvent; typedef SDL_WindowEvent WindowEvent; typedef SDL_KeyboardEvent KeyEvent; +typedef SDL_EventFilter EventFilter; + // structure definitions @@ -421,6 +423,7 @@ void SDLOpenAudio(void); void SDLCloseAudio(void); void SDLWaitEvent(Event *); +void SDLCorrectMouseEventXY(int *, int *); void HandleJoystickEvent(Event *); void SDLInitJoysticks(void); diff --git a/src/libgame/system.c b/src/libgame/system.c index 6f27daf6..7fcb784d 100644 --- a/src/libgame/system.c +++ b/src/libgame/system.c @@ -1623,6 +1623,11 @@ void SetAudioMode(boolean enabled) // event functions // ============================================================================ +void InitEventFilter(EventFilter filter_function) +{ + SDL_SetEventFilter(filter_function, NULL); +} + boolean PendingEvent(void) { return (SDL_PollEvent(NULL) ? TRUE : FALSE); diff --git a/src/libgame/system.h b/src/libgame/system.h index d4e732e9..290f0cb7 100644 --- a/src/libgame/system.h +++ b/src/libgame/system.h @@ -1857,6 +1857,7 @@ void OpenAudio(void); void CloseAudio(void); void SetAudioMode(boolean); +void InitEventFilter(EventFilter); boolean PendingEvent(void); void WaitEvent(Event *event); void PeekEvent(Event *event); -- 2.34.1