From ead1273632f36c52c6496b992d9aa74dbc18bc75 Mon Sep 17 00:00:00 2001 From: Shannon Booth Date: Sun, 19 Jan 2020 12:13:26 +1300 Subject: [PATCH] WindowServer: More natural mouse menu navigation Use an imaginary triangle between the top and bottom of the submenu of a hovered item to determine whether the mouse is moving towards the submenu. If it is, we do not update the hovered item. This allows the submenu to stay open, making for much easier menu navigation. Closes #1094 --- Servers/WindowServer/WSMenu.cpp | 20 +++++++++++++++++++- Servers/WindowServer/WSMenu.h | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Servers/WindowServer/WSMenu.cpp b/Servers/WindowServer/WSMenu.cpp index 3d0ee4c5c8a1c2..cfcc88a42dc553 100644 --- a/Servers/WindowServer/WSMenu.cpp +++ b/Servers/WindowServer/WSMenu.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2020, Shannon Booth * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,6 +38,7 @@ #include #include #include +#include #include #include @@ -279,7 +281,23 @@ void WSMenu::event(CEvent& event) { if (event.type() == WSEvent::MouseMove) { ASSERT(menu_window()); - int index = item_index_at(static_cast(event).position()); + auto mouse_event = static_cast(event); + + if (hovered_item() && hovered_item()->is_submenu()) { + + auto item = *hovered_item(); + auto submenu_top_left = item.rect().location() + Point { item.rect().width(), 0 }; + auto submenu_bottom_left = submenu_top_left + Point { 0, item.submenu()->height() }; + + auto safe_hover_triangle = Triangle { m_last_position_in_hover, submenu_top_left, submenu_bottom_left }; + m_last_position_in_hover = mouse_event.position(); + + // Don't update the hovered item if mouse is moving towards a submenu + if (safe_hover_triangle.contains(mouse_event.position())) + return; + } + + int index = item_index_at(mouse_event.position()); if (m_hovered_item_index == index) return; m_hovered_item_index = index; diff --git a/Servers/WindowServer/WSMenu.h b/Servers/WindowServer/WSMenu.h index 2ecb4bccb6c395..8aea48650164fe 100644 --- a/Servers/WindowServer/WSMenu.h +++ b/Servers/WindowServer/WSMenu.h @@ -133,7 +133,7 @@ class WSMenu final : public CObject { WeakPtr m_window_menu_of; bool m_is_window_menu_open = { false }; - + Point m_last_position_in_hover; int m_theme_index_at_last_paint { -1 }; int m_hovered_item_index { -1 }; bool m_in_submenu { false };