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.
This commit is contained in:
thankyouverycool 2022-02-07 14:04:19 -05:00 committed by Andreas Kling
parent ee637b44fb
commit 1cd77fd1b4
Notes: sideshowbarker 2024-07-17 19:36:41 +09:00
2 changed files with 44 additions and 2 deletions

View File

@ -674,6 +674,7 @@ void WindowManager::start_window_move(Window& window, Gfx::IntPoint const& origi
m_move_window->set_default_positioned(false); m_move_window->set_default_positioned(false);
m_move_origin = origin; m_move_origin = origin;
m_move_window_origin = window.position(); 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<WindowGeometryOverlay>(window); m_geometry_overlay = Compositor::the().create_overlay<WindowGeometryOverlay>(window);
m_geometry_overlay->set_enabled(true); m_geometry_overlay->set_enabled(true);
window.invalidate(true, true); window.invalidate(true, true);
@ -774,7 +775,9 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event)
m_move_origin = event.position(); m_move_origin = event.position();
if (m_move_origin.y() <= secondary_deadzone + desktop.top()) if (m_move_origin.y() <= secondary_deadzone + desktop.top())
return true; 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(); m_move_window_origin = m_move_window->position();
} }
} else { } else {
@ -809,7 +812,9 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event)
bool force_titlebar_visible = !(m_keyboard_modifiers & Mod_Super); bool force_titlebar_visible = !(m_keyboard_modifiers & Mod_Super);
m_move_window->nudge_into_desktop(&cursor_screen, force_titlebar_visible); m_move_window->nudge_into_desktop(&cursor_screen, force_titlebar_visible);
} else if (pixels_moved_from_start > 5) { } 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_origin = event.position();
m_move_window_origin = m_move_window->position(); m_move_window_origin = m_move_window->position();
} }
@ -820,6 +825,33 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event)
return true; 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) bool WindowManager::process_ongoing_window_resize(MouseEvent const& event)
{ {
if (!m_resize_window) if (!m_resize_window)
@ -1181,6 +1213,12 @@ void WindowManager::process_mouse_event_for_window(HitTestResult& result, MouseE
auto& window = *result.window; auto& window = *result.window;
auto* blocking_modal_window = window.blocking_modal_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). // 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. // In those cases, the event is swallowed by the window manager.
if (!blocking_modal_window && window.is_movable()) { if (!blocking_modal_window && window.is_movable()) {

View File

@ -409,6 +409,8 @@ private:
bool is_considered_doubleclick(MouseEvent const&, DoubleClickInfo::ClickMetadata const&) const; 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; DoubleClickInfo m_double_click_info;
int m_double_click_speed { 0 }; int m_double_click_speed { 0 };
int m_max_distance_for_double_click { 4 }; int m_max_distance_for_double_click { 4 };
@ -423,6 +425,8 @@ private:
WeakPtr<Window> m_move_window; WeakPtr<Window> m_move_window;
Gfx::IntPoint m_move_origin; Gfx::IntPoint m_move_origin;
Gfx::IntPoint m_move_window_origin; Gfx::IntPoint m_move_window_origin;
Gfx::IntPoint m_move_window_cursor_position;
Gfx::IntPoint m_mouse_down_origin;
WeakPtr<Window> m_resize_window; WeakPtr<Window> m_resize_window;
WeakPtr<Window> m_resize_candidate; WeakPtr<Window> m_resize_candidate;