1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-23 09:17:36 +00:00

WindowServer: Make automatic menu dismissal feel more "natural."

This commit is contained in:
Andreas Kling 2019-02-11 13:59:26 +01:00
parent 43d9994d93
commit 3c863e0ffa
4 changed files with 29 additions and 12 deletions

View file

@ -3,6 +3,7 @@
#include "WSWindow.h" #include "WSWindow.h"
#include "WSMessage.h" #include "WSMessage.h"
#include "WSMessageLoop.h" #include "WSMessageLoop.h"
#include "WSWindowManager.h"
#include <SharedGraphics/Painter.h> #include <SharedGraphics/Painter.h>
#include <SharedGraphics/Font.h> #include <SharedGraphics/Font.h>
@ -131,6 +132,7 @@ void WSMenu::did_activate(WSMenuItem& item)
{ {
if (on_item_activation) if (on_item_activation)
on_item_activation(item); on_item_activation(item);
close();
} }
WSMenuItem* WSMenu::item_at(const Point& position) WSMenuItem* WSMenu::item_at(const Point& position)
@ -142,3 +144,8 @@ WSMenuItem* WSMenu::item_at(const Point& position)
} }
return nullptr; return nullptr;
} }
void WSMenu::close()
{
WSWindowManager::the().close_menu(*this);
};

View file

@ -62,6 +62,8 @@ public:
Function<void(WSMenuItem&)> on_item_activation; Function<void(WSMenuItem&)> on_item_activation;
void close();
private: private:
void did_activate(WSMenuItem&); void did_activate(WSMenuItem&);

View file

@ -199,7 +199,7 @@ WSWindowManager::WSWindowManager()
menubar->add_menu(move(menu)); menubar->add_menu(move(menu));
} }
{ {
auto menu = make<WSMenu>("Application"); auto menu = make<WSMenu>("Terminal");
menu->add_item(make<WSMenuItem>(5, "Foo.")); menu->add_item(make<WSMenuItem>(5, "Foo."));
menu->add_item(make<WSMenuItem>(6, "Bar?")); menu->add_item(make<WSMenuItem>(6, "Bar?"));
menu->add_item(make<WSMenuItem>(7, "Baz!")); menu->add_item(make<WSMenuItem>(7, "Baz!"));
@ -380,8 +380,9 @@ void WSWindowManager::notify_rect_changed(WSWindow& window, const Rect& old_rect
void WSWindowManager::handle_menu_mouse_event(WSMenu& menu, WSMouseEvent& event) void WSWindowManager::handle_menu_mouse_event(WSMenu& menu, WSMouseEvent& event)
{ {
bool should_open_menu = (event.type() == WSMouseEvent::MouseMove && event.buttons() & (unsigned)MouseButton::Left) bool is_hover_with_any_menu_open = event.type() == WSMouseEvent::MouseMove && m_current_menu;
|| (event.type() == WSMouseEvent::MouseDown && event.button() == MouseButton::Left); bool is_mousedown_with_left_button = event.type() == WSMouseEvent::MouseDown && event.button() == MouseButton::Left;
bool should_open_menu = &menu != m_current_menu && (is_hover_with_any_menu_open || is_mousedown_with_left_button);
if (should_open_menu) { if (should_open_menu) {
if (m_current_menu == &menu) if (m_current_menu == &menu)
@ -393,7 +394,7 @@ void WSWindowManager::handle_menu_mouse_event(WSMenu& menu, WSMouseEvent& event)
m_current_menu = &menu; m_current_menu = &menu;
return; return;
} }
if (event.type() == WSMouseEvent::MouseUp && event.button() == MouseButton::Left) { if (event.type() == WSMouseEvent::MouseDown && event.button() == MouseButton::Left) {
close_current_menu(); close_current_menu();
return; return;
} }
@ -486,16 +487,16 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event)
return; return;
} }
if (m_current_menu && m_current_menu->hovered_item() && !m_current_menu->menu_window()->rect().contains(event.position())) { if (m_current_menu) {
m_current_menu->clear_hovered_item(); bool event_is_inside_current_menu = m_current_menu->menu_window()->rect().contains(event.position());
if (!event_is_inside_current_menu) {
if (m_current_menu->hovered_item())
m_current_menu->clear_hovered_item();
if (event.type() == WSMessage::MouseDown || event.type() == WSMessage::MouseUp)
close_current_menu();
}
} }
// FIXME: Figure out an automatic menu dismissal logic that feels right.
#if 0
if (m_current_menu && event.type() == WSMouseEvent::MouseUp && event.button() == MouseButton::Left)
close_current_menu();
#endif
for (auto* window = m_windows_in_order.tail(); window; window = window->prev()) { for (auto* window = m_windows_in_order.tail(); window; window = window->prev()) {
if (!window->is_visible()) if (!window->is_visible())
continue; continue;
@ -764,3 +765,8 @@ void WSWindowManager::flush(const Rect& a_rect)
} }
} }
void WSWindowManager::close_menu(WSMenu& menu)
{
ASSERT(m_current_menu == &menu);
close_current_menu();
}

View file

@ -51,6 +51,8 @@ public:
Font& font() { return *m_font; } Font& font() { return *m_font; }
const Font& font() const { return *m_font; } const Font& font() const { return *m_font; }
void close_menu(WSMenu&);
private: private:
WSWindowManager(); WSWindowManager();
virtual ~WSWindowManager() override; virtual ~WSWindowManager() override;