widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #03155
[Merge] lp:~widelands-dev/widelands/fix_some_resizing_bugs into lp:widelands
SirVer has proposed merging lp:~widelands-dev/widelands/fix_some_resizing_bugs into lp:widelands.
Requested reviews:
Widelands Developers (widelands-dev)
Related bugs:
Bug #536500 in widelands: "Can not toggle fullscreen with Alt+Enter or resize with w.m."
https://bugs.launchpad.net/widelands/+bug/536500
Bug #536559 in widelands: "Fullscreen must not change physical screen resolution"
https://bugs.launchpad.net/widelands/+bug/536559
Bug #1203006 in widelands: "Increasing resolution in fullscreen results in the right and bottom sides not being updated properly"
https://bugs.launchpad.net/widelands/+bug/1203006
For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/fix_some_resizing_bugs/+merge/242593
- Make fullscreen toggle work. Fullscreen is now always at the native resolution
so that we do not switch the resolution any more.
- Never destroy g_gr. This fixes tons of bugs and makes the surface_cache
(nearly) unneeded. It also fixes crashes when switching resolution in the
options.
--
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/fix_some_resizing_bugs into lp:widelands.
=== modified file 'src/editor/editorinteractive.cc'
--- src/editor/editorinteractive.cc 2014-11-22 10:18:20 +0000
+++ src/editor/editorinteractive.cc 2014-11-23 14:42:44 +0000
@@ -422,7 +422,7 @@
break;
case SDLK_f:
- g_gr->toggle_fullscreen();
+ g_gr->set_fullscreen(!g_gr->fullscreen());
handled = true;
break;
=== modified file 'src/graphic/graphic.cc'
--- src/graphic/graphic.cc 2014-11-22 21:31:21 +0000
+++ src/graphic/graphic.cc 2014-11-23 14:42:44 +0000
@@ -46,6 +46,7 @@
#include "io/filesystem/layered_filesystem.h"
#include "io/streamwrite.h"
#include "logic/roadtype.h"
+#include "notifications/notifications.h"
#include "ui_basic/progresswindow.h"
using namespace std;
@@ -58,9 +59,6 @@
/// These are all surfaces that are not loaded from disk.
const uint32_t TRANSIENT_SURFACE_CACHE_SIZE = 160 << 20; // shifting converts to MB
-constexpr int kFallbackGraphicsWidth = 800;
-constexpr int kFallbackGraphicsHeight = 600;
-
// Sets the icon for the application.
void set_icon(SDL_Window* sdl_window) {
#ifndef _WIN32
@@ -78,49 +76,30 @@
/**
* Initialize the SDL video mode.
*/
-Graphic::Graphic()
- :
- m_fallback_settings_in_effect(false),
- m_update(true),
- surface_cache_(create_surface_cache(TRANSIENT_SURFACE_CACHE_SIZE)),
- image_cache_(new ImageCache(surface_cache_.get())),
- animation_manager_(new AnimationManager())
+Graphic::Graphic(int window_mode_w, int window_mode_h, bool fullscreen)
+ : m_window_mode_width(window_mode_w),
+ m_window_mode_height(window_mode_h),
+ m_update(true),
+ surface_cache_(create_surface_cache(TRANSIENT_SURFACE_CACHE_SIZE)),
+ image_cache_(new ImageCache(surface_cache_.get())),
+ animation_manager_(new AnimationManager())
{
ImageTransformations::initialize();
- m_sdl_window = nullptr;
- m_glcontext = nullptr;
-}
-
-void Graphic::initialize(int32_t w, int32_t h, bool fullscreen) {
- cleanup();
-
// Request an OpenGL 2 context with double buffering.
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
- int32_t flags = SDL_WINDOW_OPENGL;
- if (fullscreen) {
- flags |= SDL_WINDOW_FULLSCREEN;
- log("Graphics: Trying FULLSCREEN\n");
- }
-
- log("Graphics: Try to set Videomode %ux%u\n", w, h);
- m_sdl_window = SDL_CreateWindow(
- "Widelands Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, flags);
- if (!m_sdl_window) {
- log("Graphics: Could not set Videomode: %s, trying minimum graphics settings\n",
- SDL_GetError());
- flags &= ~SDL_WINDOW_FULLSCREEN;
- m_sdl_window = SDL_CreateWindow("Widelands Window",
- SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
- kFallbackGraphicsWidth, kFallbackGraphicsHeight, flags);
- m_fallback_settings_in_effect = true;
- if (!m_sdl_window) {
- throw wexception("Graphics: could not set video mode: %s", SDL_GetError());
- }
- }
+ log("Graphics: Try to set Videomode %ux%u\n", m_window_mode_width, m_window_mode_height);
+ m_sdl_window = SDL_CreateWindow("Widelands Window",
+ SDL_WINDOWPOS_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED,
+ m_window_mode_width,
+ m_window_mode_height,
+ SDL_WINDOW_OPENGL);
+ resolution_changed();
+ set_fullscreen(fullscreen);
SDL_SetWindowTitle(m_sdl_window, ("Widelands " + build_id() + '(' + build_type() + ')').c_str());
set_icon(m_sdl_window);
@@ -162,8 +141,6 @@
SDL_GL_SwapWindow(m_sdl_window);
- screen_.reset(new GLSurfaceScreen(w, h));
-
/* Information about the video capabilities. */
{
SDL_DisplayMode disp_mode;
@@ -180,18 +157,12 @@
assert(SDL_BYTESPERPIXEL(disp_mode.format) == 4);
}
- m_rendertarget.reset(new RenderTarget(screen_.get()));
-
pic_road_normal_.reset(load_image("world/pics/roadt_normal.png"));
pic_road_busy_.reset(load_image("world/pics/roadt_busy.png"));
}
-bool Graphic::check_fallback_settings_in_effect()
+Graphic::~Graphic()
{
- return m_fallback_settings_in_effect;
-}
-
-void Graphic::cleanup() {
m_maptextures.clear();
surface_cache_->flush();
// TODO(unknown): this should really not be needed, but currently is :(
@@ -208,15 +179,10 @@
}
}
-Graphic::~Graphic()
-{
- cleanup();
-}
-
/**
* Return the screen x resolution
*/
-int32_t Graphic::get_xres()
+int Graphic::get_xres()
{
return screen_->width();
}
@@ -224,14 +190,31 @@
/**
* Return the screen x resolution
*/
-int32_t Graphic::get_yres()
+int Graphic::get_yres()
{
return screen_->height();
}
-bool Graphic::is_fullscreen()
-{
- return SDL_GetWindowFlags(m_sdl_window) & SDL_WINDOW_FULLSCREEN;
+void Graphic::change_resolution(int w, int h) {
+ m_window_mode_width = w;
+ m_window_mode_height = h;
+
+ if (!fullscreen()) {
+ SDL_SetWindowSize(m_sdl_window, w, h);
+ resolution_changed();
+ }
+}
+
+void Graphic::resolution_changed() {
+ int new_w, new_h;
+ SDL_GetWindowSize(m_sdl_window, &new_w, &new_h);
+
+ screen_.reset(new GLSurfaceScreen(new_w, new_h));
+ m_rendertarget.reset(new RenderTarget(screen_.get()));
+
+ Notifications::publish(GraphicResolutionChanged{new_w, new_h});
+
+ update();
}
/**
@@ -240,27 +223,39 @@
RenderTarget * Graphic::get_render_target()
{
m_rendertarget->reset();
-
return m_rendertarget.get();
}
-/**
- * Switch from fullscreen to windowed mode or vice-versa
-*/
-void Graphic::toggle_fullscreen()
-{
- // TODO(unknown): implement proper fullscreening here. The way it can work is to
- // recreate SurfaceCache but keeping ImageCache around. Then exiting and
- // reinitalizing the SDL Video Mode should just work: all surface are
- // recreated dynamically and correctly.
- // Note: Not all Images are cached in the ImageCache, at time of me writing
- // this, only InMemoryImage does not safe itself in the ImageCache. And this
- // should only be a problem for Images loaded from maps.
- if (SDL_GetWindowFlags(m_sdl_window) & SDL_WINDOW_FULLSCREEN) {
+bool Graphic::fullscreen()
+{
+ uint32_t flags = SDL_GetWindowFlags(m_sdl_window);
+ return (flags & SDL_WINDOW_FULLSCREEN) || (flags & SDL_WINDOW_FULLSCREEN_DESKTOP);
+}
+
+void Graphic::set_fullscreen(const bool value)
+{
+ if (value == fullscreen()) {
+ return;
+ }
+
+ // Widelands is not resolution agnostic, so when we set fullscreen, we want
+ // it at the full resolution of the desktop and we want to know about the
+ // true resolution (SDL supports hiding the true resolution from the
+ // application). Since SDL ignores requests to change the size of the window
+ // whet fullscreen, we do it when in windowed mode.
+ if (value) {
+ SDL_DisplayMode display_mode;
+ SDL_GetDesktopDisplayMode(SDL_GetWindowDisplayIndex(m_sdl_window), &display_mode);
+ SDL_SetWindowSize(m_sdl_window, display_mode.w, display_mode.h);
+
+ SDL_SetWindowFullscreen(m_sdl_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
+ } else {
SDL_SetWindowFullscreen(m_sdl_window, 0);
- } else {
- SDL_SetWindowFullscreen(m_sdl_window, SDL_WINDOW_FULLSCREEN);
+
+ // Next line does not work. See comment in refresh().
+ SDL_SetWindowSize(m_sdl_window, m_window_mode_width, m_window_mode_height);
}
+ resolution_changed();
}
@@ -283,6 +278,17 @@
*/
void Graphic::refresh()
{
+ // Setting the window size immediately after going out of fullscreen does
+ // not work properly. We work around this issue by resizing the window in
+ // refresh() when in window mode.
+ if (!fullscreen()) {
+ int true_width, true_height;
+ SDL_GetWindowSize(m_sdl_window, &true_width, &true_height);
+ if (true_width != m_window_mode_width || true_height != m_window_mode_height) {
+ SDL_SetWindowSize(m_sdl_window, m_window_mode_width, m_window_mode_height);
+ }
+ }
+
SDL_GL_SwapWindow(m_sdl_window);
m_update = false;
}
=== modified file 'src/graphic/graphic.h'
--- src/graphic/graphic.h 2014-11-22 18:36:33 +0000
+++ src/graphic/graphic.h 2014-11-23 14:42:44 +0000
@@ -28,6 +28,8 @@
#include "base/rect.h"
#include "graphic/image_cache.h"
+#include "notifications/notifications.h"
+#include "notifications/note_ids.h"
#define MAX_RECTS 20
@@ -38,6 +40,15 @@
class StreamWrite;
struct Texture;
+// Will be send whenever the resolution changes.
+struct GraphicResolutionChanged {
+ CAN_BE_SEND_AS_NOTE(NoteId::GraphicResolutionChanged)
+
+ // New width and height in pixels.
+ int width;
+ int height;
+};
+
/**
* This class is a kind of Swiss Army knife for your graphics need. It
* initializes the graphic system and provides access to resolutions. It has an
@@ -46,18 +57,21 @@
*/
class Graphic {
public:
- Graphic();
+ // Creates a new graphic mode with the given resolution if fullscreen is
+ // false, otherwise a window that fills the screen.
+ Graphic(int window_mode_w, int window_mode_height, bool fullscreen);
~Graphic();
- // Initialize or reinitialize the graphics system. Throws on error.
- void initialize(int32_t w, int32_t h, bool fullscreen);
+ // Gets and sets the resolution.
+ void change_resolution(int w, int h);
+ int get_xres();
+ int get_yres();
- int32_t get_xres();
- int32_t get_yres();
- bool is_fullscreen();
+ // Changes the window to be fullscreen or not.
+ bool fullscreen();
+ void set_fullscreen(bool);
RenderTarget * get_render_target();
- void toggle_fullscreen();
void update();
bool need_update() const;
void refresh();
@@ -79,12 +93,13 @@
Surface& get_road_texture(int32_t roadtex);
- bool check_fallback_settings_in_effect();
-
private:
- void cleanup();
+ // Called when the resolution (might) have changed.
+ void resolution_changed();
- bool m_fallback_settings_in_effect;
+ // The height & width of the window should we be in window mode.
+ int m_window_mode_width;
+ int m_window_mode_height;
/// This is the main screen Surface.
/// A RenderTarget for this can be retrieved with get_render_target()
=== modified file 'src/graphic/text/test/render_richtext.cc'
--- src/graphic/text/test/render_richtext.cc 2014-11-23 10:13:14 +0000
+++ src/graphic/text/test/render_richtext.cc 2014-11-23 14:42:44 +0000
@@ -98,8 +98,7 @@
g_fs = new LayeredFileSystem();
g_fs->add_file_system(&FileSystem::create(INSTALL_DATADIR));
- g_gr = new Graphic();
- g_gr->initialize(1, 1, false);
+ g_gr = new Graphic(1, 1, false);
}
} // namespace
=== modified file 'src/logic/map_info.cc'
--- src/logic/map_info.cc 2014-11-22 21:31:21 +0000
+++ src/logic/map_info.cc 2014-11-23 14:42:44 +0000
@@ -49,8 +49,7 @@
g_fs = new LayeredFileSystem();
g_fs->add_file_system(&FileSystem::create(INSTALL_DATADIR));
- g_gr = new Graphic();
- g_gr->initialize(1, 1, false);
+ g_gr = new Graphic(1, 1, false);
}
} // namespace
=== modified file 'src/logic/ware_descr.cc'
--- src/logic/ware_descr.cc 2014-09-10 08:55:04 +0000
+++ src/logic/ware_descr.cc 2014-11-23 14:42:44 +0000
@@ -36,7 +36,7 @@
m_tribe (gtribe),
m_helptext (global_s.get_string("help", "")),
m_icon_fname (directory + "/menu.png"),
- m_icon(g_gr ? g_gr->images().get("pics/but0.png") : nullptr) // because of dedicated
+ m_icon(g_gr->images().get("pics/but0.png"))
{
m_default_target_quantity =
global_s.get_positive("default_target_quantity", std::numeric_limits<uint32_t>::max());
=== modified file 'src/notifications/note_ids.h'
--- src/notifications/note_ids.h 2014-09-10 19:54:01 +0000
+++ src/notifications/note_ids.h 2014-11-23 14:42:44 +0000
@@ -32,6 +32,8 @@
FieldPossession,
FieldTransformed,
ProductionSiteOutOfResources,
+
+ GraphicResolutionChanged,
};
#endif // end of include guard: WL_NOTIFICATIONS_NOTE_IDS_H
=== modified file 'src/wlapplication.cc'
--- src/wlapplication.cc 2014-11-22 18:36:33 +0000
+++ src/wlapplication.cc 2014-11-23 14:42:44 +0000
@@ -244,7 +244,6 @@
m_homedir = m_commandline["homedir"];
m_commandline.erase("homedir");
}
- bool dedicated = m_commandline.count("dedicated");
#ifdef REDIRECT_OUTPUT
if (!redirect_output())
redirect_output(m_homedir);
@@ -259,18 +258,15 @@
init_language(); // search paths must already be set up
cleanup_replays();
- if (!dedicated) {
- // handling of graphics
- init_hardware();
-
- if (TTF_Init() == -1)
- throw wexception
- ("True Type library did not initialize: %s\n", TTF_GetError());
-
- UI::g_fh = new UI::FontHandler();
- UI::g_fh1 = UI::create_fonthandler(g_gr);
- } else
- g_gr = nullptr;
+ // handling of graphics
+ init_hardware();
+
+ if (TTF_Init() == -1)
+ throw wexception
+ ("True Type library did not initialize: %s\n", TTF_GetError());
+
+ UI::g_fh = new UI::FontHandler();
+ UI::g_fh1 = UI::create_fonthandler(g_gr);
if (SDLNet_Init() == -1)
throw wexception("SDLNet_Init failed: %s\n", SDLNet_GetError());
@@ -440,9 +436,6 @@
g_sound_handler.change_music("menu", 1000);
mainmenu();
-
- delete g_gr;
- g_gr = nullptr;
}
g_sound_handler.stop_music(500);
@@ -671,38 +664,14 @@
}
}
-/**
- * Initialize the graphics subsystem (or shutdown, if w and h are 0)
- * with the given resolution.
- * Throws an exception on failure.
- */
-void WLApplication::init_graphics(int32_t w, int32_t h, bool fullscreen)
-{
- if (!w && !h) { // shutdown.
- delete g_gr;
- g_gr = nullptr;
- return;
- }
- assert(w > 0 && h > 0);
-
- if (!g_gr) {
- g_gr = new Graphic();
- g_gr->initialize(w, h, fullscreen);
- } else {
- if (g_gr->get_xres() != w || g_gr->get_yres() != h || g_gr->is_fullscreen() != fullscreen) {
- g_gr->initialize(w, h, fullscreen);
- }
- }
-}
-
void WLApplication::refresh_graphics()
{
Section & s = g_options.pull_section("global");
- // Switch to the new graphics system now, if necessary.
- init_graphics(s.get_int("xres", DEFAULT_RESOLUTION_W),
- s.get_int("yres", DEFAULT_RESOLUTION_H),
- s.get_bool("fullscreen", false));
+ g_gr->change_resolution(
+ s.get_int("xres", DEFAULT_RESOLUTION_W), s.get_int("yres", DEFAULT_RESOLUTION_H));
+ g_gr->set_fullscreen(s.get_bool("fullscreen", false));
+
// does only work with a window
set_input_grab(s.get_bool("inputgrab", false));
}
@@ -827,7 +796,9 @@
SDL_ShowCursor(SDL_DISABLE);
- refresh_graphics();
+ g_gr = new Graphic(s.get_int("xres", DEFAULT_RESOLUTION_W),
+ s.get_int("yres", DEFAULT_RESOLUTION_H),
+ s.get_bool("fullscreen", false));
// Start the audio subsystem
// must know the locale before calling this!
@@ -838,14 +809,9 @@
void WLApplication::shutdown_hardware()
{
- if (g_gr)
- wout
- <<
- "WARNING: Hardware shutting down although graphics system is still "
- "alive!"
- << std::endl;
+ delete g_gr;
+ g_gr = nullptr;
- init_graphics(0, 0, false);
SDL_QuitSubSystem(SDL_INIT_TIMER|SDL_INIT_VIDEO|SDL_INIT_JOYSTICK);
#ifndef _WIN32
@@ -1049,14 +1015,6 @@
std::string messagetitle;
std::string message;
- if (g_gr->check_fallback_settings_in_effect())
- {
- messagetitle = "Fallback settings in effect";
- message = _
- ("Your video settings could not be enabled, and fallback settings are in effect. "
- "Please check the graphics options!");
- }
-
for (;;) {
// Refresh graphics system in case we just changed resolution.
refresh_graphics();
=== modified file 'src/wlapplication.h'
--- src/wlapplication.h 2014-11-22 18:36:33 +0000
+++ src/wlapplication.h 2014-11-23 14:42:44 +0000
@@ -164,13 +164,8 @@
void set_mouse_lock(const bool locked) {m_mouse_locked = locked;}
//@}
- void init_graphics(int32_t w, int32_t h, bool fullscreen);
- /**
- * Refresh the graphics from the latest options.
- *
- * \note See caveats for \ref init_graphics()
- */
+ // Refresh the graphics settings with the latest options.
void refresh_graphics();
void handle_input(InputCallback const *);
=== modified file 'src/wui/interactive_base.cc'
--- src/wui/interactive_base.cc 2014-11-22 10:18:20 +0000
+++ src/wui/interactive_base.cc 2014-11-23 14:42:44 +0000
@@ -79,12 +79,7 @@
};
InteractiveBase::InteractiveBase(EditorGameBase& the_egbase, Section& global_s)
- : MapView(nullptr,
- 0,
- 0,
- global_s.get_int("xres", DEFAULT_RESOLUTION_W),
- global_s.get_int("yres", DEFAULT_RESOLUTION_H),
- *this),
+ : MapView(nullptr, 0, 0, g_gr->get_xres(), g_gr->get_yres(), *this),
// Initialize chatoveraly before the toolbar so it is below
m_show_workarea_preview(global_s.get_bool("workareapreview", true)),
m_chatOverlay(new ChatOverlay(this, 10, 25, get_w() / 2, get_h() - 25)),
@@ -107,10 +102,19 @@
m_label_speed(this, get_w(), 1, std::string(), UI::Align_TopRight),
unique_window_handler_(new UniqueWindowHandler()),
// Start at idx 0 for 2 enhancements, idx 3 for 1, idx 5 if none
- m_workarea_pics
- {g_gr->images().get("pics/workarea123.png"), g_gr->images().get("pics/workarea23.png"),
- g_gr->images().get("pics/workarea3.png"), g_gr->images().get("pics/workarea12.png"),
- g_gr->images().get("pics/workarea2.png"), g_gr->images().get("pics/workarea1.png")} {
+ m_workarea_pics{g_gr->images().get("pics/workarea123.png"),
+ g_gr->images().get("pics/workarea23.png"),
+ g_gr->images().get("pics/workarea3.png"),
+ g_gr->images().get("pics/workarea12.png"),
+ g_gr->images().get("pics/workarea2.png"),
+ g_gr->images().get("pics/workarea1.png")} {
+
+ graphic_resolution_changed_subscriber_ = Notifications::subscribe<GraphicResolutionChanged>(
+ [this](const GraphicResolutionChanged& message) {
+ set_size(message.width, message.height);
+ adjust_toolbar_position();
+ });
+
m_toolbar.set_layout_toplevel(true);
m->quicknavigation->set_setview
(boost::bind(&MapView::set_viewpoint, this, _1, true));
=== modified file 'src/wui/interactive_base.h'
--- src/wui/interactive_base.h 2014-10-14 06:30:20 +0000
+++ src/wui/interactive_base.h 2014-11-23 14:42:44 +0000
@@ -24,15 +24,17 @@
#include <SDL_keycode.h>
+#include "graphic/graphic.h"
#include "logic/editor_game_base.h"
#include "logic/map.h"
+#include "notifications/notifications.h"
+#include "ui_basic/box.h"
+#include "ui_basic/textarea.h"
+#include "ui_basic/unique_window.h"
#include "wui/chatoverlay.h"
#include "wui/debugconsole.h"
#include "wui/mapview.h"
#include "wui/overlay_manager.h"
-#include "ui_basic/box.h"
-#include "ui_basic/textarea.h"
-#include "ui_basic/unique_window.h"
namespace Widelands {struct CoordPath;}
@@ -179,6 +181,9 @@
} m_sel;
std::unique_ptr<InteractiveBaseInternals> m;
+
+ std::unique_ptr<Notifications::Subscriber<GraphicResolutionChanged>>
+ graphic_resolution_changed_subscriber_;
Widelands::EditorGameBase & m_egbase;
uint32_t m_display_flags;
uint32_t m_lastframe; // system time (milliseconds)
=== modified file 'src/wui/interactive_player.cc'
--- src/wui/interactive_player.cc 2014-11-22 10:18:20 +0000
+++ src/wui/interactive_player.cc 2014-11-23 14:42:44 +0000
@@ -402,7 +402,7 @@
return true;
case SDLK_f:
- g_gr->toggle_fullscreen();
+ g_gr->set_fullscreen(!g_gr->fullscreen());
return true;
case SDLK_KP_7:
=== modified file 'src/wui/interactive_spectator.cc'
--- src/wui/interactive_spectator.cc 2014-11-22 10:18:20 +0000
+++ src/wui/interactive_spectator.cc 2014-11-23 14:42:44 +0000
@@ -264,7 +264,7 @@
return true;
case SDLK_f:
- g_gr->toggle_fullscreen();
+ g_gr->set_fullscreen(!g_gr->fullscreen());
return true;
case SDLK_RETURN:
Follow ups