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.
This commit is contained in:
Celtic Minstrel 2017-07-23 16:17:08 -04:00
parent 82829b0011
commit b4990801ef
4 changed files with 57 additions and 8 deletions

View file

@ -209,8 +209,8 @@ public:
* mapx is the width of the portion of the display which shows the game area.
* Between mapx and x is the sidebar region.
*/
int w() const { return screen_.getx(); } /**< width */
int h() const { return screen_.gety(); } /**< height */
int w() const { return screen_.get_window() ? screen_.get_window()->get_output_size().x : 0; } /**< width */
int h() const { return screen_.get_window() ? screen_.get_window()->get_output_size().y : 0; } /**< height */
const SDL_Rect& minimap_area() const
{ return theme_.mini_map_location(screen_area()); }
const SDL_Rect& palette_area() const

View file

@ -73,6 +73,22 @@ 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;
SDL_GetRendererOutputSize(*this, &res.x, &res.y);
return res;
}
void window::center()
{
SDL_SetWindowPosition(window_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);

View file

@ -83,6 +83,21 @@ public:
*/
void set_size(const int w, const int h);
/**
* 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();
/**
* Dummy function for centering the window.
*/

View file

@ -131,7 +131,13 @@ bool CVideo::non_interactive() const
SDL_Rect screen_area()
{
return {0, 0, frameBuffer->w, frameBuffer->h};
sdl::window* w = CVideo::get_singleton().get_window();
if(!w) {
return sdl::empty_rect;
}
SDL_Point size = w->get_size();
return {0, 0, size.x, size.y};
}
void CVideo::video_event_handler::handle_window_event(const SDL_Event &event)
@ -282,7 +288,11 @@ void CVideo::setMode(int x, int y, const MODE_EVENT mode)
int CVideo::getx() const
{
return frameBuffer->w;
if(!window) {
return 0;
}
return window->get_size().y;
}
int CVideo::gety() const
@ -390,14 +400,23 @@ std::vector<std::pair<int, int>> CVideo::get_available_resolutions(const bool in
const std::pair<int,int> min_res = std::make_pair(preferences::min_window_width, preferences::min_window_height);
const std::pair<int,int> 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;
}
@ -428,10 +447,9 @@ surface& CVideo::getSurface()
std::pair<int,int> 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 {