From eb43e2d544e10b9a9f6ff80c7d5f16f502afe781 Mon Sep 17 00:00:00 2001 From: Shannon Booth Date: Sat, 9 May 2020 15:57:25 +1200 Subject: [PATCH] WindowServer: Add basic search functionality in menus Perform a case insensitive search through the current menu. Jump to the first item matching all keys in the current search. Backspace can clear the current search, and the search will timeout after 3 seconds. --- Services/WindowServer/MenuManager.cpp | 27 +++++++++++++++++++++++++++ Services/WindowServer/MenuManager.h | 4 ++++ 2 files changed, 31 insertions(+) diff --git a/Services/WindowServer/MenuManager.cpp b/Services/WindowServer/MenuManager.cpp index 76d8dbdd98..8b094a69e5 100644 --- a/Services/WindowServer/MenuManager.cpp +++ b/Services/WindowServer/MenuManager.cpp @@ -42,6 +42,7 @@ namespace WindowServer { static MenuManager* s_the; +static constexpr int s_search_timeout = 3000; MenuManager& MenuManager::the() { @@ -59,6 +60,10 @@ MenuManager::MenuManager() m_window = Window::construct(*this, WindowType::Menubar); m_window->set_rect(menubar_rect()); + + m_search_timer = Core::Timer::create_single_shot(0, [this] { + m_current_search.clear(); + }); } MenuManager::~MenuManager() @@ -133,6 +138,26 @@ void MenuManager::event(Core::Event& event) return; } + if (key_event.key() == Key_Backspace) { + m_current_search.clear(); + return; + } + + if (m_current_menu && event.type() == Event::KeyDown + && ((key_event.key() >= Key_A && key_event.key() <= Key_Z) + || (key_event.key() >= Key_0 && key_event.key() <= Key_9))) { + m_current_search.append(key_event.character()); + m_search_timer->restart(s_search_timeout); + for (int i = 0; i < m_current_menu->item_count(); ++i) { + auto text = m_current_menu->item(i).text(); + if (text.to_lowercase().starts_with(m_current_search.to_string().to_lowercase())) { + m_current_menu->set_hovered_item(i); + return; + } + } + return; + } + if (event.type() == Event::KeyDown) { if (key_event.key() == Key_Left) { @@ -285,6 +310,7 @@ void MenuManager::close_everyone() menu->clear_hovered_item(); } m_open_menu_stack.clear(); + m_current_search.clear(); m_current_menu = nullptr; refresh(); } @@ -382,6 +408,7 @@ void MenuManager::set_current_menu(Menu* menu) return; } + m_current_search.clear(); m_current_menu = menu->make_weak_ptr(); } diff --git a/Services/WindowServer/MenuManager.h b/Services/WindowServer/MenuManager.h index fa99c047f9..f314b75d70 100644 --- a/Services/WindowServer/MenuManager.h +++ b/Services/WindowServer/MenuManager.h @@ -30,7 +30,9 @@ #include "MenuBar.h" #include "Window.h" #include +#include #include +#include namespace WindowServer { @@ -110,6 +112,8 @@ private: WeakPtr m_current_menu; Vector> m_open_menu_stack; + RefPtr m_search_timer; + StringBuilder m_current_search; WeakPtr m_system_menu; bool m_needs_window_resize { false };