From 27249d42edfa6e5f0854fe56ee9f5b62a104373a Mon Sep 17 00:00:00 2001 From: Chris Thrasher Date: Sun, 30 Apr 2023 18:00:04 -0600 Subject: [PATCH] Add `sf::WindowBase::set{Min|Max}imumSize()` Co-authored-by: Shane Whitmire Co-authored-by: michael.david.howard@outlook.com --- examples/opengl/OpenGL.cpp | 2 + include/SFML/Window/WindowBase.hpp | 21 ++++++ src/SFML/Window/Android/WindowImplAndroid.cpp | 14 ++++ src/SFML/Window/Android/WindowImplAndroid.hpp | 20 +++++ src/SFML/Window/DRM/WindowImplDRM.cpp | 12 +++ src/SFML/Window/DRM/WindowImplDRM.hpp | 20 +++++ src/SFML/Window/OSX/SFViewController.mm | 12 +++ src/SFML/Window/OSX/SFWindowController.mm | 14 ++++ src/SFML/Window/OSX/WindowImplCocoa.hpp | 20 +++++ src/SFML/Window/OSX/WindowImplCocoa.mm | 22 ++++++ .../Window/OSX/WindowImplDelegateProtocol.h | 16 ++++ src/SFML/Window/Unix/WindowImplX11.cpp | 40 ++++++++++ src/SFML/Window/Unix/WindowImplX11.hpp | 26 +++++++ src/SFML/Window/Win32/WindowImplWin32.cpp | 74 ++++++++++++++++--- src/SFML/Window/Win32/WindowImplWin32.hpp | 10 +++ src/SFML/Window/WindowBase.cpp | 59 ++++++++++++++- src/SFML/Window/WindowImpl.cpp | 28 +++++++ src/SFML/Window/WindowImpl.hpp | 39 ++++++++++ src/SFML/Window/iOS/WindowImplUIKit.hpp | 20 +++++ src/SFML/Window/iOS/WindowImplUIKit.mm | 14 ++++ test/Window/WindowBase.test.cpp | 34 ++++++++- 21 files changed, 502 insertions(+), 15 deletions(-) diff --git a/examples/opengl/OpenGL.cpp b/examples/opengl/OpenGL.cpp index 7c4f1d54..a3eb4081 100644 --- a/examples/opengl/OpenGL.cpp +++ b/examples/opengl/OpenGL.cpp @@ -50,6 +50,8 @@ int main() // Create the main window sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML graphics with OpenGL", sf::Style::Default, contextSettings); window.setVerticalSyncEnabled(true); + window.setMinimumSize(sf::Vector2u(400, 300)); + window.setMaximumSize(sf::Vector2u(1200, 900)); // Create a sprite for the background sf::Texture backgroundTexture; diff --git a/include/SFML/Window/WindowBase.hpp b/include/SFML/Window/WindowBase.hpp index 637be9a1..47c4ada0 100644 --- a/include/SFML/Window/WindowBase.hpp +++ b/include/SFML/Window/WindowBase.hpp @@ -36,6 +36,7 @@ #include #include +#include namespace sf @@ -255,6 +256,26 @@ public: //////////////////////////////////////////////////////////// void setSize(const Vector2u& size); + //////////////////////////////////////////////////////////// + /// \brief Set the minimum window rendering region size + /// + /// Pass std::nullopt to unset the minimum size + /// + /// \param minimumSize New minimum size, in pixels + /// + //////////////////////////////////////////////////////////// + void setMinimumSize(const std::optional& minimumSize); + + //////////////////////////////////////////////////////////// + /// \brief Set the maximum window rendering region size + /// + /// Pass std::nullopt to unset the maximum size + /// + /// \param maximumSize New maximum size, in pixels + /// + //////////////////////////////////////////////////////////// + void setMaximumSize(const std::optional& maximumSize); + //////////////////////////////////////////////////////////// /// \brief Change the title of the window /// diff --git a/src/SFML/Window/Android/WindowImplAndroid.cpp b/src/SFML/Window/Android/WindowImplAndroid.cpp index 265d76b0..9c4a270b 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.cpp +++ b/src/SFML/Window/Android/WindowImplAndroid.cpp @@ -149,6 +149,20 @@ void WindowImplAndroid::setSize(const Vector2u& /* size */) } +//////////////////////////////////////////////////////////// +void WindowImplAndroid::setMinimumSize(const std::optional& /* minimumSize */) +{ + // Not applicable +} + + +//////////////////////////////////////////////////////////// +void WindowImplAndroid::setMaximumSize(const std::optional& /* maximumSize */) +{ + // Not applicable +} + + //////////////////////////////////////////////////////////// void WindowImplAndroid::setTitle(const String& /* title */) { diff --git a/src/SFML/Window/Android/WindowImplAndroid.hpp b/src/SFML/Window/Android/WindowImplAndroid.hpp index 96f641df..3aa99eba 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.hpp +++ b/src/SFML/Window/Android/WindowImplAndroid.hpp @@ -110,6 +110,26 @@ public: //////////////////////////////////////////////////////////// void setSize(const Vector2u& size) override; + //////////////////////////////////////////////////////////// + /// \brief Set the minimum window rendering region size + /// + /// Pass std::nullopt to unset the minimum size + /// + /// \param minimumSize New minimum size, in pixels + /// + //////////////////////////////////////////////////////////// + void setMinimumSize(const std::optional& minimumSize) override; + + //////////////////////////////////////////////////////////// + /// \brief Set the maximum window rendering region size + /// + /// Pass std::nullopt to unset the maximum size + /// + /// \param maximumSize New maximum size, in pixels + /// + //////////////////////////////////////////////////////////// + void setMaximumSize(const std::optional& maximumSize) override; + //////////////////////////////////////////////////////////// /// \brief Change the title of the window /// diff --git a/src/SFML/Window/DRM/WindowImplDRM.cpp b/src/SFML/Window/DRM/WindowImplDRM.cpp index 5b98139c..2ce3cf5a 100644 --- a/src/SFML/Window/DRM/WindowImplDRM.cpp +++ b/src/SFML/Window/DRM/WindowImplDRM.cpp @@ -91,6 +91,18 @@ void WindowImplDRM::setSize(const Vector2u& /*size*/) } +//////////////////////////////////////////////////////////// +void WindowImplDRM::setMinimumSize(const std::optional& /* minimumSize */) +{ +} + + +//////////////////////////////////////////////////////////// +void WindowImplDRM::setMaximumSize(const std::optional& /* maximumSize */) +{ +} + + //////////////////////////////////////////////////////////// void WindowImplDRM::setTitle(const String& /*title*/) { diff --git a/src/SFML/Window/DRM/WindowImplDRM.hpp b/src/SFML/Window/DRM/WindowImplDRM.hpp index e9e7c5bd..4d4bb5c0 100644 --- a/src/SFML/Window/DRM/WindowImplDRM.hpp +++ b/src/SFML/Window/DRM/WindowImplDRM.hpp @@ -104,6 +104,26 @@ public: //////////////////////////////////////////////////////////// void setSize(const Vector2u& size) override; + //////////////////////////////////////////////////////////// + /// \brief Set the minimum window rendering region size + /// + /// Pass std::nullopt to unset the minimum size + /// + /// \param minimumSize New minimum size, in pixels + /// + //////////////////////////////////////////////////////////// + void setMinimumSize(const std::optional& minimumSize) override; + + //////////////////////////////////////////////////////////// + /// \brief Set the maximum window rendering region size + /// + /// Pass std::nullopt to unset the maximum size + /// + /// \param maximumSize New maximum size, in pixels + /// + //////////////////////////////////////////////////////////// + void setMaximumSize(const std::optional& maximumSize) override; + //////////////////////////////////////////////////////////// /// \brief Change the title of the window /// diff --git a/src/SFML/Window/OSX/SFViewController.mm b/src/SFML/Window/OSX/SFViewController.mm index 8e9acbaa..631ae9dd 100644 --- a/src/SFML/Window/OSX/SFViewController.mm +++ b/src/SFML/Window/OSX/SFViewController.mm @@ -173,6 +173,18 @@ } +//////////////////////////////////////////////////////// +- (void)setMinimumSize:(NSSize)size +{ +} + + +//////////////////////////////////////////////////////// +- (void)setMaximumSize:(NSSize)size +{ +} + + //////////////////////////////////////////////////////// - (void)changeTitle:(NSString*)title { diff --git a/src/SFML/Window/OSX/SFWindowController.mm b/src/SFML/Window/OSX/SFWindowController.mm index d09dd80d..9e223649 100644 --- a/src/SFML/Window/OSX/SFWindowController.mm +++ b/src/SFML/Window/OSX/SFWindowController.mm @@ -471,6 +471,20 @@ } +//////////////////////////////////////////////////////// +- (void)setMinimumSize:(NSSize)size +{ + [m_window setContentMinSize:size]; +} + + +//////////////////////////////////////////////////////// +- (void)setMaximumSize:(NSSize)size +{ + [m_window setContentMaxSize:size]; +} + + //////////////////////////////////////////////////////// - (void)changeTitle:(NSString*)title { diff --git a/src/SFML/Window/OSX/WindowImplCocoa.hpp b/src/SFML/Window/OSX/WindowImplCocoa.hpp index 38e3a142..a3fd59ed 100644 --- a/src/SFML/Window/OSX/WindowImplCocoa.hpp +++ b/src/SFML/Window/OSX/WindowImplCocoa.hpp @@ -279,6 +279,26 @@ public: //////////////////////////////////////////////////////////// void setSize(const Vector2u& size) override; + //////////////////////////////////////////////////////////// + /// \brief Set the minimum window rendering region size + /// + /// Pass std::nullopt to unset the minimum size + /// + /// \param minimumSize New minimum size, in pixels + /// + //////////////////////////////////////////////////////////// + void setMinimumSize(const std::optional& minimumSize) override; + + //////////////////////////////////////////////////////////// + /// \brief Set the maximum window rendering region size + /// + /// Pass std::nullopt to unset the maximum size + /// + /// \param maximumSize New maximum size, in pixels + /// + //////////////////////////////////////////////////////////// + void setMaximumSize(const std::optional& maximumSize) override; + //////////////////////////////////////////////////////////// /// \brief Change the title of the window /// diff --git a/src/SFML/Window/OSX/WindowImplCocoa.mm b/src/SFML/Window/OSX/WindowImplCocoa.mm index dae93d98..c53aef94 100644 --- a/src/SFML/Window/OSX/WindowImplCocoa.mm +++ b/src/SFML/Window/OSX/WindowImplCocoa.mm @@ -39,6 +39,7 @@ #include #include +#include #include namespace sf::priv @@ -437,6 +438,27 @@ void WindowImplCocoa::setSize(const Vector2u& size) } +//////////////////////////////////////////////////////////// +void WindowImplCocoa::setMinimumSize(const std::optional& minimumSize) +{ + WindowImpl::setMinimumSize(minimumSize); + const AutoreleasePool pool; + const NSSize size = minimumSize ? NSMakeSize(minimumSize->x, minimumSize->y) : NSMakeSize(0, 0); + [m_delegate setMinimumSize:size]; +} + + +//////////////////////////////////////////////////////////// +void WindowImplCocoa::setMaximumSize(const std::optional& maximumSize) +{ + WindowImpl::setMaximumSize(maximumSize); + const AutoreleasePool pool; + const NSSize size = maximumSize ? NSMakeSize(maximumSize->x, maximumSize->y) + : NSMakeSize(std::numeric_limits::max(), std::numeric_limits::max()); + [m_delegate setMaximumSize:size]; +} + + //////////////////////////////////////////////////////////// void WindowImplCocoa::setTitle(const String& title) { diff --git a/src/SFML/Window/OSX/WindowImplDelegateProtocol.h b/src/SFML/Window/OSX/WindowImplDelegateProtocol.h index f8063d98..3d0bb456 100644 --- a/src/SFML/Window/OSX/WindowImplDelegateProtocol.h +++ b/src/SFML/Window/OSX/WindowImplDelegateProtocol.h @@ -151,6 +151,22 @@ class WindowImplCocoa; //////////////////////////////////////////////////////////// - (void)resizeTo:(unsigned int)width by:(unsigned int)height; +//////////////////////////////////////////////////////////// +/// \brief Set the minimize window/view size +/// +/// \param size minimum size +/// +//////////////////////////////////////////////////////////// +- (void)setMinimumSize:(NSSize)size; + +//////////////////////////////////////////////////////////// +/// \brief Set the maximum window/view size +/// +/// \param size maximum size +/// +//////////////////////////////////////////////////////////// +- (void)setMaximumSize:(NSSize)size; + //////////////////////////////////////////////////////////// /// \brief Set the window's title /// diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 527cfd46..4b29af53 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -843,6 +843,22 @@ void WindowImplX11::setSize(const Vector2u& size) } +//////////////////////////////////////////////////////////// +void WindowImplX11::setMinimumSize(const std::optional& minimumSize) +{ + WindowImpl::setMinimumSize(minimumSize); + setWindowSizeConstraints(); +} + + +//////////////////////////////////////////////////////////// +void WindowImplX11::setMaximumSize(const std::optional& maximumSize) +{ + WindowImpl::setMaximumSize(maximumSize); + setWindowSizeConstraints(); +} + + //////////////////////////////////////////////////////////// void WindowImplX11::setTitle(const String& title) { @@ -2139,4 +2155,28 @@ Vector2i WindowImplX11::getPrimaryMonitorPosition() return monitorPosition; } + +//////////////////////////////////////////////////////////// +void WindowImplX11::setWindowSizeConstraints() const +{ + // Do nothing if resizing is disabled + if (m_useSizeHints) + return; + + XSizeHints sizeHints{}; + if (const auto minimumSize = getMinimumSize()) + { + sizeHints.flags |= PMinSize; + sizeHints.min_width = static_cast(minimumSize->x); + sizeHints.min_height = static_cast(minimumSize->y); + } + if (const auto maximumSize = getMaximumSize()) + { + sizeHints.flags |= PMaxSize; + sizeHints.max_width = static_cast(maximumSize->x); + sizeHints.max_height = static_cast(maximumSize->y); + } + XSetWMNormalHints(m_display, m_window, &sizeHints); +} + } // namespace sf::priv diff --git a/src/SFML/Window/Unix/WindowImplX11.hpp b/src/SFML/Window/Unix/WindowImplX11.hpp index d49d8900..6522fe85 100644 --- a/src/SFML/Window/Unix/WindowImplX11.hpp +++ b/src/SFML/Window/Unix/WindowImplX11.hpp @@ -111,6 +111,26 @@ public: //////////////////////////////////////////////////////////// void setSize(const Vector2u& size) override; + //////////////////////////////////////////////////////////// + /// \brief Set the minimum window rendering region size + /// + /// Pass std::nullopt to unset the minimum size + /// + /// \param minimumSize New minimum size, in pixels + /// + //////////////////////////////////////////////////////////// + void setMinimumSize(const std::optional& minimumSize) override; + + //////////////////////////////////////////////////////////// + /// \brief Set the maximum window rendering region size + /// + /// Pass std::nullopt to unset the maximum size + /// + /// \param maximumSize New maximum size, in pixels + /// + //////////////////////////////////////////////////////////// + void setMaximumSize(const std::optional& maximumSize) override; + //////////////////////////////////////////////////////////// /// \brief Change the title of the window /// @@ -291,6 +311,12 @@ private: //////////////////////////////////////////////////////////// Vector2i getPrimaryMonitorPosition(); + //////////////////////////////////////////////////////////// + /// \brief Set min/max window size + /// + //////////////////////////////////////////////////////////// + void setWindowSizeConstraints() const; + //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// diff --git a/src/SFML/Window/Win32/WindowImplWin32.cpp b/src/SFML/Window/Win32/WindowImplWin32.cpp index 58d7293f..af80467e 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.cpp +++ b/src/SFML/Window/Win32/WindowImplWin32.cpp @@ -329,13 +329,7 @@ Vector2u WindowImplWin32::getSize() const //////////////////////////////////////////////////////////// void WindowImplWin32::setSize(const Vector2u& size) { - // SetWindowPos wants the total size of the window (including title bar and borders), - // so we have to compute it - RECT rectangle = {0, 0, static_cast(size.x), static_cast(size.y)}; - AdjustWindowRect(&rectangle, static_cast(GetWindowLongPtr(m_handle, GWL_STYLE)), false); - const int width = rectangle.right - rectangle.left; - const int height = rectangle.bottom - rectangle.top; - + const auto [width, height] = contentSizeToWindowSize(size); SetWindowPos(m_handle, nullptr, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER); } @@ -560,6 +554,20 @@ void WindowImplWin32::grabCursor(bool grabbed) } } + +//////////////////////////////////////////////////////////// +Vector2i WindowImplWin32::contentSizeToWindowSize(const Vector2u& size) +{ + // SetWindowPos wants the total size of the window (including title bar and borders) so we have to compute it + RECT rectangle = {0, 0, static_cast(size.x), static_cast(size.y)}; + AdjustWindowRect(&rectangle, static_cast(GetWindowLongPtr(m_handle, GWL_STYLE)), false); + const auto width = rectangle.right - rectangle.left; + const auto height = rectangle.bottom - rectangle.top; + + return {width, height}; +} + + //////////////////////////////////////////////////////////// Keyboard::Scancode WindowImplWin32::toScancode(WPARAM wParam, LPARAM lParam) { @@ -780,14 +788,28 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) break; } - // The system request the min/max window size and position + // Fix violations of minimum or maximum size case WM_GETMINMAXINFO: { // We override the returned information to remove the default limit // (the OS doesn't allow windows bigger than the desktop by default) - auto* info = reinterpret_cast(lParam); - info->ptMaxTrackSize.x = 50000; - info->ptMaxTrackSize.y = 50000; + + const auto maximumSize = contentSizeToWindowSize(getMaximumSize().value_or(Vector2u(50'000, 50'000))); + + MINMAXINFO& minMaxInfo = *reinterpret_cast(lParam); + minMaxInfo.ptMaxTrackSize.x = maximumSize.x; + minMaxInfo.ptMaxTrackSize.y = maximumSize.y; + if (getMaximumSize().has_value()) + { + minMaxInfo.ptMaxSize.x = maximumSize.x; + minMaxInfo.ptMaxSize.y = maximumSize.y; + } + if (getMinimumSize().has_value()) + { + const auto minimumSize = contentSizeToWindowSize(getMinimumSize().value()); + minMaxInfo.ptMinTrackSize.x = minimumSize.x; + minMaxInfo.ptMinTrackSize.y = minimumSize.y; + } break; } @@ -1122,6 +1144,36 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) break; } + + // Work around Windows 10 bug + // When a maximum size is specified and the window is snapped to the edge of the display the window size is subtly too big + case WM_WINDOWPOSCHANGED: + { + WINDOWPOS& pos = *reinterpret_cast(lParam); + if (pos.flags & SWP_NOSIZE) + break; + + if (!getMaximumSize().has_value()) + break; + const auto maximumSize = contentSizeToWindowSize(getMaximumSize().value()); + + bool shouldResize = false; + if (pos.cx > maximumSize.x) + { + pos.cx = maximumSize.x; + shouldResize = true; + } + if (pos.cy > maximumSize.y) + { + pos.cy = maximumSize.y; + shouldResize = true; + } + + if (shouldResize) + SetWindowPos(m_handle, pos.hwndInsertAfter, pos.x, pos.y, pos.cx, pos.cy, 0); + + break; + } } } diff --git a/src/SFML/Window/Win32/WindowImplWin32.hpp b/src/SFML/Window/Win32/WindowImplWin32.hpp index d46aba8e..a4a4ab65 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.hpp +++ b/src/SFML/Window/Win32/WindowImplWin32.hpp @@ -242,6 +242,16 @@ private: //////////////////////////////////////////////////////////// void grabCursor(bool grabbed); + //////////////////////////////////////////////////////////// + /// \brief Convert content size to window size including window chrome + /// + /// \param size Size to convert + /// + /// \return Converted size including window chrome + /// + //////////////////////////////////////////////////////////// + Vector2i contentSizeToWindowSize(const Vector2u& size); + //////////////////////////////////////////////////////////// /// \brief Convert a Win32 virtual key code to a SFML key code /// diff --git a/src/SFML/Window/WindowBase.cpp b/src/SFML/Window/WindowBase.cpp index 7c969a5f..81b26687 100644 --- a/src/SFML/Window/WindowBase.cpp +++ b/src/SFML/Window/WindowBase.cpp @@ -31,8 +31,12 @@ #include +#include +#include #include +#include + namespace { @@ -207,11 +211,22 @@ void WindowBase::setSize(const Vector2u& size) { if (m_impl) { - m_impl->setSize(size); + // Constrain requested size within minimum and maximum bounds + const auto minimumSize = m_impl->getMinimumSize().value_or(Vector2u()); + const auto maximumSize = m_impl->getMaximumSize().value_or( + Vector2u(std::numeric_limits::max(), std::numeric_limits::max())); + const auto width = std::clamp(size.x, minimumSize.x, maximumSize.x); + const auto height = std::clamp(size.y, minimumSize.y, maximumSize.y); + + // Do nothing if requested size matches current size + const Vector2u clampedSize(width, height); + if (clampedSize == m_size) + return; + + m_impl->setSize(clampedSize); // Cache the new size - m_size.x = size.x; - m_size.y = size.y; + m_size = clampedSize; // Notify the derived class onResize(); @@ -219,6 +234,44 @@ void WindowBase::setSize(const Vector2u& size) } +//////////////////////////////////////////////////////////// +void WindowBase::setMinimumSize(const std::optional& minimumSize) +{ + if (m_impl) + { + [[maybe_unused]] const auto validateMinimumSize = [this, minimumSize]() + { + if (!minimumSize.has_value() || !m_impl->getMaximumSize().has_value()) + return true; + return minimumSize->x <= m_impl->getMaximumSize()->x && minimumSize->y <= m_impl->getMaximumSize()->y; + }; + assert(validateMinimumSize() && "Minimum size cannot be bigger than the maximum size along either axis"); + + m_impl->setMinimumSize(minimumSize); + setSize(getSize()); + } +} + + +//////////////////////////////////////////////////////////// +void WindowBase::setMaximumSize(const std::optional& maximumSize) +{ + if (m_impl) + { + [[maybe_unused]] const auto validateMaxiumSize = [this, maximumSize]() + { + if (!maximumSize.has_value() || !m_impl->getMinimumSize().has_value()) + return true; + return maximumSize->x >= m_impl->getMinimumSize()->x && maximumSize->y >= m_impl->getMinimumSize()->y; + }; + assert(validateMaxiumSize() && "Maximum size cannot be smaller than the minimum size along either axis"); + + m_impl->setMaximumSize(maximumSize); + setSize(getSize()); + } +} + + //////////////////////////////////////////////////////////// void WindowBase::setTitle(const String& title) { diff --git a/src/SFML/Window/WindowImpl.cpp b/src/SFML/Window/WindowImpl.cpp index 3d8b3700..800063f1 100644 --- a/src/SFML/Window/WindowImpl.cpp +++ b/src/SFML/Window/WindowImpl.cpp @@ -135,6 +135,20 @@ WindowImpl::WindowImpl() : m_joystickStatesImpl(std::make_unique WindowImpl::getMinimumSize() const +{ + return m_minimumSize; +} + + +//////////////////////////////////////////////////////////// +std::optional WindowImpl::getMaximumSize() const +{ + return m_maximumSize; +} + + //////////////////////////////////////////////////////////// void WindowImpl::setJoystickThreshold(float threshold) { @@ -142,6 +156,20 @@ void WindowImpl::setJoystickThreshold(float threshold) } +//////////////////////////////////////////////////////////// +void WindowImpl::setMinimumSize(const std::optional& minimumSize) +{ + m_minimumSize = minimumSize; +} + + +//////////////////////////////////////////////////////////// +void WindowImpl::setMaximumSize(const std::optional& maximumSize) +{ + m_maximumSize = maximumSize; +} + + //////////////////////////////////////////////////////////// bool WindowImpl::popEvent(Event& event, bool block) { diff --git a/src/SFML/Window/WindowImpl.hpp b/src/SFML/Window/WindowImpl.hpp index ba0c88db..b3f81cbd 100644 --- a/src/SFML/Window/WindowImpl.hpp +++ b/src/SFML/Window/WindowImpl.hpp @@ -40,6 +40,7 @@ #include #include +#include #include #include @@ -142,6 +143,22 @@ public: //////////////////////////////////////////////////////////// virtual Vector2i getPosition() const = 0; + //////////////////////////////////////////////////////////// + /// \brief Get the minimum window rendering region size + /// + /// \return Minimum size + /// + //////////////////////////////////////////////////////////// + std::optional getMinimumSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the maximum window rendering region size + /// + /// \return Maximum size + /// + //////////////////////////////////////////////////////////// + std::optional getMaximumSize() const; + //////////////////////////////////////////////////////////// /// \brief Change the position of the window on screen /// @@ -166,6 +183,26 @@ public: //////////////////////////////////////////////////////////// virtual void setSize(const Vector2u& size) = 0; + //////////////////////////////////////////////////////////// + /// \brief Set the minimum window rendering region size + /// + /// Pass std::nullopt to unset the minimum size + /// + /// \param minimumSize New minimum size, in pixels + /// + //////////////////////////////////////////////////////////// + virtual void setMinimumSize(const std::optional& minimumSize); + + //////////////////////////////////////////////////////////// + /// \brief Set the maximum window rendering region size + /// + /// Pass std::nullopt to unset the maximum size + /// + /// \param maximumSize New maximum size, in pixels + /// + //////////////////////////////////////////////////////////// + virtual void setMaximumSize(const std::optional& maximumSize); + //////////////////////////////////////////////////////////// /// \brief Change the title of the window /// @@ -298,6 +335,8 @@ private: Vector3f m_sensorValue[Sensor::Count]; //!< Previous value of the sensors float m_joystickThreshold{0.1f}; //!< Joystick threshold (minimum motion for "move" event to be generated) float m_previousAxes[Joystick::Count][Joystick::AxisCount]; //!< Position of each axis last time a move event triggered, in range [-100, 100] + std::optional m_minimumSize; //!< Minimum window size + std::optional m_maximumSize; //!< Maximum window size }; } // namespace priv diff --git a/src/SFML/Window/iOS/WindowImplUIKit.hpp b/src/SFML/Window/iOS/WindowImplUIKit.hpp index 4a6d0c1c..c90a05cf 100644 --- a/src/SFML/Window/iOS/WindowImplUIKit.hpp +++ b/src/SFML/Window/iOS/WindowImplUIKit.hpp @@ -105,6 +105,26 @@ public: //////////////////////////////////////////////////////////// void setSize(const Vector2u& size) override; + //////////////////////////////////////////////////////////// + /// \brief Set the minimum window rendering region size + /// + /// Pass std::nullopt to unset the minimum size + /// + /// \param minimumSize New minimum size, in pixels + /// + //////////////////////////////////////////////////////////// + void setMinimumSize(const std::optional& minimumSize) override; + + //////////////////////////////////////////////////////////// + /// \brief Set the maximum window rendering region size + /// + /// Pass std::nullopt to unset the maximum size + /// + /// \param maximumSize New maximum size, in pixels + /// + //////////////////////////////////////////////////////////// + void setMaximumSize(const std::optional& maximumSize) override; + //////////////////////////////////////////////////////////// /// \brief Change the title of the window /// diff --git a/src/SFML/Window/iOS/WindowImplUIKit.mm b/src/SFML/Window/iOS/WindowImplUIKit.mm index 30d53962..7152047f 100644 --- a/src/SFML/Window/iOS/WindowImplUIKit.mm +++ b/src/SFML/Window/iOS/WindowImplUIKit.mm @@ -146,6 +146,20 @@ void WindowImplUIKit::setSize(const Vector2u& size) } +//////////////////////////////////////////////////////////// +void WindowImplUIKit::setMinimumSize(const std::optional& /* minimumSize */) +{ + // Not applicable +} + + +//////////////////////////////////////////////////////////// +void WindowImplUIKit::setMaximumSize(const std::optional& /* maximumSize */) +{ + // Not applicable +} + + //////////////////////////////////////////////////////////// void WindowImplUIKit::setTitle(const String& /* title */) { diff --git a/test/Window/WindowBase.test.cpp b/test/Window/WindowBase.test.cpp index 5fe52a4e..74eddc88 100644 --- a/test/Window/WindowBase.test.cpp +++ b/test/Window/WindowBase.test.cpp @@ -89,7 +89,7 @@ TEST_CASE("[Window] sf::WindowBase" * doctest::skip(skipDisplayTests)) CHECK(!windowBase.waitEvent(event)); } - SUBCASE("Get/set position") + SUBCASE("Set/get position") { sf::WindowBase windowBase; windowBase.setPosition({12, 34}); @@ -111,5 +111,37 @@ TEST_CASE("[Window] sf::WindowBase" * doctest::skip(skipDisplayTests)) windowBase.setSize({128, 256}); CHECK(windowBase.getSize() == sf::Vector2u(128, 256)); } + + SUBCASE("Minimum size") + { + sf::WindowBase windowBase(sf::VideoMode({360, 240}), "WindowBase Tests"); + windowBase.setMinimumSize(sf::Vector2u(128, 256)); + windowBase.setSize({100, 100}); + CHECK(windowBase.getSize() == sf::Vector2u(128, 256)); + } + + SUBCASE("Maximum size") + { + sf::WindowBase windowBase(sf::VideoMode({360, 240}), "WindowBase Tests"); + windowBase.setMaximumSize(sf::Vector2u(128, 256)); + windowBase.setSize({400, 400}); + CHECK(windowBase.getSize() == sf::Vector2u(128, 256)); + } + } + + SUBCASE("setMinimumSize()") + { + sf::WindowBase windowBase(sf::VideoMode({100, 100}), "WindowBase Tests", sf::Style::Default ^ sf::Style::Resize); + windowBase.setMinimumSize(sf::Vector2u(200, 300)); + CHECK(windowBase.getSize() == sf::Vector2u(200, 300)); + windowBase.setMaximumSize(sf::Vector2u(200, 300)); + } + + SUBCASE("setMinimumSize()") + { + sf::WindowBase windowBase(sf::VideoMode({400, 400}), "WindowBase Tests", sf::Style::Default ^ sf::Style::Resize); + windowBase.setMaximumSize(sf::Vector2u(200, 300)); + CHECK(windowBase.getSize() == sf::Vector2u(200, 300)); + windowBase.setMinimumSize(sf::Vector2u(200, 300)); } }