From 45ed58865ed7ae26a61f8710dc2bba4a667221a3 Mon Sep 17 00:00:00 2001 From: Peter Elliott Date: Fri, 21 Aug 2020 14:19:10 -0600 Subject: [PATCH] LibGUI+WindowServer: Add resize_aspect_ratio() When a resize_aspect_ratio is specified, and window will only be resized to a multiple of that ratio. When resize_aspect_ratio is set, windows cannot be tiled. --- Libraries/LibGUI/Window.cpp | 11 +++++++++++ Libraries/LibGUI/Window.h | 5 +++++ Services/WindowServer/ClientConnection.cpp | 15 +++++++++++++++ Services/WindowServer/ClientConnection.h | 1 + Services/WindowServer/Window.cpp | 5 ++++- Services/WindowServer/Window.h | 4 ++++ Services/WindowServer/WindowManager.cpp | 9 +++++++++ Services/WindowServer/WindowServer.ipc | 2 ++ 8 files changed, 51 insertions(+), 1 deletion(-) diff --git a/Libraries/LibGUI/Window.cpp b/Libraries/LibGUI/Window.cpp index de1206b918..72a6885b54 100644 --- a/Libraries/LibGUI/Window.cpp +++ b/Libraries/LibGUI/Window.cpp @@ -107,6 +107,7 @@ void Window::show() m_opacity_when_windowless, m_base_size, m_size_increment, + m_resize_aspect_ratio, (i32)m_window_type, m_title_when_windowless, parent_window ? parent_window->window_id() : 0); @@ -837,6 +838,16 @@ void Window::set_size_increment(const Gfx::IntSize& size_increment) WindowServerConnection::the().send_sync(m_window_id, m_base_size, m_size_increment); } +void Window::set_resize_aspect_ratio(const Optional& ratio) +{ + if (m_resize_aspect_ratio == ratio) + return; + + m_resize_aspect_ratio = ratio; + if (is_visible()) + WindowServerConnection::the().send_sync(m_window_id, m_resize_aspect_ratio); +} + void Window::did_add_widget(Badge, Widget& widget) { if (!m_focused_widget && widget.accepts_focus()) diff --git a/Libraries/LibGUI/Window.h b/Libraries/LibGUI/Window.h index 4d8f96e4ce..88b7b39fa6 100644 --- a/Libraries/LibGUI/Window.h +++ b/Libraries/LibGUI/Window.h @@ -179,6 +179,10 @@ public: void set_size_increment(const Gfx::IntSize&); Gfx::IntSize base_size() const { return m_base_size; } void set_base_size(const Gfx::IntSize&); + const Optional& resize_aspect_ratio() const { return m_resize_aspect_ratio; } + void set_resize_aspect_ratio(int width, int height) { set_resize_aspect_ratio(Gfx::IntSize(width, height)); } + void set_no_resize_aspect_ratio() { set_resize_aspect_ratio({}); } + void set_resize_aspect_ratio(const Optional& ratio); void set_override_cursor(StandardCursor); void set_override_cursor(const Gfx::Bitmap&); @@ -260,6 +264,7 @@ private: bool m_double_buffering_enabled { true }; bool m_modal { false }; bool m_resizable { true }; + Optional m_resize_aspect_ratio {}; bool m_minimizable { true }; bool m_fullscreen { false }; bool m_frameless { false }; diff --git a/Services/WindowServer/ClientConnection.cpp b/Services/WindowServer/ClientConnection.cpp index 0af1a8f184..1c6937e76f 100644 --- a/Services/WindowServer/ClientConnection.cpp +++ b/Services/WindowServer/ClientConnection.cpp @@ -479,6 +479,7 @@ OwnPtr ClientConnection::handle(co window->set_opacity(message.opacity()); window->set_size_increment(message.size_increment()); window->set_base_size(message.base_size()); + window->set_resize_aspect_ratio(message.resize_aspect_ratio()); window->invalidate(); if (window->type() == WindowType::MenuApplet) AppletManager::the().add_applet(*window); @@ -816,6 +817,20 @@ OwnPtr Client return make(); } +OwnPtr ClientConnection::handle(const Messages::WindowServer::SetWindowResizeAspectRatio& message) +{ + auto it = m_windows.find(message.window_id()); + if (it == m_windows.end()) { + did_misbehave("SetWindowResizeAspectRatioResponse: Bad window ID"); + return nullptr; + } + + auto& window = *it->value; + window.set_resize_aspect_ratio(message.resize_aspect_ratio()); + + return make(); +} + void ClientConnection::handle(const Messages::WindowServer::EnableDisplayLink&) { if (m_has_display_link) diff --git a/Services/WindowServer/ClientConnection.h b/Services/WindowServer/ClientConnection.h index d5b261329b..e45438cd2f 100644 --- a/Services/WindowServer/ClientConnection.h +++ b/Services/WindowServer/ClientConnection.h @@ -138,6 +138,7 @@ private: virtual OwnPtr handle(const Messages::WindowServer::SetSystemTheme&) override; virtual OwnPtr handle(const Messages::WindowServer::GetSystemTheme&) override; virtual OwnPtr handle(const Messages::WindowServer::SetWindowBaseSizeAndSizeIncrement&) override; + virtual OwnPtr handle(const Messages::WindowServer::SetWindowResizeAspectRatio&) override; virtual void handle(const Messages::WindowServer::EnableDisplayLink&) override; virtual void handle(const Messages::WindowServer::DisableDisplayLink&) override; virtual void handle(const Messages::WindowServer::SetWindowProgress&) override; diff --git a/Services/WindowServer/Window.cpp b/Services/WindowServer/Window.cpp index f089b10a75..df7886bb1c 100644 --- a/Services/WindowServer/Window.cpp +++ b/Services/WindowServer/Window.cpp @@ -297,7 +297,7 @@ void Window::set_maximized(bool maximized) { if (m_maximized == maximized) return; - if (maximized && !is_resizable()) + if (maximized && (!is_resizable() || resize_aspect_ratio().has_value())) return; set_tiled(WindowTileType::None); m_maximized = maximized; @@ -616,6 +616,9 @@ void Window::set_tiled(WindowTileType tiled) if (m_tiled == tiled) return; + if (resize_aspect_ratio().has_value()) + return; + m_tiled = tiled; if (tiled != WindowTileType::None) m_untiled_rect = m_rect; diff --git a/Services/WindowServer/Window.h b/Services/WindowServer/Window.h index cdf7c0ce05..8d6d245185 100644 --- a/Services/WindowServer/Window.h +++ b/Services/WindowServer/Window.h @@ -207,6 +207,9 @@ public: Gfx::IntSize size_increment() const { return m_size_increment; } void set_size_increment(const Gfx::IntSize& increment) { m_size_increment = increment; } + const Optional& resize_aspect_ratio() const { return m_resize_aspect_ratio; } + void set_resize_aspect_ratio(const Optional& ratio) { m_resize_aspect_ratio = ratio; } + Gfx::IntSize base_size() const { return m_base_size; } void set_base_size(const Gfx::IntSize& size) { m_base_size = size; } @@ -314,6 +317,7 @@ private: bool m_minimizable { false }; bool m_frameless { false }; bool m_resizable { false }; + Optional m_resize_aspect_ratio {}; bool m_listens_to_wm_events { false }; bool m_minimized { false }; bool m_maximized { false }; diff --git a/Services/WindowServer/WindowManager.cpp b/Services/WindowServer/WindowManager.cpp index 2d860dea60..3ab32955bc 100644 --- a/Services/WindowServer/WindowManager.cpp +++ b/Services/WindowServer/WindowManager.cpp @@ -643,6 +643,15 @@ bool WindowManager::process_ongoing_window_resize(const MouseEvent& event, Windo new_rect.set_height(m_resize_window->base_size().height() + vertical_incs * m_resize_window->size_increment().height()); } + if (m_resize_window->resize_aspect_ratio().has_value()) { + auto& ratio = m_resize_window->resize_aspect_ratio().value(); + if (abs(change_w) > abs(change_h)) { + new_rect.set_height(new_rect.width() * ratio.height() / ratio.width()); + } else { + new_rect.set_width(new_rect.height() * ratio.width() / ratio.height()); + } + } + // Second, set its position so that the sides of the window // that end up moving are the same ones as the user is dragging, // no matter which part of the logic above caused us to decide diff --git a/Services/WindowServer/WindowServer.ipc b/Services/WindowServer/WindowServer.ipc index 6f472cbab3..871898db81 100644 --- a/Services/WindowServer/WindowServer.ipc +++ b/Services/WindowServer/WindowServer.ipc @@ -43,6 +43,7 @@ endpoint WindowServer = 2 float opacity, Gfx::IntSize base_size, Gfx::IntSize size_increment, + Optional resize_aspect_ratio, i32 type, [UTF8] String title, i32 parent_window_id) => (i32 window_id) @@ -99,6 +100,7 @@ endpoint WindowServer = 2 GetSystemTheme() => ([UTF8] String theme_name) SetWindowBaseSizeAndSizeIncrement(i32 window_id, Gfx::IntSize base_size, Gfx::IntSize size_increment) => () + SetWindowResizeAspectRatio(i32 window_id, Optional resize_aspect_ratio) => () EnableDisplayLink() =| DisableDisplayLink() =|