Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closing a menu where an item displays a tooltip from a layer-shell window causes a protocol error #178

Closed
Tamaranch opened this issue Mar 25, 2024 · 2 comments · Fixed by #190

Comments

@Tamaranch
Copy link

Tamaranch commented Mar 25, 2024

If the window is not layer-shell, GTK displays a warning, but this does not cause a protocol error.

Code to reproduce the issue:

static gboolean
press (GtkWidget *widget,
       GdkEventButton *event,
       gpointer data)
{
  gtk_menu_popup_at_pointer (data, (GdkEvent *) event);
  return FALSE;
}

gint main (gint argc, gchar **argv)
{
  gtk_init (&argc, &argv);

  GtkWidget *menu = gtk_menu_new ();
  GtkWidget *item = gtk_menu_item_new_with_label ("item1");
  gtk_widget_set_tooltip_text (item, "tooltip1");
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
  item = gtk_menu_item_new_with_label ("item2");
  gtk_widget_set_tooltip_text (item, "tooltip2");
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
  item = gtk_menu_item_new_with_label ("item3");
  gtk_widget_set_tooltip_text (item, "tooltip3");
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
  gtk_widget_show_all (menu);
  gtk_widget_hide (menu);

  GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  GtkWidget *widget = gtk_button_new_with_label ("press me");
  gtk_layer_init_for_window (GTK_WINDOW (window));
  gtk_layer_set_keyboard_mode (GTK_WINDOW (window), GTK_LAYER_SHELL_KEYBOARD_MODE_ON_DEMAND);
  gtk_container_add (GTK_CONTAINER (window), widget);
  g_signal_connect (widget, "button-press-event", G_CALLBACK (press), menu);
  gtk_widget_show_all (window);

  GMainLoop *loop = g_main_loop_new (NULL, FALSE);
  g_signal_connect_swapped (window, "destroy", G_CALLBACK (g_main_loop_quit), loop);
  g_main_loop_run (loop);
  g_main_loop_unref (loop);
}

Steps to reproduce the issue:

  • Press the button
  • Hover over a menu item to display the tooltip
  • Press Escape

I get these logs in labwc, but it crashes with any compositor:

[2714599.198] [email protected](848, 36449698, 1, 1)
[2714613.766]  -> [email protected]()
[2714613.883]  -> [email protected]()
[2714613.940]  -> [email protected]()
[2714613.995]  -> [email protected]()
[2714614.037]  -> [email protected]()
[2714614.253]  -> [email protected]_cursor(846, wl_surface@24, 7, 4)
[2714614.313]  -> [email protected](wl_buffer@35, 0, 0)
[2714614.358]  -> [email protected]_buffer_scale(1)
[2714614.399]  -> [email protected](0, 0, 24, 24)
[2714614.444]  -> [email protected]()
[2714614.573]  -> [email protected]()
[2714614.618]  -> [email protected]()
[2714614.673]  -> [email protected]()
[2714614.723]  -> [email protected]()
[2714614.762]  -> [email protected]()
[2714615.250]  -> [email protected]()
[2714619.765] [email protected](xdg_wm_base@29, 2, "xdg_popup was destroyed while it was not the topmost popup")
Gdk-Message: 18:37:48.286: Error 71 (Erreur de protocole) dispatching to Wayland display.

If you comment out the layer-shell part in the code above, it doesn't crash and here are the logs:

[2781397.776] [email protected](1037, 36516497, 1, 1)

(q:204306): Gdk-WARNING **: 18:38:55.075: Tried to unmap the parent of a popup
[2781409.513]  -> [email protected]()
[2781409.541]  -> [email protected]()
[2781410.116]  -> [email protected]()
[2781410.156]  -> [email protected]()
[2781410.181]  -> [email protected]()
[2781410.275]  -> [email protected]()
[2781410.303]  -> [email protected]()
[2781410.332]  -> [email protected]()
[2781410.360]  -> [email protected]()
[2781410.383]  -> [email protected]()
[2781410.792]  -> [email protected]_cursor(1035, wl_surface@24, 7, 4)
[2781410.848]  -> [email protected](wl_buffer@36, 0, 0)
[2781410.866]  -> [email protected]_buffer_scale(1)
[2781410.904]  -> [email protected](0, 0, 24, 24)
[2781410.929]  -> [email protected]()
[2781411.824]  -> [email protected]()

gtk-layer-shell 0.8.2
gtk 3.24.41

@wmww
Copy link
Owner

wmww commented Sep 2, 2024

Oh! this is an interesting one. Thanks for the nice simple reproducer, and sorry it took me so long to get to.

Normally GTK makes sure popups are unmapped before parents. However we need to delete our Wayland objects before the GTK unmap handler runs (or else we get a different protocol error), so we override it to do our stuff first. This causes us to unmap parents before children, causing this problem.

There's not an obvious way to let GTK handle unmapping children, so instead I opted to keep a list of children and handle unmapping myself. This adds a little complexity but seems to work.

With some improvements to the integration test system I managed to add a test for this bug, so that should keep it from popping up again.

@Tamaranch
Copy link
Author

Thanks, I can confirm it also fixes the issue in my real use case (app menu in xfce4-panel).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants