Unable to focus on second level GTK menu using keybindings on Wayland
If we want to open a GTK menu on menubar with keybindings, and the first menuitem in menu has a second level menu, the second menu should be focused and popup with a delay. For example, with following program, we can press Alt+H
to open the menu:
#include <gtk/gtk.h>
static void on_activate(GtkApplication *app, gpointer data)
{
GtkWidget *window = gtk_application_window_new(app);
gtk_window_set_title(GTK_WINDOW(window), "gtk-test");
GtkWidget *menu_bar = gtk_menu_bar_new();
GtkWidget *menu = gtk_menu_new();
GtkWidget *submenu = gtk_menu_new();
GtkWidget *menu_item = gtk_menu_item_new_with_mnemonic("_Hello");
GtkWidget *menu_item1 = gtk_menu_item_new_with_label("Hello1");
GtkWidget *menu_item2 = gtk_menu_item_new_with_label("Hello2");
GtkWidget *menu_item3 = gtk_menu_item_new_with_label("Hello3");
GtkWidget *menu_item4 = gtk_menu_item_new_with_label("Hello4");
GtkWidget *menu_item5 = gtk_menu_item_new_with_label("Hello5");
gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menu_item4);
gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menu_item5);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item1), submenu);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item1);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item2);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item3);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), menu);
gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), menu_item);
gtk_container_add(GTK_CONTAINER(window), menu_bar);
gtk_widget_show_all(window);
}
int main(int argc, char *argv[])
{
GtkApplication *app = gtk_application_new("moe.alynx.gtk-test", G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK(on_activate), NULL);
int status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
}
But under mutter/wayland, there is a bug, if you press Alt+H
and release Alt
very very fast (before second level menu popup), you'll see menus disappear. You need to reproduce this in some specific key sequences like:
- Press
Alt+H
, quickly releaseH
, then quickly releaseAlt
, all happens before 2nd level menu popup. -
Or press
Alt+H
, quickly releseAlt
, but don't releaseH
.
This is a very strange problem, and after 3-days debug, I find the reason happens because this commit 2dbacfa8d6
, revert this commit fix it.
I have read !180 (merged) by @jadahl related to this commit, and find some reason why this happens: when menu popup, mutter will check whether key_down_serial
is correct, and if we release key too quick, it will check key_up_serial
instead, but also key_down_keycode
should equals to key_up_keycode
, this logic is correct when we have 1-key keybindings, but for 2-key-keybindings like this, if we release Alt
in the previous 2 situations, key_down_keycode
is h
but key_up_keycode
is Alt
at that time, so it failed.
This leads into some problem in production, for example we are using openQA to test openSUSE, and openQA uses Qemu's send-key call to send menu accelerators, because of this logic, menu cannot popup, and test failed.
@jadahl I cannot understand your commit message, but at my case revert this commit does not make some bugs, would you mind to talking about the logic here? In my opinion we may revert it, or find some better way to handle multi-keys keybindings here, because users may have more keys for a menu accelerator. Thanks!