Refactored handling of window/renderer size getters

* Removed display::screen_area(), display::w(), and display::h().
* Moved the global screen_area() function into the CVideo class.
* Renamed CVideo::getx() and gety() to get_width() and get_height()
* Made those two functions return the result of screen_area() instead of the other way around.
* Added preliminary support for high-DPI rendering to screen_area()

Note on the last point: When I fixed bug #1772 (aa8f6c7e7 right now but will probably change with rebasing)
I noted that SDL_GetWindowSize and SDL_GetRendererOutputSize returned the same results for me (even with
Window's automatic scaling for non-high-DPI-enabled apps disabled) but that the SDL documentation stated the
former returned screen coordinates and the latter pixels. In that same commit I changed the dimension functions
to use SDL_GetWindowSize. I've now reversed that decision and gone back to using SDL_GetRendererOutputSize so
I can guarantee output in pixels. If use_pixels is false, the code will return coordinates in 96 DPI, so I need
to have pixel measurements for the calculations.

Again, though, I do not know if SDL_GetWindowSize returns a different value that pixel size (which it's said
to do) on macOS or iOS. I'll need to do some testing. It's possible on those platforms I won't need the 96 DPI
measurements, but it's also possible it will be needed on on platforms, since all of our code relies on pixel
measurements.
This commit is contained in:
Charles Dang 2017-07-22 07:44:49 +11:00
parent ade69102bc
commit de1a9724eb
16 changed files with 78 additions and 73 deletions

View file

@ -176,7 +176,7 @@ bool controller_base::handle_scroll(int mousex, int mousey, int mouse_flags, dou
dy -= scroll_speed; dy -= scroll_speed;
} }
if(mousey > get_display().h() - scroll_threshold) { if(mousey > get_display().video().get_height() - scroll_threshold) {
dy += scroll_speed; dy += scroll_speed;
} }
@ -184,7 +184,7 @@ bool controller_base::handle_scroll(int mousex, int mousey, int mouse_flags, dou
dx -= scroll_speed; dx -= scroll_speed;
} }
if(mousex > get_display().w() - scroll_threshold) { if(mousex > get_display().video().get_width() - scroll_threshold) {
dx += scroll_speed; dx += scroll_speed;
} }
} }
@ -245,7 +245,7 @@ void controller_base::play_slice(bool is_delay_enabled)
const theme::menu* const m = get_display().menu_pressed(); const theme::menu* const m = get_display().menu_pressed();
if(m != nullptr) { if(m != nullptr) {
const SDL_Rect& menu_loc = m->location(get_display().screen_area()); const SDL_Rect& menu_loc = m->location(get_display().video().screen_area());
show_menu(m->items(), menu_loc.x + 1, menu_loc.y + menu_loc.h + 1, false, get_display()); show_menu(m->items(), menu_loc.x + 1, menu_loc.y + menu_loc.h + 1, false, get_display());
return; return;
@ -253,7 +253,7 @@ void controller_base::play_slice(bool is_delay_enabled)
const theme::action* const a = get_display().action_pressed(); const theme::action* const a = get_display().action_pressed();
if(a != nullptr) { if(a != nullptr) {
const SDL_Rect& action_loc = a->location(get_display().screen_area()); const SDL_Rect& action_loc = a->location(get_display().video().screen_area());
execute_action(a->items(), action_loc.x + 1, action_loc.y + action_loc.h + 1, false); execute_action(a->items(), action_loc.x + 1, action_loc.y + action_loc.h + 1, false);
return; return;

View file

@ -167,7 +167,7 @@ display::display(const display_context * dc, std::weak_ptr<wb::manager> wb, repo
xpos_(0), xpos_(0),
ypos_(0), ypos_(0),
view_locked_(false), view_locked_(false),
theme_(theme_cfg, screen_area()), theme_(theme_cfg, screen_.screen_area()),
zoom_index_(0), zoom_index_(0),
fake_unit_man_(new fake_unit_manager(*this)), fake_unit_man_(new fake_unit_manager(*this)),
builder_(new terrain_builder(level, &dc_->map(), theme_.border().tile_image)), builder_(new terrain_builder(level, &dc_->map(), theme_.border().tile_image)),
@ -276,7 +276,7 @@ display::~display()
} }
void display::set_theme(config theme_cfg) { void display::set_theme(config theme_cfg) {
theme_ = theme(theme_cfg, screen_area()); theme_ = theme(theme_cfg, screen_.screen_area());
menu_buttons_.clear(); menu_buttons_.clear();
action_buttons_.clear(); action_buttons_.clear();
create_buttons(); create_buttons();
@ -876,7 +876,7 @@ void display::layout_buttons()
for(const auto& menu : theme_.menus()) { for(const auto& menu : theme_.menus()) {
std::shared_ptr<gui::button> b = find_menu_button(menu.get_id()); std::shared_ptr<gui::button> b = find_menu_button(menu.get_id());
if(b) { if(b) {
const SDL_Rect& loc = menu.location(screen_area()); const SDL_Rect& loc = menu.location(screen_.screen_area());
b->set_location(loc); b->set_location(loc);
b->set_measurements(0,0); b->set_measurements(0,0);
b->set_label(menu.title()); b->set_label(menu.title());
@ -888,7 +888,7 @@ void display::layout_buttons()
for(const auto& action : theme_.actions()) { for(const auto& action : theme_.actions()) {
std::shared_ptr<gui::button> b = find_action_button(action.get_id()); std::shared_ptr<gui::button> b = find_action_button(action.get_id());
if(b) { if(b) {
const SDL_Rect& loc = action.location(screen_area()); const SDL_Rect& loc = action.location(screen_.screen_area());
b->set_location(loc); b->set_location(loc);
b->set_measurements(0,0); b->set_measurements(0,0);
b->set_label(action.title()); b->set_label(action.title());
@ -1437,7 +1437,7 @@ static void draw_panel(CVideo &video, const theme::panel& panel, std::vector<std
surface surf(image::get_image(panel.image())); surface surf(image::get_image(panel.image()));
const SDL_Rect screen = screen_area(); const SDL_Rect screen = video.screen_area();
SDL_Rect& loc = panel.location(screen); SDL_Rect& loc = panel.location(screen);
DBG_DP << "panel location: x=" << loc.x << ", y=" << loc.y DBG_DP << "panel location: x=" << loc.x << ", y=" << loc.y
@ -1469,7 +1469,7 @@ static void draw_label(CVideo& video, surface target, const theme::label& label)
text = color.str(); text = color.str();
} }
const std::string& icon = label.icon(); const std::string& icon = label.icon();
SDL_Rect& loc = label.location(screen_area()); SDL_Rect& loc = label.location(video.screen_area());
if(icon.empty() == false) { if(icon.empty() == false) {
surface surf(image::get_image(icon)); surface surf(image::get_image(icon));
@ -2427,7 +2427,7 @@ void display::redraw_everything()
tooltips::clear_tooltips(); tooltips::clear_tooltips();
theme_.set_resolution(screen_area()); theme_.set_resolution(screen_.screen_area());
if(!menu_buttons_.empty() || !action_buttons_.empty()) { if(!menu_buttons_.empty() || !action_buttons_.empty()) {
create_buttons(); create_buttons();
@ -2825,7 +2825,7 @@ void display::refresh_report(const std::string& report_name, const config * new_
new_cfg = &generated_cfg; new_cfg = &generated_cfg;
SDL_Rect &rect = reportRects_[report_name]; SDL_Rect &rect = reportRects_[report_name];
const SDL_Rect &new_rect = item->location(screen_area()); const SDL_Rect &new_rect = item->location(screen_.screen_area());
surface &surf = reportSurfaces_[report_name]; surface &surf = reportSurfaces_[report_name];
config &report = reports_[report_name]; config &report = reports_[report_name];

View file

@ -206,22 +206,16 @@ public:
virtual const std::set<std::string>& observers() const { static const std::set<std::string> fake_obs = std::set<std::string> (); return fake_obs; } virtual const std::set<std::string>& observers() const { static const std::set<std::string> fake_obs = std::set<std::string> (); return fake_obs; }
/** /**
* the dimensions of the display. x and y are width/height.
* mapx is the width of the portion of the display which shows the game area. * mapx is the width of the portion of the display which shows the game area.
* Between mapx and x is the sidebar region. * Between mapx and x is the sidebar region.
*/ */
int w() const { return screen_.getx(); } /**< width */
int h() const { return screen_.gety(); } /**< height */
const SDL_Rect& minimap_area() const const SDL_Rect& minimap_area() const
{ return theme_.mini_map_location(screen_area()); } { return theme_.mini_map_location(screen_.screen_area()); }
const SDL_Rect& palette_area() const const SDL_Rect& palette_area() const
{ return theme_.palette_location(screen_area()); } { return theme_.palette_location(screen_.screen_area()); }
const SDL_Rect& unit_image_area() const const SDL_Rect& unit_image_area() const
{ return theme_.unit_image_location(screen_area()); } { return theme_.unit_image_location(screen_.screen_area()); }
SDL_Rect screen_area() const
{ return {0, 0, w(), h()}; }
/** /**
* Returns the maximum area used for the map * Returns the maximum area used for the map
@ -240,7 +234,7 @@ public:
* applied to it. * applied to it.
*/ */
const SDL_Rect& map_outside_area() const { return map_screenshot_ ? const SDL_Rect& map_outside_area() const { return map_screenshot_ ?
max_map_area() : theme_.main_map_location(screen_area()); } max_map_area() : theme_.main_map_location(screen_.screen_area()); }
/** Check if the bbox of the hex at x,y has pixels outside the area rectangle. */ /** Check if the bbox of the hex at x,y has pixels outside the area rectangle. */
bool outside_area(const SDL_Rect& area, const int x,const int y) const; bool outside_area(const SDL_Rect& area, const int x,const int y) const;

View file

@ -641,8 +641,8 @@ void raise_resize_event()
event.window.type = SDL_WINDOWEVENT; event.window.type = SDL_WINDOWEVENT;
event.window.event = SDL_WINDOWEVENT_RESIZED; event.window.event = SDL_WINDOWEVENT_RESIZED;
event.window.windowID = 0; // We don't check this anyway... I think... event.window.windowID = 0; // We don't check this anyway... I think...
event.window.data1 = CVideo::get_singleton().getx(); event.window.data1 = CVideo::get_singleton().get_width();
event.window.data2 = CVideo::get_singleton().gety(); event.window.data2 = CVideo::get_singleton().get_height();
SDL_PushEvent(&event); SDL_PushEvent(&event);
} }

View file

@ -19,6 +19,7 @@
#include "font/standard_colors.hpp" #include "font/standard_colors.hpp"
#include "font/text.hpp" #include "font/text.hpp"
#include "log.hpp" #include "log.hpp"
#include "video.hpp"
#include <map> #include <map>
#include <set> #include <set>
@ -60,7 +61,7 @@ floating_label::floating_label(const std::string& text, const surface& surf)
, lifetime_(-1) , lifetime_(-1)
, width_(-1) , width_(-1)
, height_(-1) , height_(-1)
, clip_rect_(screen_area()) , clip_rect_(CVideo::get_singleton().screen_area())
, alpha_change_(0) , alpha_change_(0)
, visible_(true) , visible_(true)
, align_(CENTER_ALIGN) , align_(CENTER_ALIGN)

View file

@ -1022,7 +1022,7 @@ void mp_lobby::show_preferences_button_callback(window& window)
* *
* @todo This might no longer be needed when gui2 is done. * @todo This might no longer be needed when gui2 is done.
*/ */
const SDL_Rect rect = screen_area(); const SDL_Rect rect = window.video().screen_area();
gui2::settings::gamemap_width += rect.w - gui2::settings::screen_width; gui2::settings::gamemap_width += rect.w - gui2::settings::screen_width;
gui2::settings::gamemap_height += rect.h - gui2::settings::screen_height; gui2::settings::gamemap_height += rect.h - gui2::settings::screen_height;

View file

@ -429,7 +429,8 @@ window* window::window_instance(const unsigned handle)
void window::update_screen_size() void window::update_screen_size()
{ {
const SDL_Rect rect = screen_area(); const SDL_Rect rect = CVideo::get_singleton().screen_area();
settings::screen_width = rect.w; settings::screen_width = rect.w;
settings::screen_height = rect.h; settings::screen_height = rect.h;
@ -703,7 +704,7 @@ void window::draw()
assert(!item.empty()); assert(!item.empty());
const SDL_Rect dirty_rect const SDL_Rect dirty_rect
= new_widgets ? screen_area() = new_widgets ? video().screen_area()
: item.back()->get_dirty_rectangle(); : item.back()->get_dirty_rectangle();
// For testing we disable the clipping rect and force the entire screen to // For testing we disable the clipping rect and force the entire screen to

View file

@ -162,11 +162,10 @@ void show_help(CVideo& video, const section &toplevel_sec,
const events::event_context dialog_events_context; const events::event_context dialog_events_context;
const gui::dialog_manager manager; const gui::dialog_manager manager;
CVideo& screen = video; SDL_Rect screen_area = video.screen_area(false);
const surface& scr = screen.getSurface();
const int width = std::min<int>(font::relative_size(1200), scr->w - font::relative_size(20)); const int width = std::min<int>(font::relative_size(1200), screen_area.w - font::relative_size(20));
const int height = std::min<int>(font::relative_size(850), scr->h - font::relative_size(150)); const int height = std::min<int>(font::relative_size(850), screen_area.h - font::relative_size(150));
const int left_padding = font::relative_size(10); const int left_padding = font::relative_size(10);
const int right_padding = font::relative_size(10); const int right_padding = font::relative_size(10);
const int top_padding = font::relative_size(10); const int top_padding = font::relative_size(10);
@ -175,8 +174,8 @@ void show_help(CVideo& video, const section &toplevel_sec,
// If not both locations were supplied, put the dialog in the middle // If not both locations were supplied, put the dialog in the middle
// of the screen. // of the screen.
if (yloc <= -1 || xloc <= -1) { if (yloc <= -1 || xloc <= -1) {
xloc = scr->w / 2 - width / 2; xloc = screen_area.w / 2 - width / 2;
yloc = scr->h / 2 - height / 2; yloc = screen_area.h / 2 - height / 2;
} }
std::vector<gui::button*> buttons_ptr; std::vector<gui::button*> buttons_ptr;
gui::button close_button_(video, _("Close")); gui::button close_button_(video, _("Close"));

View file

@ -240,7 +240,7 @@ std::string unit_topic_generator::operator()() const {
const unit_type& female_type = type_.get_gender_unit_type(unit_race::FEMALE); const unit_type& female_type = type_.get_gender_unit_type(unit_race::FEMALE);
const unit_type& male_type = type_.get_gender_unit_type(unit_race::MALE); const unit_type& male_type = type_.get_gender_unit_type(unit_race::MALE);
const int screen_width = CVideo::get_singleton().getx(); const int screen_width = CVideo::get_singleton().get_width();
ss << "Level " << type_.level(); ss << "Level " << type_.level();
ss << "\n\n"; ss << "\n\n";

View file

@ -204,7 +204,7 @@ dialog_frame::dimension_measurements dialog_frame::layout(int x, int y, int w, i
h += dim_.title.h + dim_.button_row.h; h += dim_.title.h + dim_.button_row.h;
dim_.button_row.x += x + w; dim_.button_row.x += x + w;
SDL_Rect bounds = screen_area(); SDL_Rect bounds = video_.screen_area();
if(have_border_) { if(have_border_) {
bounds.x += left_->w; bounds.x += left_->w;
bounds.y += top_->h; bounds.y += top_->h;
@ -324,7 +324,7 @@ void dialog_frame::draw_background()
SDL_Rect dialog_frame::draw_title(CVideo* video) SDL_Rect dialog_frame::draw_title(CVideo* video)
{ {
SDL_Rect rect = screen_area(); SDL_Rect rect = CVideo::get_singleton().screen_area();
return font::draw_text(video, rect, font::SIZE_TITLE, font::TITLE_COLOR, return font::draw_text(video, rect, font::SIZE_TITLE, font::TITLE_COLOR,
title_, dim_.title.x, dim_.title.y, false, TTF_STYLE_NORMAL); title_, dim_.title.x, dim_.title.y, false, TTF_STYLE_NORMAL);
} }

View file

@ -62,14 +62,16 @@ static void clear_tooltip()
static void show_tooltip(const tooltip& tip) static void show_tooltip(const tooltip& tip)
{ {
if(CVideo::get_singleton().faked()) { CVideo& video = CVideo::get_singleton();
if(video.faked()) {
return; return;
} }
clear_tooltip(); clear_tooltip();
const color_t bgcolor {0,0,0,160}; const color_t bgcolor {0,0,0,160};
SDL_Rect area = screen_area(); SDL_Rect area = video.screen_area();
unsigned int border = 10; unsigned int border = 10;

View file

@ -136,17 +136,6 @@ bool CVideo::non_interactive() const
return fake_interactive ? false : (window == nullptr); return fake_interactive ? false : (window == nullptr);
} }
SDL_Rect screen_area()
{
sdl::window* w = CVideo::get_singleton().get_window();
if(!w) {
return {0, 0, frameBuffer->w, frameBuffer->h};
}
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) void CVideo::video_event_handler::handle_window_event(const SDL_Event& event)
{ {
if(event.type == SDL_WINDOWEVENT) { if(event.type == SDL_WINDOWEVENT) {
@ -303,22 +292,35 @@ void CVideo::set_window_mode(const MODE_EVENT mode, const point& size)
} }
} }
int CVideo::getx() const SDL_Rect CVideo::screen_area(bool as_pixels) const
{ {
if(!window) { if(!window) {
return frameBuffer->w; return {0, 0, frameBuffer->w, frameBuffer->h};
} }
return window->get_size().x; // First, get the renderer size in pixels.
SDL_Point size = window->get_output_size();
// Then convert the dimensions into screen coordinates, if applicable.
if(!as_pixels) {
float scale_x, scale_y;
std::tie(scale_x, scale_y) = get_dpi_scale_factor();
size.x /= scale_x;
size.y /= scale_y;
}
return {0, 0, size.x, size.y};
} }
int CVideo::gety() const int CVideo::get_width(bool as_pixels) const
{ {
if(!window) { return screen_area(as_pixels).w;
return frameBuffer->h; }
}
return window->get_size().y; int CVideo::get_height(bool as_pixels) const
{
return screen_area(as_pixels).h;
} }
void CVideo::delay(unsigned int milliseconds) void CVideo::delay(unsigned int milliseconds)
@ -487,7 +489,7 @@ int CVideo::set_help_string(const std::string& str)
int size = font::SIZE_LARGE; int size = font::SIZE_LARGE;
while(size > 0) { while(size > 0) {
if(font::line_width(str, size) > getx()) { if(font::line_width(str, size) > get_width()) {
size--; size--;
} else { } else {
break; break;
@ -498,7 +500,7 @@ int CVideo::set_help_string(const std::string& str)
font::floating_label flabel(str); font::floating_label flabel(str);
flabel.set_font_size(size); flabel.set_font_size(size);
flabel.set_position(getx() / 2, gety()); flabel.set_position(get_width() / 2, get_height());
flabel.set_bg_color(color); flabel.set_bg_color(color);
flabel.set_border_size(border); flabel.set_border_size(border);

View file

@ -28,8 +28,6 @@ namespace sdl
class window; class window;
} }
SDL_Rect screen_area();
class CVideo class CVideo
{ {
public: public:
@ -108,11 +106,19 @@ public:
/** Returns the list of available screen resolutions. */ /** Returns the list of available screen resolutions. */
std::vector<point> get_available_resolutions(const bool include_current = false); std::vector<point> get_available_resolutions(const bool include_current = false);
/** The current width of the window, is screen coordinates. */ /**
int getx() const; * Returns the current window renderer area, either in pixels or screen coordinates.
*
* @param as_pixels Whether to return the area in pixels (default true) or
* DPI-independent (DIP) screen coordinates.
*/
SDL_Rect screen_area(bool as_pixels = true) const;
/** The current height of the window, is screen coordinates. */ /** Returns the window renderer width in pixels or screen coordinates. */
int gety() const; int get_width(bool as_pixels = true) const;
/** Returns the window renderer height in pixels or in screen coordinates. */
int get_height(bool as_pixels = true) const;
/** The current scale factor on High-DPI screens. */ /** The current scale factor on High-DPI screens. */
std::pair<float, float> get_dpi_scale_factor() const; std::pair<float, float> get_dpi_scale_factor() const;

View file

@ -228,7 +228,7 @@ void button::calculate_size()
} }
if (type_ != TYPE_IMAGE){ if (type_ != TYPE_IMAGE){
textRect_ = font::draw_text(nullptr, screen_area(), font_size, textRect_ = font::draw_text(nullptr, video().screen_area(), font_size,
font::BUTTON_COLOR, label_text_, 0, 0); font::BUTTON_COLOR, label_text_, 0, 0);
} }

View file

@ -486,7 +486,7 @@ size_t menu::max_items_onscreen() const
return size_t(max_items_); return size_t(max_items_);
} }
const size_t max_height = (max_height_ == -1 ? (video().gety()*66)/100 : max_height_) - heading_height(); const size_t max_height = (max_height_ == -1 ? (video().get_height()*66)/100 : max_height_) - heading_height();
std::vector<int> heights; std::vector<int> heights;
size_t n; size_t n;
@ -912,7 +912,7 @@ void menu::draw_row(const size_t row_index, const SDL_Rect& rect, ROW_TYPE type)
{ {
//called from style, draws one row's contents in a generic and adaptable way //called from style, draws one row's contents in a generic and adaptable way
const std::vector<std::string>& row = (type == HEADING_ROW) ? heading_ : items_[row_index].fields; const std::vector<std::string>& row = (type == HEADING_ROW) ? heading_ : items_[row_index].fields;
SDL_Rect const &area = screen_area(); SDL_Rect const &area = video().screen_area();
SDL_Rect const &loc = inner_location(); SDL_Rect const &loc = inner_location();
const std::vector<int>& widths = column_widths(); const std::vector<int>& widths = column_widths();
bool lang_rtl = current_language_rtl(); bool lang_rtl = current_language_rtl();
@ -1137,7 +1137,7 @@ SDL_Rect menu::get_item_rect_internal(size_t item) const
SDL_Rect res = sdl::create_rect(loc.x, y, loc.w, get_item_height(item)); SDL_Rect res = sdl::create_rect(loc.x, y, loc.w, get_item_height(item));
SDL_Rect const &screen_area = ::screen_area(); SDL_Rect const &screen_area = video().screen_area();
if(res.x > screen_area.w) { if(res.x > screen_area.w) {
return sdl::empty_rect; return sdl::empty_rect;

View file

@ -39,7 +39,7 @@ textbox::textbox(CVideo &video, int width, const std::string& text, bool editabl
edit_target_(nullptr) edit_target_(nullptr)
,listening_(false) ,listening_(false)
{ {
// static const SDL_Rect area = d.screen_area(); // static const SDL_Rect area = video.screen_area();
// const int height = font::draw_text(nullptr,area,font_size,font::NORMAL_COLOR,"ABCD",0,0).h; // const int height = font::draw_text(nullptr,area,font_size,font::NORMAL_COLOR,"ABCD",0,0).h;
set_measurements(width, font::get_max_height(font_size_)); set_measurements(width, font::get_max_height(font_size_));
set_scroll_rate(font::get_max_height(font_size_) / 2); set_scroll_rate(font::get_max_height(font_size_) / 2);
@ -206,7 +206,7 @@ void textbox::draw_contents()
src.w = std::min<size_t>(loc.w,text_image_->w); src.w = std::min<size_t>(loc.w,text_image_->w);
src.h = std::min<size_t>(loc.h,text_image_->h); src.h = std::min<size_t>(loc.h,text_image_->h);
src.x = text_pos_; src.x = text_pos_;
SDL_Rect dest = screen_area(); SDL_Rect dest = video().screen_area();
dest.x = loc.x; dest.x = loc.x;
dest.y = loc.y; dest.y = loc.y;