WindowServer: Support Alt shortcuts inside menus as well

Menu items can now also have Alt shortcut, and they work the same way
top-level menu Alt shortcuts do. This replaces the previous "type to
search" mechanism we had in menus.
This commit is contained in:
Andreas Kling 2021-04-09 13:48:26 +02:00
parent 2b9bc605d2
commit 0fc2651303
4 changed files with 32 additions and 31 deletions

View file

@ -43,7 +43,7 @@
namespace WindowServer {
static u32 find_ampersand_shortcut_character(const String& string)
u32 find_ampersand_shortcut_character(const StringView& string)
{
Utf8View utf8_view { string };
for (auto it = utf8_view.begin(); it != utf8_view.end(); ++it) {
@ -265,7 +265,7 @@ void Menu::draw()
auto& previous_font = painter.font();
if (item.is_default())
painter.set_font(Gfx::FontDatabase::default_bold_font());
painter.draw_text(text_rect, item.text(), Gfx::TextAlignment::CenterLeft, text_color);
painter.draw_ui_text(text_rect, item.text(), painter.font(), Gfx::TextAlignment::CenterLeft, text_color);
if (!item.shortcut_text().is_empty()) {
painter.draw_text(item.rect().translated(-right_padding(), 0), item.shortcut_text(), Gfx::TextAlignment::CenterRight, text_color);
}

View file

@ -42,10 +42,10 @@ namespace WindowServer {
class ClientConnection;
class MenuBar;
class Event;
class Menu final : public Core::Object {
C_OBJECT(Menu)
C_OBJECT(Menu);
public:
Menu(ClientConnection*, int menu_id, String name);
virtual ~Menu() override;
@ -160,4 +160,6 @@ private:
int m_max_scroll_offset { 0 };
};
u32 find_ampersand_shortcut_character(const StringView&);
}

View file

@ -30,11 +30,11 @@
#include <WindowServer/MenuManager.h>
#include <WindowServer/Screen.h>
#include <WindowServer/WindowManager.h>
#include <ctype.h>
namespace WindowServer {
static MenuManager* s_the;
static constexpr int s_search_timeout = 3000;
MenuManager& MenuManager::the()
{
@ -45,10 +45,6 @@ MenuManager& MenuManager::the()
MenuManager::MenuManager()
{
s_the = this;
m_search_timer = Core::Timer::create_single_shot(0, [this] {
m_current_search.clear();
});
}
MenuManager::~MenuManager()
@ -91,23 +87,33 @@ 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_code_point(key_event.code_point());
m_search_timer->restart(s_search_timeout);
// FIXME: Maybe cache this on the menu instead of recomputing it on every alphanumeric menu keystroke?
HashMap<u32, size_t> alt_shortcut_to_item_index;
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;
}
auto& item = m_current_menu->item(i);
if (!item.is_enabled())
continue;
auto alt_shortcut = find_ampersand_shortcut_character(item.text());
if (!alt_shortcut)
continue;
alt_shortcut_to_item_index.set(tolower(alt_shortcut), i);
}
auto it = alt_shortcut_to_item_index.find(tolower(key_event.code_point()));
if (it != alt_shortcut_to_item_index.end()) {
auto& item = m_current_menu->item(it->value);
m_current_menu->set_hovered_item(it->value);
if (item.is_submenu())
m_current_menu->descend_into_submenu_at_hovered_item();
else
m_current_menu->open_hovered_item(false);
}
return;
}
@ -246,7 +252,6 @@ void MenuManager::close_everyone()
menu->clear_hovered_item();
}
m_open_menu_stack.clear();
m_current_search.clear();
clear_current_menu();
refresh();
}
@ -372,8 +377,6 @@ void MenuManager::set_current_menu(Menu* menu)
return;
}
m_current_search.clear();
Menu* previous_current_menu = m_current_menu;
m_current_menu = menu;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -31,13 +31,12 @@
#include "Window.h"
#include <AK/HashMap.h>
#include <AK/StringBuilder.h>
#include <LibCore/Object.h>
#include <LibCore/Timer.h>
namespace WindowServer {
class MenuManager final : public Core::Object {
C_OBJECT(MenuManager)
C_OBJECT(MenuManager);
public:
static MenuManager& the();
@ -80,9 +79,6 @@ private:
WeakPtr<Window> m_previous_input_window;
Vector<WeakPtr<Menu>> m_open_menu_stack;
RefPtr<Core::Timer> m_search_timer;
StringBuilder m_current_search;
int m_theme_index { 0 };
WeakPtr<Menu> m_hovered_menu;