From 35f1a69dcb19f2932b6acf09dca6aa9c6fbd1754 Mon Sep 17 00:00:00 2001
From: David Gow <[EMAIL REDACTED]>
Date: Mon, 26 Jul 2021 11:42:45 +0800
Subject: [PATCH] Scale relative mouse motion with OpenGL Logical Scaling
This makes it match the SDL_Render-based scaling, which does this.
The SDL_MOUSE_RELATIVE_SCALING hint is also now supported for OpenGL
scaling, again to match the SDL_Render path. It's enabled by default,
though obviously is a no-op if OpenGL scaling is not used.
Note that this _doesn't quite_ match the SDL_Render version, in that
it's not accumulating the remainer. This'll be fixed in a follow-up
commit.
---
src/SDL12_compat.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c
index 59e8ea8..1354ec3 100644
--- a/src/SDL12_compat.c
+++ b/src/SDL12_compat.c
@@ -929,6 +929,7 @@ static JoystickOpenedItem JoystickOpenList[16];
static Uint8 KeyState[SDLK12_LAST];
static SDL_bool MouseInputIsRelative = SDL_FALSE;
static SDL_Point MousePosition = { 0, 0 };
+static SDL_bool UseMouseRelativeScaling = SDL_FALSE;
static OpenGLEntryPoints OpenGLFuncs;
static int OpenGLBlitLockCount = 0;
static GLuint OpenGLBlitTexture = 0;
@@ -2192,6 +2193,7 @@ GetOpenGLLogicalScalingViewport(int physical_width, int physical_height)
return dstrect;
}
+/* Scale a point (e.g. absolute mouse position) to the logical scaling size */
static void
AdjustOpenGLLogicalScalingPoint(int *x, int *y)
{
@@ -2220,6 +2222,30 @@ AdjustOpenGLLogicalScalingPoint(int *x, int *y)
*y = SDL_max(SDL_min(adjusted_y, OpenGLLogicalScalingHeight), 0);
}
+/* Scale a vector (e.g. relative mouse movement) to the logical scaling size */
+static void
+AdjustOpenGLLogicalScalingVector(int *x, int *y)
+{
+ SDL_Rect viewport;
+ int physical_w, physical_h;
+ float scale_x, scale_y;
+
+ /* Don't adjust anything if we're not using Logical Scaling */
+ if (!OpenGLLogicalScalingFBO) {
+ return;
+ }
+
+ /* we want to scale based on the window size, which is dpi-scaled */
+ SDL20_GetWindowSize(VideoWindow20, &physical_w, &physical_h);
+ viewport = GetOpenGLLogicalScalingViewport(physical_w, physical_h);
+
+ scale_x = (float)OpenGLLogicalScalingWidth / viewport.w;
+ scale_y = (float)OpenGLLogicalScalingHeight / viewport.h;
+
+ *x = (int) (*x * scale_x);
+ *y = (int) (*y * scale_y);
+}
+
static Uint8 MouseButtonState20to12(const Uint32 state20)
{
@@ -3129,6 +3155,9 @@ EventFilter20to12(void *data, SDL_Event *event20)
AdjustOpenGLLogicalScalingPoint(&event20->motion.x, &event20->motion.y);
event12.motion.x = (Uint16) event20->motion.x;
event12.motion.y = (Uint16) event20->motion.y;
+ if (UseMouseRelativeScaling) {
+ AdjustOpenGLLogicalScalingVector(&event20->motion.xrel, &event20->motion.yrel);
+ }
event12.motion.xrel = (Sint16) event20->motion.xrel;
event12.motion.yrel = (Sint16) event20->motion.yrel;
if (MouseInputIsRelative) {
@@ -4088,6 +4117,12 @@ glCopyTexSubImage3D_shim_for_scaling(GLenum target, GLint level, GLint xoffset,
static SDL_bool
InitializeOpenGLScaling(const int w, const int h)
{
+ const char *env;
+
+ /* Support the MOUSE_RELATIVE_SCALING hint from SDL 2.0 for OpenGL scaling. */
+ env = SDL20_getenv("SDL_MOUSE_RELATIVE_SCALING");
+ UseMouseRelativeScaling = (!env || SDL20_atoi(env)) ? SDL_TRUE : SDL_FALSE;
+
if (!OpenGLFuncs.SUPPORTS_GL_ARB_framebuffer_object) {
return SDL_FALSE; /* no FBOs, no scaling. */
}