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;
}
if(mousey > get_display().h() - scroll_threshold) {
if(mousey > get_display().video().get_height() - scroll_threshold) {
dy += scroll_speed;
}
@ -184,7 +184,7 @@ bool controller_base::handle_scroll(int mousex, int mousey, int mouse_flags, dou
dx -= scroll_speed;
}
if(mousex > get_display().w() - scroll_threshold) {
if(mousex > get_display().video().get_width() - scroll_threshold) {
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();
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());
return;
@ -253,7 +253,7 @@ void controller_base::play_slice(bool is_delay_enabled)
const theme::action* const a = get_display().action_pressed();
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);
return;

View file

@ -167,7 +167,7 @@ display::display(const display_context * dc, std::weak_ptr<wb::manager> wb, repo
xpos_(0),
ypos_(0),
view_locked_(false),
theme_(theme_cfg, screen_area()),
theme_(theme_cfg, screen_.screen_area()),
zoom_index_(0),
fake_unit_man_(new fake_unit_manager(*this)),
builder_(new terrain_builder(level, &dc_->map(), theme_.border().tile_image)),
@ -276,7 +276,7 @@ display::~display()
}
void display::set_theme(config theme_cfg) {
theme_ = theme(theme_cfg, screen_area());
theme_ = theme(theme_cfg, screen_.screen_area());
menu_buttons_.clear();
action_buttons_.clear();
create_buttons();
@ -876,7 +876,7 @@ void display::layout_buttons()
for(const auto& menu : theme_.menus()) {
std::shared_ptr<gui::button> b = find_menu_button(menu.get_id());
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_measurements(0,0);
b->set_label(menu.title());
@ -888,7 +888,7 @@ void display::layout_buttons()
for(const auto& action : theme_.actions()) {
std::shared_ptr<gui::button> b = find_action_button(action.get_id());
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_measurements(0,0);
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()));
const SDL_Rect screen = screen_area();
const SDL_Rect screen = video.screen_area();
SDL_Rect& loc = panel.location(screen);
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();
}
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) {
surface surf(image::get_image(icon));
@ -2427,7 +2427,7 @@ void display::redraw_everything()
tooltips::clear_tooltips();
theme_.set_resolution(screen_area());
theme_.set_resolution(screen_.screen_area());
if(!menu_buttons_.empty() || !action_buttons_.empty()) {
create_buttons();
@ -2825,7 +2825,7 @@ void display::refresh_report(const std::string& report_name, const config * new_
new_cfg = &generated_cfg;
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];
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; }
/**
* 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.
* 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
{ return theme_.mini_map_location(screen_area()); }
{ return theme_.mini_map_location(screen_.screen_area()); }
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
{ return theme_.unit_image_location(screen_area()); }
SDL_Rect screen_area() const
{ return {0, 0, w(), h()}; }
{ return theme_.unit_image_location(screen_.screen_area()); }
/**
* Returns the maximum area used for the map
@ -240,7 +234,7 @@ public:
* applied to it.
*/
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. */
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.event = SDL_WINDOWEVENT_RESIZED;
event.window.windowID = 0; // We don't check this anyway... I think...
event.window.data1 = CVideo::get_singleton().getx();
event.window.data2 = CVideo::get_singleton().gety();
event.window.data1 = CVideo::get_singleton().get_width();
event.window.data2 = CVideo::get_singleton().get_height();
SDL_PushEvent(&event);
}

View file

@ -19,6 +19,7 @@
#include "font/standard_colors.hpp"
#include "font/text.hpp"
#include "log.hpp"
#include "video.hpp"
#include <map>
#include <set>
@ -60,7 +61,7 @@ floating_label::floating_label(const std::string& text, const surface& surf)
, lifetime_(-1)
, width_(-1)
, height_(-1)
, clip_rect_(screen_area())
, clip_rect_(CVideo::get_singleton().screen_area())
, alpha_change_(0)
, visible_(true)
, 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.
*/
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_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()
{
const SDL_Rect rect = screen_area();
const SDL_Rect rect = CVideo::get_singleton().screen_area();
settings::screen_width = rect.w;
settings::screen_height = rect.h;
@ -703,7 +704,7 @@ void window::draw()
assert(!item.empty());
const SDL_Rect dirty_rect
= new_widgets ? screen_area()
= new_widgets ? video().screen_area()
: item.back()->get_dirty_rectangle();
// 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 gui::dialog_manager manager;
CVideo& screen = video;
const surface& scr = screen.getSurface();
SDL_Rect screen_area = video.screen_area(false);
const int width = std::min<int>(font::relative_size(1200), scr->w - font::relative_size(20));
const int height = std::min<int>(font::relative_size(850), scr->h - font::relative_size(150));
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), screen_area.h - font::relative_size(150));
const int left_padding = font::relative_size(10);
const int right_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
// of the screen.
if (yloc <= -1 || xloc <= -1) {
xloc = scr->w / 2 - width / 2;
yloc = scr->h / 2 - height / 2;
xloc = screen_area.w / 2 - width / 2;
yloc = screen_area.h / 2 - height / 2;
}
std::vector<gui::button*> buttons_ptr;
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& 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 << "\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;
dim_.button_row.x += x + w;
SDL_Rect bounds = screen_area();
SDL_Rect bounds = video_.screen_area();
if(have_border_) {
bounds.x += left_->w;
bounds.y += top_->h;
@ -324,7 +324,7 @@ void dialog_frame::draw_background()
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,
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)
{
if(CVideo::get_singleton().faked()) {
CVideo& video = CVideo::get_singleton();
if(video.faked()) {
return;
}
clear_tooltip();
const color_t bgcolor {0,0,0,160};
SDL_Rect area = screen_area();
SDL_Rect area = video.screen_area();
unsigned int border = 10;

View file

@ -136,17 +136,6 @@ bool CVideo::non_interactive() const
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)
{
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) {
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;
}
int CVideo::gety() const
return {0, 0, size.x, size.y};
}
int CVideo::get_width(bool as_pixels) const
{
if(!window) {
return frameBuffer->h;
return screen_area(as_pixels).w;
}
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)
@ -487,7 +489,7 @@ int CVideo::set_help_string(const std::string& str)
int size = font::SIZE_LARGE;
while(size > 0) {
if(font::line_width(str, size) > getx()) {
if(font::line_width(str, size) > get_width()) {
size--;
} else {
break;
@ -498,7 +500,7 @@ int CVideo::set_help_string(const std::string& str)
font::floating_label flabel(str);
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_border_size(border);

View file

@ -28,8 +28,6 @@ namespace sdl
class window;
}
SDL_Rect screen_area();
class CVideo
{
public:
@ -108,11 +106,19 @@ public:
/** Returns the list of available screen resolutions. */
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. */
int gety() const;
/** Returns the window renderer width in pixels or screen coordinates. */
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. */
std::pair<float, float> get_dpi_scale_factor() const;

View file

@ -228,7 +228,7 @@ void button::calculate_size()
}
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);
}

View file

@ -486,7 +486,7 @@ size_t menu::max_items_onscreen() const
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;
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
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();
const std::vector<int>& widths = column_widths();
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 const &screen_area = ::screen_area();
SDL_Rect const &screen_area = video().screen_area();
if(res.x > screen_area.w) {
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)
,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;
set_measurements(width, font::get_max_height(font_size_));
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.h = std::min<size_t>(loc.h,text_image_->h);
src.x = text_pos_;
SDL_Rect dest = screen_area();
SDL_Rect dest = video().screen_area();
dest.x = loc.x;
dest.y = loc.y;