Merge pull request #6629 from mesilliac/pixel_scale_multiplier

Add a pixel scale multiplier option, enabling integer scaling of the game to higher resolutions.
This commit is contained in:
Charles Dang 2022-04-30 03:22:11 -04:00 committed by GitHub
commit e05745e64c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 698 additions and 177 deletions

View File

@ -51,6 +51,38 @@
[/column]
[/row]
[row]
{GUI_FILLER}
[column]
horizontal_grow = true
{_GUI_PREFERENCES_MAIN_COMPOSITE_SLIDER
( _ "Pixel scale multiplier:")
pixel_scale_slider (
minimum_value,maximum_value=1,4
step_size=1
tooltip= _ "Set the global pixel scale multiplier. A pixel scale multiplier of 2 will make everything look twice as large."
)
}
[/column]
[/row]
[row]
{GUI_FILLER}
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[toggle_button]
id = "auto_pixel_scale"
label = _ "Automatic pixel scale multiplier"
tooltip = _ "Choose pixel scale multiplier automatically based on current resolution"
[/toggle_button]
[/column]
[/row]
[/grid]
[/column]
[/row]

View File

@ -821,6 +821,7 @@
91A215E21CAD9B9000927AEA /* libpango-1.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = EC5C242E18EF07B4001FA499 /* libpango-1.0.0.dylib */; };
91A215E31CAD9B9000927AEA /* libpangocairo-1.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = EC5C242F18EF07B4001FA499 /* libpangocairo-1.0.0.dylib */; };
91A41F901CA22A98008B10D5 /* libreadline.8.1.dylib in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = ECA9E7461CA20AA800A947D6 /* libreadline.8.1.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
91AF556D281101C4007A7652 /* input.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91AF556C281101C3007A7652 /* input.cpp */; };
91B621A21B76A3CC00B00E0F /* build_info.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91B621A11B76A3CC00B00E0F /* build_info.cpp */; };
91B621BA1B76B2C900B00E0F /* version.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91B621B91B76B2C900B00E0F /* version.cpp */; };
91B6220A1B76C0A600B00E0F /* libcairo.2.dylib in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = B513B2270ED36BFB0006E551 /* libcairo.2.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
@ -2132,6 +2133,8 @@
919B37F71BAF789D00E0094C /* synced_user_choice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = synced_user_choice.cpp; sourceTree = "<group>"; };
919B37F91BAF78AB00E0094C /* synced_user_choice.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = synced_user_choice.hpp; sourceTree = "<group>"; };
91A214E41CAD618700927AEA /* gettext.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = gettext.hpp; sourceTree = "<group>"; };
91AF556B281101C3007A7652 /* input.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = input.hpp; sourceTree = "<group>"; };
91AF556C281101C3007A7652 /* input.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = input.cpp; sourceTree = "<group>"; };
91B621801B766ED500B00E0F /* buffered_istream.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = buffered_istream.hpp; sourceTree = "<group>"; };
91B621811B766F1900B00E0F /* carryover.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = carryover.hpp; sourceTree = "<group>"; };
91B621821B766FD200B00E0F /* display_context.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = display_context.hpp; sourceTree = "<group>"; };
@ -4165,6 +4168,8 @@
ECB6A6311FB8AAC400877C20 /* point.hpp */,
ECFB9FAB193BFB6E00146ED0 /* rect.cpp */,
91B621F11B76BBC500B00E0F /* rect.hpp */,
91AF556C281101C3007A7652 /* input.cpp */,
91AF556B281101C3007A7652 /* input.hpp */,
EC669C251DFC95AF00172EED /* surface.cpp */,
467D9DF5205EC3DA00FA2FC4 /* surface.hpp */,
467D9DF0205EC3D200FA2FC4 /* userevent.hpp */,
@ -5159,6 +5164,7 @@
46F92DCF2174F6A300602C1C /* label_settings.cpp in Sources */,
62CC8E7517B9063E00C16B75 /* conditional_wml.cpp in Sources */,
46F92F192174FEC000602C1C /* text_formatting.cpp in Sources */,
91AF556D281101C4007A7652 /* input.cpp in Sources */,
46F92DD92174F6A300602C1C /* tooltip.cpp in Sources */,
4664B9441F462ED9009E4881 /* irdya_datetime.cpp in Sources */,
EC669C261DFC95AF00172EED /* surface.cpp in Sources */,

View File

@ -342,6 +342,7 @@ scripting/mapgen_lua_kernel.cpp
scripting/plugins/context.cpp
scripting/plugins/manager.cpp
sdl/point.cpp
sdl/input.cpp
map_settings.cpp
side_filter.cpp
statistics.cpp

View File

@ -28,6 +28,7 @@
#include "sound.hpp"
#include "video.hpp"
#include "addon/manager.hpp"
#include "sdl/point.hpp"
#include <algorithm>
#include <fstream>
@ -579,7 +580,12 @@ list_formatter video_settings_report_internal(const std::string& heading = "")
}
fmt.insert("SDL video drivers", format_sdl_driver_list(drivers, current_driver));
fmt.insert("Window size", geometry_to_string(video.get_width(), video.get_height()));
fmt.insert("Window size", geometry_to_string(
video.current_resolution().x, video.current_resolution().y));
fmt.insert("Game canvas size", geometry_to_string(
video.get_width(), video.get_height()));
fmt.insert("Final render target size", geometry_to_string(
video.output_size().x, video.output_size().y));
fmt.insert("Screen refresh rate", std::to_string(video.current_refresh_rate()));
fmt.insert("Screen dots per inch", dpi_report);
fmt.insert("Screen dpi scale factor", scale_report);

View File

@ -29,6 +29,7 @@
#include "gui/core/event/handler.hpp" // gui2::is_in_dialog
#include "soundsource.hpp"
#include "gui/core/timer.hpp"
#include "sdl/input.hpp" // get_mouse_state
static lg::log_domain log_display("display");
#define ERR_DP LOG_STREAM(err, log_display)
@ -65,7 +66,7 @@ void controller_base::long_touch_callback(int x, int y)
if(long_touch_timer_ != 0 && !get_mouse_handler_base().dragging_started()) {
int x_now;
int y_now;
uint32_t mouse_state = SDL_GetMouseState(&x_now, &y_now);
uint32_t mouse_state = sdl::get_mouse_state(&x_now, &y_now);
#ifdef MOUSE_TOUCH_EMULATION
if(mouse_state & SDL_BUTTON(SDL_BUTTON_RIGHT)) {
@ -398,7 +399,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().video().screen_area());
const SDL_Rect& menu_loc = m->location(get_display().video().draw_area());
show_menu(m->items(), menu_loc.x + 1, menu_loc.y + menu_loc.h + 1, false, get_display());
return;
@ -406,7 +407,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().video().screen_area());
const SDL_Rect& action_loc = a->location(get_display().video().draw_area());
execute_action(a->items(), action_loc.x + 1, action_loc.y + action_loc.h + 1, false);
return;
@ -421,7 +422,7 @@ void controller_base::play_slice(bool is_delay_enabled)
bool was_scrolling = scrolling_;
int mousex, mousey;
uint8_t mouse_flags = SDL_GetMouseState(&mousex, &mousey);
uint8_t mouse_flags = sdl::get_mouse_state(&mousex, &mousey);
scrolling_ = handle_scroll(mousex, mousey, mouse_flags);

View File

@ -183,7 +183,7 @@ display::display(const display_context* dc,
, xpos_(0)
, ypos_(0)
, view_locked_(false)
, theme_(theme::get_theme_config(theme_id.empty() ? preferences::theme() : theme_id), screen_.screen_area())
, theme_(theme::get_theme_config(theme_id.empty() ? preferences::theme() : theme_id), screen_.draw_area())
, zoom_index_(0)
, fake_unit_man_(new fake_unit_manager(*this))
, builder_(new terrain_builder(level, (dc_ ? &dc_->map() : nullptr), theme_.border().tile_image, theme_.border().show_border))
@ -248,7 +248,7 @@ display::display(const display_context* dc,
read(level.child_or_empty("display"));
if(screen_.non_interactive()
&& (screen_.getSurface() != nullptr
&& (screen_.getDrawingSurface() != nullptr
&& screen_.faked())) {
screen_.lock_updates(true);
}
@ -290,7 +290,7 @@ display::~display()
void display::set_theme(const std::string& new_theme)
{
theme_ = theme{theme::get_theme_config(new_theme), screen_.screen_area()};
theme_ = theme{theme::get_theme_config(new_theme), screen_.draw_area()};
builder_->set_draw_border(theme_.border().show_border);
menu_buttons_.clear();
action_buttons_.clear();
@ -779,7 +779,7 @@ map_location display::minimap_location_on(int x, int y)
surface display::screenshot(bool map_screenshot)
{
if (!map_screenshot) {
return screen_.getSurface().clone();
return screen_.getDrawingSurface().clone();
} else {
if (get_map().empty()) {
ERR_DP << "No map loaded, cannot create a map screenshot.\n";
@ -843,7 +843,7 @@ void display::layout_buttons()
DBG_DP << "positioning menu buttons...\n";
for(const auto& menu : theme_.menus()) {
if(auto b = find_menu_button(menu.get_id())) {
const SDL_Rect& loc = menu.location(screen_.screen_area());
const SDL_Rect& loc = menu.location(screen_.draw_area());
b->set_location(loc);
b->set_measurements(0,0);
b->set_label(menu.title());
@ -854,7 +854,7 @@ void display::layout_buttons()
DBG_DP << "positioning action buttons...\n";
for(const auto& action : theme_.actions()) {
if(auto b = find_action_button(action.get_id())) {
const SDL_Rect& loc = action.location(screen_.screen_area());
const SDL_Rect& loc = action.location(screen_.draw_area());
b->set_location(loc);
b->set_measurements(0,0);
b->set_label(action.title());
@ -1318,15 +1318,15 @@ void display::flip()
return;
}
surface& frameBuffer = video().getSurface();
surface& drawingSurface = video().getDrawingSurface();
font::draw_floating_labels(frameBuffer);
font::draw_floating_labels(drawingSurface);
events::raise_volatile_draw_event();
video().flip();
events::raise_volatile_undraw_event();
font::undraw_floating_labels(frameBuffer);
font::undraw_floating_labels(drawingSurface);
}
// frametime is in milliseconds
@ -1405,7 +1405,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 = video.screen_area();
const SDL_Rect screen = video.draw_area();
SDL_Rect& loc = panel.location(screen);
DBG_DP << "panel location: x=" << loc.x << ", y=" << loc.y
@ -1426,7 +1426,7 @@ static void draw_label(CVideo& video, surface target, const theme::label& label)
const std::string& text = label.text();
const color_t text_color = label.font_rgb_set() ? label.font_rgb() : font::NORMAL_COLOR;
const std::string& icon = label.icon();
SDL_Rect& loc = label.location(video.screen_area());
SDL_Rect& loc = label.location(video.draw_area());
if(icon.empty() == false) {
surface surf(image::get_image(icon));
@ -1448,7 +1448,7 @@ static void draw_label(CVideo& video, surface target, const theme::label& label)
void display::draw_all_panels()
{
surface& screen(screen_.getSurface());
surface& screen(screen_.getDrawingSurface());
/*
* The minimap is also a panel, force it to update its contents.
@ -1764,7 +1764,7 @@ void display::draw_minimap()
}
}
const surface& screen(screen_.getSurface());
const surface& screen(screen_.getDrawingSurface());
clip_rect_setter clip_setter(screen, &area);
color_t back_color {31,31,23,SDL_ALPHA_OPAQUE};
@ -1821,7 +1821,7 @@ void display::draw_minimap()
};
for(const auto& r : outline_parts) {
SDL_FillRect(screen_.getSurface(), &r, 0x00FFFFFF);
SDL_FillRect(screen_.getDrawingSurface(), &r, 0x00FFFFFF);
}
}
@ -1873,7 +1873,7 @@ void display::draw_minimap_units()
// no render clipping rectangle set operaton was queued,
// so let's not use the render API to draw the rectangle.
SDL_FillRect(screen_.getSurface(), &r, col.to_argb_bytes());
SDL_FillRect(screen_.getDrawingSurface(), &r, col.to_argb_bytes());
}
}
@ -1923,7 +1923,7 @@ bool display::scroll(int xmove, int ymove, bool force)
//
if(!screen_.update_locked()) {
surface& screen(screen_.getSurface());
surface& screen(screen_.getDrawingSurface());
SDL_Rect dstrect = map_area();
dstrect.x += diff_x;
@ -2380,7 +2380,7 @@ void display::redraw_everything()
tooltips::clear_tooltips();
theme_.set_resolution(screen_.screen_area());
theme_.set_resolution(screen_.draw_area());
if(!menu_buttons_.empty() || !action_buttons_.empty()) {
create_buttons();
@ -2734,13 +2734,13 @@ void display::draw_image_for_report(surface& img, SDL_Rect& rect)
target.h = visible_area.h;
}
sdl_blit(img,&visible_area,screen_.getSurface(),&target);
sdl_blit(img, &visible_area, screen_.getDrawingSurface(), &target);
} else {
if(img->w != rect.w || img->h != rect.h) {
img = scale_surface(img,rect.w,rect.h);
}
sdl_blit(img,nullptr,screen_.getSurface(),&target);
sdl_blit(img, nullptr, screen_.getDrawingSurface(), &target);
}
}
@ -2772,7 +2772,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_.screen_area());
const SDL_Rect &new_rect = item->location(screen_.draw_area());
surface &surf = reportSurfaces_[report_name];
config &report = reports_[report_name];
@ -2785,7 +2785,7 @@ void display::refresh_report(const std::string& report_name, const config * new_
report = *new_cfg;
if (surf) {
sdl_blit(surf, nullptr, screen_.getSurface(), &rect);
sdl_blit(surf, nullptr, screen_.getDrawingSurface(), &rect);
}
// If the rectangle has just changed, assign the surface to it
@ -2799,7 +2799,7 @@ void display::refresh_report(const std::string& report_name, const config * new_
// (Images generally won't need backing up,
// unless they are transparent, but that is done later).
if (rect.w > 0 && rect.h > 0) {
surf = get_surface_portion(screen_.getSurface(), rect);
surf = get_surface_portion(screen_.getDrawingSurface(), rect);
if (reportSurfaces_[report_name] == nullptr) {
ERR_DP << "Could not backup background for report!" << std::endl;
}

View File

@ -205,7 +205,7 @@ public:
CVideo& video() { return screen_; }
/** return the screen surface or the surface used for map_screenshot. */
surface& get_screen_surface() { return map_screenshot_ ? map_screenshot_surf_ : screen_.getSurface();}
surface& get_screen_surface() { return map_screenshot_ ? map_screenshot_surf_ : screen_.getDrawingSurface();}
virtual bool in_game() const { return false; }
virtual bool in_editor() const { return false; }
@ -221,11 +221,11 @@ public:
*/
const SDL_Rect& minimap_area() const
{ return theme_.mini_map_location(screen_.screen_area()); }
{ return theme_.mini_map_location(screen_.draw_area()); }
const SDL_Rect& palette_area() const
{ return theme_.palette_location(screen_.screen_area()); }
{ return theme_.palette_location(screen_.draw_area()); }
const SDL_Rect& unit_image_area() const
{ return theme_.unit_image_location(screen_.screen_area()); }
{ return theme_.unit_image_location(screen_.draw_area()); }
/**
* Returns the maximum area used for the map
@ -244,7 +244,7 @@ public:
* applied to it.
*/
const SDL_Rect& map_outside_area() const { return map_screenshot_ ?
max_map_area() : theme_.main_map_location(screen_.screen_area()); }
max_map_area() : theme_.main_map_location(screen_.draw_area()); }
/** Check if the bbox of the hex at x,y has pixels outside the area rectangle. */
static bool outside_area(const SDL_Rect& area, const int x,const int y);

View File

@ -54,6 +54,7 @@
#include "units/animation_component.hpp"
#include "game_config_manager.hpp"
#include "quit_confirmation.hpp"
#include "sdl/input.hpp" // get_mouse_button_mask
#include <functional>
@ -1258,10 +1259,10 @@ void editor_controller::mouse_motion(int x, int y, const bool /*browse*/,
// last_undo is a non-owning pointer. Although it could have other uses, it seems to be
// mainly (only?) used for printing debugging information.
auto last_undo = get_current_map_context().last_undo_action();
if (dragging_left_ && (SDL_GetMouseState(nullptr, nullptr) & SDL_BUTTON(1)) != 0) {
if (dragging_left_ && (sdl::get_mouse_button_mask() & SDL_BUTTON(1)) != 0) {
if (!get_current_map_context().map().on_board_with_border(hex_clicked)) return;
a = get_mouse_action().drag_left(*gui_, x, y, partial, last_undo);
} else if (dragging_right_ && (SDL_GetMouseState(nullptr, nullptr) & SDL_BUTTON(3)) != 0) {
} else if (dragging_right_ && (sdl::get_mouse_button_mask() & SDL_BUTTON(3)) != 0) {
if (!get_current_map_context().map().on_board_with_border(hex_clicked)) return;
a = get_mouse_action().drag_right(*gui_, x, y, partial, last_undo);
}

View File

@ -24,6 +24,7 @@
#include "editor/action/mouse/mouse_action_select.hpp"
#include "game_config_view.hpp"
#include "sdl/input.hpp" // get_mouse_state
namespace editor {
@ -131,7 +132,7 @@ void editor_toolkit::update_mouse_action_highlights()
{
DBG_ED << __func__ << "\n";
int x, y;
SDL_GetMouseState(&x, &y);
sdl::get_mouse_state(&x, &y);
map_location hex_clicked = gui_.hex_clicked_on(x,y);
get_mouse_action().update_brush_highlights(gui_, hex_clicked);
}

View File

@ -567,7 +567,7 @@ void pump()
if(event.motion.state & SDL_BUTTON(SDL_BUTTON_RIGHT))
{
SDL_Rect r = CVideo::get_singleton().screen_area();
SDL_Rect r = CVideo::get_singleton().input_area();
// TODO: Check if SDL_FINGERMOTION is actually signaled for COMPLETE motions (I doubt, but tbs)
SDL_Event touch_event;
@ -594,7 +594,7 @@ void pump()
event.button.button = SDL_BUTTON_LEFT;
event.button.which = SDL_TOUCH_MOUSEID;
SDL_Rect r = CVideo::get_singleton().screen_area();
SDL_Rect r = CVideo::get_singleton().input_area();
SDL_Event touch_event;
touch_event.type = (event.type == SDL_MOUSEBUTTONDOWN) ? SDL_FINGERDOWN : SDL_FINGERUP;
touch_event.tfinger.type = touch_event.type;
@ -761,12 +761,13 @@ void raise_process_event()
void raise_resize_event()
{
SDL_Point size = CVideo::get_singleton().window_size();
SDL_Event 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().get_width();
event.window.data2 = CVideo::get_singleton().get_height();
event.window.data1 = size.x;
event.window.data2 = size.y;
SDL_PushEvent(&event);
}
@ -860,6 +861,7 @@ void peek_for_resize()
for(int i = 0; i < num; ++i) {
if(events[i].type == SDL_WINDOWEVENT && events[i].window.event == SDL_WINDOWEVENT_RESIZED) {
CVideo::get_singleton().update_framebuffer();
break;
}
}
}

View File

@ -63,7 +63,7 @@ floating_label::floating_label(const std::string& text, const surface& surf)
, lifetime_(-1)
, width_(-1)
, height_(-1)
, clip_rect_(CVideo::get_singleton().screen_area())
, clip_rect_(CVideo::get_singleton().draw_area())
, visible_(true)
, align_(CENTER_ALIGN)
, border_(0)

View File

@ -141,7 +141,7 @@ SDL_Rect pango_draw_text(CVideo* gui, const SDL_Rect& area, int size, const colo
{
static surface null_surf{};
return pango_draw_text(gui != nullptr ? gui->getSurface() : null_surf, area, size, color, text, x, y, use_tooltips, style);
return pango_draw_text(gui != nullptr ? gui->getDrawingSurface() : null_surf, area, size, color, text, x, y, use_tooltips, style);
}
SDL_Rect pango_draw_text(surface& dst, const SDL_Rect& area, int size, const color_t& color, const std::string& text, int x, int y, bool use_tooltips, pango_text::FONT_STYLE style)

View File

@ -78,7 +78,6 @@ game_display::game_display(game_board& board,
, mode_(RUNNING)
, needs_rebuild_(false)
{
video().clear_screen();
}
game_display::~game_display()

View File

@ -870,7 +870,7 @@ void canvas::blit(surface& surf, SDL_Rect rect)
* can be seen in the title screen. So also use the not 32 bpp method
* for this situation.
*/
if(surf != CVideo::get_singleton().getSurface() && surf.is_neutral()) {
if(surf != CVideo::get_singleton().getDrawingSurface() && surf.is_neutral()) {
blur_surface(surf, rect, blur_depth_);
} else {
// Can't directly blur the surface if not 32 bpp.

View File

@ -179,6 +179,17 @@ void disconnect_signal_mouse_left_click(dispatcher& dispatcher, const signal& si
dispatcher.disconnect_signal<LEFT_BUTTON_CLICK>(signal);
}
void connect_signal_mouse_left_release(dispatcher& dispatcher, const signal& signal)
{
dispatcher.connect_signal<LEFT_BUTTON_UP>(signal);
}
void disconnect_signal_mouse_left_release(dispatcher& dispatcher, const signal& signal)
{
dispatcher.disconnect_signal<LEFT_BUTTON_UP>(signal);
}
void connect_signal_mouse_left_double_click(dispatcher& dispatcher, const signal& signal)
{
dispatcher.connect_signal<LEFT_BUTTON_DOUBLE_CLICK>(signal, dispatcher::back_post_child);

View File

@ -649,6 +649,12 @@ void connect_signal_mouse_left_click(dispatcher& dispatcher, const signal& signa
/** Disconnects a signal handler for a left mouse button click. */
void disconnect_signal_mouse_left_click(dispatcher& dispatcher, const signal& signal);
/** Connects a signal handler for a left mouse button release. */
void connect_signal_mouse_left_release(dispatcher& dispatcher, const signal& signal);
/** Disconnects a signal handler for a left mouse button release. */
void disconnect_signal_mouse_left_release(dispatcher& dispatcher, const signal& signal);
/**
* Connects a signal handler for a left mouse button double click.
*

View File

@ -25,6 +25,7 @@
#include "gui/widgets/widget.hpp"
#include "gui/widgets/window.hpp"
#include "sdl/userevent.hpp"
#include "sdl/input.hpp" // get_mouse_button_mask
#include <array>
#include <functional>
@ -529,7 +530,7 @@ void mouse_button<I>::signal_handler_sdl_button_up(
if(mouse_captured_) {
const unsigned mask = SDL_BUTTON_LMASK | SDL_BUTTON_MMASK | SDL_BUTTON_RMASK;
if((SDL_GetMouseState(nullptr, nullptr) & mask) == 0) {
if((sdl::get_mouse_button_mask() & mask) == 0) {
mouse_captured_ = false;
}
@ -662,7 +663,7 @@ distributor::~distributor()
void distributor::initialize_state()
{
const uint32_t button_state = SDL_GetMouseState(nullptr, nullptr);
const uint32_t button_state = sdl::get_mouse_button_mask();
mouse_button_left::initialize_state(button_state);
mouse_button_middle::initialize_state(button_state);

View File

@ -458,7 +458,7 @@ void sdl_event_handler::handle_event(const SDL_Event& event)
break;
case SDL_WINDOWEVENT_RESIZED:
video_resize({event.window.data1, event.window.data2});
video_resize(point(video.get_width(), video.get_height()));
break;
case SDL_WINDOWEVENT_ENTER:
@ -479,7 +479,7 @@ void sdl_event_handler::handle_event(const SDL_Event& event)
case SDL_FINGERMOTION:
{
SDL_Rect r = video.screen_area();
SDL_Rect r = video.draw_area();
touch_motion(point(event.tfinger.x * r.w, event.tfinger.y * r.h),
point(event.tfinger.dx * r.w, event.tfinger.dy * r.h));
}
@ -487,21 +487,21 @@ void sdl_event_handler::handle_event(const SDL_Event& event)
case SDL_FINGERUP:
{
SDL_Rect r = video.screen_area();
SDL_Rect r = video.draw_area();
touch_up(point(event.tfinger.x * r.w, event.tfinger.y * r.h));
}
break;
case SDL_FINGERDOWN:
{
SDL_Rect r = video.screen_area();
SDL_Rect r = video.draw_area();
touch_down(point(event.tfinger.x * r.w, event.tfinger.y * r.h));
}
break;
case SDL_MULTIGESTURE:
{
SDL_Rect r = video.screen_area();
SDL_Rect r = video.draw_area();
touch_multi_gesture(point(event.mgesture.x * r.w, event.mgesture.y * r.h),
event.mgesture.dTheta, event.mgesture.dDist, event.mgesture.numFingers);
}

View File

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

View File

@ -71,6 +71,12 @@ void disable_widget_on_toggle(window& window, widget& w, const std::string& id)
find_widget<W>(&window, id, false).set_active(dynamic_cast<selectable_item&>(w).get_value_bool());
}
template<typename W>
void disable_widget_on_toggle_inverted(window& window, widget& w, const std::string& id)
{
find_widget<W>(&window, id, false).set_active(!dynamic_cast<selectable_item&>(w).get_value_bool());
}
// Ensure the specified index is between 0 and one less than the max
// number of pager layers (since get_layer_count returns one-past-end).
int index_in_pager_range(const int first, const stacked_widget& pager)
@ -311,6 +317,22 @@ void preferences_dialog::initialize_sound_option_group(const std::string& id_suf
std::bind(volume_setter_on_change<vol_setter>, std::placeholders::_1));
}
void preferences_dialog::apply_pixel_scale()
{
// Update pixel scale preference.
slider& ps_slider = find_widget<slider>(get_window(), "pixel_scale_slider", false);
set_pixel_scale(ps_slider.get_value());
// Update auto pixel scale preference.
toggle_button& auto_ps_toggle =
find_widget<toggle_button>(get_window(), "auto_pixel_scale", false);
set_auto_pixel_scale(auto_ps_toggle.get_value_bool());
// Update draw buffers, taking these into account.
CVideo::get_singleton().update_buffers();
}
/**
* Sets up states and callbacks for each of the widgets
*/
@ -408,6 +430,25 @@ void preferences_dialog::post_build(window& window)
connect_signal_notify_modified(res_list,
std::bind(&preferences_dialog::handle_res_select, this));
/* PIXEL SCALE */
register_integer("pixel_scale_slider", true,
pixel_scale, set_pixel_scale);
slider& ps_slider =
find_widget<slider>(&window, "pixel_scale_slider", false);
connect_signal_mouse_left_release(ps_slider,
std::bind(&preferences_dialog::apply_pixel_scale, this));
/* AUTOMATIC PIXEL SCALE */
register_bool("auto_pixel_scale", true,
auto_pixel_scale, set_auto_pixel_scale,
[&](widget& w) { disable_widget_on_toggle_inverted<slider>(window, w, "pixel_scale_slider"); }, true);
toggle_button& auto_ps_toggle =
find_widget<toggle_button>(get_window(), "auto_pixel_scale", false);
connect_signal_mouse_left_click(auto_ps_toggle,
std::bind(&preferences_dialog::apply_pixel_scale, this));
/* SHOW FLOATING LABELS */
register_bool("show_floating_labels", true,
show_floating_labels, set_show_floating_labels);
@ -985,6 +1026,7 @@ void preferences_dialog::pre_show(window& window)
gui2::bind_status_label<slider>(&window, "max_saves_slider");
gui2::bind_status_label<slider>(&window, "turbo_slider");
gui2::bind_status_label<slider>(&window, "pixel_scale_slider");
//gui2::bind_status_label<slider>(&window, "scaling_slider", [](slider& s)->std::string {
// return s.get_value_label() + "%";

View File

@ -91,6 +91,8 @@ private:
template<bool(*toggle_getter)(), bool(*toggle_setter)(bool), int(*vol_getter)(), void(*vol_setter)(int)>
void initialize_sound_option_group(const std::string& id_suffix);
void apply_pixel_scale();
std::map<std::string, string_map> get_friends_list_row_data(const preferences::acquaintance& entry);
void add_friend_list_entry(const bool is_friend, text_box& textbox);

View File

@ -109,7 +109,7 @@ static void launch_lua_console()
static void make_screenshot()
{
surface screenshot = CVideo::get_singleton().getSurface().clone();
surface screenshot = CVideo::get_singleton().getDrawingSurface().clone();
if(screenshot) {
std::string filename = filesystem::get_screenshot_dir() + "/" + _("Screenshot") + "_";
filename = filesystem::get_next_filename(filename, ".jpg");

View File

@ -25,6 +25,7 @@
#include "gui/widgets/settings.hpp"
#include "sdl/rect.hpp"
#include "tstring.hpp"
#include "sdl/input.hpp" // get_mouse_location
#include <SDL2/SDL.h>
@ -117,10 +118,7 @@ wfl::map_formula_callable get_screen_size_variables()
point get_mouse_position()
{
int x, y;
SDL_GetMouseState(&x, &y);
return point(x, y);
return sdl::get_mouse_location();
}
std::string debug_truncate(const std::string& text)

View File

@ -51,13 +51,15 @@ std::vector<game_tip> tips;
void update_screen_size_variables()
{
CVideo& vid = CVideo::get_singleton();
const SDL_Rect rect = vid.screen_area();
CVideo& video = CVideo::get_singleton();
const SDL_Rect rect = video.draw_area();
screen_width = rect.w;
screen_height = rect.h;
auto [scalew, scaleh] = vid.get_dpi_scale_factor();
// Use of screen_pitch_microns should probably be deprecated, as physical
// DPI is not an accurate method of determining perceptual pixel size.
auto [scalew, scaleh] = video.get_dpi_scale_factor();
float avgscale = (scalew + scaleh)/2;
screen_pitch_microns = MICRONS_PER_INCH / (avgscale * MAGIC_DPI_MATCH_VIDEO);

View File

@ -61,6 +61,7 @@
#include "video.hpp"
#include "wml_exception.hpp"
#include "sdl/userevent.hpp"
#include "sdl/input.hpp" // get_mouse_button_mask
#include <functional>
@ -551,7 +552,7 @@ int window::show(const bool restore, const unsigned auto_close_timeout)
* return the proper button state. When initializing here all
* works fine.
*/
mouse_button_state_ = SDL_GetMouseState(nullptr, nullptr);
mouse_button_state_ = sdl::get_mouse_button_mask();
mouse_button_state_initialized = true;
}
@ -578,8 +579,8 @@ int window::show(const bool restore, const unsigned auto_close_timeout)
// restore area
if(restore_) {
SDL_Rect rect = get_rectangle();
sdl_blit(restorer_, 0, video_.getSurface(), &rect);
font::undraw_floating_labels(video_.getSurface());
sdl_blit(restorer_, 0, video_.getDrawingSurface(), &rect);
font::undraw_floating_labels(video_.getDrawingSurface());
}
throw;
}
@ -589,8 +590,8 @@ int window::show(const bool restore, const unsigned auto_close_timeout)
// restore area
if(restore_) {
SDL_Rect rect = get_rectangle();
sdl_blit(restorer_, 0, video_.getSurface(), &rect);
font::undraw_floating_labels(video_.getSurface());
sdl_blit(restorer_, 0, video_.getDrawingSurface(), &rect);
font::undraw_floating_labels(video_.getDrawingSurface());
}
if(text_box_base* tb = dynamic_cast<text_box_base*>(event_distributor_->keyboard_focus())) {
@ -608,7 +609,7 @@ void window::draw()
return;
}
surface& frame_buffer = video_.getSurface();
surface& drawing_surface = video_.getDrawingSurface();
/***** ***** Layout and get dirty list ***** *****/
if(need_layout_) {
@ -617,7 +618,7 @@ void window::draw()
// doesn't work yet we need to undraw the window.
if(restore_ && restorer_) {
SDL_Rect rect = get_rectangle();
sdl_blit(restorer_, 0, frame_buffer, &rect);
sdl_blit(restorer_, 0, drawing_surface, &rect);
}
layout();
@ -628,11 +629,11 @@ void window::draw()
// We want the labels underneath the window so draw them and use them
// as restore point.
if(is_toplevel_) {
font::draw_floating_labels(frame_buffer);
font::draw_floating_labels(drawing_surface);
}
if(restore_) {
restorer_ = get_surface_portion(frame_buffer, rect);
restorer_ = get_surface_portion(drawing_surface, rect);
}
// Need full redraw so only set ourselves dirty.
@ -677,7 +678,7 @@ void window::draw()
assert(!item.empty());
const SDL_Rect dirty_rect
= new_widgets ? video_.screen_area()
= new_widgets ? video_.draw_area()
: item.back()->get_dirty_rectangle();
// For testing we disable the clipping rect and force the entire screen to
@ -686,7 +687,7 @@ void window::draw()
dirty_list_.clear();
dirty_list_.emplace_back(1, this);
#else
clip_rect_setter clip(frame_buffer, &dirty_rect);
clip_rect_setter clip(drawing_surface, &dirty_rect);
#endif
/*
@ -733,7 +734,7 @@ void window::draw()
// Restore.
if(restore_) {
SDL_Rect rect = get_rectangle();
sdl_blit(restorer_, 0, frame_buffer, &rect);
sdl_blit(restorer_, 0, drawing_surface, &rect);
}
// Background.
@ -741,12 +742,12 @@ void window::draw()
itor != item.end();
++itor) {
(**itor).draw_background(frame_buffer, 0, 0);
(**itor).draw_background(drawing_surface, 0, 0);
}
// Children.
if(!item.empty()) {
item.back()->draw_children(frame_buffer, 0, 0);
item.back()->draw_children(drawing_surface, 0, 0);
}
// Foreground.
@ -754,7 +755,7 @@ void window::draw()
ritor != item.rend();
++ritor) {
(**ritor).draw_foreground(frame_buffer, 0, 0);
(**ritor).draw_foreground(drawing_surface, 0, 0);
(**ritor).set_is_dirty(false);
}
}
@ -777,9 +778,8 @@ void window::undraw()
{
if(restore_ && restorer_) {
SDL_Rect rect = get_rectangle();
sdl_blit(restorer_, 0, video_.getSurface(), &rect);
// Since the old area might be bigger as the new one, invalidate
// it.
sdl_blit(restorer_, 0, video_.getDrawingSurface(), &rect);
// Since the old area might be bigger than the new one, invalidate it.
}
}

View File

@ -194,10 +194,10 @@ void show_with_toplevel(const section &toplevel_sec,
const events::event_context dialog_events_context;
const gui::dialog_manager manager;
SDL_Rect screen_area = video.screen_area();
SDL_Rect draw_area = video.draw_area();
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 width = std::min<int>(font::relative_size(1200), draw_area.w - font::relative_size(20));
const int height = std::min<int>(font::relative_size(850), draw_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);
@ -206,8 +206,8 @@ void show_with_toplevel(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 = screen_area.w / 2 - width / 2;
yloc = screen_area.h / 2 - height / 2;
xloc = draw_area.w / 2 - width / 2;
yloc = draw_area.h / 2 - height / 2;
}
std::vector<gui::button*> buttons_ptr;
gui::button close_button_(video, _("Close"));

View File

@ -15,7 +15,6 @@
#include "help/help_browser.hpp"
#include <iostream> // for operator<<, basic_ostream, etc
#include <SDL2/SDL_mouse.h> // for SDL_GetMouseState, etc
#include "cursor.hpp" // for set, CURSOR_TYPE::HYPERLINK, etc
#include "font/constants.hpp" // for relative_size
#include "gettext.hpp" // for _
@ -25,6 +24,7 @@
#include "key.hpp" // for CKey
#include "log.hpp" // for log_scope
#include "sdl/rect.hpp"
#include "sdl/input.hpp" // for get_mouse_state
class CVideo;
struct SDL_Rect;
@ -97,7 +97,7 @@ void help_browser::process_event()
{
CKey key;
int mousex, mousey;
SDL_GetMouseState(&mousex,&mousey);
sdl::get_mouse_state(&mousex,&mousey);
// Fake focus functionality for the menu, only process it if it has focus.
if (sdl::point_in_rect(mousex, mousey, menu_.location())) {
@ -193,7 +193,7 @@ void help_browser::handle_event(const SDL_Event &event)
void help_browser::update_cursor()
{
int mousex, mousey;
SDL_GetMouseState(&mousex,&mousey);
sdl::get_mouse_state(&mousex,&mousey);
const std::string ref = text_area_.ref_at(mousex, mousey);
if (!ref.empty() && !ref_cursor_) {
cursor::set(cursor::HYPERLINK);

View File

@ -19,6 +19,7 @@
#include "help/help_impl.hpp" // for section, topic, topic_list, etc
#include "sound.hpp" // for play_UI_sound
#include "wml_separators.hpp" // for IMG_TEXT_SEPARATOR, etc
#include "sdl/input.hpp" // for get_mouse_state
#include <algorithm> // for find
#include <iostream> // for basic_ostream, operator<<, etc
@ -157,7 +158,7 @@ int help_menu::process()
{
int res = menu::process();
int mousex, mousey;
SDL_GetMouseState(&mousex,&mousey);
sdl::get_mouse_state(&mousex, &mousey);
if (!visible_items_.empty() &&
static_cast<std::size_t>(res) < visible_items_.size()) {

View File

@ -537,7 +537,7 @@ void help_text_area::draw_contents()
{
const SDL_Rect& loc = inner_location();
bg_restore();
surface& screen = video().getSurface();
surface& screen = video().getDrawingSurface();
clip_rect_setter clip_rect_set(screen, &loc);
for(std::list<item>::const_iterator it = items_.begin(), end = items_.end(); it != end; ++it) {
SDL_Rect dst = it->rect;

View File

@ -33,6 +33,7 @@
#include "show_dialog.hpp"
#include "../resources.hpp"
#include "../playmp_controller.hpp"
#include "sdl/input.hpp" // get_mouse_state
#include <functional>
@ -421,7 +422,7 @@ void command_executor::show_menu(const std::vector<config>& items_arg, int xloc,
const theme::menu* submenu = gui.get_theme().get_menu_item(items[res]["id"]);
if (submenu) {
int y,x;
SDL_GetMouseState(&x,&y);
sdl::get_mouse_state(&x,&y);
this->show_menu(submenu->items(), x, y, submenu->is_context(), gui);
} else {
const hotkey::hotkey_command& cmd = hotkey::get_hotkey_command(items[res]["id"]);

View File

@ -43,8 +43,8 @@
#include "units/unit.hpp" // for unit
#include "whiteboard/manager.hpp" // for manager, etc
#include "whiteboard/typedefs.hpp" // for whiteboard_lock
#include "sdl/input.hpp" // for get_mouse_state
#include <SDL2/SDL_mouse.h> // for SDL_GetMouseState
#include <cassert> // for assert
#include <new> // for bad_alloc
#include <ostream> // for operator<<, basic_ostream, etc
@ -101,7 +101,7 @@ void mouse_handler::touch_motion(int x, int y, const bool browse, bool update, m
{
// Frankensteining from mouse_motion(), as it has a lot in common, but a lot of differences too.
// Copy-pasted from everywhere. TODO: generalize the two.
SDL_GetMouseState(&x,&y);
sdl::get_mouse_state(&x,&y);
// This is from mouse_handler_base::mouse_motion_default()
tooltips::process(x, y);
@ -130,7 +130,7 @@ void mouse_handler::touch_motion(int x, int y, const bool browse, bool update, m
int my = drag_from_y_;
if(is_dragging() && !dragging_started_) {
if(dragging_touch_) {
SDL_GetMouseState(&mx, &my);
sdl::get_mouse_state(&mx, &my);
const double drag_distance = std::pow(static_cast<double>(drag_from_x_- mx), 2)
+ std::pow(static_cast<double>(drag_from_y_- my), 2);
if(drag_distance > drag_threshold()*drag_threshold()) {
@ -143,7 +143,7 @@ void mouse_handler::touch_motion(int x, int y, const bool browse, bool update, m
const auto found_unit = find_unit(selected_hex_);
bool selected_hex_has_my_unit = found_unit.valid() && found_unit.get_shared_ptr()->side() == side_num_;
if((browse || !found_unit.valid()) && is_dragging() && dragging_started_) {
SDL_GetMouseState(&mx, &my);
sdl::get_mouse_state(&mx, &my);
if(sdl::point_in_rect(x, y, gui().map_area())) {
int dx = drag_from_x_ - mx;
@ -388,7 +388,7 @@ void mouse_handler::mouse_motion(int x, int y, const bool browse, bool update, m
// to highlight all the hexes where the mouse passed.
// Also, sometimes it seems to have one *very* obsolete
// and isolated mouse motion event when using drag&drop
SDL_GetMouseState(&x, &y); // <-- modify x and y
sdl::get_mouse_state(&x, &y); // <-- modify x and y
if(mouse_handler_base::mouse_motion_default(x, y, update)) {
return;
@ -629,7 +629,7 @@ const map_location mouse_handler::hovered_hex() const
{
int x = -1;
int y = -1;
SDL_GetMouseState(&x, &y);
sdl::get_mouse_state(&x, &y);
return gui_->hex_clicked_on(x, y);
}

View File

@ -22,6 +22,7 @@
#include "preferences/general.hpp"
#include "sdl/rect.hpp"
#include "tooltips.hpp"
#include "sdl/input.hpp" // get_mouse_state
static lg::log_domain log_display("display");
#define WRN_DP LOG_STREAM(warn, log_display)
@ -92,7 +93,7 @@ void mouse_handler_base::touch_motion_event(const SDL_TouchFingerEvent& event, c
void mouse_handler_base::mouse_update(const bool browse, map_location loc)
{
int x, y;
SDL_GetMouseState(&x, &y);
sdl::get_mouse_state(&x, &y);
mouse_motion(x, y, browse, true, loc);
}
@ -108,7 +109,7 @@ bool mouse_handler_base::mouse_motion_default(int x, int y, bool /*update*/)
// if the game is run in a window, we could miss a LMB/MMB up event
// if it occurs outside our window.
// thus, we need to check if the LMB/MMB is still down
minimap_scrolling_ = ((SDL_GetMouseState(nullptr, nullptr) & (SDL_BUTTON(SDL_BUTTON_LEFT) | SDL_BUTTON(SDL_BUTTON_MIDDLE))) != 0);
minimap_scrolling_ = ((sdl::get_mouse_button_mask() & (SDL_BUTTON(SDL_BUTTON_LEFT) | SDL_BUTTON(SDL_BUTTON_MIDDLE))) != 0);
if(minimap_scrolling_) {
const map_location& loc = gui().minimap_location_on(x, y);
if(loc.valid()) {
@ -133,7 +134,7 @@ bool mouse_handler_base::mouse_motion_default(int x, int y, bool /*update*/)
int my = drag_from_y_;
if(is_dragging() && !dragging_started_) {
Uint32 mouse_state = dragging_left_ || dragging_right_ ? SDL_GetMouseState(&mx, &my) : 0;
Uint32 mouse_state = dragging_left_ || dragging_right_ ? sdl::get_mouse_state(&mx, &my) : 0;
#ifdef MOUSE_TOUCH_EMULATION
if(dragging_left_ && (mouse_state & SDL_BUTTON(SDL_BUTTON_RIGHT))) {
// Monkey-patch touch controls again to make them look like left button.
@ -311,7 +312,7 @@ void mouse_handler_base::left_drag_end(int /*x*/, int /*y*/, const bool browse)
void mouse_handler_base::mouse_wheel(int scrollx, int scrolly, bool browse)
{
int x, y;
SDL_GetMouseState(&x, &y);
sdl::get_mouse_state(&x, &y);
int movex = scrollx * preferences::scroll_speed();
int movey = scrolly * preferences::scroll_speed();
@ -361,7 +362,7 @@ void mouse_handler_base::right_mouse_up(int x, int y, const bool browse)
void mouse_handler_base::init_dragging(bool& dragging_flag)
{
dragging_flag = true;
SDL_GetMouseState(&drag_from_x_, &drag_from_y_);
sdl::get_mouse_state(&drag_from_x_, &drag_from_y_);
drag_from_hex_ = gui().hex_clicked_on(drag_from_x_, drag_from_y_);
}

View File

@ -64,14 +64,20 @@ namespace preferences {
* Add any variables of similar type here.
*/
const int min_window_width = 800;
const int min_window_height = 600;
const int min_window_height = 540;
const int def_window_width = 1280;
const int def_window_height = 720;
const int max_window_width = 1920;
const int max_window_height = 1080;
const int min_font_scaling = 80;
const int max_font_scaling = 150;
const int min_pixel_scale = 1;
const int max_pixel_scale = 4;
class prefs_event_handler : public events::sdl_handler {
public:
virtual void handle_event(const SDL_Event &) {}
@ -116,7 +122,7 @@ void prefs_event_handler::handle_window_event(const SDL_Event& event)
switch(event.window.event) {
case SDL_WINDOWEVENT_RESIZED:
_set_resolution(point(event.window.data1,event.window.data2));
_set_resolution(CVideo::get_singleton().window_size());
break;
@ -406,6 +412,27 @@ point resolution()
);
}
int pixel_scale()
{
// For now this has a minimum value of 1 and a maximum of 4.
return std::max<int>(std::min<int>(prefs["pixel_scale"].to_int(1), max_pixel_scale), min_pixel_scale);
}
void set_pixel_scale(const int scale)
{
prefs["pixel_scale"] = std::clamp(scale, min_pixel_scale, max_pixel_scale);
}
bool auto_pixel_scale()
{
return get("auto_pixel_scale", true);
}
void set_auto_pixel_scale(bool choice)
{
prefs["auto_pixel_scale"] = choice;
}
bool maximized()
{
return get("maximized", !fullscreen());

View File

@ -41,9 +41,15 @@ namespace preferences {
extern const int def_window_width;
extern const int def_window_height;
extern const int max_window_width;
extern const int max_window_height;
extern const int min_font_scaling;
extern const int max_font_scaling;
extern const int min_pixel_scale;
extern const int max_pixel_scale;
void write_preferences();
void set(const std::string& key, const std::string &value);
@ -75,6 +81,12 @@ namespace preferences {
point resolution();
void _set_resolution(const point& res);
int pixel_scale();
void set_pixel_scale(const int scale);
bool auto_pixel_scale();
void set_auto_pixel_scale(bool choice);
bool maximized();
void _set_maximized(bool ison);

View File

@ -41,6 +41,7 @@
#include "tstring.hpp"
#include "game_data.hpp"
#include "game_state.hpp"
#include "sdl/input.hpp" // get_mouse_state
#include <functional>
#include <optional>
@ -184,7 +185,7 @@ int show_story(lua_State* L) {
int show_menu(lua_State* L) {
std::vector<config> items = lua_check<std::vector<config>>(L, 1);
SDL_Rect pos {1,1,1,1};
SDL_GetMouseState(&pos.x, &pos.y);
sdl::get_mouse_state(&pos.x, &pos.y);
int initial = -1;
bool markup = false;

73
src/sdl/input.cpp Normal file
View File

@ -0,0 +1,73 @@
/*
Copyright (C) 2022
by Thomas Iorns <mesilliac@tomanui.nz>
Part of the Battle for Wesnoth Project https://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include "sdl/input.hpp"
#include "sdl/point.hpp"
#include <SDL2/SDL_mouse.h>
namespace {
SDL_Point drawing_surface_size;
SDL_Point window_size;
}
namespace sdl
{
uint32_t get_mouse_state(int *x, int *y)
{
uint32_t buttons = SDL_GetMouseState(x, y);
if (window_size.x == 0 || window_size.y == 0) {
// This will give bad results, but will not outright crash.
return buttons;
}
if (window_size.x != drawing_surface_size.x) {
*x = (*x * drawing_surface_size.x) / window_size.x;
}
if (window_size.y != drawing_surface_size.y) {
*y = (*y * drawing_surface_size.y) / window_size.y;
}
return buttons;
}
uint32_t get_mouse_button_mask()
{
return SDL_GetMouseState(nullptr, nullptr);
}
SDL_Point get_mouse_location()
{
SDL_Point p;
get_mouse_state(&p.x, &p.y);
return p;
}
void update_input_dimensions(
int draw_width, int draw_height,
int input_width, int input_height
) {
drawing_surface_size.x = draw_width;
drawing_surface_size.y = draw_height;
window_size.x = input_width;
window_size.y = input_height;
}
void update_input_dimensions(SDL_Point draw_size, SDL_Point input_size)
{
drawing_surface_size = draw_size;
window_size = input_size;
}
} // namespace sdl

61
src/sdl/input.hpp Normal file
View File

@ -0,0 +1,61 @@
/*
Copyright (C) 2022
by Thomas Iorns <mesilliac@tomanui.nz>
Part of the Battle for Wesnoth Project https://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include <cstdint>
#pragma once
/**
* @file
* Contains functions for cleanly handling SDL input.
*/
struct SDL_Point;
namespace sdl
{
/**
* A wrapper for SDL_GetMouseState that gives coordinates in draw space.
*/
uint32_t get_mouse_state(int *x, int *y);
/** Returns the current mouse button mask */
uint32_t get_mouse_button_mask();
/** Returns the currnet mouse location in draw space. */
SDL_Point get_mouse_location();
/**
* Update the cached drawing area and input area sizes. These correspond to
* the size of the drawing surface in pixels, and the size of the window in
* display coordinates.
*
* This should be called every time the window is resized, or the pixel scale
* multiplier changes.
*
* @param draw_width The width of the drawing surface, in pixels
* @param draw_height The height of the drawing surface, in pixels
* @param input_width The width of the input surface, in display coordinates
* @param input_height The height of the input surface, in display coordinates
*/
void update_input_dimensions(
int draw_width, int draw_height,
int input_width, int input_height
);
void update_input_dimensions(SDL_Point draw_size, SDL_Point input_size);
} // namespace sdl

View File

@ -115,7 +115,7 @@ void surface_restorer::restore(const SDL_Rect& dst) const
SDL_Rect src = dst2;
src.x -= rect_.x;
src.y -= rect_.y;
sdl_blit(surface_, &src, target_->getSurface(), &dst2);
sdl_blit(surface_, &src, target_->getDrawingSurface(), &dst2);
}
void surface_restorer::restore() const
@ -125,7 +125,7 @@ void surface_restorer::restore() const
}
SDL_Rect dst = rect_;
sdl_blit(surface_, nullptr, target_->getSurface(), &dst);
sdl_blit(surface_, nullptr, target_->getDrawingSurface(), &dst);
}
void surface_restorer::update()
@ -133,7 +133,7 @@ void surface_restorer::update()
if(rect_.w <= 0 || rect_.h <= 0) {
surface_ = nullptr;
} else {
surface_ = ::get_surface_portion(target_->getSurface(),rect_);
surface_ = ::get_surface_portion(target_->getDrawingSurface(),rect_);
}
}

View File

@ -15,6 +15,7 @@
#include "sdl/surface.hpp"
#include "sdl/window.hpp"
#include "sdl/input.hpp"
#include "sdl/exception.hpp"
@ -69,6 +70,9 @@ window::window(const std::string& title,
fill(0,0,0);
// Now that we have a window and renderer we can scale input correctly.
update_input_dimensions(get_logical_size(), get_size());
render();
}
@ -82,6 +86,7 @@ window::~window()
void window::set_size(const int w, const int h)
{
SDL_SetWindowSize(window_, w, h);
update_input_dimensions(get_logical_size(), get_size());
}
SDL_Point window::get_size()
@ -108,21 +113,25 @@ void window::center()
void window::maximize()
{
SDL_MaximizeWindow(window_);
update_input_dimensions(get_logical_size(), get_size());
}
void window::to_window()
{
SDL_SetWindowFullscreen(window_, 0);
update_input_dimensions(get_logical_size(), get_size());
}
void window::restore()
{
SDL_RestoreWindow(window_);
update_input_dimensions(get_logical_size(), get_size());
}
void window::full_screen()
{
SDL_SetWindowFullscreen(window_, SDL_WINDOW_FULLSCREEN_DESKTOP);
update_input_dimensions(get_logical_size(), get_size());
}
void window::fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
@ -157,6 +166,8 @@ uint32_t window::get_flags()
void window::set_minimum_size(int min_w, int min_h)
{
SDL_SetWindowMinimumSize(window_, min_w, min_h);
// Can this change the size of the window?
update_input_dimensions(get_logical_size(), get_size());
}
int window::get_display_index()
@ -164,6 +175,32 @@ int window::get_display_index()
return SDL_GetWindowDisplayIndex(window_);
}
void window::set_logical_size(int w, int h)
{
SDL_Renderer* r = SDL_GetRenderer(window_);
SDL_RenderSetLogicalSize(r, w, h);
update_input_dimensions(get_logical_size(), get_size());
}
SDL_Point window::get_logical_size() const
{
SDL_Renderer* r = SDL_GetRenderer(window_);
int w, h;
SDL_RenderGetLogicalSize(r, &w, &h);
return {w, h};
}
void window::get_logical_size(int& w, int& h) const
{
SDL_Renderer* r = SDL_GetRenderer(window_);
SDL_RenderGetLogicalSize(r, &w, &h);
}
uint32_t window::pixel_format()
{
return pixel_format_;
}
window::operator SDL_Window*()
{
return window_;

View File

@ -169,6 +169,24 @@ public:
int get_display_index();
/**
* Sets the desired size of the rendering surface. Input event coordinates
* will be scaled as if the window were also of this size. For best
* results this should be an integer fraction of the window size.
*
* This is a wrapper for SDL_RenderSetLogicalSize.
*
* @param w Width of the window's rendering surface
* @param h Height of the window's rendering surface
*/
void set_logical_size(int w, int h);
SDL_Point get_logical_size() const;
void get_logical_size(int& w, int& h) const;
/** The current pixel format of the renderer. */
uint32_t pixel_format();
/***** ***** ***** Conversion operators. ***** ***** *****/
/**

View File

@ -27,6 +27,7 @@
#include "font/sdl_ttf_compat.hpp"
#include "font/standard_colors.hpp"
#include "sdl/rect.hpp"
#include "sdl/input.hpp" // get_mouse_state
static lg::log_domain log_display("display");
#define ERR_DP LOG_STREAM(err, log_display)
@ -64,7 +65,7 @@ dialog_manager::~dialog_manager()
{
is_in_dialog = reset_to;
int mousex, mousey;
SDL_GetMouseState(&mousex, &mousey);
sdl::get_mouse_state(&mousex, &mousey);
SDL_Event pb_event;
pb_event.type = SDL_MOUSEMOTION;
pb_event.motion.state = 0;
@ -201,7 +202,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 = video_.screen_area();
SDL_Rect bounds = video_.draw_area();
if(have_border_) {
bounds.x += left_->w;
bounds.y += top_->h;
@ -297,9 +298,9 @@ void dialog_frame::draw_background()
}
if (dialog_style_.blur_radius) {
surface surf = ::get_surface_portion(video_.getSurface(), dim_.exterior);
surface surf = ::get_surface_portion(video_.getDrawingSurface(), dim_.exterior);
surf = blur_surface(surf, dialog_style_.blur_radius);
sdl_blit(surf, nullptr, video_.getSurface(), &dim_.exterior);
sdl_blit(surf, nullptr, video_.getDrawingSurface(), &dim_.exterior);
}
if(bg_ == nullptr) {
@ -314,14 +315,14 @@ void dialog_frame::draw_background()
SDL_Rect dst = src;
dst.x = dim_.interior.x + i;
dst.y = dim_.interior.y + j;
sdl_blit(bg_, &src, video_.getSurface(), &dst);
sdl_blit(bg_, &src, video_.getDrawingSurface(), &dst);
}
}
}
SDL_Rect dialog_frame::draw_title(CVideo* video)
{
SDL_Rect rect = CVideo::get_singleton().screen_area();
SDL_Rect rect = CVideo::get_singleton().draw_area();
return font::pango_draw_text(video, rect, font::SIZE_TITLE, font::TITLE_COLOR,
title_, dim_.title.x, dim_.title.y, false, font::pango_text::STYLE_NORMAL);
}

View File

@ -69,7 +69,7 @@ static void show_tooltip(const tooltip& tip)
clear_tooltip();
const color_t bgcolor {0,0,0,192};
SDL_Rect area = video.screen_area();
SDL_Rect area = video.draw_area();
unsigned int border = 10;

View File

@ -25,12 +25,15 @@
#include "sdl/userevent.hpp"
#include "sdl/utils.hpp"
#include "sdl/window.hpp"
#include "sdl/input.hpp"
#ifdef TARGET_OS_OSX
#include "desktop/apple_video.hpp"
#include "game_version.hpp"
#endif
#include <SDL2/SDL_render.h> // SDL_Texture
#include <cassert>
#include <vector>
@ -42,7 +45,7 @@ CVideo* CVideo::singleton_ = nullptr;
namespace
{
surface frameBuffer = nullptr;
surface drawingSurface = nullptr;
bool fake_interactive = false;
const unsigned MAGIC_DPI_SCALE_NUMBER = 96;
@ -70,8 +73,8 @@ void trigger_full_redraw()
SDL_Event event;
event.type = SDL_WINDOWEVENT;
event.window.event = SDL_WINDOWEVENT_RESIZED;
event.window.data1 = (*frameBuffer).h;
event.window.data2 = (*frameBuffer).w;
event.window.data1 = (*drawingSurface).h;
event.window.data2 = (*drawingSurface).w;
for(const auto& layer : draw_layers) {
layer->handle_window_event(event);
@ -90,6 +93,7 @@ void trigger_full_redraw()
CVideo::CVideo(FAKE_TYPES type)
: window()
, drawing_texture_(nullptr)
, fake_screen_(false)
, help_string_(0)
, updated_locked_(0)
@ -162,7 +166,7 @@ void CVideo::video_event_handler::handle_window_event(const SDL_Event& event)
void CVideo::blit_surface(int x, int y, surface surf, SDL_Rect* srcrect, SDL_Rect* clip_rect)
{
surface& target(getSurface());
surface& target(getDrawingSurface());
SDL_Rect dst{x, y, 0, 0};
const clip_rect_setter clip_setter(target, clip_rect, clip_rect != nullptr);
@ -174,12 +178,12 @@ void CVideo::make_fake()
fake_screen_ = true;
refresh_rate_ = 1;
frameBuffer = SDL_CreateRGBSurfaceWithFormat(0, 16, 16, 24, SDL_PIXELFORMAT_BGR888);
drawingSurface = SDL_CreateRGBSurfaceWithFormat(0, 16, 16, 24, SDL_PIXELFORMAT_BGR888);
}
void CVideo::make_test_fake(const unsigned width, const unsigned height)
{
frameBuffer = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, SDL_PIXELFORMAT_BGR888);
drawingSurface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, SDL_PIXELFORMAT_BGR888);
fake_interactive = true;
refresh_rate_ = 1;
@ -191,8 +195,91 @@ void CVideo::update_framebuffer()
return;
}
surface fb = SDL_GetWindowSurface(*window);
frameBuffer = fb;
// Find max valid pixel scale at current window size.
point wsize(window->get_size());
int max_scale = std::min(
wsize.x / preferences::min_window_width,
wsize.y / preferences::min_window_height);
max_scale = std::min(max_scale, preferences::max_pixel_scale);
// Determine best pixel scale according to preference and window size
int scale = 1;
if (preferences::auto_pixel_scale()) {
// Try to match the default size (1280x720) but do not reduce below
int def_scale = std::min(
wsize.x / preferences::def_window_width,
wsize.y / preferences::def_window_height);
scale = std::min(max_scale, def_scale);
// Otherwise reduce to keep below the max window size (1920x1080).
int min_scale = std::min(
wsize.x / (preferences::max_window_width+1) + 1,
wsize.y / (preferences::max_window_height+1) + 1);
scale = std::max(scale, min_scale);
} else {
scale = std::min(max_scale, preferences::pixel_scale());
}
// Update logical size if it doesn't match the current resolution and scale.
point lsize(window->get_logical_size());
point osize(window->get_output_size());
if (lsize.x != wsize.x / scale || lsize.y != wsize.y / scale) {
if (!preferences::auto_pixel_scale() && scale < preferences::pixel_scale()) {
LOG_DP << "reducing pixel scale from desired "
<< preferences::pixel_scale() << " to maximum allowable "
<< scale << std::endl;
}
LOG_DP << "pixel scale: " << scale << std::endl;
LOG_DP << "overriding logical size" << std::endl;
LOG_DP << " old lsize: " << lsize << std::endl;
LOG_DP << " old wsize: " << wsize << std::endl;
LOG_DP << " old osize: " << osize << std::endl;
window->set_logical_size(osize.x / scale, osize.y / scale);
lsize = window->get_logical_size();
wsize = window->get_size();
osize = window->get_output_size();
LOG_DP << " new lsize: " << lsize << std::endl;
LOG_DP << " new wsize: " << wsize << std::endl;
LOG_DP << " new osize: " << osize << std::endl;
}
// Update the drawing surface if required.
if (!drawingSurface
|| drawingSurface->w != wsize.x / scale
|| drawingSurface->h != wsize.y / scale)
{
uint32_t format = window->pixel_format();
int bpp = SDL_BITSPERPIXEL(format);
// This should match the old system, and so shouldn't cause any
// problems that weren't there already.
LOG_DP << "creating " << bpp << "bpp drawing surface with format "
<< SDL_GetPixelFormatName(format) << std::endl;
// Note: "surface" destructor automatically frees the old surface
drawingSurface = SDL_CreateRGBSurfaceWithFormat(
0,
wsize.x / scale,
wsize.y / scale,
bpp,
format
);
// Also update the drawing texture, with matching format and size.
if (drawing_texture_) {
LOG_DP << "destroying old drawing texture" << std::endl;
SDL_DestroyTexture(drawing_texture_);
}
LOG_DP << "creating drawing texture" << std::endl;
drawing_texture_ = SDL_CreateTexture(
*window.get(),
drawingSurface->format->format,
SDL_TEXTUREACCESS_STREAMING,
drawingSurface->w,
drawingSurface->h
);
}
// Update sizes for input conversion.
sdl::update_input_dimensions(lsize.x, lsize.y, wsize.x, wsize.y);
}
void CVideo::init_window()
@ -220,7 +307,11 @@ void CVideo::init_window()
window_flags |= SDL_WINDOW_MAXIMIZED;
}
// TODO: fix whatever is crashing the rendering context when accelerated
// We can force software rendering here,
// but if we don't specify anything SDL should choose correctly.
uint32_t renderer_flags = SDL_RENDERER_SOFTWARE;
//uint32_t renderer_flags = 0;
if(supports_vsync() && preferences::vsync()) {
LOG_DP << "VSYNC on\n";
renderer_flags |= SDL_RENDERER_PRESENTVSYNC;
@ -274,34 +365,37 @@ void CVideo::set_window_mode(const MODE_EVENT mode, const point& size)
update_framebuffer();
}
SDL_Rect CVideo::screen_area(bool as_pixels) const
SDL_Point CVideo::output_size() const
{
if(!window) {
return {0, 0, frameBuffer->w, frameBuffer->h};
}
// 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) {
auto [scale_x, scale_y] = get_dpi_scale_factor();
size.x /= scale_x;
size.y /= scale_y;
}
return {0, 0, size.x, size.y};
// As we are rendering to the drawingSurface, we should never need this.
return window->get_output_size();
}
int CVideo::get_width(bool as_pixels) const
SDL_Point CVideo::window_size() const
{
return screen_area(as_pixels).w;
return window->get_size();
}
int CVideo::get_height(bool as_pixels) const
SDL_Rect CVideo::draw_area() const
{
return screen_area(as_pixels).h;
return {0, 0, drawingSurface->w, drawingSurface->h};
}
SDL_Rect CVideo::input_area() const
{
// This should always match draw_area.
SDL_Point p(window->get_logical_size());
return {0, 0, p.x, p.y};
}
int CVideo::get_width() const
{
return drawingSurface->w;
}
int CVideo::get_height() const
{
return drawingSurface->h;
}
void CVideo::delay(unsigned int milliseconds)
@ -317,6 +411,25 @@ void CVideo::flip()
return;
}
if (drawingSurface && drawing_texture_) {
// Upload the drawing surface to the drawing texture.
void* pixels_out; // somewhere we can write raw pixel data to
int pitch; // the length of one row of pixels in bytes
SDL_LockTexture(drawing_texture_, nullptr, &pixels_out, &pitch);
if (pitch != drawingSurface->pitch) {
// If these don't match we are not gonna have a good time.
throw game::error("drawing surface and texture are incompatible");
}
size_t num_bytes = drawingSurface->h * pitch;
memcpy(pixels_out, drawingSurface->pixels, num_bytes);
SDL_UnlockTexture(drawing_texture_);
//SDL_UpdateTexture(drawing_texture_, nullptr, drawingSurface->pixels, drawingSurface->pitch);
// Copy the drawing texture to the render target.
SDL_RenderCopy(*window.get(), drawing_texture_, nullptr, nullptr);
}
if(window) {
window->render();
}
@ -418,6 +531,10 @@ std::pair<float, float> CVideo::get_dpi_scale_factor() const
{
auto dpi = get_dpi();
if(dpi.first != 0.0f && dpi.second != 0.0f) {
// adjust for pixel scale
SDL_Point wsize = window_size();
dpi.first /= wsize.x / get_width();
dpi.second /= wsize.y / get_height();
return { dpi.first / MAGIC_DPI_SCALE_NUMBER, dpi.second / MAGIC_DPI_SCALE_NUMBER };
}
// Assume a scale factor of 1.0 if the screen dpi is currently unknown.
@ -481,9 +598,9 @@ std::vector<point> CVideo::get_available_resolutions(const bool include_current)
return result;
}
surface& CVideo::getSurface()
surface& CVideo::getDrawingSurface()
{
return frameBuffer;
return drawingSurface;
}
point CVideo::current_resolution()
@ -593,6 +710,7 @@ bool CVideo::set_resolution(const point& resolution)
}
// Change the saved values in preferences.
LOG_DP << "updating resolution to " << resolution << std::endl;
preferences::_set_resolution(resolution);
preferences::_set_maximized(false);
@ -603,6 +721,27 @@ bool CVideo::set_resolution(const point& resolution)
return true;
}
void CVideo::update_buffers()
{
LOG_DP << "updating buffers" << std::endl;
// We could also double-check the resolution here.
/*if (preferences::resolution() != current_resolution()) {
LOG_DP << "updating resolution from " << current_resolution()
<< " to " << preferences::resolution() << std::endl;
set_window_mode(TO_RES, preferences::resolution());
}*/
update_framebuffer();
if(display* d = display::get_singleton()) {
d->redraw_everything();
}
// 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();
}
void CVideo::lock_flips(bool lock)
{
if(lock) {

View File

@ -23,6 +23,7 @@
class surface;
struct point;
struct SDL_Texture;
namespace sdl
{
@ -120,22 +121,54 @@ public:
point current_resolution();
/**
* Update buffers to match current resolution and pixel scale settings.
* Also triggers a full redraw.
*/
void update_buffers();
/** Returns the list of available screen resolutions. */
std::vector<point> get_available_resolutions(const bool include_current = false);
/**
* 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.
* Returns the size of the final render target. This is irrelevant
* for most purposes. Use draw_area() in stead.
*/
SDL_Rect screen_area(bool as_pixels = true) const;
SDL_Point output_size() const;
/** Returns the window renderer width in pixels or screen coordinates. */
int get_width(bool as_pixels = true) const;
/**
* Returns the size of the window in display units / screen coordinates.
* This should match the value sent by window resize events, and also
* those used for setting resolution.
*/
SDL_Point window_size() const;
/** Returns the window renderer height in pixels or in screen coordinates. */
int get_height(bool as_pixels = true) const;
/**
* Returns the size and location of the current drawing area in pixels.
* This will usually be an SDL_Rect indicating the full drawing surface.
*/
SDL_Rect draw_area() const;
/**
* Returns the size and location of the window's input area in pixels.
* We use SDL_RendererSetLogicalSize to ensure this always matches
* draw_area(), but for clarity there are two separate functions.
*/
SDL_Rect input_area() const;
/**
* Returns the width of the drawing surface in pixels.
* Input coordinates are automatically scaled to correspond,
* so this also indicates the width of the input surface.
*/
int get_width() const;
/**
* Returns the height of the drawing surface in pixels.
* Input coordinates are automatically scaled to correspond,
* so this also indicates the height of the input surface.
*/
int get_height() const;
/** The current game screen dpi. */
std::pair<float, float> get_dpi() const;
@ -172,14 +205,14 @@ public:
/***** ***** ***** ***** Drawing functions ***** ***** ****** *****/
/**
* Draws a surface directly onto the screen framebuffer.
* Copies an area of a surface to the drawing surface.
*
* @param x The x coordinate at which to draw.
* @param y The y coordinate at which to draw.
* @param surf The surface to draw.
* @param srcrect The area of the surface to draw. This defaults to nullptr,
* which implies the entire thing.
* @param clip_rect The clippin rect. If not null, the surface will only be drawn
* @param clip_rect The clipping rect. If not null, the surface will only be drawn
* within the bounds of the given rectangle.
*/
void blit_surface(int x, int y, surface surf, SDL_Rect* srcrect = nullptr, SDL_Rect* clip_rect = nullptr);
@ -196,8 +229,8 @@ public:
/** Clear the screen contents */
void clear_screen();
/** Returns a reference to the framebuffer. */
surface& getSurface();
/** Returns a reference to the drawing surface. */
surface& getDrawingSurface();
/**
* Stop the screen being redrawn. Anything that happens while the updates are locked will
@ -263,6 +296,9 @@ private:
/** The SDL window object. */
std::unique_ptr<sdl::window> window;
/** The drawing texture. */
SDL_Texture* drawing_texture_;
/** Initializes the SDL video subsystem. */
void initSDL();

View File

@ -210,7 +210,7 @@ void button::calculate_size()
}
if (type_ != TYPE_IMAGE){
textRect_ = font::pango_draw_text(nullptr, video().screen_area(), font_size_, font::BUTTON_COLOR, label_text_, 0, 0);
textRect_ = font::pango_draw_text(nullptr, video().draw_area(), font_size_, font::BUTTON_COLOR, label_text_, 0, 0);
}
// TODO: There's a weird text clipping bug, allowing the code below to run fixes it.

View File

@ -865,7 +865,7 @@ void menu::draw_row(const std::size_t row_index, const SDL_Rect& rect, ROW_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;
const SDL_Rect& area = video().screen_area();
const SDL_Rect& area = video().draw_area();
const SDL_Rect& loc = inner_location();
const std::vector<int>& widths = column_widths();
bool lang_rtl = current_language_rtl();
@ -992,7 +992,7 @@ void menu::draw()
bg_restore();
clip_rect_setter clipping_rect =
clip_rect_setter(video().getSurface(), clip_rect(), clip_rect() != nullptr);
clip_rect_setter(video().getDrawingSurface(), clip_rect(), clip_rect() != nullptr);
draw_contents();
@ -1078,18 +1078,18 @@ SDL_Rect menu::get_item_rect_internal(std::size_t item) const
SDL_Rect res = sdl::create_rect(loc.x, y, loc.w, get_item_height(item));
const SDL_Rect& screen_area = video().screen_area();
const SDL_Rect& draw_area = video().draw_area();
if(res.x > screen_area.w) {
if(res.x > draw_area.w) {
return sdl::empty_rect;
} else if(res.x + res.w > screen_area.w) {
res.w = screen_area.w - res.x;
} else if(res.x + res.w > draw_area.w) {
res.w = draw_area.w - res.x;
}
if(res.y > screen_area.h) {
if(res.y > draw_area.h) {
return sdl::empty_rect;
} else if(res.y + res.h > screen_area.h) {
res.h = screen_area.h - res.y;
} else if(res.y + res.h > draw_area.h) {
res.h = draw_area.h - res.y;
}
//only insert into the cache if the menu's co-ordinates have

View File

@ -18,7 +18,7 @@
#include "widgets/scrollarea.hpp"
#include "sdl/rect.hpp"
#include "video.hpp"
#include "sdl/input.hpp" // get_mouse_state
namespace gui {
@ -156,7 +156,7 @@ void scrollarea::handle_event(const SDL_Event& event)
if (event.type == SDL_MOUSEWHEEL) {
const SDL_MouseWheelEvent &ev = event.wheel;
int x, y;
SDL_GetMouseState(&x, &y);
sdl::get_mouse_state(&x, &y);
if (sdl::point_in_rect(x, y, inner_location())) {
if (ev.y > 0) {
scrollbar_.scroll_up();
@ -171,7 +171,7 @@ void scrollarea::handle_event(const SDL_Event& event)
}
if (event.type == SDL_FINGERDOWN || event.type == SDL_FINGERMOTION) {
SDL_Rect r = video().screen_area();
SDL_Rect r = video().draw_area();
auto tx = static_cast<int>(event.tfinger.x * r.w);
auto ty = static_cast<int>(event.tfinger.y * r.h);
auto dy = static_cast<int>(event.tfinger.dy * r.h);

View File

@ -21,6 +21,7 @@
#include "sdl/rect.hpp"
#include "sdl/utils.hpp"
#include "video.hpp"
#include "sdl/input.hpp" // get_mouse_state
#include <iostream>
@ -278,7 +279,7 @@ void scrollbar::handle_event(const SDL_Event& event)
{
const SDL_MouseWheelEvent& e = event.wheel;
int x, y;
SDL_GetMouseState(&x, &y);
sdl::get_mouse_state(&x, &y);
bool on_groove = sdl::point_in_rect(x, y, groove);
if (on_groove && e.y < 0) {
move_position(scroll_rate_);

View File

@ -24,6 +24,7 @@
#include "sdl/rect.hpp"
#include "serialization/string_utils.hpp"
#include "video.hpp"
#include "sdl/input.hpp" // get_mouse_state
static lg::log_domain log_display("display");
#define WRN_DP LOG_STREAM(warn, log_display)
@ -41,7 +42,7 @@ textbox::textbox(CVideo &video, int width, const std::string& text, bool editabl
edit_target_(nullptr)
,listening_(false)
{
// static const SDL_Rect area = video.screen_area();
// static const SDL_Rect area = video.draw_area();
// const int height = font::pango_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);
@ -192,7 +193,7 @@ void textbox::draw_contents()
{
const SDL_Rect& loc = inner_location();
surface& surf = video().getSurface();
surface& surf = video().getDrawingSurface();
color_t c(0, 0, 0);
@ -212,7 +213,7 @@ void textbox::draw_contents()
src.w = std::min<std::size_t>(loc.w,text_image_->w);
src.h = std::min<std::size_t>(loc.h,text_image_->h);
src.x = text_pos_;
SDL_Rect dest = video().screen_area();
SDL_Rect dest = video().draw_area();
dest.x = loc.x;
dest.y = loc.y;
@ -652,7 +653,7 @@ void textbox::handle_event(const SDL_Event& event, bool was_forwarded)
}
int mousex, mousey;
const uint8_t mousebuttons = SDL_GetMouseState(&mousex,&mousey);
const uint8_t mousebuttons = sdl::get_mouse_state(&mousex,&mousey);
if(!(mousebuttons & SDL_BUTTON(1))) {
grabmouse_ = false;
}

View File

@ -240,7 +240,7 @@ void widget::bg_update()
void widget::bg_restore() const
{
clip_rect_setter clipper(video().getSurface(), &clip_rect_, clip_);
clip_rect_setter clipper(video().getDrawingSurface(), &clip_rect_, clip_);
if (needs_restore_) {
for(std::vector< surface_restorer >::const_iterator i = restorer_.begin(),
@ -252,7 +252,7 @@ void widget::bg_restore() const
void widget::bg_restore(const SDL_Rect& rect) const
{
clip_rect_setter clipper(video().getSurface(), &clip_rect_, clip_);
clip_rect_setter clipper(video().getDrawingSurface(), &clip_rect_, clip_);
for(std::vector< surface_restorer >::const_iterator i = restorer_.begin(),
i_end = restorer_.end(); i != i_end; ++i)
@ -273,7 +273,7 @@ void widget::draw()
bg_restore();
clip_rect_setter clipper(video().getSurface(), &clip_rect_, clip_);
clip_rect_setter clipper(video().getDrawingSurface(), &clip_rect_, clip_);
draw_contents();