Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
3cbf4e2
Enable non-resizable windows (SDL2 only)
falbrechtskirchinger Jul 10, 2023
9b0dc2e
Implement full support for borderless windows
Flamefire Feb 15, 2026
c510829
Make `CHECK_SDL` a function
Flamefire Feb 15, 2026
1419169
Make setting member naming consistent
Flamefire Feb 21, 2026
f2e76b1
Disallow comparison of Bitfields
Flamefire Feb 21, 2026
1afa888
Allow opening (advanced) ingame settings with F10
Flamefire Feb 22, 2026
59e37e8
Refactor control creation of dskOptions
Flamefire Feb 22, 2026
43acdcb
Fix check for GUI scaling support in AUTO mode
Flamefire Feb 25, 2026
410d5a4
Translate docstrings in VideoWinAPI
Flamefire Feb 25, 2026
284f61e
Add extra option for locking Window size and make "Borderless Window"…
Flamefire Feb 25, 2026
fee45c3
Pass `VideoMode` by value
Flamefire Feb 25, 2026
fbda80f
Fix parameter name
Flamefire Feb 25, 2026
28f643b
Return vector from `ListVideoModes` instead of output param
Flamefire Feb 26, 2026
fc61e07
Add fallback to makeUnique for non-orderable elements
Flamefire Feb 26, 2026
a0e148c
Add option to change text of a combobox item
Flamefire Feb 26, 2026
d4e1123
Add adaptive controls for changing window size
Flamefire Feb 26, 2026
b9640df
Filter small video modes earlier
Flamefire Feb 26, 2026
590d816
Add constant for minimum window size
Flamefire Feb 26, 2026
921f69f
Fix WinAPI glitch on first window resize: Window moves to background
Flamefire Feb 26, 2026
e0db98b
Fix centering window in SDL2
Flamefire Feb 26, 2026
e5a6df3
Fix positioning of FPS display for unscaled desktops
Flamefire Feb 26, 2026
302f59a
Fix misplaced buttons in game interface for very small windows
Flamefire Feb 26, 2026
f74569a
Explicitly instantiate `Window::Scale`
Flamefire Feb 27, 2026
4bb3d41
Translate and update docstrings of Window class
Flamefire Feb 27, 2026
4597ccb
Store Window controls as `unique_ptr`
Flamefire Feb 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion data/RTTR/texte/de/keyboardlayout.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ F1:................... (Spiel laden)
F2:................... Spiel speichern
F8:................... Tastaturbelegung anzeigen
F9:................... ReadMe-Datei anzeigen
F10:.................. Einstellungen (UI, ...)
F11:.................. Musik-Spieler
F12:.................. Kontrollfenster

Expand All @@ -47,6 +48,6 @@ P:.................... Pause/Fortsetzen (Auch nach GF Sprung)
1-7:.................. Spielerwechsel

------------------------------------------------------------------------
https://www.siedler25.org Copyright (C) 2005-2022 Settlers Freaks
https://www.siedler25.org Copyright (C) 2005-2026 Settlers Freaks
------------------------------------------------------------------------

3 changes: 2 additions & 1 deletion data/RTTR/texte/keyboardlayout.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ F1:................... (Load game)
F2:................... Save game
F8:................... Readme "Keyboard layout"
F9:................... Readme
F10:.................. Settings (UI, ...)
F11:.................. Musicplayer
F12:.................. Options window

Expand All @@ -46,5 +47,5 @@ J:.................... Go to specific GF
P:.................... Pause/Resume (also after GF jump)
1-7:.................. Change to other player
------------------------------------------------------------------------
https://www.siedler25.org Copyright (C) 2005-2022 Settlers Freaks
https://www.siedler25.org Copyright (C) 2005-2026 Settlers Freaks
------------------------------------------------------------------------
2 changes: 1 addition & 1 deletion external/libutil
174 changes: 118 additions & 56 deletions extras/videoDrivers/SDL2/VideoSDL2.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Copyright (C) 2005 - 2025 Settlers Freaks (sf-team at siedler25.org)
// Copyright (C) 2005 - 2026 Settlers Freaks (sf-team at siedler25.org)
//
// SPDX-License-Identifier: GPL-2.0-or-later

#include "VideoSDL2.h"
#include "RTTR_Assert.h"
#include "driver/Interface.h"
#include "driver/VideoDriverLoaderInterface.h"
#include "driver/VideoInterface.h"
Expand Down Expand Up @@ -31,17 +32,18 @@
# include <gl4esinit.h>
#endif

#define CHECK_SDL(call) \
([&]() -> bool { \
if((call) < 0) \
{ \
PrintError(SDL_GetError()); \
return false; \
} \
return true; \
})()

namespace {

/// Check that the (SDL) call returns success or print the error
/// Can be used in conditions: if(CHECK_SDL(SDL_Foo()))
bool CHECK_SDL(int sdlResult)
{
if(sdlResult >= 0)
return true;
VideoSDL2::PrintError();
return false;
}

template<typename T>
struct SDLMemoryDeleter
{
Expand Down Expand Up @@ -102,7 +104,7 @@ bool VideoSDL2::Initialize()
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
if(SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
{
PrintError(SDL_GetError());
PrintError();
return false;
}

Expand Down Expand Up @@ -132,7 +134,16 @@ void VideoSDL2::UpdateCurrentSizes()
SetNewSize(VideoMode(w, h), Extent(w2, h2));
}

bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode& size, bool fullscreen)
static VideoMode getDesktopSize(SDL_Window* window, VideoMode fallback)
{
const int display = window ? std::max(0, SDL_GetWindowDisplayIndex(window)) : 0;
SDL_DisplayMode dskSize;
if(CHECK_SDL(SDL_GetDesktopDisplayMode(display, &dskSize)))
return VideoMode(dskSize.w, dskSize.h);
return fallback;
}

bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode size, DisplayMode displayMode)
{
if(!initialized)
return false;
Expand All @@ -155,34 +166,45 @@ bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode& size, bo
CHECK_SDL(SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8));
CHECK_SDL(SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1));

int wndPos = SDL_WINDOWPOS_CENTERED;

const auto requestedSize = fullscreen ? FindClosestVideoMode(size) : size;
unsigned commonFlags = SDL_WINDOW_OPENGL;
const int wndPos = SDL_WINDOWPOS_CENTERED;
const unsigned commonFlags = SDL_WINDOW_OPENGL;
// TODO: Fix GUI scaling with High DPI support enabled.
// See https://github.com/Return-To-The-Roots/s25client/issues/1621
// commonFlags |= SDL_WINDOW_ALLOW_HIGHDPI;

window = SDL_CreateWindow(title.c_str(), wndPos, wndPos, requestedSize.width, requestedSize.height,
commonFlags | (fullscreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE));

// Fallback to non-fullscreen
if(!window && fullscreen)
unsigned windowTypeFlag = 0;
auto requestedSize = size;
if(displayMode == DisplayMode::Fullscreen)
{
window = SDL_CreateWindow(title.c_str(), wndPos, wndPos, requestedSize.width, requestedSize.height,
commonFlags | SDL_WINDOW_RESIZABLE);
}
windowTypeFlag = SDL_WINDOW_FULLSCREEN;
requestedSize = FindClosestVideoMode(size);
} else if(displayMode == DisplayMode::BorderlessWindow)
{
windowTypeFlag = SDL_WINDOW_BORDERLESS;
requestedSize = getDesktopSize(nullptr, size);
} else if(displayMode.resizeable)
windowTypeFlag = SDL_WINDOW_RESIZABLE;

window = SDL_CreateWindow(title.c_str(), wndPos, wndPos, requestedSize.width, requestedSize.height,
commonFlags | windowTypeFlag);

if(!window)
{
PrintError(SDL_GetError());
PrintError();
// Fallback to borderless fullscreen if unable to set resolution
if(displayMode == DisplayMode::Fullscreen)
return CreateScreen(title, size, DisplayMode::BorderlessWindow);
// No borderless -> Resizable window as last fallback to at least show something
if(displayMode == DisplayMode::BorderlessWindow)
return CreateScreen(title, size, DisplayMode::Windowed);
PrintError();
return false;
}

isFullscreen_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0;
UpdateCurrentDisplayMode();
UpdateCurrentSizes();

if(!isFullscreen_)
if(displayMode != DisplayMode::Fullscreen)
MoveWindowToCenter();

SDL_Surface* iconSurf =
Expand All @@ -192,7 +214,7 @@ bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode& size, bo
SDL_SetWindowIcon(window, iconSurf);
SDL_FreeSurface(iconSurf);
} else
PrintError(SDL_GetError());
PrintError();

context = SDL_GL_CreateContext(window);

Expand All @@ -207,50 +229,67 @@ bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode& size, bo
return true;
}

bool VideoSDL2::ResizeScreen(const VideoMode& newSize, bool fullscreen)
bool VideoSDL2::ResizeScreen(VideoMode newSize, DisplayMode displayMode)
{
if(!initialized)
return false;

if(isFullscreen_ != fullscreen)
bool centerWindow = false;

if(displayMode_ != displayMode)
{
SDL_SetWindowFullscreen(window, fullscreen ? SDL_WINDOW_FULLSCREEN : 0);
isFullscreen_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0;
if(!isFullscreen_)
if(displayMode_ == DisplayMode::Fullscreen || displayMode == DisplayMode::Fullscreen)
{
SDL_SetWindowResizable(window, SDL_TRUE);
MoveWindowToCenter();
if(!CHECK_SDL(
SDL_SetWindowFullscreen(window, (displayMode == DisplayMode::Fullscreen) ? SDL_WINDOW_FULLSCREEN : 0)))
{
if(displayMode == DisplayMode::Fullscreen)
displayMode = DisplayMode::BorderlessWindow;
}
}
}
SDL_SetWindowResizable(window,
static_cast<SDL_bool>(displayMode == DisplayMode::Windowed && displayMode.resizeable));
SDL_SetWindowBordered(window, static_cast<SDL_bool>(displayMode == DisplayMode::Windowed));

UpdateCurrentDisplayMode();
centerWindow = true;
}
if(displayMode_ == DisplayMode::BorderlessWindow)
newSize = getDesktopSize(nullptr, newSize);
if(newSize != GetWindowSize())
{
if(isFullscreen_)
if(displayMode_ == DisplayMode::Fullscreen)
{
auto const targetMode = FindClosestVideoMode(newSize);
SDL_DisplayMode target;
target.w = targetMode.width;
target.h = targetMode.height;
target.format = 0; // don't care
target.refresh_rate = 0; // don't care
target.driverdata = nullptr; // initialize to 0
target.format = 0; // don't care
target.refresh_rate = 0; // don't care
target.driverdata = nullptr;
// Explicitly change the window size to avoid a bug with SDL reporting the wrong size until alt+tab
SDL_SetWindowSize(window, target.w, target.h);
if(SDL_SetWindowDisplayMode(window, &target) < 0)
{
PrintError(SDL_GetError());
if(!CHECK_SDL(SDL_SetWindowDisplayMode(window, &target)))
return false;
}
} else
{
SDL_SetWindowSize(window, newSize.width, newSize.height);
centerWindow = true;
}
UpdateCurrentSizes();
}
if(centerWindow)
MoveWindowToCenter();

return true;
}

void VideoSDL2::PrintError(const std::string& msg) const
void VideoSDL2::PrintError()
{
PrintError(SDL_GetError());
}

void VideoSDL2::PrintError(const std::string& msg)
{
boost::nowide::cerr << msg << std::endl;
}
Expand Down Expand Up @@ -308,7 +347,7 @@ bool VideoSDL2::MessageLoop()
{
case SDL_WINDOWEVENT_RESIZED:
{
isFullscreen_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0;
UpdateCurrentDisplayMode();
VideoMode newSize(ev.window.data1, ev.window.data2);
if(newSize != GetWindowSize())
{
Expand Down Expand Up @@ -508,23 +547,25 @@ unsigned long VideoSDL2::GetTickCount() const
return SDL_GetTicks();
}

void VideoSDL2::ListVideoModes(std::vector<VideoMode>& video_modes) const
std::vector<VideoMode> VideoSDL2::ListVideoModes() const
{
int display = SDL_GetWindowDisplayIndex(window);
if(display < 0)
display = 0;
std::vector<VideoMode> video_modes;
for(int i = SDL_GetNumDisplayModes(display) - 1; i >= 0; --i)
{
SDL_DisplayMode mode;
if(SDL_GetDisplayMode(display, i, &mode) != 0)
PrintError(SDL_GetError());
PrintError();
else
{
VideoMode vm(mode.w, mode.h);
if(!helpers::contains(video_modes, vm))
video_modes.push_back(vm);
}
}
return video_modes;
}

OpenGL_Loader_Proc VideoSDL2::GetLoaderFunction() const
Expand Down Expand Up @@ -565,17 +606,38 @@ void* VideoSDL2::GetMapPointer() const

void VideoSDL2::MoveWindowToCenter()
{
SDL_PumpEvents(); // Let window system run update events/initialization
const int display = window ? std::max(0, SDL_GetWindowDisplayIndex(window)) : 0;

SDL_Rect usableBounds;
CHECK_SDL(SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(window), &usableBounds));
CHECK_SDL(SDL_GetDisplayUsableBounds(display, &usableBounds));
int top, left, bottom, right;
if(CHECK_SDL(SDL_GetWindowBordersSize(window, &top, &left, &bottom, &right)) != 0)
if(!CHECK_SDL(SDL_GetWindowBordersSize(window, &top, &left, &bottom, &right)))
top = left = bottom = right = 0;
usableBounds.w -= left + right;
usableBounds.h -= top + bottom;
if(usableBounds.w < GetWindowSize().width || usableBounds.h < GetWindowSize().height)
auto wndOuterSize = GetWindowSize();
wndOuterSize.width += left + right;
wndOuterSize.height += top + bottom;
if(usableBounds.w < wndOuterSize.width || usableBounds.h < wndOuterSize.height)
{
SDL_SetWindowSize(window, usableBounds.w, usableBounds.h);
SDL_SetWindowSize(window, usableBounds.w - left - right, usableBounds.h - top - bottom);
UpdateCurrentSizes();
wndOuterSize.width = usableBounds.w;
wndOuterSize.height = usableBounds.h;
}
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
const int x = usableBounds.x + (usableBounds.w - wndOuterSize.width) / 2 + left;
const int y = usableBounds.y + (usableBounds.h - wndOuterSize.height) / 2 + top;
SDL_SetWindowPosition(window, x, y);
}

void VideoSDL2::UpdateCurrentDisplayMode()
{
RTTR_Assert(window);
const auto flags = SDL_GetWindowFlags(window);
if(flags & SDL_WINDOW_FULLSCREEN)
displayMode_ = DisplayMode::Fullscreen;
else if((flags & SDL_WINDOW_BORDERLESS) != 0)
displayMode_ = DisplayMode::BorderlessWindow;
else
displayMode_ = DisplayMode::Windowed;
displayMode_.resizeable = (flags & SDL_WINDOW_RESIZABLE) != 0;
}
15 changes: 9 additions & 6 deletions extras/videoDrivers/SDL2/VideoSDL2.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org)
// Copyright (C) 2005 - 2026 Settlers Freaks (sf-team at siedler25.org)
//
// SPDX-License-Identifier: GPL-2.0-or-later

Expand All @@ -24,8 +24,8 @@ class VideoSDL2 final : public VideoDriver

bool Initialize() override;

bool CreateScreen(const std::string& title, const VideoMode& size, bool fullscreen) override;
bool ResizeScreen(const VideoMode& newSize, bool fullscreen) override;
bool CreateScreen(const std::string& title, VideoMode size, DisplayMode displayMode) override;
bool ResizeScreen(VideoMode newSize, DisplayMode displayMode) override;

void DestroyScreen() override;

Expand All @@ -41,8 +41,8 @@ class VideoSDL2 final : public VideoDriver

OpenGL_Loader_Proc GetLoaderFunction() const override;

/// Add supported video modes
void ListVideoModes(std::vector<VideoMode>& video_modes) const override;
/// Get supported video modes
std::vector<VideoMode> ListVideoModes() const override;

/// Set mouse position
void SetMousePos(Position pos) override;
Expand All @@ -53,11 +53,14 @@ class VideoSDL2 final : public VideoDriver
/// Get (device-dependent!) window pointer, HWND in Windows
void* GetMapPointer() const override;

static void PrintError();
static void PrintError(const std::string& msg);

private:
void PrintError(const std::string& msg) const;
void HandlePaste();
void UpdateCurrentSizes();
void MoveWindowToCenter();
void UpdateCurrentDisplayMode();

SDL_Window* window;
SDL_GLContext context;
Expand Down
Loading
Loading