[Commits] SDL: Fixed bug 3311 - Broken touch positions with SDL_RenderSetL...

libsdl.org revision control commits-owner at libsdl.org
Wed Aug 2 13:38:53 PDT 2017


details:   https://hg.libsdl.org/SDL/rev/0ef6b8b9ca6d
changeset: 11178:0ef6b8b9ca6d
user:      Sam Lantinga <slouken at libsdl.org>
date:      Wed Aug 02 13:38:46 2017 -0700
description:
Fixed bug 3311 - Broken touch positions with SDL_RenderSetLogicalSize & HIGHDPI on iOS

Eric wing

Hi, I think I found a bug when using SDL_WINDOW_ALLOW_HIGHDPI with SDL_RenderSetLogicalSize on iOS. I use SDL_RenderSetLogicalSize for all my stuff. I just tried turning on SDL_WINDOW_ALLOW_HIGHDPI on iOS and suddenly all my touch/mouse positions are really broken/far-off-the-mark.

I actually don't have a real retina device (still) so I'm seeing this using the iOS simulator with a 6plus template.

Attached is a simple test program that can reproduce the problem. It uses RenderSetLogicalSize and draws some moving happy faces (to show the boundaries/space of the LogicalSize and that it is working correctly for that part).

When you click/touch, it will draw one more happy face where your button point is.

If you comment out SDL_WINDOW_ALLOW_HIGHDPI, everything works as expected. But if you compile with it in, the mouse coordinates seem really far off the mark. (Face appears far up and to the left.)


Alex Szpakowski on the mailing list suggests the problem is
"I believe this is a bug in SDL_Render’s platform-agnostic mouse coordinate scaling code. It assumes the units of the mouse coordinates are always in pixels, which isn’t the case where high-DPI is involved (regardless of whether iOS is used) – they’re actually in “DPI independent” coordinates (which matches the window size, but not the renderer output size)."

Additionally, if this is correct, the Mac under Retina is also probably affected too and "as well as any other platform SDL adds high-dpi support for in the future".

diffstat:

 src/render/SDL_render.c    |  36 ++++++++++++++++++++++++------------
 src/render/SDL_sysrender.h |   3 +++
 2 files changed, 27 insertions(+), 12 deletions(-)

diffs (77 lines):

diff -r 393fa47cb702 -r 0ef6b8b9ca6d src/render/SDL_render.c
--- a/src/render/SDL_render.c	Wed Aug 02 10:28:13 2017 -0700
+++ b/src/render/SDL_render.c	Wed Aug 02 13:38:46 2017 -0700
@@ -168,29 +168,29 @@
     } else if (event->type == SDL_MOUSEMOTION) {
         SDL_Window *window = SDL_GetWindowFromID(event->motion.windowID);
         if (renderer->logical_w && window == renderer->window) {
-            event->motion.x -= renderer->viewport.x;
-            event->motion.y -= renderer->viewport.y;
-            event->motion.x = (int)(event->motion.x / renderer->scale.x);
-            event->motion.y = (int)(event->motion.y / renderer->scale.y);
+            event->motion.x -= (renderer->viewport.x * renderer->dpi_scale.x);
+            event->motion.y -= (renderer->viewport.y * renderer->dpi_scale.y);
+            event->motion.x = (int)(event->motion.x / (renderer->scale.x * renderer->dpi_scale.x));
+            event->motion.y = (int)(event->motion.y / (renderer->scale.y * renderer->dpi_scale.y));
             if (event->motion.xrel > 0) {
-                event->motion.xrel = SDL_max(1, (int)(event->motion.xrel / renderer->scale.x));
+                event->motion.xrel = SDL_max(1, (int)(event->motion.xrel / (renderer->scale.x * renderer->dpi_scale.x)));
             } else if (event->motion.xrel < 0) {
-                event->motion.xrel = SDL_min(-1, (int)(event->motion.xrel / renderer->scale.x));
+                event->motion.xrel = SDL_min(-1, (int)(event->motion.xrel / (renderer->scale.x * renderer->dpi_scale.x)));
             }
             if (event->motion.yrel > 0) {
-                event->motion.yrel = SDL_max(1, (int)(event->motion.yrel / renderer->scale.y));
+                event->motion.yrel = SDL_max(1, (int)(event->motion.yrel / (renderer->scale.y * renderer->dpi_scale.y)));
             } else if (event->motion.yrel < 0) {
-                event->motion.yrel = SDL_min(-1, (int)(event->motion.yrel / renderer->scale.y));
+                event->motion.yrel = SDL_min(-1, (int)(event->motion.yrel / (renderer->scale.y * renderer->dpi_scale.y)));
             }
         }
     } else if (event->type == SDL_MOUSEBUTTONDOWN ||
                event->type == SDL_MOUSEBUTTONUP) {
         SDL_Window *window = SDL_GetWindowFromID(event->button.windowID);
         if (renderer->logical_w && window == renderer->window) {
-            event->button.x -= renderer->viewport.x;
-            event->button.y -= renderer->viewport.y;
-            event->button.x = (int)(event->button.x / renderer->scale.x);
-            event->button.y = (int)(event->button.y / renderer->scale.y);
+            event->motion.x -= (renderer->viewport.x * renderer->dpi_scale.x);
+            event->motion.y -= (renderer->viewport.y * renderer->dpi_scale.y);
+            event->motion.x = (int)(event->motion.x / (renderer->scale.x * renderer->dpi_scale.x));
+            event->motion.y = (int)(event->motion.y / (renderer->scale.y * renderer->dpi_scale.y));
         }
     }
     return 0;
@@ -289,6 +289,18 @@
         renderer->window = window;
         renderer->scale.x = 1.0f;
         renderer->scale.y = 1.0f;
+        renderer->dpi_scale.x = 1.0f;
+        renderer->dpi_scale.y = 1.0f;
+
+        if (window && renderer->GetOutputSize) {
+            int window_w, window_h;
+            int output_w, output_h;
+            if (renderer->GetOutputSize(renderer, &output_w, &output_h) == 0) {
+                SDL_GetWindowSize(renderer->window, &window_w, &window_h);
+                renderer->dpi_scale.x = (float)window_w / output_w;
+                renderer->dpi_scale.y = (float)window_h / output_h;
+            }
+        }
 
         if (SDL_GetWindowFlags(window) & (SDL_WINDOW_HIDDEN|SDL_WINDOW_MINIMIZED)) {
             renderer->hidden = SDL_TRUE;
diff -r 393fa47cb702 -r 0ef6b8b9ca6d src/render/SDL_sysrender.h
--- a/src/render/SDL_sysrender.h	Wed Aug 02 10:28:13 2017 -0700
+++ b/src/render/SDL_sysrender.h	Wed Aug 02 13:38:46 2017 -0700
@@ -154,6 +154,9 @@
     SDL_FPoint scale;
     SDL_FPoint scale_backup;
 
+    /* The pixel to point coordinate scale */
+    SDL_FPoint dpi_scale;
+
     /* The list of textures */
     SDL_Texture *textures;
     SDL_Texture *target;


More information about the commits mailing list