Fix null pointer dereference when creating fullscreen window

Regression introduced in 7556d1b
This commit is contained in:
Chris Thrasher 2024-07-08 10:12:20 -06:00
parent dc8b6dbbfa
commit 5873a7a157
5 changed files with 37 additions and 102 deletions

View File

@ -491,19 +491,6 @@ protected:
private: private:
friend class Window; friend class Window;
////////////////////////////////////////////////////////////
/// \brief Create (or recreate) the window
///
/// Implementation detail for sharing underlying implementation
/// with sf::Window
///
/// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window)
/// \param style %Window style, a bitwise OR combination of sf::Style enumerators
/// \param state %Window state
///
////////////////////////////////////////////////////////////
void create(VideoMode mode, std::uint32_t& style, State& state);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Processes an event before it is sent to the user /// \brief Processes an event before it is sent to the user
/// ///

View File

@ -84,9 +84,6 @@ void Window::create(VideoMode mode, const String& title, std::uint32_t style, St
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Window::create(VideoMode mode, const String& title, std::uint32_t style, State state, const ContextSettings& settings) void Window::create(VideoMode mode, const String& title, std::uint32_t style, State state, const ContextSettings& settings)
{ {
// Delegate to base class for creation logic
WindowBase::create(mode, style, state);
// Recreate the window implementation // Recreate the window implementation
m_impl = priv::WindowImpl::create(mode, title, style, state, settings); m_impl = priv::WindowImpl::create(mode, title, style, state, settings);
@ -108,9 +105,6 @@ void Window::create(WindowHandle handle)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Window::create(WindowHandle handle, const ContextSettings& settings) void Window::create(WindowHandle handle, const ContextSettings& settings)
{ {
// Destroy the previous window implementation
close();
// Recreate the window implementation // Recreate the window implementation
WindowBase::create(handle); WindowBase::create(handle);

View File

@ -35,12 +35,8 @@
#include <SFML/Window/WindowHandle.hpp> #include <SFML/Window/WindowHandle.hpp>
#include <SFML/Window/WindowImpl.hpp> #include <SFML/Window/WindowImpl.hpp>
#include <SFML/System/Err.hpp>
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
#include <ostream>
#include <vector>
#include <cassert> #include <cassert>
#include <cstdlib> #include <cstdlib>
@ -88,8 +84,6 @@ WindowBase& WindowBase::operator=(WindowBase&&) noexcept = default;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowBase::create(VideoMode mode, const String& title, std::uint32_t style, State state) void WindowBase::create(VideoMode mode, const String& title, std::uint32_t style, State state)
{ {
WindowBase::create(mode, style, state);
// Recreate the window implementation // Recreate the window implementation
m_impl = priv::WindowImpl::create(mode, m_impl = priv::WindowImpl::create(mode,
title, title,
@ -111,9 +105,6 @@ void WindowBase::create(VideoMode mode, const String& title, std::uint32_t style
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowBase::create(WindowHandle handle) void WindowBase::create(WindowHandle handle)
{ {
// Destroy the previous window implementation
close();
// Recreate the window implementation // Recreate the window implementation
m_impl = priv::WindowImpl::create(handle); m_impl = priv::WindowImpl::create(handle);
@ -366,51 +357,6 @@ void WindowBase::onResize()
} }
////////////////////////////////////////////////////////////
void WindowBase::create(VideoMode mode, std::uint32_t& style, State& state)
{
// Destroy the previous window implementation
close();
// Fullscreen style requires some tests
if (state == State::Fullscreen)
{
// Make sure there's not already a fullscreen window (only one is allowed)
if (m_impl->getFullscreenWindow())
{
err() << "Creating two fullscreen windows is not allowed, switching to windowed mode" << std::endl;
state = State::Windowed;
}
else
{
// Make sure that the chosen video mode is compatible
if (!mode.isValid())
{
err() << "The requested video mode is not available, switching to a valid mode" << std::endl;
assert(!VideoMode::getFullscreenModes().empty() && "No video modes available");
mode = VideoMode::getFullscreenModes()[0];
err() << " VideoMode: { size: { " << mode.size.x << ", " << mode.size.y
<< " }, bitsPerPixel: " << mode.bitsPerPixel << " }" << std::endl;
}
// Update the fullscreen window
m_impl->setFullscreenWindow();
}
}
// Check validity of style according to the underlying platform
#if defined(SFML_SYSTEM_IOS) || defined(SFML_SYSTEM_ANDROID)
if (state == State::Fullscreen)
style &= ~static_cast<std::uint32_t>(Style::Titlebar);
else
style |= Style::Titlebar;
#else
if ((style & Style::Close) || (style & Style::Resize))
style |= Style::Titlebar;
#endif
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowBase::filterEvent(const Event& event) void WindowBase::filterEvent(const Event& event)
{ {

View File

@ -31,12 +31,14 @@
#include <SFML/Window/SensorManager.hpp> #include <SFML/Window/SensorManager.hpp>
#include <SFML/Window/WindowImpl.hpp> #include <SFML/Window/WindowImpl.hpp>
#include <SFML/System/Err.hpp>
#include <SFML/System/Sleep.hpp> #include <SFML/System/Sleep.hpp>
#include <SFML/System/Time.hpp> #include <SFML/System/Time.hpp>
#include <array> #include <array>
#include <chrono> #include <chrono>
#include <memory> #include <memory>
#include <ostream>
#include <cmath> #include <cmath>
@ -118,7 +120,41 @@ std::unique_ptr<WindowImpl> WindowImpl::create(
State state, State state,
const ContextSettings& settings) const ContextSettings& settings)
{ {
return std::make_unique<WindowImplType>(mode, title, style, state, settings); // Fullscreen style requires some tests
if (state == State::Fullscreen)
{
// Make sure there's not already a fullscreen window (only one is allowed)
if (WindowImplImpl::fullscreenWindow != nullptr)
{
err() << "Creating two fullscreen windows is not allowed, switching to windowed mode" << std::endl;
state = State::Windowed;
}
// Make sure that the chosen video mode is compatible
else if (!mode.isValid())
{
err() << "The requested video mode is not available, switching to a valid mode" << std::endl;
assert(!VideoMode::getFullscreenModes().empty() && "No video modes available");
mode = VideoMode::getFullscreenModes()[0];
err() << " VideoMode: { size: { " << mode.size.x << ", " << mode.size.y
<< " }, bitsPerPixel: " << mode.bitsPerPixel << " }" << std::endl;
}
}
// Check validity of style according to the underlying platform
#if defined(SFML_SYSTEM_IOS) || defined(SFML_SYSTEM_ANDROID)
if (state == State::Fullscreen)
style &= ~static_cast<std::uint32_t>(Style::Titlebar);
else
style |= Style::Titlebar;
#else
if ((style & Style::Close) || (style & Style::Resize))
style |= Style::Titlebar;
#endif
auto windowImpl = std::make_unique<WindowImplType>(mode, title, style, state, settings);
if (state == State::Fullscreen)
WindowImplImpl::fullscreenWindow = windowImpl.get();
return windowImpl;
} }
@ -362,18 +398,4 @@ bool WindowImpl::createVulkanSurface([[maybe_unused]] const VkInstance&
#endif #endif
} }
////////////////////////////////////////////////////////////
const WindowImpl* WindowImpl::getFullscreenWindow() const
{
return WindowImplImpl::fullscreenWindow;
}
////////////////////////////////////////////////////////////
void WindowImpl::setFullscreenWindow() const
{
WindowImplImpl::fullscreenWindow = this;
}
} // namespace sf::priv } // namespace sf::priv

View File

@ -305,20 +305,6 @@ public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool createVulkanSurface(const VkInstance& instance, VkSurfaceKHR& surface, const VkAllocationCallbacks* allocator) const; bool createVulkanSurface(const VkInstance& instance, VkSurfaceKHR& surface, const VkAllocationCallbacks* allocator) const;
////////////////////////////////////////////////////////////
/// \brief Get the fullscreen window
///
/// \return The fullscreen window or a null pointer if there is none
///
////////////////////////////////////////////////////////////
[[nodiscard]] const WindowImpl* getFullscreenWindow() const;
////////////////////////////////////////////////////////////
/// \brief Set a window as the fullscreen window
///
////////////////////////////////////////////////////////////
void setFullscreenWindow() const;
protected: protected:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Default constructor /// \brief Default constructor