From 503aebaefc7fbda98c3411b927f3c2bea56170aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Offenh=C3=A4user?= Date: Sat, 5 Dec 2020 02:26:21 +0100 Subject: [PATCH] WindowServer: Allow for more flexible tiling The desktop can now be split up into halves (both vertical and horizontal) and quarters by dragging a window into the corresponding edge or corner. This makes tiling behave more like you would expect from similiar window managers. --- Services/WindowServer/Window.cpp | 42 ++++++++++++++++++++++--- Services/WindowServer/Window.h | 6 ++++ Services/WindowServer/WindowManager.cpp | 30 ++++++++++++------ 3 files changed, 64 insertions(+), 14 deletions(-) diff --git a/Services/WindowServer/Window.cpp b/Services/WindowServer/Window.cpp index 6c1c5275f3..d1c007dc6a 100644 --- a/Services/WindowServer/Window.cpp +++ b/Services/WindowServer/Window.cpp @@ -598,19 +598,53 @@ void Window::set_fullscreen(bool fullscreen) Gfx::IntRect Window::tiled_rect(WindowTileType tiled) const { int frame_width = (m_frame.rect().width() - m_rect.width()) / 2; + int title_bar_height = m_frame.title_bar_rect().height(); + int menu_height = WindowManager::the().maximized_window_rect(*this).y(); + int max_height = WindowManager::the().maximized_window_rect(*this).height(); + switch (tiled) { case WindowTileType::None: return m_untiled_rect; case WindowTileType::Left: return Gfx::IntRect(0, - WindowManager::the().maximized_window_rect(*this).y(), + menu_height, Screen::the().width() / 2 - frame_width, - WindowManager::the().maximized_window_rect(*this).height()); + max_height); case WindowTileType::Right: return Gfx::IntRect(Screen::the().width() / 2 + frame_width, - WindowManager::the().maximized_window_rect(*this).y(), + menu_height, Screen::the().width() / 2 - frame_width, - WindowManager::the().maximized_window_rect(*this).height()); + max_height); + case WindowTileType::Top: + return Gfx::IntRect(0, + menu_height, + Screen::the().width() - frame_width, + (max_height - title_bar_height) / 2 - frame_width); + case WindowTileType::Bottom: + return Gfx::IntRect(0, + menu_height + (title_bar_height + max_height) / 2 + frame_width, + Screen::the().width() - frame_width, + (max_height - title_bar_height) / 2 - frame_width); + case WindowTileType::TopLeft: + return Gfx::IntRect(0, + menu_height, + Screen::the().width() / 2 - frame_width, + (max_height - title_bar_height) / 2 - frame_width); + case WindowTileType::TopRight: + return Gfx::IntRect(Screen::the().width() / 2 + frame_width, + menu_height, + Screen::the().width() / 2 - frame_width, + (max_height - title_bar_height) / 2 - frame_width); + case WindowTileType::BottomLeft: + return Gfx::IntRect(0, + menu_height + (title_bar_height + max_height) / 2 + frame_width, + Screen::the().width() / 2 - frame_width, + (max_height - title_bar_height) / 2); + case WindowTileType::BottomRight: + return Gfx::IntRect(Screen::the().width() / 2 + frame_width, + menu_height + (title_bar_height + max_height) / 2 + frame_width, + Screen::the().width() / 2 - frame_width, + (max_height - title_bar_height) / 2); default: ASSERT_NOT_REACHED(); } diff --git a/Services/WindowServer/Window.h b/Services/WindowServer/Window.h index 2ff46c2ce9..75e7175a41 100644 --- a/Services/WindowServer/Window.h +++ b/Services/WindowServer/Window.h @@ -55,6 +55,12 @@ enum class WindowTileType { None = 0, Left, Right, + Top, + Bottom, + TopLeft, + TopRight, + BottomLeft, + BottomRight }; enum class PopupMenuItem { diff --git a/Services/WindowServer/WindowManager.cpp b/Services/WindowServer/WindowManager.cpp index 68291c016a..b25c72c82b 100644 --- a/Services/WindowServer/WindowManager.cpp +++ b/Services/WindowServer/WindowManager.cpp @@ -528,7 +528,8 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event, Window*& hove #endif - const int maximization_deadzone = 2; + const int tiling_deadzone = 10; + const int secondary_deadzone = 2; if (m_move_window->is_maximized()) { auto pixels_moved_from_start = event.position().pixels_moved(m_move_origin); @@ -536,7 +537,7 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event, Window*& hove if (pixels_moved_from_start > 5) { // dbg() << "[WM] de-maximizing window"; m_move_origin = event.position(); - if (m_move_origin.y() <= maximization_deadzone) + if (m_move_origin.y() <= secondary_deadzone) return true; auto width_before_resize = m_move_window->width(); m_move_window->set_maximized(false); @@ -546,17 +547,26 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event, Window*& hove } else { bool is_resizable = m_move_window->is_resizable(); auto pixels_moved_from_start = event.position().pixels_moved(m_move_origin); - const int tiling_deadzone = 5; + auto desktop = desktop_rect(); - if (is_resizable && event.y() <= maximization_deadzone) { - m_move_window->set_tiled(WindowTileType::None); - m_move_window->set_maximized(true); - return true; - } if (is_resizable && event.x() <= tiling_deadzone) { - m_move_window->set_tiled(WindowTileType::Left); + if (event.y() <= tiling_deadzone + desktop.top()) + m_move_window->set_tiled(WindowTileType::TopLeft); + else if (event.y() >= desktop.height() - tiling_deadzone) + m_move_window->set_tiled(WindowTileType::BottomLeft); + else + m_move_window->set_tiled(WindowTileType::Left); } else if (is_resizable && event.x() >= Screen::the().width() - tiling_deadzone) { - m_move_window->set_tiled(WindowTileType::Right); + if (event.y() <= tiling_deadzone + desktop.top()) + m_move_window->set_tiled(WindowTileType::TopRight); + else if (event.y() >= desktop.height() - tiling_deadzone) + m_move_window->set_tiled(WindowTileType::BottomRight); + else + m_move_window->set_tiled(WindowTileType::Right); + } else if (is_resizable && event.y() <= secondary_deadzone + desktop.top()) { + m_move_window->set_tiled(WindowTileType::Top); + } else if (is_resizable && event.y() >= desktop.bottom() - secondary_deadzone) { + m_move_window->set_tiled(WindowTileType::Bottom); } else if (pixels_moved_from_start > 5 || m_move_window->tiled() == WindowTileType::None) { m_move_window->set_tiled(WindowTileType::None); Gfx::IntPoint pos = m_move_window_origin.translated(event.position() - m_move_origin);