Subject: Re: bug#75905: 31.0.50; feature/igc: crash when clicking menubar

From: Pip Cet <[email-masked]>
Date: Tue, 28 Jan 2025 19:38:04 +0000

"Andrew Cohen" <[email-masked]> writes:

Hi!

Thanks for the report!

> pgtk emacs with mpc crashes whenever the menubar is clicked. Same
> configuration without igc has no problem.

That makes sense.  I'd just fixed this bug in the X case (the X case is
slightly different: when you click a popup menu, you'll always get nil,
the "no" answer in y-or-no-p, right now), but there seem to be a few
more places that need it.

(Note that the glib_user_data thing isn't working as well as it should,
and I'm working on an improved version.  The current code should be
usable on plain GTK and may be usable on PGTK, but if you use menu bars
and many frames things may be slow).

Can you please try this patch?

From: Pip Cet <[email-masked]>
Subject: [PATCH] [MPS] Use glib_user_data more consistently (bug#75905)

* src/gtkutil.c (style_changed_cb):
(xg_dialog_response_cb):
(xg_toggle_notify_cb):
(xg_finish_scroll_bar_creation):
(menu_bar_button_pressed_cb):
(find_scrollbar_cb):
(create_menus):
(xg_create_frame_widgets):
(xg_create_frame_outer_widgets):
(xg_tool_bar_callback):
(xg_tool_bar_help_callback):
(xg_make_tool_item):
(xg_dialog_run):
(xg_get_file_with_chooser):
(xg_get_widget_from_map): Use glib_user_data, free_glib_user_data.
* src/pgtkmenu.c (menubar_selection_callback):
(popup_selection_callback): Use glib_user_data, get_glib_user_data.
---
 src/gtkutil.c  | 92 ++++++++++++++++++++++++++++----------------------
 src/pgtkmenu.c |  4 +--
 2 files changed, 54 insertions(+), 42 deletions(-)

diff --git a/src/gtkutil.c b/src/gtkutil.c
index 09ba18e1526..2bb2735105c 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -1474,7 +1474,7 @@ style_changed_cb (GObject *go,
                   gpointer user_data)
 {
   struct input_event event;
-  GdkDisplay *gdpy = user_data;
+  GdkDisplay *gdpy = get_glib_user_data (user_data);
   const char *display_name = gdk_display_get_name (gdpy);
 #ifndef HAVE_PGTK
   Display *dpy = GDK_DISPLAY_XDISPLAY (gdpy);
@@ -1788,9 +1788,10 @@ xg_create_frame_widgets (struct frame *f)
                                  (gpointer) G_CALLBACK (style_changed_cb),
                                  0))
       {
-        g_signal_connect (G_OBJECT (gs), "notify::gtk-theme-name",
-                          G_CALLBACK (style_changed_cb),
-                          gdk_screen_get_display (screen));
+        g_signal_connect_data (G_OBJECT (gs), "notify::gtk-theme-name",
+			       G_CALLBACK (style_changed_cb),
+			       glib_user_data (gdk_screen_get_display (screen)),
+			       free_glib_user_data, 0);
       }
   }
 
@@ -1893,9 +1894,10 @@ xg_create_frame_outer_widgets (struct frame *f)
                                  (gpointer) G_CALLBACK (style_changed_cb),
                                  0))
       {
-        g_signal_connect (G_OBJECT (gs), "notify::gtk-theme-name",
-                          G_CALLBACK (style_changed_cb),
-                          gdk_screen_get_display (screen));
+        g_signal_connect_data (G_OBJECT (gs), "notify::gtk-theme-name",
+			       G_CALLBACK (style_changed_cb),
+			       glib_user_data (gdk_screen_get_display (screen)),
+			       free_glib_user_data, 0);
       }
   }
 
@@ -2442,7 +2444,7 @@ xg_dialog_response_cb (GtkDialog *w,
 		       gint response,
 		       gpointer user_data)
 {
-  struct xg_dialog_data *dd = user_data;
+  struct xg_dialog_data *dd = get_glib_user_data (user_data);
   dd->response = response;
   g_main_loop_quit (dd->loop);
 }
@@ -2509,10 +2511,11 @@ xg_dialog_run (struct frame *f, GtkWidget *w)
   dd.w = w;
   dd.timerid = 0;
 
-  g_signal_connect (G_OBJECT (w),
-                    "response",
-                    G_CALLBACK (xg_dialog_response_cb),
-                    &dd);
+  g_signal_connect_data (G_OBJECT (w),
+			 "response",
+			 G_CALLBACK (xg_dialog_response_cb),
+			 glib_user_data (&dd), free_glib_user_data,
+			 0);
   /* Don't destroy the widget if closed by the window manager close button.  */
   g_signal_connect (G_OBJECT (w), "delete-event", G_CALLBACK (gtk_true), NULL);
   gtk_widget_show (w);
@@ -2580,7 +2583,7 @@ xg_toggle_notify_cb (GObject *gobject, GParamSpec *arg1, gpointer user_data)
 {
   if (strcmp (arg1->name, "show-hidden") == 0)
     {
-      GtkWidget *wtoggle = GTK_WIDGET (user_data);
+      GtkWidget *wtoggle = GTK_WIDGET (get_glib_user_data (user_data));
       gboolean visible, toggle_on;
 
       g_object_get (G_OBJECT (gobject), "show-hidden", &visible, NULL);
@@ -2646,10 +2649,13 @@ xg_get_file_with_chooser (struct frame *f,
 				x_gtk_show_hidden_files);
 
   gtk_widget_show (wtoggle);
-  g_signal_connect (G_OBJECT (wtoggle), "clicked",
-                    G_CALLBACK (xg_toggle_visibility_cb), filewin);
-  g_signal_connect (G_OBJECT (filewin), "notify",
-                    G_CALLBACK (xg_toggle_notify_cb), wtoggle);
+  g_signal_connect_data (G_OBJECT (wtoggle), "clicked",
+			 G_CALLBACK (xg_toggle_visibility_cb),
+			 glib_user_data (filewin),
+			 free_glib_user_data, 0);
+  g_signal_connect_data (G_OBJECT (filewin), "notify",
+			 G_CALLBACK (xg_toggle_notify_cb), glib_user_data (wtoggle),
+			 free_glib_user_data, 0);
 
   if (x_gtk_file_dialog_help_text)
     {
@@ -3362,7 +3368,7 @@ xg_create_one_menuitem (widget_value *item,
 menu_bar_button_pressed_cb (GtkWidget *widget, GdkEvent *event,
 			    gpointer user_data)
 {
-  struct frame *f = user_data;
+  struct frame *f = get_glib_user_data (user_data);
 
   if (event->button.button < 4
       && event->button.window != gtk_widget_get_window (widget)
@@ -3440,9 +3446,9 @@ create_menus (widget_value *data,
 
 #ifdef HAVE_PGTK
 	  g_signal_connect_data (G_OBJECT (wmenu), "button-press-event",
-			    G_CALLBACK (menu_bar_button_pressed_cb),
-			    glib_user_data (f), free_glib_user_data,
-			    0);
+				 G_CALLBACK (menu_bar_button_pressed_cb),
+				 glib_user_data (f), free_glib_user_data,
+				 0);
 #endif
           /* Set width of menu bar to a small value so it doesn't enlarge
              a small initial frame size.  The width will be set to the
@@ -4443,7 +4449,7 @@ xg_get_widget_from_map (ptrdiff_t idx, Display *dpy)
 static void
 find_scrollbar_cb (GtkWidget *widget, gpointer user_data)
 {
-  GtkWidget **scroll_bar = user_data;
+  GtkWidget **scroll_bar = get_glib_user_data (user_data);
 
   if (GTK_IS_SCROLLBAR (widget))
     *scroll_bar = widget;
@@ -4464,9 +4470,11 @@ xg_get_widget_from_map (ptrdiff_t window, Display *dpy)
       event.any.type = GDK_NOTHING;
       gwdesc = gtk_get_event_widget (&event);
 
+      gpointer user_data = glib_user_data (&scroll_bar);
       if (gwdesc && GTK_IS_EVENT_BOX (gwdesc))
 	gtk_container_forall (GTK_CONTAINER (gwdesc),
-			      find_scrollbar_cb, &scroll_bar);
+			      find_scrollbar_cb, user_data);
+      free_glib_user_data (user_data, NULL);
     }
   else
     return NULL;
@@ -4634,10 +4642,11 @@ xg_finish_scroll_bar_creation (struct frame *f,
 #if defined HAVE_PGTK || !defined HAVE_GTK3
   ptrdiff_t scroll_id = xg_store_widget_in_map (wscroll);
 
-  g_signal_connect (G_OBJECT (wscroll),
-                    "destroy",
-                    G_CALLBACK (xg_gtk_scroll_destroy),
-                    (gpointer) scroll_id);
+  g_signal_connect_data (G_OBJECT (wscroll),
+			 "destroy",
+			 G_CALLBACK (xg_gtk_scroll_destroy),
+			 glib_user_data ((gpointer) scroll_id),
+			 free_glib_user_data, 0);
 #endif
 
 #ifdef HAVE_MPS
@@ -5382,7 +5391,7 @@ xg_tool_bar_button_cb (GtkWidget *widget,
 static void
 xg_tool_bar_callback (GtkWidget *w, gpointer client_data)
 {
-  intptr_t idx = (intptr_t) client_data;
+  intptr_t idx = (intptr_t) get_glib_user_data (client_data);
   gpointer gmod = g_object_get_data (G_OBJECT (w), XG_TOOL_BAR_LAST_MODIFIER);
   intptr_t mod = (intptr_t) gmod;
 
@@ -5444,7 +5453,7 @@ xg_tool_bar_help_callback (GtkWidget *w,
                            GdkEventCrossing *event,
                            gpointer client_data)
 {
-  intptr_t idx = (intptr_t) client_data;
+  intptr_t idx = (intptr_t) get_glib_user_data (client_data);
   struct frame *f = g_object_get_data (G_OBJECT (w), XG_FRAME_DATA);
   Lisp_Object help, frame;
 
@@ -5692,9 +5701,10 @@ xg_make_tool_item (struct frame *f,
       intptr_t ii = i;
       gpointer gi = (gpointer) ii;
 
-      g_signal_connect (G_OBJECT (wb), "clicked",
-                        G_CALLBACK (xg_tool_bar_callback),
-                        gi);
+      g_signal_connect_data (G_OBJECT (wb), "clicked",
+			     G_CALLBACK (xg_tool_bar_callback),
+			     glib_user_data (gi), free_glib_user_data,
+			     0);
 
       g_object_set_data (G_OBJECT (weventbox), XG_FRAME_DATA, (gpointer)f);
 
@@ -5721,14 +5731,16 @@ xg_make_tool_item (struct frame *f,
          rather than the GtkButton specific signals "enter" and
          "leave", so we can have only one callback.  The event
          will tell us what kind of event it is.  */
-      g_signal_connect (G_OBJECT (weventbox),
-                        "enter-notify-event",
-                        G_CALLBACK (xg_tool_bar_help_callback),
-                        gi);
-      g_signal_connect (G_OBJECT (weventbox),
-                        "leave-notify-event",
-                        G_CALLBACK (xg_tool_bar_help_callback),
-                        gi);
+      g_signal_connect_data (G_OBJECT (weventbox),
+			     "enter-notify-event",
+			     G_CALLBACK (xg_tool_bar_help_callback),
+			     glib_user_data (gi), free_glib_user_data,
+			     0);
+      g_signal_connect_data (G_OBJECT (weventbox),
+			     "leave-notify-event",
+			     G_CALLBACK (xg_tool_bar_help_callback),
+			     glib_user_data (gi), free_glib_user_data,
+			     0);
     }
 
   if (wbutton) *wbutton = wb;
diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c
index a2e09b6cb58..f25425435da 100644
--- a/src/pgtkmenu.c
+++ b/src/pgtkmenu.c
@@ -188,7 +188,7 @@ menu_highlight_callback (GtkWidget *widget, gpointer call_data)
 static void
 menubar_selection_callback (GtkWidget *widget, gpointer client_data)
 {
-  xg_menu_item_cb_data *cb_data = client_data;
+  xg_menu_item_cb_data *cb_data = get_glib_user_data (client_data);
 
   if (xg_crazy_callback_abort)
     return;
@@ -510,7 +510,7 @@ initialize_frame_menubar (struct frame *f)
 static void
 popup_selection_callback (GtkWidget *widget, gpointer client_data)
 {
-  xg_menu_item_cb_data *cb_data = client_data;
+  xg_menu_item_cb_data *cb_data = get_glib_user_data (client_data);
 
   if (xg_crazy_callback_abort)
     return;
-- 
2.47.1

Thanks!

Pip