Cleaned up various areas of code related to setting window resolution

* Added a point ctor that takes an SDL_Point.
* Added a toggle_fullscreen function to CVideo.
* Change all management of resolution data to use point instead of std::pair<int, int>. This
  shortens the code considerably.
* Cleaned up preferences_dialog::set_resolution_list
* Made CVideo::set_resolution return a bool indicating whether resolution was changed.
* Swapped which of the two set_resolution overloads contains the main implementation.
* Moved the events::raise_resize_event() call when setting resolution to the CVideo function
  where it should have always been (instead of the prefs dialog callback). This is a pretty
  essential component and having it localized in one place meant any other area of the code
  that might have called set_resolution wouldn't have it.
This commit is contained in:
Charles Dang 2017-11-27 05:53:23 +11:00
parent 4ff249da7d
commit a21697fef3
11 changed files with 101 additions and 74 deletions

View file

@ -213,7 +213,7 @@ game_launcher::game_launcher(const commandline_options& cmdline_opts, const char
const int xres = std::get<0>(*cmdline_opts_.resolution);
const int yres = std::get<1>(*cmdline_opts_.resolution);
if(xres > 0 && yres > 0) {
preferences::_set_resolution(std::make_pair(xres, yres));
preferences::_set_resolution(point(xres, yres));
preferences::_set_maximized(false);
}
}

View file

@ -179,7 +179,7 @@ void mp_lobby::post_build(window& win)
{
/** @todo Should become a global hotkey after 1.8, then remove it here. */
win.register_hotkey(hotkey::HOTKEY_FULLSCREEN,
std::bind(&CVideo::set_fullscreen, std::ref(win.video()), !preferences::fullscreen()));
std::bind(&CVideo::toggle_fullscreen, std::ref(win.video())));
/*** Local hotkeys. ***/
win.register_hotkey(hotkey::HOTKEY_PREFERENCES,

View file

@ -119,18 +119,20 @@ void preferences_dialog::set_resolution_list(menu_button& res_list, CVideo& vide
resolutions_ = video.get_available_resolutions(true);
std::vector<config> options;
for(const auto& res : resolutions_)
{
for(const point& res : resolutions_) {
config option;
option["label"] = formatter() << res.first << font::unicode_multiplication_sign << res.second;
option["label"] = formatter() << res.x << font::unicode_multiplication_sign << res.y;
const int div = boost::math::gcd(res.first, res.second);
const int ratio[2] {res.first/div, res.second/div};
if(ratio[0] <= 10 || ratio[1] <= 10) {
option["details"] = formatter() << "<span color='#777777'>(" << ratio[0] << ':' << ratio[1] << ")</span>";
const int div = boost::math::gcd(res.x, res.y);
const int x_ratio = res.x / div;
const int y_ratio = res.y / div;
if(x_ratio <= 10 || y_ratio <= 10) {
option["details"] = formatter() << "<span color='#777777'>(" << y_ratio << ':' << y_ratio << ")</span>";
}
options.push_back(option);
options.push_back(std::move(option));
}
const unsigned current_res = std::find(resolutions_.begin(), resolutions_.end(),
@ -1037,15 +1039,10 @@ void preferences_dialog::fullscreen_toggle_callback(window& window)
void preferences_dialog::handle_res_select(window& window)
{
menu_button& res_list = find_widget<menu_button>(&window, "resolution_set", false);
const int choice = res_list.get_value();
if(resolutions_[static_cast<size_t>(choice)] == window.video().current_resolution()) {
return;
if(window.video().set_resolution(resolutions_[res_list.get_value()])) {
set_resolution_list(res_list, window.video());
}
window.video().set_resolution(resolutions_[static_cast<size_t>(choice)]);
events::raise_resize_event();
set_resolution_list(res_list, window.video());
}
void preferences_dialog::on_page_select(window& window)

View file

@ -30,6 +30,8 @@ namespace hotkey {
struct hotkey_command;
}
struct point;
namespace preferences {
enum PREFERENCE_VIEW {
VIEW_DEFAULT,
@ -125,7 +127,7 @@ private:
(SPECIAL, "custom")
)
std::vector<std::pair<int,int> > resolutions_;
std::vector<point> resolutions_;
std::vector<config> adv_preferences_cfg_;
int last_selected_item_;

View file

@ -216,7 +216,7 @@ void title_screen::pre_show(window& win)
std::bind(&title_screen::hotkey_callback_select_tests, this, std::ref(win)));
win.register_hotkey(hotkey::HOTKEY_FULLSCREEN,
std::bind(&CVideo::set_fullscreen, std::ref(win.video()), !preferences::fullscreen()));
std::bind(&CVideo::toggle_fullscreen, std::ref(win.video())));
// A wrapper is needed here since the relevant display function is overloaded, and
// since the wrapper's signature doesn't exactly match what register_hotkey expects.

View file

@ -561,7 +561,7 @@ void execute_command(const hotkey_command& command, command_executor* executor,
executor->recalculate_minimap();
break;
case HOTKEY_FULLSCREEN:
executor->get_video().set_fullscreen(!preferences::fullscreen());
executor->get_video().toggle_fullscreen();
break;
case HOTKEY_SCREENSHOT:
make_screenshot(_("Screenshot"), executor->get_video(), &::screenshot);

View file

@ -19,18 +19,20 @@
#define GETTEXT_DOMAIN "wesnoth-lib"
#include "preferences/general.hpp"
#include "config.hpp"
#include "credentials.hpp"
#include "filesystem.hpp"
#include "game_config.hpp"
#include "hotkey/hotkey_item.hpp"
#include "lexical_cast.hpp"
#include "log.hpp"
#include "credentials.hpp"
#include "preferences/general.hpp"
#include "sound.hpp"
#include "video.hpp" // non_interactive()
#include "sdl/point.hpp"
#include "serialization/parser.hpp"
#include "sound.hpp"
#include "utils/general.hpp"
#include "video.hpp" // non_interactive()
#include <sys/stat.h> // for setting the permissions of the preferences file
#ifndef _WIN32
@ -135,7 +137,7 @@ void prefs_event_handler::handle_window_event(const SDL_Event& event)
switch(event.window.event) {
case SDL_WINDOWEVENT_RESIZED:
_set_resolution(std::make_pair(event.window.data1,event.window.data2));
_set_resolution(point(event.window.data1,event.window.data2));
break;
@ -370,19 +372,19 @@ void set_scroll_to_action(bool ison)
prefs["scroll_to_action"] = ison;
}
std::pair<int,int> resolution()
point resolution()
{
const std::string& x = prefs["xresolution"], y = prefs["yresolution"];
if (!x.empty() && !y.empty()) {
try {
return std::make_pair(
return point(
std::max(std::stoi(x), min_window_width),
std::max(std::stoi(y), min_window_height));
} catch(std::invalid_argument) {}
}
return std::pair<int,int>(def_window_width, def_window_height);
return point(def_window_width, def_window_height);
}
bool maximized()
@ -395,10 +397,10 @@ bool fullscreen()
return get("fullscreen", false);
}
void _set_resolution(const std::pair<int, int>& res)
void _set_resolution(const point& res)
{
preferences::set("xresolution", std::to_string(res.first));
preferences::set("yresolution", std::to_string(res.second));
preferences::set("xresolution", std::to_string(res.x));
preferences::set("yresolution", std::to_string(res.y));
}
void _set_maximized(bool ison)

View file

@ -24,6 +24,8 @@ class display;
#include <utility>
struct point;
namespace hotkey {
class hotkey_item;
}
@ -81,8 +83,8 @@ namespace preferences {
bool scroll_to_action();
void set_scroll_to_action(bool ison);
std::pair<int,int> resolution();
void _set_resolution(const std::pair<int,int>& res);
point resolution();
void _set_resolution(const point& res);
bool maximized();
void _set_maximized(bool ison);

View file

@ -21,11 +21,21 @@
/** Holds a 2D point. */
struct point
{
point() : x(0), y(0)
point()
: x(0)
, y(0)
{
}
point(const int x_, const int y_) : x(x_), y(y_)
point(const int x_, const int y_)
: x(x_)
, y(y_)
{
}
point(const SDL_Point& p)
: x(p.x)
, y(p.y)
{
}
@ -42,10 +52,12 @@ struct point
{
return x == point.x && y == point.y;
}
bool operator!=(const point& point) const
{
return x != point.x || y != point.y;
return !operator==(point);
}
bool operator<(const point& point) const
{
return x < point.x || (x == point.x && y < point.y);

View file

@ -19,6 +19,7 @@
#include "image.hpp"
#include "log.hpp"
#include "preferences/general.hpp"
#include "sdl/point.hpp"
#include "sdl/userevent.hpp"
#include "sdl/utils.hpp"
#include "sdl/window.hpp"
@ -233,8 +234,8 @@ void CVideo::init_window()
const int y = preferences::fullscreen() ? SDL_WINDOWPOS_UNDEFINED : SDL_WINDOWPOS_CENTERED;
// Dimensions
const int w = preferences::resolution().first;
const int h = preferences::resolution().second;
const int w = preferences::resolution().x;
const int h = preferences::resolution().y;
// Video flags
int video_flags = 0;
@ -267,7 +268,7 @@ void CVideo::init_window()
}
}
void CVideo::set_window_mode(int x, int y, const MODE_EVENT mode)
void CVideo::set_window_mode(const MODE_EVENT mode, const point& size)
{
assert(window);
if(fake_screen_) {
@ -291,7 +292,7 @@ void CVideo::set_window_mode(int x, int y, const MODE_EVENT mode)
case TO_RES:
window->restore();
window->set_size(x, y);
window->set_size(size.x, size.y);
window->center();
break;
}
@ -412,9 +413,9 @@ std::pair<float, float> CVideo::get_dpi_scale_factor() const
return result;
}
std::vector<std::pair<int, int>> CVideo::get_available_resolutions(const bool include_current)
std::vector<point> CVideo::get_available_resolutions(const bool include_current)
{
std::vector<std::pair<int, int>> result;
std::vector<point> result;
if(!window) {
return result;
@ -428,8 +429,7 @@ std::vector<std::pair<int, int>> CVideo::get_available_resolutions(const bool in
return result;
}
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();
const point min_res(preferences::min_window_width, preferences::min_window_height);
#if 0
// DPI scale factor.
@ -451,7 +451,7 @@ std::vector<std::pair<int, int>> CVideo::get_available_resolutions(const bool in
continue;
}
if(mode.w >= min_res.first && mode.h >= min_res.second) {
if(mode.w >= min_res.x && mode.h >= min_res.y) {
result.emplace_back(mode.w, mode.h);
}
}
@ -462,7 +462,7 @@ std::vector<std::pair<int, int>> CVideo::get_available_resolutions(const bool in
}
if(include_current) {
result.push_back(current_res);
result.push_back(current_resolution());
}
std::sort(result.begin(), result.end());
@ -476,10 +476,9 @@ surface& CVideo::getSurface()
return frameBuffer;
}
std::pair<int, int> CVideo::current_resolution()
point CVideo::current_resolution()
{
SDL_Point size = window->get_size();
return std::make_pair(size.x, size.y);
return point(window->get_size()); // Convert from plain SDL_Point
}
bool CVideo::is_fullscreen() const
@ -535,7 +534,7 @@ void CVideo::clear_all_help_strings()
void CVideo::set_fullscreen(bool ison)
{
if(window && is_fullscreen() != ison) {
const std::pair<int, int>& res = preferences::resolution();
const point& res = preferences::resolution();
MODE_EVENT mode;
@ -545,10 +544,10 @@ void CVideo::set_fullscreen(bool ison)
mode = preferences::maximized() ? TO_MAXIMIZED_WINDOW : TO_WINDOWED;
}
set_window_mode(res.first, res.second, mode);
set_window_mode(mode, res);
if(display::get_singleton()) {
display::get_singleton()->redraw_everything();
if(display* d = display::get_singleton()) {
d->redraw_everything();
}
}
@ -556,27 +555,37 @@ void CVideo::set_fullscreen(bool ison)
preferences::_set_fullscreen(ison);
}
void CVideo::set_resolution(const std::pair<int, int>& resolution)
void CVideo::toggle_fullscreen()
{
set_resolution(resolution.first, resolution.second);
set_fullscreen(!preferences::fullscreen());
}
void CVideo::set_resolution(const unsigned width, const unsigned height)
bool CVideo::set_resolution(const unsigned width, const unsigned height)
{
if(static_cast<unsigned int>(current_resolution().first) == width
&& static_cast<unsigned int>(current_resolution().second) == height) {
return;
return set_resolution(point(width, height));
}
bool CVideo::set_resolution(const point& resolution)
{
if(resolution == current_resolution()) {
return false;
}
set_window_mode(width, height, TO_RES);
set_window_mode(TO_RES, resolution);
if(display::get_singleton()) {
display::get_singleton()->redraw_everything();
if(display* d = display::get_singleton()) {
d->redraw_everything();
}
// Change the config values.
preferences::_set_resolution(std::make_pair(width, height));
// Change the saved values in preferences.
preferences::_set_resolution(resolution);
preferences::_set_maximized(false);
// Push a window-resized event to the queue. This is necessary so various areas
// of the game (like GUI2) update properly with the new size.
events::raise_resize_event();
return true;
}
void CVideo::lock_flips(bool lock)

View file

@ -21,6 +21,7 @@
#include <memory>
class surface;
struct point;
namespace sdl
{
@ -79,31 +80,33 @@ private:
/**
* Sets the window's mode - ie, changing it to fullscreen, maximizing, etc.
*
* @param x The new window width, if @a mode is TO_RES.
* @param y The new window height, if @a mode is TO_RES.
* @param mode The action to perform.
* @param size The new window size. Utilized if @a mode is TO_RES.
*/
void set_window_mode(int x, int y, const MODE_EVENT mode);
void set_window_mode(const MODE_EVENT mode, const point& size);
public:
void set_fullscreen(bool ison);
void toggle_fullscreen();
bool is_fullscreen() const;
void set_resolution(const std::pair<int, int>& res);
bool set_resolution(const unsigned width, const unsigned height);
/**
* Set the resolution.
* Set the window resolution.
*
* @param width The new width.
* @param height The new height.
* @param resolution The new width and height.
*
* @returns Whether the resolution was sucessfully changed.
*/
void set_resolution(const unsigned width, const unsigned height);
bool set_resolution(const point& resolution);
std::pair<int, int> current_resolution();
point current_resolution();
/** Returns the list of available screen resolutions. */
std::vector<std::pair<int, int>> 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;