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 76d8dbdd988..8b094a69e51 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 fa99c047f9d..f314b75d705 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 };