From b924fb97d6fddba818b9ad57722eaf777244e826 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Thu, 13 Jun 2019 15:31:08 +0300 Subject: Add ability to limit maximum/minimum window size. --- platform/osx/os_osx.h | 7 ++ platform/osx/os_osx.mm | 66 +++++++++++++++++++ platform/windows/os_windows.cpp | 47 +++++++++++++- platform/windows/os_windows.h | 7 ++ platform/x11/os_x11.cpp | 137 +++++++++++++++++++++++++++++++++++----- platform/x11/os_x11.h | 7 ++ 6 files changed, 255 insertions(+), 16 deletions(-) (limited to 'platform') diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index eed230ba89..f81aa432ed 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -134,6 +134,9 @@ public: String im_text; Point2 im_selection; + Size2 min_size; + Size2 max_size; + PowerOSX *power_manager; CrashHandler crash_handler; @@ -232,6 +235,10 @@ public: virtual Point2 get_window_position() const; virtual void set_window_position(const Point2 &p_position); + virtual Size2 get_max_window_size() const; + virtual Size2 get_min_window_size() const; + virtual void set_min_window_size(const Size2 p_size); + virtual void set_max_window_size(const Size2 p_size); virtual void set_window_size(const Size2 p_size); virtual void set_window_fullscreen(bool p_enabled); virtual bool is_window_fullscreen() const; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index bdc17c7124..d06c44b635 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -267,10 +267,23 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt - (void)windowDidEnterFullScreen:(NSNotification *)notification { OS_OSX::singleton->zoomed = true; + + [OS_OSX::singleton->window_object setContentMinSize:NSMakeSize(0, 0)]; + [OS_OSX::singleton->window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; } - (void)windowDidExitFullScreen:(NSNotification *)notification { OS_OSX::singleton->zoomed = false; + + if (OS_OSX::singleton->min_size != Size2()) { + Size2 size = OS_OSX::singleton->min_size / OS_OSX::singleton->_display_scale(); + [OS_OSX::singleton->window_object setContentMinSize:NSMakeSize(size.x, size.y)]; + } + if (OS_OSX::singleton->max_size != Size2()) { + Size2 size = OS_OSX::singleton->max_size / OS_OSX::singleton->_display_scale(); + [OS_OSX::singleton->window_object setContentMaxSize:NSMakeSize(size.x, size.y)]; + } + if (!OS_OSX::singleton->resizable) [OS_OSX::singleton->window_object setStyleMask:[OS_OSX::singleton->window_object styleMask] & ~NSWindowStyleMaskResizable]; } @@ -2350,6 +2363,46 @@ Size2 OS_OSX::get_real_window_size() const { return Size2(frame.size.width, frame.size.height) * _display_scale(); } +Size2 OS_OSX::get_max_window_size() const { + return max_size; +} + +Size2 OS_OSX::get_min_window_size() const { + return min_size; +} + +void OS_OSX::set_min_window_size(const Size2 p_size) { + + if ((p_size != Size2()) && (max_size != Size2()) && ((p_size.x > max_size.x) || (p_size.y > max_size.y))) { + WARN_PRINT("Minimum window size can't be larger than maximum window size!"); + return; + } + min_size = p_size; + + if ((min_size != Size2()) && !zoomed) { + Size2 size = min_size / _display_scale(); + [window_object setContentMinSize:NSMakeSize(size.x, size.y)]; + } else { + [window_object setContentMinSize:NSMakeSize(0, 0)]; + } +} + +void OS_OSX::set_max_window_size(const Size2 p_size) { + + if ((p_size != Size2()) && ((p_size.x < min_size.x) || (p_size.y < min_size.y))) { + WARN_PRINT("Maximum window size can't be smaller than minimum window size!"); + return; + } + max_size = p_size; + + if ((max_size != Size2()) && !zoomed) { + Size2 size = max_size / _display_scale(); + [window_object setContentMaxSize:NSMakeSize(size.x, size.y)]; + } else { + [window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; + } +} + void OS_OSX::set_window_size(const Size2 p_size) { Size2 size = p_size / _display_scale(); @@ -2379,6 +2432,19 @@ void OS_OSX::set_window_fullscreen(bool p_enabled) { set_window_per_pixel_transparency_enabled(false); if (!resizable) [window_object setStyleMask:[window_object styleMask] | NSWindowStyleMaskResizable]; + if (p_enabled) { + [window_object setContentMinSize:NSMakeSize(0, 0)]; + [window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; + } else { + if (min_size != Size2()) { + Size2 size = min_size / _display_scale(); + [window_object setContentMinSize:NSMakeSize(size.x, size.y)]; + } + if (max_size != Size2()) { + Size2 size = max_size / _display_scale(); + [window_object setContentMaxSize:NSMakeSize(size.x, size.y)]; + } + } [window_object toggleFullScreen:nil]; } zoomed = p_enabled; diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 4cd637a4b2..7229be618b 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -353,7 +353,23 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) return 0; // Return To The Message Loop } - + case WM_GETMINMAXINFO: { + if (video_mode.resizable && !video_mode.fullscreen) { + Size2 decor = get_real_window_size() - get_window_size(); // Size of window decorations + MINMAXINFO *min_max_info = (MINMAXINFO *)lParam; + if (min_size != Size2()) { + min_max_info->ptMinTrackSize.x = min_size.x + decor.x; + min_max_info->ptMinTrackSize.y = min_size.y + decor.y; + } + if (max_size != Size2()) { + min_max_info->ptMaxTrackSize.x = max_size.x + decor.x; + min_max_info->ptMaxTrackSize.y = max_size.y + decor.y; + } + return 0; + } else { + break; + } + } case WM_PAINT: Main::force_redraw(); @@ -1769,6 +1785,7 @@ void OS_Windows::set_window_position(const Point2 &p_position) { last_pos = p_position; update_real_mouse_position(); } + Size2 OS_Windows::get_window_size() const { if (minimized) { @@ -1781,6 +1798,33 @@ Size2 OS_Windows::get_window_size() const { } return Size2(); } + +Size2 OS_Windows::get_max_window_size() const { + return max_size; +} + +Size2 OS_Windows::get_min_window_size() const { + return min_size; +} + +void OS_Windows::set_min_window_size(const Size2 p_size) { + + if ((p_size != Size2()) && (max_size != Size2()) && ((p_size.x > max_size.x) || (p_size.y > max_size.y))) { + WARN_PRINT("Minimum window size can't be larger than maximum window size!"); + return; + } + min_size = p_size; +} + +void OS_Windows::set_max_window_size(const Size2 p_size) { + + if ((p_size != Size2()) && ((p_size.x < min_size.x) || (p_size.y < min_size.y))) { + WARN_PRINT("Maximum window size can't be smaller than minimum window size!"); + return; + } + max_size = p_size; +} + Size2 OS_Windows::get_real_window_size() const { RECT r; @@ -1789,6 +1833,7 @@ Size2 OS_Windows::get_real_window_size() const { } return Size2(); } + void OS_Windows::set_window_size(const Size2 p_size) { int w = p_size.width; diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 0aacbcb9ff..7f72ca6543 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -124,6 +124,9 @@ class OS_Windows : public OS { HCURSOR hCursor; + Size2 min_size; + Size2 max_size; + Size2 window_rect; VideoMode video_mode; bool preserve_window_size = false; @@ -236,6 +239,10 @@ public: virtual void set_window_position(const Point2 &p_position); virtual Size2 get_window_size() const; virtual Size2 get_real_window_size() const; + virtual Size2 get_max_window_size() const; + virtual Size2 get_min_window_size() const; + virtual void set_min_window_size(const Size2 p_size); + virtual void set_max_window_size(const Size2 p_size); virtual void set_window_size(const Size2 p_size); virtual void set_window_fullscreen(bool p_enabled); virtual bool is_window_fullscreen() const; diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 510f3d6114..bbd7884b91 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -1001,18 +1001,30 @@ void OS_X11::set_wm_fullscreen(bool p_enabled) { XFlush(x11_display); - if (!p_enabled && !is_window_resizable()) { + if (!p_enabled) { // Reset the non-resizable flags if we un-set these before. Size2 size = get_window_size(); XSizeHints *xsh; - xsh = XAllocSizeHints(); - xsh->flags = PMinSize | PMaxSize; - xsh->min_width = size.x; - xsh->max_width = size.x; - xsh->min_height = size.y; - xsh->max_height = size.y; - + if (!is_window_resizable()) { + xsh->flags = PMinSize | PMaxSize; + xsh->min_width = size.x; + xsh->max_width = size.x; + xsh->min_height = size.y; + xsh->max_height = size.y; + } else { + xsh->flags = 0L; + if (min_size != Size2()) { + xsh->flags |= PMinSize; + xsh->min_width = min_size.x; + xsh->min_height = min_size.y; + } + if (max_size != Size2()) { + xsh->flags |= PMaxSize; + xsh->max_width = max_size.x; + xsh->max_height = max_size.y; + } + } XSetWMNormalHints(x11_display, x11_window, xsh); XFree(xsh); } @@ -1239,6 +1251,72 @@ Size2 OS_X11::get_real_window_size() const { return Size2(w, h); } +Size2 OS_X11::get_max_window_size() const { + return max_size; +} + +Size2 OS_X11::get_min_window_size() const { + return min_size; +} + +void OS_X11::set_min_window_size(const Size2 p_size) { + + if ((p_size != Size2()) && (max_size != Size2()) && ((p_size.x > max_size.x) || (p_size.y > max_size.y))) { + WARN_PRINT("Minimum window size can't be larger than maximum window size!"); + return; + } + min_size = p_size; + + if (is_window_resizable()) { + XSizeHints *xsh; + xsh = XAllocSizeHints(); + xsh->flags = 0L; + if (min_size != Size2()) { + xsh->flags |= PMinSize; + xsh->min_width = min_size.x; + xsh->min_height = min_size.y; + } + if (max_size != Size2()) { + xsh->flags |= PMaxSize; + xsh->max_width = max_size.x; + xsh->max_height = max_size.y; + } + XSetWMNormalHints(x11_display, x11_window, xsh); + XFree(xsh); + + XFlush(x11_display); + } +} + +void OS_X11::set_max_window_size(const Size2 p_size) { + + if ((p_size != Size2()) && ((p_size.x < min_size.x) || (p_size.y < min_size.y))) { + WARN_PRINT("Maximum window size can't be smaller than minimum window size!"); + return; + } + max_size = p_size; + + if (is_window_resizable()) { + XSizeHints *xsh; + xsh = XAllocSizeHints(); + xsh->flags = 0L; + if (min_size != Size2()) { + xsh->flags |= PMinSize; + xsh->min_width = min_size.x; + xsh->min_height = min_size.y; + } + if (max_size != Size2()) { + xsh->flags |= PMaxSize; + xsh->max_width = max_size.x; + xsh->max_height = max_size.y; + } + XSetWMNormalHints(x11_display, x11_window, xsh); + XFree(xsh); + + XFlush(x11_display); + } +} + void OS_X11::set_window_size(const Size2 p_size) { if (current_videomode.width == p_size.width && current_videomode.height == p_size.height) @@ -1251,17 +1329,29 @@ void OS_X11::set_window_size(const Size2 p_size) { int old_h = xwa.height; // If window resizable is disabled we need to update the attributes first + XSizeHints *xsh; + xsh = XAllocSizeHints(); if (!is_window_resizable()) { - XSizeHints *xsh; - xsh = XAllocSizeHints(); xsh->flags = PMinSize | PMaxSize; xsh->min_width = p_size.x; xsh->max_width = p_size.x; xsh->min_height = p_size.y; xsh->max_height = p_size.y; - XSetWMNormalHints(x11_display, x11_window, xsh); - XFree(xsh); + } else { + xsh->flags = 0L; + if (min_size != Size2()) { + xsh->flags |= PMinSize; + xsh->min_width = min_size.x; + xsh->min_height = min_size.y; + } + if (max_size != Size2()) { + xsh->flags |= PMaxSize; + xsh->max_width = max_size.x; + xsh->max_height = max_size.y; + } } + XSetWMNormalHints(x11_display, x11_window, xsh); + XFree(xsh); // Resize the window XResizeWindow(x11_display, x11_window, p_size.x, p_size.y); @@ -1307,20 +1397,37 @@ bool OS_X11::is_window_fullscreen() const { } void OS_X11::set_window_resizable(bool p_enabled) { - XSizeHints *xsh; - Size2 size = get_window_size(); + XSizeHints *xsh; xsh = XAllocSizeHints(); - xsh->flags = p_enabled ? 0L : PMinSize | PMaxSize; if (!p_enabled) { + Size2 size = get_window_size(); + + xsh->flags = PMinSize | PMaxSize; xsh->min_width = size.x; xsh->max_width = size.x; xsh->min_height = size.y; xsh->max_height = size.y; + } else { + xsh->flags = 0L; + if (min_size != Size2()) { + xsh->flags |= PMinSize; + xsh->min_width = min_size.x; + xsh->min_height = min_size.y; + } + if (max_size != Size2()) { + xsh->flags |= PMaxSize; + xsh->max_width = max_size.x; + xsh->max_height = max_size.y; + } } + XSetWMNormalHints(x11_display, x11_window, xsh); XFree(xsh); + current_videomode.resizable = p_enabled; + + XFlush(x11_display); } bool OS_X11::is_window_resizable() const { diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index ad35cdb4f9..bf6df3a65e 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -119,6 +119,9 @@ class OS_X11 : public OS_Unix { bool im_active; Vector2 im_position; + Size2 min_size; + Size2 max_size; + Point2 last_mouse_pos; bool last_mouse_pos_valid; Point2i last_click_pos; @@ -265,6 +268,10 @@ public: virtual void set_window_position(const Point2 &p_position); virtual Size2 get_window_size() const; virtual Size2 get_real_window_size() const; + virtual Size2 get_max_window_size() const; + virtual Size2 get_min_window_size() const; + virtual void set_min_window_size(const Size2 p_size); + virtual void set_max_window_size(const Size2 p_size); virtual void set_window_size(const Size2 p_size); virtual void set_window_fullscreen(bool p_enabled); virtual bool is_window_fullscreen() const; -- cgit v1.2.3