mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-14 02:10:36 +00:00
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:
parent
2b9bc605d2
commit
0fc2651303
Notes:
sideshowbarker
2024-07-18 20:37:41 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/0fc26513039
4 changed files with 32 additions and 31 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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&);
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue