added SDL event filter to track mouse position from mouse motion events
authorHolger Schemel <info@artsoft.org>
Thu, 4 Apr 2019 21:15:20 +0000 (23:15 +0200)
committerHolger Schemel <info@artsoft.org>
Thu, 4 Apr 2019 21:24:32 +0000 (23:24 +0200)
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
src/events.h
src/init.c
src/libgame/sdl.c
src/libgame/sdl.h
src/libgame/system.c
src/libgame/system.h

index 3a22c7426f36215175cad6312a68f8bcbe04a230..bd82a609734afb1c06ebf95f52862a82594ab54c 100644 (file)
@@ -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
index 823670bcc124d20c81f3136781cbad413fc0a0f4..3467e76799e88077e4f872d83cd1530c651bc91e 100644 (file)
@@ -20,6 +20,7 @@
 #define USEREVENT_ANIM_EVENT_ACTION    2
 
 
+int FilterMouseMotionEvents(void *, Event *);
 boolean NextValidEvent(Event *);
 
 void EventLoop(void);
index 2bbc623807d772c1f57f755135ad58d79324445f..1d4243db2667c5052b4948793df41d5e58281d2e 100644 (file)
@@ -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();
index 4bd1987331b2a0d342f85c35ed666c2b5468fa33..45f7f2ce69a823b9b4f635bb6a8c334765f87736 100644 (file)
@@ -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
index e4b2b68418c8cafbf4156e9d2be5d85380718016..35d6a2411c3c7af8edd90677d04cf1630c550f15 100644 (file)
@@ -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);
index 6f27daf6e94a24461ce60311ce0b1630139fdcba..7fcb784d66c9f7608f00dad238a52b76cc0ce464 100644 (file)
@@ -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);
index d4e732e9fb22a535c1329dcb652ff80aafc9db6a..290f0cb7827af8e501be7cf2c38e2114f96a1c7c 100644 (file)
@@ -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);