From 1cd77fd1b478969b80aa967a7d5bfd8ebfebd0a9 Mon Sep 17 00:00:00 2001 From: thankyouverycool <66646555+thankyouverycool@users.noreply.github.com> Date: Mon, 7 Feb 2022 14:04:19 -0500 Subject: [PATCH] WindowServer: Preserve cursor position when dragging between states Previously windows would end up in awkward positions relative to the move cursor when dragging between tile types or unmaximizing. This feels a bit more ergonomic. --- .../Services/WindowServer/WindowManager.cpp | 42 ++++++++++++++++++- .../Services/WindowServer/WindowManager.h | 4 ++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/Userland/Services/WindowServer/WindowManager.cpp b/Userland/Services/WindowServer/WindowManager.cpp index 1899b6e60c..e3fec05163 100644 --- a/Userland/Services/WindowServer/WindowManager.cpp +++ b/Userland/Services/WindowServer/WindowManager.cpp @@ -674,6 +674,7 @@ void WindowManager::start_window_move(Window& window, Gfx::IntPoint const& origi m_move_window->set_default_positioned(false); m_move_origin = origin; m_move_window_origin = window.position(); + m_move_window_cursor_position = window.is_tiled() || window.is_maximized() ? to_floating_cursor_position(m_mouse_down_origin) : m_mouse_down_origin; m_geometry_overlay = Compositor::the().create_overlay(window); m_geometry_overlay->set_enabled(true); window.invalidate(true, true); @@ -774,7 +775,9 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event) m_move_origin = event.position(); if (m_move_origin.y() <= secondary_deadzone + desktop.top()) return true; - m_move_window->set_maximized(false, event.position()); + Gfx::IntPoint adjusted_position = event.position().translated(-m_move_window_cursor_position); + m_move_window->set_maximized(false); + m_move_window->move_to(adjusted_position); m_move_window_origin = m_move_window->position(); } } else { @@ -809,7 +812,9 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event) bool force_titlebar_visible = !(m_keyboard_modifiers & Mod_Super); m_move_window->nudge_into_desktop(&cursor_screen, force_titlebar_visible); } else if (pixels_moved_from_start > 5) { - m_move_window->set_untiled(event.position()); + Gfx::IntPoint adjusted_position = event.position().translated(-m_move_window_cursor_position); + m_move_window->set_untiled(); + m_move_window->move_to(adjusted_position); m_move_origin = event.position(); m_move_window_origin = m_move_window->position(); } @@ -820,6 +825,33 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event) return true; } +Gfx::IntPoint WindowManager::to_floating_cursor_position(Gfx::IntPoint const& origin) const +{ + VERIFY(m_move_window); + + Gfx::IntPoint new_position; + auto dist_from_right = m_move_window->rect().width() - origin.x(); + auto dist_from_bottom = m_move_window->rect().height() - origin.y(); + auto floating_width = m_move_window->floating_rect().width(); + auto floating_height = m_move_window->floating_rect().height(); + + if (origin.x() < dist_from_right && origin.x() < floating_width / 2) + new_position.set_x(origin.x()); + else if (dist_from_right < origin.x() && dist_from_right < floating_width / 2) + new_position.set_x(floating_width - dist_from_right); + else + new_position.set_x(floating_width / 2); + + if (origin.y() < dist_from_bottom && origin.y() < floating_height / 2) + new_position.set_y(origin.y()); + else if (dist_from_bottom < origin.y() && dist_from_bottom < floating_height / 2) + new_position.set_y(floating_height - dist_from_bottom); + else + new_position.set_y(floating_height / 2); + + return new_position; +} + bool WindowManager::process_ongoing_window_resize(MouseEvent const& event) { if (!m_resize_window) @@ -1181,6 +1213,12 @@ void WindowManager::process_mouse_event_for_window(HitTestResult& result, MouseE auto& window = *result.window; auto* blocking_modal_window = window.blocking_modal_window(); + if (event.type() == Event::MouseDown) { + m_mouse_down_origin = result.is_frame_hit + ? event.position().translated(-window.position()) + : result.window_relative_position; + } + // First check if we should initiate a move or resize (Super+LMB or Super+RMB). // In those cases, the event is swallowed by the window manager. if (!blocking_modal_window && window.is_movable()) { diff --git a/Userland/Services/WindowServer/WindowManager.h b/Userland/Services/WindowServer/WindowManager.h index d7f8214222..3be36cbc59 100644 --- a/Userland/Services/WindowServer/WindowManager.h +++ b/Userland/Services/WindowServer/WindowManager.h @@ -409,6 +409,8 @@ private: bool is_considered_doubleclick(MouseEvent const&, DoubleClickInfo::ClickMetadata const&) const; + Gfx::IntPoint to_floating_cursor_position(Gfx::IntPoint const&) const; + DoubleClickInfo m_double_click_info; int m_double_click_speed { 0 }; int m_max_distance_for_double_click { 4 }; @@ -423,6 +425,8 @@ private: WeakPtr m_move_window; Gfx::IntPoint m_move_origin; Gfx::IntPoint m_move_window_origin; + Gfx::IntPoint m_move_window_cursor_position; + Gfx::IntPoint m_mouse_down_origin; WeakPtr m_resize_window; WeakPtr m_resize_candidate;