testwm2: Fix video modes menu hit detection when highdpi or logical size used (#4936) * SDLTest_CommonDrawWindowInfo: log SDL_RenderGetScale, SDL_RenderGetLogicalSize * testwm2: fix video modes menu hit detection in High DPI cases - also when logical size is specified, e.g. `--logical 640x480 --resizable --allow-highdpi` * add function to determine logical coordinates of renderer point when given window point * change since to the targeted milestone * fix typo * rename for consistency * Change logical coordinate type to float, since we can render with floating point precision. * add function to convert logical to window coordinates * testwm2: use new SDL_RenderWindowToLogical * SDL_render.c: alternate SDL_RenderWindowToLogical/SDL_RenderLogicalToWindow Co-authored-by: John Blat <johnblat64@protonmail.com> Co-authored-by: John Blat <47202511+johnblat64@users.noreply.github.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
diff --git a/include/SDL_render.h b/include/SDL_render.h
index a74fc12..97ccac5 100644
--- a/include/SDL_render.h
+++ b/include/SDL_render.h
@@ -980,6 +980,48 @@ extern DECLSPEC void SDLCALL SDL_RenderGetScale(SDL_Renderer * renderer,
float *scaleX, float *scaleY);
/**
+ * Get logical coordinates of point in renderer when given real coordinates of point in window.
+ * Logical coordinates will differ from real coordinates when render is scaled and logical renderer size set
+ *
+ * \param renderer the renderer from which the logical coordinates should be calcualted
+ * \param windowX the real X coordinate in the window
+ * \param windowY the real Y coordinate in the window
+ * \param logicalX the pointer filled with the logical x coordinate
+ * \param logicalY the pointer filled with the logical y coordinate
+ *
+ * \since This function is available since SDL 2.0.20.
+ *
+ * \sa SDL_RenderGetScale
+ * \sa SDL_RenderSetScale
+ * \sa SDL_RenderGetLogicalSize
+ * \sa SDL_RenderSetLogicalSize
+ */
+extern DECLSPEC void SDLCALL SDL_RenderWindowToLogical(SDL_Renderer * renderer,
+ int windowX, int windowY,
+ float *logicalX, float *logicalY);
+
+ /**
+ * Get real coordinates of point in window when given logical coordinates of point in renderer.
+ * Logical coordinates will differ from real coordinates when render is scaled and logical renderer size set
+ *
+ * \param renderer the renderer from which the window coordinates should be calculated
+ * \param logicalX the logical x coordinate
+ * \param logicalY the logical y coordinate
+ * \param windowX the pointer filled with the real X coordinate in the window
+ * \param windowY the pointer filled with the real Y coordinate in the window
+
+ *
+ * \since This function is available since SDL 2.0.20.
+ *
+ * \sa SDL_RenderGetScale
+ * \sa SDL_RenderSetScale
+ * \sa SDL_RenderGetLogicalSize
+ * \sa SDL_RenderSetLogicalSize
+ */
+extern DECLSPEC void SDLCALL SDL_RenderLogicalToWindow(SDL_Renderer * renderer,
+ float logicalX, float logicalY,
+ int *windowX, int *windowY);
+/**
* Set the color used for drawing operations (Rect, Line and Clear).
*
* Set the color for drawing or filling rectangles, lines, and points, and for
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index 20d9e70..9077bb0 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -844,3 +844,5 @@
#define SDL_hid_get_indexed_string SDL_hid_get_indexed_string_REAL
#define SDL_SetWindowMouseRect SDL_SetWindowMouseRect_REAL
#define SDL_GetWindowMouseRect SDL_GetWindowMouseRect_REAL
+#define SDL_RenderWindowToLogical SDL_RenderWindowToLogical_REAL
+#define SDL_RenderLogicalToWindow SDL_RenderLogicalToWindow_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index d2c1d13..93be9fb 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -913,3 +913,5 @@ SDL_DYNAPI_PROC(int,SDL_hid_get_serial_number_string,(SDL_hid_device *a, wchar_t
SDL_DYNAPI_PROC(int,SDL_hid_get_indexed_string,(SDL_hid_device *a, int b, wchar_t *c, size_t d),(a,b,c,d),return)
SDL_DYNAPI_PROC(int,SDL_SetWindowMouseRect,(SDL_Window *a, const SDL_Rect *b),(a,b),return)
SDL_DYNAPI_PROC(const SDL_Rect*,SDL_GetWindowMouseRect,(SDL_Window *a),(a),return)
+SDL_DYNAPI_PROC(void,SDL_RenderWindowToLogical,(SDL_Renderer *a, int b, int c, float *d, float *e),(a,b,c,d,e),)
+SDL_DYNAPI_PROC(void,SDL_RenderLogicalToWindow,(SDL_Renderer *a, float b, float c, int *d, int *e),(a,b,c,d,e),)
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index 1a0add9..5bca652 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -2491,6 +2491,42 @@ SDL_RenderGetScale(SDL_Renderer * renderer, float *scaleX, float *scaleY)
}
}
+void
+SDL_RenderWindowToLogical(SDL_Renderer * renderer, int windowX, int windowY, float *logicalX, float *logicalY)
+{
+ float window_physical_x, window_physical_y;
+
+ CHECK_RENDERER_MAGIC(renderer, );
+
+ window_physical_x = ((float) windowX) / renderer->dpi_scale.x;
+ window_physical_y = ((float) windowY) / renderer->dpi_scale.y;
+
+ if (logicalX) {
+ *logicalX = (window_physical_x - renderer->viewport.x) / renderer->scale.x;
+ }
+ if (logicalY) {
+ *logicalY = (window_physical_y - renderer->viewport.y) / renderer->scale.y;
+ }
+}
+
+void
+SDL_RenderLogicalToWindow(SDL_Renderer * renderer, float logicalX, float logicalY, int *windowX, int *windowY)
+{
+ float window_physical_x, window_physical_y;
+
+ CHECK_RENDERER_MAGIC(renderer, );
+
+ window_physical_x = (logicalX * renderer->scale.x) + renderer->viewport.x;
+ window_physical_y = (logicalY * renderer->scale.y) + renderer->viewport.y;
+
+ if (windowX) {
+ *windowX = (int)(window_physical_x * renderer->dpi_scale.x);
+ }
+ if (windowY) {
+ *windowY = (int)(window_physical_y * renderer->dpi_scale.y);
+ }
+}
+
int
SDL_SetRenderDrawColor(SDL_Renderer * renderer,
Uint8 r, Uint8 g, Uint8 b, Uint8 a)
diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c
index 6dcbee0..3b6effb 100644
--- a/src/test/SDL_test_common.c
+++ b/src/test/SDL_test_common.c
@@ -2234,6 +2234,7 @@ SDLTest_CommonDrawWindowInfo(SDL_Renderer * renderer, SDL_Window * window, int *
SDL_Rect rect;
SDL_DisplayMode mode;
float ddpi, hdpi, vdpi;
+ float scaleX, scaleY;
Uint32 flags;
const int windowDisplayIndex = SDL_GetWindowDisplayIndex(window);
SDL_RendererInfo info;
@@ -2276,6 +2277,17 @@ SDLTest_CommonDrawWindowInfo(SDL_Renderer * renderer, SDL_Window * window, int *
SDLTest_DrawString(renderer, 0, textY, text);
textY += lineHeight;
+ SDL_RenderGetScale(renderer, &scaleX, &scaleY);
+ SDL_snprintf(text, sizeof(text), "SDL_RenderGetScale: %f,%f",
+ scaleX, scaleY);
+ SDLTest_DrawString(renderer, 0, textY, text);
+ textY += lineHeight;
+
+ SDL_RenderGetLogicalSize(renderer, &w, &h);
+ SDL_snprintf(text, sizeof(text), "SDL_RenderGetLogicalSize: %dx%d", w, h);
+ SDLTest_DrawString(renderer, 0, textY, text);
+ textY += lineHeight;
+
/* Window */
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
diff --git a/test/testwm2.c b/test/testwm2.c
index 03530e5..86b89a9 100644
--- a/test/testwm2.c
+++ b/test/testwm2.c
@@ -52,7 +52,7 @@ quit(int rc)
/* Draws the modes menu, and stores the mode index under the mouse in highlighted_mode */
static void
-draw_modes_menu(SDL_Window* window, SDL_Renderer* renderer, SDL_Rect viewport)
+draw_modes_menu(SDL_Window *window, SDL_Renderer *renderer, SDL_Rect viewport)
{
SDL_DisplayMode mode;
char text[1024];
@@ -68,7 +68,14 @@ draw_modes_menu(SDL_Window* window, SDL_Renderer* renderer, SDL_Rect viewport)
/* Get mouse position */
if (SDL_GetMouseFocus() == window) {
- SDL_GetMouseState(&mouse_pos.x, &mouse_pos.y);
+ int window_x, window_y;
+ float logical_x, logical_y;
+
+ SDL_GetMouseState(&window_x, &window_y);
+ SDL_RenderWindowToLogical(renderer, window_x, window_y, &logical_x, &logical_y);
+
+ mouse_pos.x = (int)logical_x;
+ mouse_pos.y = (int)logical_y;
}
x = 0;