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:
parent
ee637b44fb
commit
1cd77fd1b4
Notes:
sideshowbarker
2024-07-17 19:36:41 +09:00
Author: https://github.com/thankyouverycool Commit: https://github.com/SerenityOS/serenity/commit/1cd77fd1b47 Pull-request: https://github.com/SerenityOS/serenity/pull/12358 Issue: https://github.com/SerenityOS/serenity/issues/5065
2 changed files with 44 additions and 2 deletions
Userland/Services/WindowServer
|
@ -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<WindowGeometryOverlay>(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()) {
|
||||
|
|
|
@ -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<Window> 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<Window> m_resize_window;
|
||||
WeakPtr<Window> m_resize_candidate;
|
||||
|
|
Loading…
Add table
Reference in a new issue