From 7aa79c38168d2e41616dae1c34cbe26c41e5bc34 Mon Sep 17 00:00:00 2001 From: Charles Dang Date: Tue, 27 Jun 2017 17:24:24 +1100 Subject: [PATCH] Fixed some issues with the resolution list (fixes #1772) Awhile back I added some code to remove any resolutions from the list that exceeded the current DPI. I seem to have misunderstood some of the functionality. First, off, GetCurrentDisplayMode doesn't seem to return current resolution. From my tests, it seems to return a "maximum maximized size" of some sort equal to GetUsableDisplayBounds - 1 (see below): * Render output size: 800, 600 * Display mode size: 1536, 864 * Window size: 800, 600 * Display Bounds: x: 0, y: 0, w: 1537, h: 865 * Usable display bounds: x: 0, y: 0, w: 1537, h: 865 The actual window size, which @celticminstrel informs me is what we should be measuring here, is actually returned by either GetWindowSize or GetRenderOutputSize. According to SDL, the latter should return pixel size and the former screen coordinates. In my tests, though, the results are the same. This might be different on macOS or iOS. Either way, I've changed current_resolution(), getx(), and gety() to use the results of GetWindowSize(). Additionally, it seems I don't need to multiply any display modes by the DPI scale factor if I check the sizes against the aforementioned "max maximized area" w/h. For that I use GetDisplayBounds however... though again, I'm not sure that's the best way to do this. It does seem to work correctly to fix the aforementioned bug, anyway. I'll need to figure out more about the handling of DPI on Windows vs macOS or iOS. There's an implication that the measurements some of these functions return is different. --- src/sdl/window.cpp | 8 ++++++++ src/sdl/window.hpp | 12 +++++++++++- src/video.cpp | 22 +++++++++++++++------- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/sdl/window.cpp b/src/sdl/window.cpp index 8291387877bc..896490cd6791 100644 --- a/src/sdl/window.cpp +++ b/src/sdl/window.cpp @@ -71,6 +71,14 @@ void window::set_size(const int w, const int h) SDL_SetWindowSize(window_, w, h); } +SDL_Point window::get_size() +{ + SDL_Point res; + SDL_GetWindowSize(*this, &res.x, &res.y); + + return res; +} + SDL_Point window::get_output_size() { SDL_Point res; diff --git a/src/sdl/window.hpp b/src/sdl/window.hpp index 9251a2e35990..a6db2a412c49 100644 --- a/src/sdl/window.hpp +++ b/src/sdl/window.hpp @@ -85,8 +85,18 @@ class window void set_size(const int w, const int h); /** - * Gets the Window's output size, in pixels. + * Gets the window's size, in screen coordinates. + * + * For the most part, this seems to return the same result as @ref get_output_size. However, + * SDL indicates for high DPI displays these two functions could differ. I could not observe + * any change in behavior with DPI virtualization on or off, but to be safe, I'm keeping the + * two functions seperate and using this for matters of window resolution. + * + * - vultraz, 6/27/2017 */ + SDL_Point get_size(); + + /** Gets the window's renderer output size, in pixels */ SDL_Point get_output_size(); /** diff --git a/src/video.cpp b/src/video.cpp index 537fff9eaf62..1634332a62df 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -142,7 +142,7 @@ SDL_Rect screen_area() return sdl::empty_rect; } - SDL_Point size = w->get_output_size(); + SDL_Point size = w->get_size(); return {0, 0, size.x, size.y}; } @@ -277,7 +277,7 @@ int CVideo::getx() const return 0; } - return window->get_output_size().x; + return window->get_size().x; } int CVideo::gety() const @@ -286,7 +286,7 @@ int CVideo::gety() const return 0; } - return window->get_output_size().y; + return window->get_size().y; } SDL_Renderer* CVideo::get_renderer() @@ -431,14 +431,23 @@ std::vector> CVideo::get_available_resolutions(const bool in const std::pair min_res = std::make_pair(preferences::min_window_width, preferences::min_window_height); const std::pair current_res = current_resolution(); +#if 0 + // DPI scale factor. float scale_h, scale_v; std::tie(scale_h, scale_v) = get_dpi_scale_factor(); +#endif + + // The maximum size to which this window can be set. For some reason this won't + // pop up as a display mode of its own. + SDL_Rect bounds; + SDL_GetDisplayBounds(display_index, &bounds); SDL_DisplayMode mode; + for(int i = 0; i < modes; ++i) { if(SDL_GetDisplayMode(display_index, i, &mode) == 0) { // Exclude any results outside the range of the current DPI. - if(mode.w > current_res.first * scale_h && mode.h > current_res.second * scale_v) { + if(mode.w > bounds.w && mode.h > bounds.h) { continue; } @@ -470,10 +479,9 @@ surface& CVideo::getSurface() std::pair CVideo::current_resolution() { - SDL_DisplayMode mode; - SDL_GetCurrentDisplayMode(window->get_display_index(), &mode); + SDL_Point size = window->get_size(); - return std::make_pair(mode.w, mode.h); + return std::make_pair(size.x, size.y); } bool CVideo::isFullScreen() const {