summaryrefslogtreecommitdiff
path: root/Servers
diff options
context:
space:
mode:
authorShannon Booth <shannon.ml.booth@gmail.com>2020-01-19 12:13:26 +1300
committerAndreas Kling <kling@serenityos.org>2020-01-19 08:45:23 +0100
commitead1273632f36c52c6496b992d9aa74dbc18bc75 (patch)
treed3f64790d6d8b8bc3a731ff57577f3dec0f8b188 /Servers
parent6ea70f57247389311b1730821dffb3a55223417b (diff)
downloadserenity-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.cpp20
-rw-r--r--Servers/WindowServer/WSMenu.h2
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 };