diff --git a/Userland/Services/WindowServer/CMakeLists.txt b/Userland/Services/WindowServer/CMakeLists.txt index ed975c387e..77875a349f 100644 --- a/Userland/Services/WindowServer/CMakeLists.txt +++ b/Userland/Services/WindowServer/CMakeLists.txt @@ -45,5 +45,5 @@ set(GENERATED_SOURCES ) serenity_bin(WindowServer) -target_link_libraries(WindowServer PRIVATE LibCore LibFileSystem LibGfx LibThreading LibIPC LibMain) +target_link_libraries(WindowServer PRIVATE LibCore LibFileSystem LibKeyboard LibGfx LibThreading LibIPC LibMain) serenity_install_headers(Services/WindowServer) diff --git a/Userland/Services/WindowServer/Window.cpp b/Userland/Services/WindowServer/Window.cpp index cee941835d..3ca0538613 100644 --- a/Userland/Services/WindowServer/Window.cpp +++ b/Userland/Services/WindowServer/Window.cpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace WindowServer { @@ -516,20 +517,32 @@ void Window::handle_keydown_event(KeyEvent const& event) return; } if (event.modifiers() == Mod_Alt && event.code_point() && m_menubar.has_menus()) { - Menu* menu_to_open = nullptr; - m_menubar.for_each_menu([&](Menu& menu) { - if (to_ascii_lowercase(menu.alt_shortcut_character()) == to_ascii_lowercase(event.code_point())) { - menu_to_open = &menu; - return IterationDecision::Break; - } - return IterationDecision::Continue; - }); + // When handling alt shortcuts, we only care about the key that has been pressed in addition + // to alt, not the code point that has been mapped to alt+[key], so we have to look up the + // scancode directly from the "unmodified" character map. + auto character_map_or_error = Keyboard::CharacterMap::fetch_system_map(); + if (!character_map_or_error.is_error()) { + auto& character_map = character_map_or_error.value(); - if (menu_to_open) { - frame().open_menubar_menu(*menu_to_open); - if (!menu_to_open->is_empty()) - menu_to_open->set_hovered_index(0); - return; + // The lowest byte serves as our index into the character table. + auto index = event.scancode() & 0xff; + u32 character = to_ascii_lowercase(character_map.character_map_data().map[index]); + + Menu* menu_to_open = nullptr; + m_menubar.for_each_menu([&](Menu& menu) { + if (to_ascii_lowercase(menu.alt_shortcut_character()) == character) { + menu_to_open = &menu; + return IterationDecision::Break; + } + return IterationDecision::Continue; + }); + + if (menu_to_open) { + frame().open_menubar_menu(*menu_to_open); + if (!menu_to_open->is_empty()) + menu_to_open->set_hovered_index(0); + return; + } } } m_client->async_key_down(m_window_id, (u32)event.code_point(), (u32)event.key(), event.modifiers(), (u32)event.scancode()); diff --git a/Userland/Services/WindowServer/main.cpp b/Userland/Services/WindowServer/main.cpp index 6b0176e1fb..c71efa5f76 100644 --- a/Userland/Services/WindowServer/main.cpp +++ b/Userland/Services/WindowServer/main.cpp @@ -25,7 +25,7 @@ RefPtr g_config; ErrorOr serenity_main(Main::Arguments) { - TRY(Core::System::pledge("stdio video thread sendfd recvfd accept rpath wpath cpath unix proc sigaction exec tty")); + TRY(Core::System::pledge("stdio video thread sendfd recvfd accept rpath wpath cpath unix proc getkeymap sigaction exec tty")); TRY(Core::System::unveil("/res", "r")); TRY(Core::System::unveil("/tmp", "cw")); TRY(Core::System::unveil("/etc/WindowServer.ini", "rwc")); @@ -42,7 +42,7 @@ ErrorOr serenity_main(Main::Arguments) act.sa_flags = SA_NOCLDWAIT; act.sa_handler = SIG_IGN; TRY(Core::System::sigaction(SIGCHLD, &act, nullptr)); - TRY(Core::System::pledge("stdio video thread sendfd recvfd accept rpath wpath cpath unix proc exec tty")); + TRY(Core::System::pledge("stdio video thread sendfd recvfd accept rpath wpath cpath unix proc getkeymap exec tty")); WindowServer::g_config = TRY(Core::ConfigFile::open("/etc/WindowServer.ini", Core::ConfigFile::AllowWriting::Yes)); auto theme_name = WindowServer::g_config->read_entry("Theme", "Name", "Default"); @@ -73,7 +73,7 @@ ErrorOr serenity_main(Main::Arguments) WindowServer::EventLoop loop; - TRY(Core::System::pledge("stdio video thread sendfd recvfd accept rpath wpath cpath unix proc exec")); + TRY(Core::System::pledge("stdio video thread sendfd recvfd accept rpath wpath cpath unix proc getkeymap exec")); // First check which screens are explicitly configured {