diff options
author | Shannon Booth <shannon.ml.booth@gmail.com> | 2020-01-19 12:13:26 +1300 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-01-19 08:45:23 +0100 |
commit | ead1273632f36c52c6496b992d9aa74dbc18bc75 (patch) | |
tree | d3f64790d6d8b8bc3a731ff57577f3dec0f8b188 /Servers | |
parent | 6ea70f57247389311b1730821dffb3a55223417b (diff) | |
download | serenity-ead1273632f36c52c6496b992d9aa74dbc18bc75.zip |
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
Diffstat (limited to 'Servers')
-rw-r--r-- | Servers/WindowServer/WSMenu.cpp | 20 | ||||
-rw-r--r-- | 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 3d0ee4c5c8..cfcc88a42d 100644 --- a/Servers/WindowServer/WSMenu.cpp +++ b/Servers/WindowServer/WSMenu.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2020, Shannon Booth <shannon.ml.booth@gmail.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,6 +38,7 @@ #include <LibDraw/GraphicsBitmap.h> #include <LibDraw/Painter.h> #include <LibDraw/StylePainter.h> +#include <LibDraw/Triangle.h> #include <WindowServer/WSClientConnection.h> #include <WindowServer/WindowClientEndpoint.h> @@ -279,7 +281,23 @@ void WSMenu::event(CEvent& event) { if (event.type() == WSEvent::MouseMove) { ASSERT(menu_window()); - int index = item_index_at(static_cast<const WSMouseEvent&>(event).position()); + auto mouse_event = static_cast<const WSMouseEvent&>(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 2ecb4bccb6..8aea486501 100644 --- a/Servers/WindowServer/WSMenu.h +++ b/Servers/WindowServer/WSMenu.h @@ -133,7 +133,7 @@ private: WeakPtr<WSWindow> 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 }; |