From 02567eb225c430df3d5432e7f0b1f930417ce136 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sat, 5 Dec 2020 17:24:24 +0100 Subject: [PATCH 01/13] source/Platform/PlatformDisplay.h: Adding setDecoration() --- source/Platform/PlatformDisplay.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/Platform/PlatformDisplay.h b/source/Platform/PlatformDisplay.h index 2147230..ea97578 100644 --- a/source/Platform/PlatformDisplay.h +++ b/source/Platform/PlatformDisplay.h @@ -39,6 +39,8 @@ public : virtual void setVisible(bool visible) = 0; + virtual void setDecoration(unsigned decoration) = 0; + virtual void minimize() = 0; virtual void maximize() = 0; From ebe3a648c56f1f50ba9bebbcd7e26a85f40ce43c Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sat, 5 Dec 2020 17:25:15 +0100 Subject: [PATCH 02/13] Platform/Win32/Win32Display: Implement setDecoration() --- source/Platform/Win32/Win32Display.cpp | 5 +++++ source/Platform/Win32/Win32Display.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/source/Platform/Win32/Win32Display.cpp b/source/Platform/Win32/Win32Display.cpp index de68f77..c38004c 100644 --- a/source/Platform/Win32/Win32Display.cpp +++ b/source/Platform/Win32/Win32Display.cpp @@ -123,6 +123,11 @@ void Win32Display::setVisible(bool visible) ::ShowWindow(m_handle, visible ? SW_SHOW : SW_HIDE); } +void Win32Display::setDecoration(unsigned decoration) +{ + ::SetWindowLong(m_handle, GWL_STYLE, getWin32Flags(decoration)); +} + void Win32Display::minimize() { ::ShowWindow(m_handle, SW_MINIMIZE); diff --git a/source/Platform/Win32/Win32Display.h b/source/Platform/Win32/Win32Display.h index 80c7cc3..ccdaecc 100644 --- a/source/Platform/Win32/Win32Display.h +++ b/source/Platform/Win32/Win32Display.h @@ -33,6 +33,8 @@ public : virtual void setVisible(bool visible); + virtual void setDecoration(unsigned decoration); + virtual void minimize(); virtual void maximize(); From ca5e2a399c80a52258114c8d40c769215094b56f Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sat, 5 Dec 2020 18:19:07 +0100 Subject: [PATCH 03/13] Platform/PlatformDisplay: adding enterFullscreen() and exitFullscreen() --- source/Platform/PlatformDisplay.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/Platform/PlatformDisplay.h b/source/Platform/PlatformDisplay.h index ea97578..3fff71f 100644 --- a/source/Platform/PlatformDisplay.h +++ b/source/Platform/PlatformDisplay.h @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -45,6 +46,10 @@ public : virtual void maximize() = 0; + virtual void enterFullscreen(DisplayMode mode) = 0; + + virtual void exitFullscreen() = 0; + virtual void setCaption(const std::string& caption) = 0; virtual void setIcon(unsigned int width, unsigned int height, const uint8_t *pixels) = 0; From 304e345a79e117477fa13117156a889795eeadc9 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sat, 5 Dec 2020 18:19:52 +0100 Subject: [PATCH 04/13] Platform/Win32/Win32Display: Implementing true fullscreen with enterFullscreen() and exitFullscreen() --- source/Platform/Win32/Win32Display.cpp | 88 +++++++++++++++++++++++++- source/Platform/Win32/Win32Display.h | 7 ++ 2 files changed, 92 insertions(+), 3 deletions(-) diff --git a/source/Platform/Win32/Win32Display.cpp b/source/Platform/Win32/Win32Display.cpp index c38004c..18e50e6 100644 --- a/source/Platform/Win32/Win32Display.cpp +++ b/source/Platform/Win32/Win32Display.cpp @@ -36,7 +36,7 @@ Win32Display::~Win32Display() bool Win32Display::create(DisplayDescription description) { - DWORD flags = getWin32Flags(description.decoration); + DWORD flags; Vector2i pos; if (firstTime) { @@ -44,7 +44,18 @@ bool Win32Display::create(DisplayDescription description) firstTime = false; } - pos = centerWindow(description.mode.width, description.mode.height); + if (description.decoration & DisplayDecorate::Fullscreen) { + m_fs_mode = description.mode; + } + + if (m_fs_mode.empty() == false) { + // Only set these flags for fullscreen (borderless) + flags = WS_VISIBLE | WS_POPUP; + } else { + // Set window to center and set decorator flags for windowed displays. + pos = centerWindow(description.mode.width, description.mode.height); + flags = getWin32Flags(description.decoration); + } // Create window. m_handle = CreateWindowExA(0, WND_CLASSNAME, "", flags, @@ -56,7 +67,11 @@ bool Win32Display::create(DisplayDescription description) return false; } - setSize(description.mode.width, description.mode.height); + if (m_fs_mode.empty() == false) { + enterFullscreen(m_fs_mode); + } else { + setSize(description.mode.width, description.mode.height); + } // Store the size for use later. m_size = getSize(); @@ -277,6 +292,60 @@ Vector2i Win32Display::centerWindow(int width, int height) return v; } +void Win32Display::enterFullscreen(DisplayMode mode) +{ + LONG rc; + ::DEVMODEW dev; + dev.dmSize = sizeof(dev); + dev.dmPelsWidth = mode.width; + dev.dmPelsHeight = mode.height; + dev.dmBitsPerPel = mode.bpp; + dev.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; + + rc = ::ChangeDisplaySettingsW(&dev, CDS_FULLSCREEN); + if (rc != DISP_CHANGE_SUCCESSFUL) { + const char *msg; + + switch(rc) { + case DISP_CHANGE_BADDUALVIEW : + msg = "The system is DualView capable"; break; + case DISP_CHANGE_BADFLAGS : + msg = "Invalid flags given"; break; + case DISP_CHANGE_BADPARAM : + msg = "Invalid parameter"; break; + case DISP_CHANGE_BADMODE : + msg = "Resolution not supported"; break; + case DISP_CHANGE_FAILED : + msg = "Display driver failed to set mode"; break; + case DISP_CHANGE_NOTUPDATED : + msg = "Unable to write settings to the registry"; break; + case DISP_CHANGE_RESTART : + msg = "System restart required"; break; + default : + msg = "Unkown error"; + } + + sp::Log::error("Win32: Failed to switch to fullscreen mode: %s.", msg); + return; + } + + ::SetWindowLong(m_handle, GWL_STYLE, WS_VISIBLE | WS_POPUP); + ::SetWindowPos(m_handle, HWND_TOP, 0, 0, mode.width, mode.height, SWP_FRAMECHANGED | SWP_SHOWWINDOW); + + grabCursor(true); + + m_fs_mode = mode; +} + +void Win32Display::exitFullscreen() +{ + if (!m_fs_mode.empty()) { + // Restore to previous mode. + ::ChangeDisplaySettingsW(NULL, 0); + m_fs_mode = DisplayMode(); + } +} + void Win32Display::processResizeMessage(const Vector2u& new_size) { // Check if the size has actually changed. @@ -301,9 +370,22 @@ void Win32Display::processMessage(UINT message, WPARAM wParam, LPARAM lParam) break; case WM_SETFOCUS : Log::debug("WM_SETFOCUS"); + if (m_fs_mode.empty() == false) { + enterFullscreen(m_fs_mode); + } break; case WM_KILLFOCUS : Log::debug("WM_KILLFOCUS"); + // If in fullscreen mode. + if (m_fs_mode.empty() == false) { + // Switch to window mode. + ::ChangeDisplaySettingsW(NULL, 0); + + // also minimize the window to get it out of the way. + minimize(); + } + + grabCursor(false); break; case WM_SIZE : diff --git a/source/Platform/Win32/Win32Display.h b/source/Platform/Win32/Win32Display.h index ccdaecc..510c275 100644 --- a/source/Platform/Win32/Win32Display.h +++ b/source/Platform/Win32/Win32Display.h @@ -35,6 +35,10 @@ public : virtual void setDecoration(unsigned decoration); + virtual void enterFullscreen(DisplayMode mode); + + virtual void exitFullscreen(); + virtual void minimize(); virtual void maximize(); @@ -76,6 +80,9 @@ protected : Vector2u m_size; Vector2u m_minSize; + + // Fullscreen mode. + DisplayMode m_fs_mode; }; } // namespace sp From ea91d50a84b374314e8ae7c0392d6b96b5fa7e8d Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sat, 5 Dec 2020 18:20:20 +0100 Subject: [PATCH 05/13] source/Graphics/OpenGL.cpp: minor fix. no need to set window decoration (default is fine) --- source/Graphics/OpenGL.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/Graphics/OpenGL.cpp b/source/Graphics/OpenGL.cpp index ef7383d..da752dd 100644 --- a/source/Graphics/OpenGL.cpp +++ b/source/Graphics/OpenGL.cpp @@ -24,8 +24,6 @@ bool Graphics::init() DisplayMode mode(m_width, m_height); DisplayDescription desc(mode); - desc.decoration = DisplayDecorate::Menu | DisplayDecorate::Close | DisplayDecorate::Resize; - if (!m_display->create(desc)) { return false; } From 74a2ff028c1c9687a08ff8b672ff48f27aa5cda9 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sat, 5 Dec 2020 18:21:34 +0100 Subject: [PATCH 06/13] source/Display/Display.cpp: Use the new display api that does not require recreating the display. --- source/Display/Display.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/source/Display/Display.cpp b/source/Display/Display.cpp index 24ced50..0691360 100644 --- a/source/Display/Display.cpp +++ b/source/Display/Display.cpp @@ -98,28 +98,29 @@ void Display::setSize(unsigned int width, unsigned int height) void Display::setVideoMode(Mode mode) { - DisplayDescription desc; - if (m_fmode == mode) { return; } - if (mode == FULLSCREEN || mode == WINDOWEDFULLSCREEN) { - - // True fullscreen - if (mode == FULLSCREEN) { - desc.mode = m_description.mode; - } else { - desc.mode = DisplayMode::getDesktopMode(); - m_cacheDesc = m_description; - } - - desc.decoration = DisplayDecorate::None; - } else { - desc = m_cacheDesc; + if (mode != FULLSCREEN) { + m_impl->exitFullscreen(); } - create(desc); + // True fullscreen + if (mode == FULLSCREEN) { + m_impl->enterFullscreen(m_description.mode); + } + // Windowed fullscreen. + else if (mode == WINDOWEDFULLSCREEN) { + DisplayMode desktop = DisplayMode::getDesktopMode(); + m_impl->setDecoration(DisplayDecorate::None); + m_impl->setSize(desktop.width, desktop.height); + } + // Window mode. + else { + // Set stored decoration. + m_impl->setDecoration(m_description.decoration); + } m_fmode = mode; } From d34d20361dee647c8ee10e894e2483949967bff3 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 5 Nov 2020 10:09:27 +0100 Subject: [PATCH 07/13] include/Spectre/Display/DisplayDescription.h: adding Fullscreen flag. --- include/Spectre/Display/DisplayDescription.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/Spectre/Display/DisplayDescription.h b/include/Spectre/Display/DisplayDescription.h index 0d6539b..ee1b468 100644 --- a/include/Spectre/Display/DisplayDescription.h +++ b/include/Spectre/Display/DisplayDescription.h @@ -13,6 +13,7 @@ namespace DisplayDecorate { Menu = 1 << 0, Resize = 1 << 1, Close = 1 << 2, + Fullscreen = 1 << 3, Default = Menu | Resize | Close, }; }; From d12d60b1ba7bf990a37646f171b73ab744dc3bae Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 12 Sep 2022 22:24:19 +0200 Subject: [PATCH 08/13] Display/Display: Cache position when entering fullscreen and restore when entering window mode again. --- include/Spectre/Display/Display.h | 5 +++++ source/Display/Display.cpp | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/include/Spectre/Display/Display.h b/include/Spectre/Display/Display.h index 0985945..073fd0d 100644 --- a/include/Spectre/Display/Display.h +++ b/include/Spectre/Display/Display.h @@ -4,6 +4,7 @@ #include "DisplayMode.h" #include "DisplayDescription.h" +#include #include #include #include @@ -71,6 +72,10 @@ protected : protected : enum Mode m_fmode; + // Cache window position when entering fullscreen + // So it can be restored when returning to window mode. + Vector2u m_cachePos; + DisplayDescription m_description; DisplayDescription m_cacheDesc; diff --git a/source/Display/Display.cpp b/source/Display/Display.cpp index 0691360..ac28096 100644 --- a/source/Display/Display.cpp +++ b/source/Display/Display.cpp @@ -106,6 +106,11 @@ void Display::setVideoMode(Mode mode) m_impl->exitFullscreen(); } + // Cache window position when entering fullscreen. + if (mode == FULLSCREEN || mode == WINDOWEDFULLSCREEN) { + m_cachePos = m_impl->getPosition(); + } + // True fullscreen if (mode == FULLSCREEN) { m_impl->enterFullscreen(m_description.mode); @@ -120,6 +125,9 @@ void Display::setVideoMode(Mode mode) else { // Set stored decoration. m_impl->setDecoration(m_description.decoration); + + // Restore position. + m_impl->setPosition(m_cachePos.x, m_cachePos.y); } m_fmode = mode; From fc38bb59a905cc297cce76c3080b2bcf68c73021 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 12 Sep 2022 22:25:15 +0200 Subject: [PATCH 09/13] source/Display/Display.cpp: restore size when entering window mode. --- source/Display/Display.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/Display/Display.cpp b/source/Display/Display.cpp index ac28096..08529f3 100644 --- a/source/Display/Display.cpp +++ b/source/Display/Display.cpp @@ -126,7 +126,8 @@ void Display::setVideoMode(Mode mode) // Set stored decoration. m_impl->setDecoration(m_description.decoration); - // Restore position. + // Restore size and position. + m_impl->setSize(m_description.mode.width, m_description.mode.height); m_impl->setPosition(m_cachePos.x, m_cachePos.y); } From 3c6a842c9d7c76f3c74f5365dc7b6ecadb13e7db Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 12 Sep 2022 22:27:08 +0200 Subject: [PATCH 10/13] Platform/Win32/Win32Display.cpp: remove fullscreen stuff in create() --- source/Platform/Win32/Win32Display.cpp | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/source/Platform/Win32/Win32Display.cpp b/source/Platform/Win32/Win32Display.cpp index 18e50e6..8ecc4a9 100644 --- a/source/Platform/Win32/Win32Display.cpp +++ b/source/Platform/Win32/Win32Display.cpp @@ -44,18 +44,9 @@ bool Win32Display::create(DisplayDescription description) firstTime = false; } - if (description.decoration & DisplayDecorate::Fullscreen) { - m_fs_mode = description.mode; - } - - if (m_fs_mode.empty() == false) { - // Only set these flags for fullscreen (borderless) - flags = WS_VISIBLE | WS_POPUP; - } else { - // Set window to center and set decorator flags for windowed displays. - pos = centerWindow(description.mode.width, description.mode.height); - flags = getWin32Flags(description.decoration); - } + // Set window to center and set decoration flags. + pos = centerWindow(description.mode.width, description.mode.height); + flags = getWin32Flags(description.decoration); // Create window. m_handle = CreateWindowExA(0, WND_CLASSNAME, "", flags, @@ -67,11 +58,7 @@ bool Win32Display::create(DisplayDescription description) return false; } - if (m_fs_mode.empty() == false) { - enterFullscreen(m_fs_mode); - } else { - setSize(description.mode.width, description.mode.height); - } + setSize(description.mode.width, description.mode.height); // Store the size for use later. m_size = getSize(); From 4761473e86ebb14751e6adcb588f77f6f9478b3a Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 12 Sep 2022 22:45:54 +0200 Subject: [PATCH 11/13] include/Spectre/Display/DisplayDescription.h: remove fullscreen here as it is not a decorator flag. --- include/Spectre/Display/DisplayDescription.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/Spectre/Display/DisplayDescription.h b/include/Spectre/Display/DisplayDescription.h index ee1b468..0d6539b 100644 --- a/include/Spectre/Display/DisplayDescription.h +++ b/include/Spectre/Display/DisplayDescription.h @@ -13,7 +13,6 @@ namespace DisplayDecorate { Menu = 1 << 0, Resize = 1 << 1, Close = 1 << 2, - Fullscreen = 1 << 3, Default = Menu | Resize | Close, }; }; From 1c27fce58c98fb269e20b7788742de624e6761a4 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 13 Sep 2022 19:35:46 +0200 Subject: [PATCH 12/13] examples/display/DisplayExample.cpp: make "W" key switch to windowed fullscreen. --- examples/display/DisplayExample.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/examples/display/DisplayExample.cpp b/examples/display/DisplayExample.cpp index 2cbe330..8a430ae 100644 --- a/examples/display/DisplayExample.cpp +++ b/examples/display/DisplayExample.cpp @@ -24,7 +24,19 @@ void DisplayExample::onEvent(const sp::Event& event) { if (event.type == sp::Event::Key && event.key.pressed == false) { - if (event.key.code == sp::Keyboard::Space) { + if (event.key.code == sp::Keyboard::W) { + + if (m_mode == sp::Display::WINDOWED) { + m_mode = sp::Display::WINDOWEDFULLSCREEN; + sp::Log::info("Windowed Fullscreen"); + } else { + m_mode = sp::Display::WINDOWED; + sp::Log::info("Windowed"); + } + + getGraphics()->setDisplayMode(m_mode); + + } else if (event.key.code == sp::Keyboard::Space) { if (m_mode == sp::Display::WINDOWED) { m_mode = sp::Display::FULLSCREEN; From deb9918b9bb847ac4b055ac7ffbb811987581afa Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 13 Sep 2022 19:52:34 +0200 Subject: [PATCH 13/13] source/Display/Display.cpp: Need to set position to 0,0 in window fullscreen, otherwise it wont stick to the top-left of the monitor. --- source/Display/Display.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source/Display/Display.cpp b/source/Display/Display.cpp index 08529f3..b7a3135 100644 --- a/source/Display/Display.cpp +++ b/source/Display/Display.cpp @@ -120,6 +120,7 @@ void Display::setVideoMode(Mode mode) DisplayMode desktop = DisplayMode::getDesktopMode(); m_impl->setDecoration(DisplayDecorate::None); m_impl->setSize(desktop.width, desktop.height); + m_impl->setPosition(0, 0); } // Window mode. else {