diff options
author | Ryan C. Gordon <icculus@icculus.org> | 2020-08-09 00:55:39 -0400 |
---|---|---|
committer | Ryan C. Gordon <icculus@icculus.org> | 2020-08-09 00:55:39 -0400 |
commit | 4d2b93a79e64f1432e2d58c046aa4678320846cd (patch) | |
tree | c1fac76b085d412e03f7d053b438e4488ad9a61e /src/render | |
parent | 866338f2b988909e45325999366e46cf552e7982 (diff) | |
download | sdl-4d2b93a79e64f1432e2d58c046aa4678320846cd.tar.gz |
render: fixes to how we convert touch events for logical scaling.
We now handle HiDPI correctly, and touches are clamped to the viewport. So
if you are rendering to a logical 640x480 in a 720p window, and touch the
letterboxing at point (640,700), it will report the touch at (0.5,1.0) instead
of outside the documented range.
Diffstat (limited to 'src/render')
-rw-r--r-- | src/render/SDL_render.c | 62 |
1 files changed, 41 insertions, 21 deletions
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index b50655652..71604bc4a 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -688,40 +688,60 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event) event->button.x = (int)(event->button.x / (scale.x * renderer->dpi_scale.x)); event->button.y = (int)(event->button.y / (scale.y * renderer->dpi_scale.y)); } - } + } } else if (event->type == SDL_FINGERDOWN || event->type == SDL_FINGERUP || event->type == SDL_FINGERMOTION) { int logical_w, logical_h; + float physical_w, physical_h; SDL_Rect viewport; SDL_FPoint scale; GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale); - if (logical_w) { - int w, h; - if (renderer->GetOutputSize) { - renderer->GetOutputSize(renderer, &w, &h); - } else { - SDL_GetWindowSize(renderer->window, &w, &h); - } + /* !!! FIXME: we probably should drop events that are outside of the + !!! FIXME: viewport, but we can't do that from an event watcher, + !!! FIXME: and we would have to track if a touch happened outside + !!! FIXME: the viewport and then slid into it to insert extra + !!! FIXME: events, which is a mess, so for now we just clamp these + !!! FIXME: events to the edge. */ - event->tfinger.x *= (w - 1); - event->tfinger.y *= (h - 1); - - event->tfinger.x -= (viewport.x * renderer->dpi_scale.x); - event->tfinger.y -= (viewport.y * renderer->dpi_scale.y); - event->tfinger.x = (event->tfinger.x / (scale.x * renderer->dpi_scale.x)); - event->tfinger.y = (event->tfinger.y / (scale.y * renderer->dpi_scale.y)); + if (renderer->GetOutputSize) { + int w, h; + renderer->GetOutputSize(renderer, &w, &h); + physical_w = (float) w; + physical_h = (float) h; + } else { + int w, h; + SDL_GetWindowSize(renderer->window, &w, &h); + physical_w = ((float) w) * renderer->dpi_scale.x; + physical_h = ((float) h) * renderer->dpi_scale.y; + } - if (logical_w > 1) { - event->tfinger.x = event->tfinger.x / (logical_w - 1); + if (physical_w == 0.0f) { /* nowhere for the touch to go, avoid division by zero and put it dead center. */ + event->tfinger.x = 0.5f; + } else { + const float normalized_viewport_x = ((float) viewport.x) / physical_w; + const float normalized_viewport_w = ((float) viewport.w) / physical_w; + if (event->tfinger.x <= normalized_viewport_x) { + event->tfinger.x = 0.0f; /* to the left of the viewport, clamp to the edge. */ + } else if (event->tfinger.x >= (normalized_viewport_x + normalized_viewport_w)) { + event->tfinger.x = 1.0f; /* to the right of the viewport, clamp to the edge. */ } else { - event->tfinger.x = 0.5f; + event->tfinger.x = (event->tfinger.x - normalized_viewport_x) / normalized_viewport_w; } - if (logical_h > 1) { - event->tfinger.y = event->tfinger.y / (logical_h - 1); + } + + if (physical_h == 0.0f) { /* nowhere for the touch to go, avoid division by zero and put it dead center. */ + event->tfinger.y = 0.5f; + } else { + const float normalized_viewport_y = ((float) viewport.y) / physical_h; + const float normalized_viewport_h = ((float) viewport.h) / physical_h; + if (event->tfinger.y <= normalized_viewport_y) { + event->tfinger.y = 0.0f; /* to the left of the viewport, clamp to the edge. */ + } else if (event->tfinger.y >= (normalized_viewport_y + normalized_viewport_h)) { + event->tfinger.y = 1.0f; /* to the right of the viewport, clamp to the edge. */ } else { - event->tfinger.y = 0.5f; + event->tfinger.y = (event->tfinger.y - normalized_viewport_y) / normalized_viewport_h; } } } |