4655: Add windowed fullscreen ( a special case for Windows ) r=def- a=Jupeyy

fixes #4597

## Checklist

- [x] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test if it works standalone, system.c especially
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: Jupeyy <jupjopjap@gmail.com>
This commit is contained in:
bors[bot] 2022-02-05 21:53:39 +00:00 committed by GitHub
commit 7ef077cfea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 70 additions and 34 deletions

View file

@ -137,7 +137,7 @@ public:
// gfx
virtual void SwitchWindowScreen(int Index) = 0;
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless) = 0;
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing) = 0;
virtual void ToggleWindowVSync() = 0;
virtual void LoadFont() = 0;
virtual void Notify(const char *pTitle, const char *pMessage) = 0;

View file

@ -668,7 +668,7 @@ void CGraphicsBackend_SDL_OpenGL::GetVideoModes(CVideoMode *pModes, int MaxModes
// Only collect fullscreen modes when requested, that makes sure in windowed mode no refresh rates are shown that aren't supported without
// fullscreen anyway(except fullscreen desktop)
bool IsFullscreenDestkop = m_pWindow != NULL && ((SDL_GetWindowFlags(m_pWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP);
bool IsFullscreenDestkop = m_pWindow != NULL && (((SDL_GetWindowFlags(m_pWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) || g_Config.m_GfxFullscreen == 3);
bool CollectFullscreenModes = m_pWindow == NULL || ((SDL_GetWindowFlags(m_pWindow) & SDL_WINDOW_FULLSCREEN) != 0 && !IsFullscreenDestkop);
if(SDL_GetDesktopDisplayMode(Screen, &DesktopMode) < 0)
@ -863,7 +863,7 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *pScreen, int *pWid
else if(Flags & (IGraphicsBackend::INITFLAG_DESKTOP_FULLSCREEN))
SdlFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
bool IsFullscreen = (SdlFlags & SDL_WINDOW_FULLSCREEN) != 0;
bool IsFullscreen = (SdlFlags & SDL_WINDOW_FULLSCREEN) != 0 || g_Config.m_GfxFullscreen == 3;
// use desktop resolution as default resolution, clamp resolution if users's display is smaller than we remembered
// if the user starts in fullscreen, and the resolution was not found use the desktop one
if((IsFullscreen && !SupportedResolution) || *pWidth == 0 || *pHeight == 0 || (IsDesktopChanged && (*pWidth > *pDesktopWidth || *pHeight > *pDesktopHeight)))
@ -1105,10 +1105,15 @@ void CGraphicsBackend_SDL_OpenGL::Maximize()
// TODO: SDL
}
void CGraphicsBackend_SDL_OpenGL::SetWindowParams(int FullscreenMode, bool IsBorderless)
void CGraphicsBackend_SDL_OpenGL::SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing)
{
if(FullscreenMode > 0)
{
bool IsDesktopFullscreen = FullscreenMode == 2;
#ifndef CONF_FAMILY_WINDOWS
// special mode for windows only
IsDesktopFullscreen |= FullscreenMode == 3;
#endif
if(FullscreenMode == 1)
{
#if defined(CONF_PLATFORM_MACOS) || defined(CONF_PLATFORM_HAIKU)
@ -1117,16 +1122,35 @@ void CGraphicsBackend_SDL_OpenGL::SetWindowParams(int FullscreenMode, bool IsBor
#else
SDL_SetWindowFullscreen(m_pWindow, SDL_WINDOW_FULLSCREEN);
#endif
SDL_SetWindowResizable(m_pWindow, SDL_TRUE);
}
else if(FullscreenMode == 2)
else if(IsDesktopFullscreen)
{
SDL_SetWindowFullscreen(m_pWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
SDL_SetWindowResizable(m_pWindow, SDL_TRUE);
}
else
{
SDL_SetWindowFullscreen(m_pWindow, 0);
SDL_SetWindowBordered(m_pWindow, SDL_TRUE);
SDL_SetWindowResizable(m_pWindow, SDL_FALSE);
SDL_DisplayMode DPMode;
if(SDL_GetDesktopDisplayMode(g_Config.m_GfxScreen, &DPMode) < 0)
{
dbg_msg("gfx", "unable to get display mode: %s", SDL_GetError());
}
else
{
ResizeWindow(DPMode.w, DPMode.h, DPMode.refresh_rate);
SDL_SetWindowPosition(m_pWindow, SDL_WINDOWPOS_CENTERED_DISPLAY(g_Config.m_GfxScreen), SDL_WINDOWPOS_CENTERED_DISPLAY(g_Config.m_GfxScreen));
}
}
}
else
{
SDL_SetWindowFullscreen(m_pWindow, 0);
SDL_SetWindowBordered(m_pWindow, SDL_bool(!IsBorderless));
SDL_SetWindowResizable(m_pWindow, SDL_TRUE);
}
}
@ -1196,7 +1220,7 @@ bool CGraphicsBackend_SDL_OpenGL::ResizeWindow(int w, int h, int RefreshRate)
{
#ifdef CONF_FAMILY_WINDOWS
// in windows make the window windowed mode first, this prevents strange window glitches (other games probably do something similar)
SetWindowParams(0, 1);
SetWindowParams(0, 1, true);
#endif
SDL_DisplayMode SetMode = {};
SDL_DisplayMode ClosestMode = {};
@ -1208,7 +1232,7 @@ bool CGraphicsBackend_SDL_OpenGL::ResizeWindow(int w, int h, int RefreshRate)
#ifdef CONF_FAMILY_WINDOWS
// now change it back to fullscreen, this will restore the above set state, bcs SDL saves fullscreen modes appart from other video modes (as of SDL 2.0.16)
// see implementation of SDL_SetWindowDisplayMode
SetWindowParams(1, 0);
SetWindowParams(1, 0, true);
#endif
return true;
}

View file

@ -253,7 +253,7 @@ public:
virtual void Minimize();
virtual void Maximize();
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless);
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing);
virtual bool SetWindowScreen(int Index);
virtual bool UpdateDisplayMode(int Index);
virtual int GetWindowScreen();

View file

@ -3950,10 +3950,10 @@ void CClient::SwitchWindowScreen(int Index)
// Todo SDL: remove this when fixed (changing screen when in fullscreen is bugged)
if(g_Config.m_GfxFullscreen)
{
SetWindowParams(0, g_Config.m_GfxBorderless);
SetWindowParams(0, g_Config.m_GfxBorderless, g_Config.m_GfxFullscreen != 3);
if(Graphics()->SetWindowScreen(Index))
g_Config.m_GfxScreen = Index;
SetWindowParams(g_Config.m_GfxFullscreen, g_Config.m_GfxBorderless);
SetWindowParams(g_Config.m_GfxFullscreen, g_Config.m_GfxBorderless, g_Config.m_GfxFullscreen != 3);
}
else
{
@ -3974,11 +3974,11 @@ void CClient::ConchainWindowScreen(IConsole::IResult *pResult, void *pUserData,
pfnCallback(pResult, pCallbackUserData);
}
void CClient::SetWindowParams(int FullscreenMode, bool IsBorderless)
void CClient::SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing)
{
g_Config.m_GfxFullscreen = clamp(FullscreenMode, 0, 2);
g_Config.m_GfxFullscreen = clamp(FullscreenMode, 0, 3);
g_Config.m_GfxBorderless = (int)IsBorderless;
Graphics()->SetWindowParams(FullscreenMode, IsBorderless);
Graphics()->SetWindowParams(FullscreenMode, IsBorderless, AllowResizing);
}
void CClient::ConchainFullscreen(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
@ -3987,7 +3987,7 @@ void CClient::ConchainFullscreen(IConsole::IResult *pResult, void *pUserData, IC
if(pSelf->Graphics() && pResult->NumArguments())
{
if(g_Config.m_GfxFullscreen != pResult->GetInteger(0))
pSelf->SetWindowParams(pResult->GetInteger(0), g_Config.m_GfxBorderless);
pSelf->SetWindowParams(pResult->GetInteger(0), g_Config.m_GfxBorderless, pResult->GetInteger(0) != 3);
}
else
pfnCallback(pResult, pCallbackUserData);
@ -3999,7 +3999,7 @@ void CClient::ConchainWindowBordered(IConsole::IResult *pResult, void *pUserData
if(pSelf->Graphics() && pResult->NumArguments())
{
if(!g_Config.m_GfxFullscreen && (g_Config.m_GfxBorderless != pResult->GetInteger(0)))
pSelf->SetWindowParams(g_Config.m_GfxFullscreen, !g_Config.m_GfxBorderless);
pSelf->SetWindowParams(g_Config.m_GfxFullscreen, !g_Config.m_GfxBorderless, g_Config.m_GfxFullscreen != 3);
}
else
pfnCallback(pResult, pCallbackUserData);

View file

@ -487,7 +487,7 @@ public:
// gfx
virtual void SwitchWindowScreen(int Index);
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless);
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing);
virtual void ToggleWindowVSync();
virtual void LoadFont();
virtual void Notify(const char *pTitle, const char *pMessage);

View file

@ -2075,14 +2075,24 @@ void CGraphics_Threaded::IndicesNumRequiredNotify(unsigned int RequiredIndicesCo
int CGraphics_Threaded::IssueInit()
{
int Flags = IGraphicsBackend::INITFLAG_RESIZABLE;
int Flags = 0;
bool IsPurlyWindowed = g_Config.m_GfxFullscreen == 0;
bool IsExclusiveFullscreen = g_Config.m_GfxFullscreen == 1;
bool IsDesktopFullscreen = g_Config.m_GfxFullscreen == 2;
#ifndef CONF_FAMILY_WINDOWS
// special mode for windows only
IsDesktopFullscreen |= g_Config.m_GfxFullscreen == 3;
#endif
if(g_Config.m_GfxBorderless)
Flags |= IGraphicsBackend::INITFLAG_BORDERLESS;
if(g_Config.m_GfxFullscreen == 1)
if(IsExclusiveFullscreen)
Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN;
else if(g_Config.m_GfxFullscreen == 2)
else if(IsDesktopFullscreen)
Flags |= IGraphicsBackend::INITFLAG_DESKTOP_FULLSCREEN;
if(IsPurlyWindowed || IsExclusiveFullscreen || IsDesktopFullscreen)
Flags |= IGraphicsBackend::INITFLAG_RESIZABLE;
if(g_Config.m_GfxVsync)
Flags |= IGraphicsBackend::INITFLAG_VSYNC;
if(g_Config.m_GfxHighdpi)
@ -2310,9 +2320,9 @@ void CGraphics_Threaded::Maximize()
m_pBackend->Maximize();
}
void CGraphics_Threaded::SetWindowParams(int FullscreenMode, bool IsBorderless)
void CGraphics_Threaded::SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing)
{
m_pBackend->SetWindowParams(FullscreenMode, IsBorderless);
m_pBackend->SetWindowParams(FullscreenMode, IsBorderless, AllowResizing);
CVideoMode CurMode;
m_pBackend->GetCurrentVideoMode(CurMode, m_ScreenHiDPIScale, g_Config.m_GfxDesktopWidth, g_Config.m_GfxDesktopHeight, g_Config.m_GfxScreen);
GotResized(CurMode.m_WindowWidth, CurMode.m_WindowHeight, CurMode.m_RefreshRate);

View file

@ -669,7 +669,7 @@ public:
virtual void Minimize() = 0;
virtual void Maximize() = 0;
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless) = 0;
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing) = 0;
virtual bool SetWindowScreen(int Index) = 0;
virtual bool UpdateDisplayMode(int Index) = 0;
virtual int GetWindowScreen() = 0;
@ -1169,7 +1169,7 @@ public:
int GetNumScreens() const override;
void Minimize() override;
void Maximize() override;
void SetWindowParams(int FullscreenMode, bool IsBorderless) override;
void SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing) override;
bool SetWindowScreen(int Index) override;
void Move(int x, int y) override;
void Resize(int w, int h, int RefreshRate) override;

View file

@ -147,7 +147,7 @@ public:
int GetNumScreens() const override { return 0; };
void Minimize() override{};
void Maximize() override{};
void SetWindowParams(int FullscreenMode, bool IsBorderless) override{};
void SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing) override{};
bool SetWindowScreen(int Index) override { return false; };
void Move(int x, int y) override{};
void Resize(int w, int h, int RefreshRate) override{};

View file

@ -209,7 +209,7 @@ public:
int WindowWidth() const { return m_ScreenWidth / m_ScreenHiDPIScale; }
int WindowHeight() const { return m_ScreenHeight / m_ScreenHiDPIScale; }
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless) = 0;
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing) = 0;
virtual bool SetWindowScreen(int Index) = 0;
virtual bool SetVSync(bool State) = 0;
virtual int GetWindowScreen() = 0;

View file

@ -104,10 +104,10 @@ MACRO_CONFIG_INT(GfxDesktopWidth, gfx_desktop_width, 0, 0, 0, CFGFLAG_SAVE | CFG
MACRO_CONFIG_INT(GfxDesktopHeight, gfx_desktop_height, 0, 0, 0, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Desktop resolution height for detecting display changes (not recommended to change manually)")
#if !defined(CONF_PLATFORM_MACOS)
MACRO_CONFIG_INT(GfxBorderless, gfx_borderless, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Borderless window (not to be used with fullscreen)")
MACRO_CONFIG_INT(GfxFullscreen, gfx_fullscreen, 1, 0, 2, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Set fullscreen mode: 0=no fullscreen, 1=pure fullscreen, 2=desktop fullscreen")
MACRO_CONFIG_INT(GfxFullscreen, gfx_fullscreen, 1, 0, 3, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Set fullscreen mode: 0=no fullscreen, 1=pure fullscreen, 2=desktop fullscreen, 3=windowed fullscreen")
#else
MACRO_CONFIG_INT(GfxBorderless, gfx_borderless, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Borderless window (not to be used with fullscreen)")
MACRO_CONFIG_INT(GfxFullscreen, gfx_fullscreen, 0, 0, 2, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Set fullscreen mode: 0=no fullscreen, 1=pure fullscreen, 2=desktop fullscreen")
MACRO_CONFIG_INT(GfxFullscreen, gfx_fullscreen, 0, 0, 3, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Set fullscreen mode: 0=no fullscreen, 1=pure fullscreen, 2=desktop fullscreen, 3=windowed fullscreen")
#endif
MACRO_CONFIG_INT(GfxHighdpi, gfx_highdpi, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Enable high-dpi")
MACRO_CONFIG_INT(GfxColorDepth, gfx_color_depth, 24, 16, 24, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Colors bits for framebuffer (fullscreen only)")

View file

@ -1170,27 +1170,29 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
// switches
static float s_ScrollValueDrop = 0;
static const int s_NumWindowMode = 4;
const char *pWindowModes[] = {Localize("Windowed"), Localize("Windowed borderless"), Localize("Windowed fullscreen"), Localize("Desktop fullscreen"), Localize("Fullscreen")};
static const int s_NumWindowMode = sizeof(pWindowModes) / sizeof(pWindowModes[0]);
static int s_aWindowModeIDs[s_NumWindowMode];
const void *aWindowModeIDs[s_NumWindowMode];
for(int i = 0; i < s_NumWindowMode; ++i)
aWindowModeIDs[i] = &s_aWindowModeIDs[i];
static int s_WindowModeDropDownState = 0;
const char *pWindowModes[] = {Localize("Windowed"), Localize("Windowed borderless"), Localize("Desktop fullscreen"), Localize("Fullscreen")};
OldSelected = (g_Config.m_GfxFullscreen ? (g_Config.m_GfxFullscreen == 1 ? 3 : 2) : (g_Config.m_GfxBorderless ? 1 : 0));
OldSelected = (g_Config.m_GfxFullscreen ? (g_Config.m_GfxFullscreen == 1 ? 4 : (g_Config.m_GfxFullscreen == 2 ? 3 : 2)) : (g_Config.m_GfxBorderless ? 1 : 0));
const int NewWindowMode = RenderDropDown(s_WindowModeDropDownState, &MainView, OldSelected, aWindowModeIDs, pWindowModes, s_NumWindowMode, &s_NumWindowMode, s_ScrollValueDrop);
if(OldSelected != NewWindowMode)
{
if(NewWindowMode == 0)
Client()->SetWindowParams(0, false);
Client()->SetWindowParams(0, false, true);
else if(NewWindowMode == 1)
Client()->SetWindowParams(0, true);
Client()->SetWindowParams(0, true, true);
else if(NewWindowMode == 2)
Client()->SetWindowParams(2, false);
Client()->SetWindowParams(3, false, false);
else if(NewWindowMode == 3)
Client()->SetWindowParams(1, false);
Client()->SetWindowParams(2, false, true);
else if(NewWindowMode == 4)
Client()->SetWindowParams(1, false, true);
}
MainView.HSplitTop(20.0f, &Button, &MainView);