Skip to content

Commit

Permalink
Enable non-resizable windows (SDL2 only)
Browse files Browse the repository at this point in the history
Add a hidden setting to control whether the window is resizable.

Fixes #1512
  • Loading branch information
falbrechtskirchinger committed Jul 22, 2023
1 parent df3aa8c commit 9cd0008
Show file tree
Hide file tree
Showing 21 changed files with 222 additions and 88 deletions.
51 changes: 31 additions & 20 deletions extras/videoDrivers/SDL2/VideoSDL2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ void VideoSDL2::UpdateCurrentSizes()
SetNewSize(VideoMode(w, h), Extent(w2, h2));
}

bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode& size, bool fullscreen)
bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode& size, DisplayMode displayMode)
{
if(!initialized)
return false;
Expand All @@ -113,30 +113,33 @@ 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 int wndPos = SDL_WINDOWPOS_CENTERED;
const auto fullscreen = (displayMode & DisplayMode::Fullscreen) != DisplayMode::None;
const auto resizable = (displayMode & DisplayMode::Resizable) != DisplayMode::None;
const auto requestedSize = fullscreen ? FindClosestVideoMode(size) : size;
const unsigned commonFlags = SDL_WINDOW_OPENGL | (resizable ? SDL_WINDOW_RESIZABLE : 0);
const unsigned fullscreenFlag = (fullscreen ? SDL_WINDOW_FULLSCREEN : 0);

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

// Fallback to non-fullscreen
if(!window && fullscreen)
{
window = SDL_CreateWindow(title.c_str(), wndPos, wndPos, requestedSize.width, requestedSize.height,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
}
window =
SDL_CreateWindow(title.c_str(), wndPos, wndPos, requestedSize.width, requestedSize.height, commonFlags);

if(!window)
{
PrintError(SDL_GetError());
return false;
}

isFullscreen_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0;
const auto flags = SDL_GetWindowFlags(window);
SetFullscreenFlag((flags & SDL_WINDOW_FULLSCREEN) != 0);
SetResizableFlag((flags & SDL_WINDOW_RESIZABLE) != 0);
UpdateCurrentSizes();

if(!isFullscreen_)
if(!IsFullscreen())
MoveWindowToCenter();

SDL_Surface* iconSurf =
Expand All @@ -161,27 +164,34 @@ bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode& size, bo
return true;
}

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

if(isFullscreen_ != fullscreen)
const auto fullscreen = (displayMode & DisplayMode::Fullscreen) != DisplayMode::None;
const auto resizable = (displayMode & DisplayMode::Resizable) != DisplayMode::None;

if(IsFullscreen() != fullscreen)
{
SDL_SetWindowFullscreen(window, fullscreen ? SDL_WINDOW_FULLSCREEN : 0);
isFullscreen_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0;
if(!isFullscreen_)
{
SetFullscreenFlag((SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0);
if(!IsFullscreen())
MoveWindowToCenter();
}

if(displayMode_ != displayMode)
{
if(!IsFullscreen())
#if SDL_VERSION_ATLEAST(2, 0, 5)
SDL_SetWindowResizable(window, SDL_TRUE);
SDL_SetWindowResizable(window, static_cast<SDL_bool>(resizable));
#endif
MoveWindowToCenter();
}
SetResizableFlag((SDL_GetWindowFlags(window) & SDL_WINDOW_RESIZABLE) != 0);
}

if(newSize != GetWindowSize())
{
if(isFullscreen_)
if(IsFullscreen())
{
auto const targetMode = FindClosestVideoMode(newSize);
SDL_DisplayMode target;
Expand All @@ -203,6 +213,7 @@ bool VideoSDL2::ResizeScreen(const VideoMode& newSize, bool fullscreen)
}
UpdateCurrentSizes();
}

return true;
}

Expand Down Expand Up @@ -265,7 +276,7 @@ bool VideoSDL2::MessageLoop()
{
case SDL_WINDOWEVENT_RESIZED:
{
isFullscreen_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0;
SetFullscreenFlag((SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0);
VideoMode newSize(ev.window.data1, ev.window.data2);
if(newSize != GetWindowSize())
{
Expand Down
4 changes: 2 additions & 2 deletions extras/videoDrivers/SDL2/VideoSDL2.h
Original file line number Diff line number Diff line change
Expand Up @@ -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, const VideoMode& size, DisplayMode displayMode) override;
bool ResizeScreen(const VideoMode& newSize, DisplayMode displayMode) override;

void DestroyScreen() override;

Expand Down
29 changes: 15 additions & 14 deletions extras/videoDrivers/WinAPI/WinAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,26 +129,25 @@ void VideoWinAPI::CleanUp()
/**
* Erstellt das Fenster mit entsprechenden Werten.
*
* @param[in] width Breite des Fensters
* @param[in] height Höhe des Fensters
* @param[in] fullscreen Vollbildmodus ja oder nein
* @param[in] width Breite des Fensters
* @param[in] height Höhe des Fensters
* @param[in] displayMode Fullscreen on/off, window resizable?
*
* @return @p true bei Erfolg, @p false bei Fehler
*
* @bug Hardwarecursor ist bei Fenstermodus sichtbar,
* Cursor deaktivieren ist fehlerhaft
*/
bool VideoWinAPI::CreateScreen(const std::string& title, const VideoMode& newSize, bool fullscreen)
bool VideoWinAPI::CreateScreen(const std::string& title, const VideoMode& newSize, DisplayMode displayMode)
{
if(!initialized)
return false;

if(!RegisterAndCreateWindow(title, newSize, fullscreen))
if(!RegisterAndCreateWindow(title, newSize, displayMode))
return false;

if(fullscreen && !MakeFullscreen(GetWindowSize()))
if(bitset::isSet(displayMode, DisplayMode::Fullscreen) && !MakeFullscreen(GetWindowSize()))
return false;
isFullscreen_ = fullscreen;

if(!InitOGL())
return false;
Expand All @@ -174,30 +173,31 @@ bool VideoWinAPI::CreateScreen(const std::string& title, const VideoMode& newSiz
*
* @todo Vollbildmodus ggf. wechseln
*/
bool VideoWinAPI::ResizeScreen(const VideoMode& newSize, bool fullscreen)
bool VideoWinAPI::ResizeScreen(const VideoMode& newSize, DisplayMode displayMode)
{
if(!initialized || !isWindowResizable)
return false;

if(isFullscreen_ == fullscreen && newSize == GetWindowSize())
const auto fullscreen = bitset::isSet(displayMode, DisplayMode::Fullscreen);
if(IsFullscreen() == fullscreen && newSize == GetWindowSize())
return true;

ShowWindow(screen, SW_HIDE);

VideoMode windowSize = fullscreen ? FindClosestVideoMode(newSize) : newSize;
// Try to switch full screen first
if(isFullscreen_ && !fullscreen)
if(IsFullscreen() && !fullscreen)
{
if(ChangeDisplaySettings(nullptr, 0) != DISP_CHANGE_SUCCESSFUL)
return false;
} else if(isFullscreen_ || fullscreen)
} else if(IsFullscreen() || fullscreen)
{
if(!MakeFullscreen(windowSize))
return false;
}

// Fensterstyle ggf. ändern
std::pair<DWORD, DWORD> style = GetStyleFlags(isFullscreen_);
std::pair<DWORD, DWORD> style = GetStyleFlags(IsFullscreen());
SetWindowLongPtr(screen, GWL_STYLE, style.first);
SetWindowLongPtr(screen, GWL_EXSTYLE, style.second);

Expand Down Expand Up @@ -253,7 +253,7 @@ RECT VideoWinAPI::CalculateWindowRect(bool fullscreen, VideoMode& size) const
return wRect;
}

bool VideoWinAPI::RegisterAndCreateWindow(const std::string& title, const VideoMode& wndSize, bool fullscreen)
bool VideoWinAPI::RegisterAndCreateWindow(const std::string& title, const VideoMode& wndSize, DisplayMode displayMode)
{
std::wstring wTitle = boost::nowide::widen(title);
windowClassName = wTitle.substr(0, wTitle.find(' '));
Expand All @@ -275,6 +275,7 @@ bool VideoWinAPI::RegisterAndCreateWindow(const std::string& title, const VideoM
return false;

// Create window
const auto fullscreen = bitset::isSet(displayMode, DisplayMode::Fullscreen);
auto adjWindowSize = fullscreen ? FindClosestVideoMode(wndSize) : wndSize;
RECT wRect = CalculateWindowRect(fullscreen, adjWindowSize);

Expand Down Expand Up @@ -405,7 +406,7 @@ void VideoWinAPI::DestroyScreen()

UnregisterClassW(windowClassName.c_str(), GetModuleHandle(nullptr));

isFullscreen_ = false;
displayMode_ = bitset::set(displayMode_, DisplayMode::Fullscreen, false);
}

/**
Expand Down
6 changes: 3 additions & 3 deletions extras/videoDrivers/WinAPI/WinAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ class VideoWinAPI final : public VideoDriver
bool Initialize() override;

/// Erstellt das Fenster mit entsprechenden Werten.
bool CreateScreen(const std::string& title, const VideoMode& newSize, bool fullscreen) override;
bool CreateScreen(const std::string& title, const VideoMode& newSize, DisplayMode displayMode) override;

/// Erstellt oder verändert das Fenster mit entsprechenden Werten.
bool ResizeScreen(const VideoMode& newSize, bool fullscreen) override;
bool ResizeScreen(const VideoMode& newSize, DisplayMode displayMode) override;

/// Schliesst das Fenster.
void DestroyScreen() override;
Expand Down Expand Up @@ -66,7 +66,7 @@ class VideoWinAPI final : public VideoDriver
std::pair<DWORD, DWORD> GetStyleFlags(bool fullscreen) const;
/// Calculate the rect for the window and adjusts the (usable) size if required
RECT CalculateWindowRect(bool fullscreen, VideoMode& size) const;
bool RegisterAndCreateWindow(const std::string& title, const VideoMode& wndSize, bool fullscreen);
bool RegisterAndCreateWindow(const std::string& title, const VideoMode& wndSize, DisplayMode displayMode);
bool InitOGL();
static bool MakeFullscreen(const VideoMode& resolution);

Expand Down
9 changes: 7 additions & 2 deletions libs/driver/include/driver/VideoDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ class VideoDriver : public IVideoDriver

VideoMode GetWindowSize() const override final { return windowSize_; }
Extent GetRenderSize() const override final { return renderSize_; }
bool IsFullscreen() const override final { return isFullscreen_; }
DisplayMode GetDisplayMode() const override final { return displayMode_; }
bool IsFullscreen() const override final { return bitset::isSet(displayMode_, DisplayMode::Fullscreen); }
bool IsResizable() const override final { return bitset::isSet(displayMode_, DisplayMode::Fullscreen); }

/// prüft auf Initialisierung.
bool IsInitialized() const override final { return initialized; }
Expand All @@ -39,11 +41,14 @@ class VideoDriver : public IVideoDriver
VideoMode FindClosestVideoMode(const VideoMode& mode) const;
void SetNewSize(VideoMode windowSize, Extent renderSize);

void SetFullscreenFlag(bool fullscreen) { displayMode_ = fullscreen ? (displayMode_ | DisplayMode::Fullscreen) : (displayMode_ & ~DisplayMode::Fullscreen); }
void SetResizableFlag(bool resizable) { displayMode_ = bitset::set(displayMode_, DisplayMode::Resizable, resizable); }

VideoDriverLoaderInterface* CallBack; /// Das DriverCallback für Rückmeldungen.
bool initialized; /// Initialisierungsstatus.
MouseCoords mouse_xy; /// Status der Maus.
std::array<bool, 512> keyboard; /// Status der Tastatur;
bool isFullscreen_; /// Vollbild an/aus?
DisplayMode displayMode_; /// Fullscreen/resizable?
private:
// cached as possibly used often
VideoMode windowSize_;
Expand Down
90 changes: 88 additions & 2 deletions libs/driver/include/driver/VideoInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,96 @@
#include "Point.h"
#include "VideoMode.h"
#include "exportImport.h"
// #include "s25util/enumUtils.h"
#include <string>
#include <type_traits>
#include <vector>

/// Function type for loading OpenGL methods
using OpenGL_Loader_Proc = void* (*)(const char*);

template<typename Enum>
struct IsBitset : std::false_type
{};

template<typename Enum>
using IsValidBitset =
std::integral_constant<bool, IsBitset<Enum>::value && std::is_unsigned<std::underlying_type_t<Enum>>::value>;

template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
constexpr auto operator~(Enum val) noexcept
{
using T = std::underlying_type_t<Enum>;
return Enum(~static_cast<T>(val));
}

template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
constexpr auto operator&(Enum lhs, Enum rhs) noexcept
{
using T = std::underlying_type_t<Enum>;
return Enum(static_cast<T>(lhs) & static_cast<T>(rhs));
}

template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
constexpr auto operator|(Enum lhs, Enum rhs) noexcept
{
using T = std::underlying_type_t<Enum>;
return Enum(static_cast<T>(lhs) | static_cast<T>(rhs));
}

template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
constexpr auto operator^(Enum lhs, Enum rhs) noexcept
{
using T = std::underlying_type_t<Enum>;
return Enum(static_cast<T>(lhs) ^ static_cast<T>(rhs));
}

template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
constexpr auto operator&=(Enum& lhs, Enum rhs) noexcept
{
lhs = lhs & rhs;
return lhs;
}

template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
constexpr auto operator|=(Enum& lhs, Enum rhs) noexcept
{
lhs = lhs | rhs;
return lhs;
}

template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
constexpr auto operator^=(Enum& lhs, Enum rhs) noexcept
{
lhs = lhs ^ rhs;
return lhs;
}

namespace bitset {
template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
constexpr bool isSet(Enum val, Enum flag)
{
return (val & flag) != Enum(0);
}

template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
[[nodiscard]] constexpr Enum set(Enum val, Enum flag, bool state)
{
return state ? (val | flag) : (val & ~flag);
}
} // namespace bitset

enum class DisplayMode : unsigned
{
None,
Fullscreen = (1 << 0),
Resizable = (1 << 1)
};

template<>
struct IsBitset<DisplayMode> : std::true_type
{};

class BOOST_SYMBOL_VISIBLE IVideoDriver
{
public:
Expand All @@ -25,9 +109,9 @@ class BOOST_SYMBOL_VISIBLE IVideoDriver
virtual bool Initialize() = 0;

/// Erstellt das Fenster mit entsprechenden Werten.
virtual bool CreateScreen(const std::string& title, const VideoMode& newSize, bool fullscreen) = 0;
virtual bool CreateScreen(const std::string& title, const VideoMode& newSize, DisplayMode displayMode) = 0;

virtual bool ResizeScreen(const VideoMode& newSize, bool fullscreen) = 0;
virtual bool ResizeScreen(const VideoMode& newSize, DisplayMode displayMode) = 0;

/// Schliesst das Fenster.
virtual void DestroyScreen() = 0;
Expand Down Expand Up @@ -61,7 +145,9 @@ class BOOST_SYMBOL_VISIBLE IVideoDriver
virtual VideoMode GetWindowSize() const = 0;
/// Get the size of the render region in pixels
virtual Extent GetRenderSize() const = 0;
virtual DisplayMode GetDisplayMode() const = 0;
virtual bool IsFullscreen() const = 0;
virtual bool IsResizable() const = 0;

/// Get state of the modifier keys
virtual KeyEvent GetModKeyState() const = 0;
Expand Down
2 changes: 1 addition & 1 deletion libs/driver/src/VideoDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ IVideoDriver::~IVideoDriver() = default;
* @param[in] CallBack DriverCallback für Rückmeldungen.
*/
VideoDriver::VideoDriver(VideoDriverLoaderInterface* CallBack)
: CallBack(CallBack), initialized(false), isFullscreen_(false), renderSize_(0, 0)
: CallBack(CallBack), initialized(false), displayMode_(DisplayMode::Resizable), renderSize_(0, 0)
{
std::fill(keyboard.begin(), keyboard.end(), false);
}
Expand Down
Loading

0 comments on commit 9cd0008

Please sign in to comment.