diff --git a/patches/libcanberra/gtk-module-Handle-display-closing-gracefully.patch b/patches/libcanberra/gtk-module-Handle-display-closing-gracefully.patch new file mode 100644 index 0000000..1f7023d --- /dev/null +++ b/patches/libcanberra/gtk-module-Handle-display-closing-gracefully.patch @@ -0,0 +1,225 @@ +From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= +Date: Fri, 8 Apr 2022 20:12:04 +0200 +Subject: gtk-module: Handle display closing gracefully + +Modern desktop environments may have X running optionally, so the +canberra module may be unloaded because of this reason. + +However we didn't handle it properly because of a long-standing issue +due to missing quit signal on Gtk 3, also we it may happen that a +widget gets destroyed because of that, but we were still trying to unref +them again during the dispatch_queue() idle. + +To avoid this, let's track the "closed" display signal and let's monitor +for disposed (same as using "destroy" signal) objects, removing them from +the queue earlier. + + #0 g_log_writer_default (log_level=, fields=0x7ffcf2f236c0, + n_fields=6, user_data=0x0) at ../../../glib/gmessages.c:557 + #1 0x00007f355eb3cc93 in g_log_structured_array (n_fields=6, + fields=0x7ffcf2f236c0, log_level=G_LOG_LEVEL_ERROR) + at ../../../glib/gmessages.c:1973 + #2 g_log_structured_array (log_level=G_LOG_LEVEL_ERROR, + fields=0x7ffcf2f236c0, n_fields=6) at ../../../glib/gmessages.c:1946 + #3 0x00007f355eb3ce93 in g_log_structured_standard ( + log_domain=log_domain@entry=0x7f355e6be063 "Gtk", + log_level=log_level@entry=G_LOG_LEVEL_ERROR, + file=file@entry=0x7f355e724138 "../../../../gtk/gtkstylecontext.c", + line=line@entry=0x7f355e6ddea4 "348", + func=func@entry=0x7f355e724c70 <__func__.70> "gtk_style_context_init", + message_format=message_format@entry=0x7f355e724458 + "Can't create a GtkStyleContext without a display connection") + at ../../../glib/gmessages.c:2030 + #4 0x00007f355e5b45cf in gtk_style_context_init (context=0x555ee32475d0) + at ../../../../gtk/gtkstylecontext.c:348 + #5 0x00007f355ec57efa in g_type_create_instance (type=) + at ../../../gobject/gtype.c:1929 + #6 0x00007f355ec3ef4d in g_object_new_internal ( + class=class@entry=0x555ee2ec1c60, params=params@entry=0x0, + n_params=n_params@entry=0) at ../../../gobject/gobject.c:2011 + #7 0x00007f355ec401ad in g_object_new_with_properties ( + object_type=93866027507792, n_properties=0, names=names@entry=0x0, + values=values@entry=0x0) at ../../../gobject/gobject.c:2181 + #8 0x00007f355ec40cb1 in g_object_new (object_type=, + first_property_name=) at ../../../gobject/gobject.c:1821 + #9 0x00007f355e393f80 in _gtk_style_new_for_path (screen=0x0, + path=path@entry=0x555ee2ccd4b0) + at ../../../../gtk/deprecated/gtkstyle.c:854 + #10 0x00007f355e3941f3 in gtk_style_new () + at ../../../../gtk/deprecated/gtkstyle.c:888 + #11 0x00007f355e398b71 in gtk_widget_get_default_style () + at ../../../../gtk/deprecated/gtkstyle.c:4061 + #12 gtk_widget_get_default_style () + at ../../../../gtk/deprecated/gtkstyle.c:4050 + #13 0x00007f355e65e8ee in gtk_widget_real_destroy (object=0x555ee3d54320) + at ../../../../gtk/gtkwidget.c:12356 + #14 0x00007f355dec62a7 in ?? () from /lib/x86_64-linux-gnu/libmutter-10.so.0 + #15 0x00007f355ec2ed2f in g_closure_invoke (closure=0x555ee10ccac0, + return_value=0x0, n_param_values=1, param_values=0x7ffcf2f24180, + invocation_hint=0x7ffcf2f24100) at ../../../gobject/gclosure.c:830 + #16 0x00007f355ec4aae0 in signal_emit_unlocked_R ( + node=node@entry=0x555ee0fcd450, detail=detail@entry=0, + instance=instance@entry=0x555ee3d54320, + emission_return=emission_return@entry=0x0, + instance_and_params=instance_and_params@entry=0x7ffcf2f24180) + at ../../../gobject/gsignal.c:3861 + #17 0x00007f355ec4c554 in g_signal_emit_valist (instance=, + signal_id=, detail=, + var_args=var_args@entry=0x7ffcf2f24330) + at ../../../gobject/gsignal.c:3496 + #18 0x00007f355ec4c7a3 in g_signal_emit ( + instance=instance@entry=0x555ee3d54320, signal_id=, + detail=detail@entry=0) at ../../../gobject/gsignal.c:3553 + #19 0x00007f355e65e600 in gtk_widget_dispose (object=0x555ee3d54320) + at ../../../../gtk/gtkwidget.c:12166 + #20 0x00007f355e66e0ee in gtk_window_dispose (object=0x555ee3d54320) + at ../../../../gtk/gtkwindow.c:3168 + #21 0x00007f355ec3cd31 in g_object_unref (_object=) + at ../../../gobject/gobject.c:3636 + #22 g_object_unref (_object=0x555ee3d54320) + at ../../../gobject/gobject.c:3553 + #23 0x00007f352d6f1bfe in free_sound_event (d=0x7f3544280870) + at /build/libcanberra-DU1C23/libcanberra-0.30/src/canberra-gtk-module.c:184 + #24 dispatch_queue () + at /build/libcanberra-DU1C23/libcanberra-0.30/src/canberra-gtk-module.c:840 + #25 idle_cb (userdata=) + at /build/libcanberra-DU1C23/libcanberra-0.30/src/canberra-gtk-module.c:847 + #26 0x00007f355da452ad in gdk_threads_dispatch (data=0x7f35080db680) + at ../../../../gdk/gdk.c:769 + #27 0x00007f355eb35c24 in g_main_dispatch (context=0x555ee08d8bd0) + at ../../../glib/gmain.c:3417 + #28 g_main_context_dispatch (context=0x555ee08d8bd0) + at ../../../glib/gmain.c:4135 + #29 0x00007f355eb8a6f8 in g_main_context_iterate.constprop.0 ( + context=0x555ee08d8bd0, block=block@entry=1, dispatch=dispatch@entry=1, + self=) at ../../../glib/gmain.c:4211 + #30 0x00007f355eb35293 in g_main_loop_run (loop=0x555ee29a8f50) + at ../../../glib/gmain.c:4411 + #31 0x00007f355dea6209 in meta_context_run_main_loop () + from /lib/x86_64-linux-gnu/libmutter-10.so.0 + #32 0x0000555edf819ed2 in ?? () + #33 0x00007f355dbd7d90 in __libc_start_call_main ( + main=main@entry=0x555edf819a30, argc=argc@entry=1, + argv=argv@entry=0x7ffcf2f24838) + at ../sysdeps/nptl/libc_start_call_main.h:58 + #34 0x00007f355dbd7e40 in __libc_start_main_impl (main=0x555edf819a30, + argc=1, argv=0x7ffcf2f24838, init=, fini=, + rtld_fini=, stack_end=0x7ffcf2f24828) + at ../csu/libc-start.c:392 + #35 0x0000555edf81a155 in ?? () + +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1949200 +--- + src/canberra-gtk-module.c | 57 ++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 52 insertions(+), 5 deletions(-) + +diff --git a/src/canberra-gtk-module.c b/src/canberra-gtk-module.c +index c1532ab..dbeca5e 100644 +--- a/src/canberra-gtk-module.c ++++ b/src/canberra-gtk-module.c +@@ -114,6 +114,8 @@ static GQuark + * exported function */ + void gtk_module_init(gint *argc, gchar ***argv[]); + ++static void on_object_disposed(gpointer data, GObject *object); ++ + static const char *translate_message_tye(GtkMessageType mt) { + static const char *const message_type_table[] = { + [GTK_MESSAGE_INFO] = "dialog-information", +@@ -180,8 +182,10 @@ static GtkDialog* find_parent_dialog(GtkWidget *w) { + } + + static void free_sound_event(SoundEventData *d) { +- +- g_object_unref(d->object); ++ if (d->object) { ++ g_object_weak_unref(d->object, on_object_disposed, d); ++ g_clear_object(&d->object); ++ } + + if (d->arg1_is_set) + g_value_unset(&d->arg1); +@@ -851,6 +855,34 @@ static gboolean idle_cb(void *userdata) { + + static void connect_settings(void); + ++static void on_object_disposed(gpointer data, GObject *object) ++{ ++ /* Workaround missing handler for gtk_quit in gtk 3.0, but safe to use in 2.0. ++ * As we may try to remove disposed objects on idle, so let's avoid this ++ * by just removing the queued events, if an object gets disposed earlier than ++ * we expect. ++ * https://gitlab.gnome.org/GNOME/glib/-/issues/389 ++ */ ++ SoundEventData *d = data; ++ ++ /* If the object is set here, it means that we're running this as per ++ * the object being disposed when the reference count has not dropped to ++ * 0 yet, as per a manual call of g_object_run_dispose (or ++ * gtk_widget_destroy), so it means that we can safely release the extra ++ * reference that had been added in emission_hook_cb() ++ */ ++ g_assert(d->object == NULL || d->object->ref_count > 1); ++ g_clear_object(&d->object); ++ ++ g_queue_remove(&sound_event_queue, d); ++ free_sound_event(d); ++ ++ if (idle_id && !sound_event_queue.length) { ++ g_source_remove(idle_id); ++ idle_id = 0; ++ } ++} ++ + static gboolean emission_hook_cb(GSignalInvocationHint *hint, guint n_param_values, const GValue *param_values, gpointer data) { + static SoundEventData *d = NULL; + GdkEvent *e; +@@ -889,6 +921,7 @@ static gboolean emission_hook_cb(GSignalInvocationHint *hint, guint n_param_valu + d = g_slice_new0(SoundEventData); + + d->object = g_object_ref(object); ++ g_object_weak_ref(object, on_object_disposed, d); + + d->signal_id = hint->signal_id; + +@@ -956,8 +989,21 @@ static void connect_settings(void) { + connected = TRUE; + } + +-#if GTK_CHECK_VERSION(3,0,0) +-#warning "We really need a quit handler in Gtk 3.0, https://bugzilla.gnome.org/show_bug.cgi?id=639770" ++#if GTK_CHECK_VERSION(3, 0, 0) ++/* Workaround missing quit_handler on gtk3 ++ * https://gitlab.gnome.org/GNOME/glib/-/issues/389 ++ */ ++ ++static void ++on_display_closed(GdkDisplay *display) ++{ ++ if (idle_id) { ++ g_source_remove(idle_id); ++ idle_id = 0; ++ } ++ ++ dispatch_queue(); ++} + #else + static gboolean quit_handler(gpointer data) { + dispatch_queue(); +@@ -966,7 +1012,6 @@ static gboolean quit_handler(gpointer data) { + #endif + + G_MODULE_EXPORT void gtk_module_init(gint *argc, gchar ***argv[]) { +- + /* This is the same quark libgnomeui uses! */ + disable_sound_quark = g_quark_from_string("gnome_disable_sound_events"); + was_iconized_quark = g_quark_from_string("canberra_was_iconized"); +@@ -994,6 +1039,8 @@ G_MODULE_EXPORT void gtk_module_init(gint *argc, gchar ***argv[]) { + + #if !GTK_CHECK_VERSION(3,0,0) + gtk_quit_add(1, quit_handler, NULL); ++#else ++ g_signal_connect(gdk_display_get_default (), "closed", G_CALLBACK (on_display_closed), NULL); + #endif + } + diff --git a/patches/libcanberra/gtk_dont_assume_x11.patch b/patches/libcanberra/gtk_dont_assume_x11.patch new file mode 100644 index 0000000..f520907 --- /dev/null +++ b/patches/libcanberra/gtk_dont_assume_x11.patch @@ -0,0 +1,121 @@ +From: Michael Meeks +Date: Fri, 9 Nov 2012 16:16:40 +0000 +Subject: gtk: Don't assume all GdkDisplays are GdkX11Displays: + broadway/wayland + +Co-Authored-By: Bastien Nocera + +Origin: https://src.fedoraproject.org/rpms/libcanberra/blob/rawhide/f/0001-gtk-Don-t-assume-all-GdkDisplays-are-GdkX11Displays-.patch +--- + src/canberra-gtk-module.c | 15 +++++++++++++++ + src/canberra-gtk.c | 28 ++++++++++++++++++++++------ + 2 files changed, 37 insertions(+), 6 deletions(-) + +diff --git a/src/canberra-gtk-module.c b/src/canberra-gtk-module.c +index 67791f0..c1532ab 100644 +--- a/src/canberra-gtk-module.c ++++ b/src/canberra-gtk-module.c +@@ -307,6 +307,11 @@ static gint window_get_desktop(GdkDisplay *d, GdkWindow *w) { + guchar *data = NULL; + gint ret = -1; + ++#ifdef GDK_IS_X11_DISPLAY ++ if (!GDK_IS_X11_DISPLAY(d)) ++ return 0; ++#endif ++ + if (XGetWindowProperty(GDK_DISPLAY_XDISPLAY(d), GDK_WINDOW_XID(w), + gdk_x11_get_xatom_by_name_for_display(d, "_NET_WM_DESKTOP"), + 0, G_MAXLONG, False, XA_CARDINAL, &type_return, +@@ -335,6 +340,11 @@ static gint display_get_desktop(GdkDisplay *d) { + guchar *data = NULL; + gint ret = -1; + ++#ifdef GDK_IS_X11_DISPLAY ++ if (!GDK_IS_X11_DISPLAY(d)) ++ return 0; ++#endif ++ + if (XGetWindowProperty(GDK_DISPLAY_XDISPLAY(d), DefaultRootWindow(GDK_DISPLAY_XDISPLAY(d)), + gdk_x11_get_xatom_by_name_for_display(d, "_NET_CURRENT_DESKTOP"), + 0, G_MAXLONG, False, XA_CARDINAL, &type_return, +@@ -365,6 +375,11 @@ static gboolean window_is_xembed(GdkDisplay *d, GdkWindow *w) { + gboolean ret = FALSE; + Atom xembed; + ++#ifdef GDK_IS_X11_DISPLAY ++ if (!GDK_IS_X11_DISPLAY(d)) ++ return FALSE; ++#endif ++ + /* Gnome Panel applets are XEMBED windows. We need to make sure we + * ignore them */ + +diff --git a/src/canberra-gtk.c b/src/canberra-gtk.c +index 34446f5..47285f8 100644 +--- a/src/canberra-gtk.c ++++ b/src/canberra-gtk.c +@@ -185,6 +185,11 @@ static gint window_get_desktop(GdkDisplay *d, GdkWindow *w) { + guchar *data = NULL; + gint ret = -1; + ++#ifdef GDK_IS_X11_DISPLAY ++ if (!GDK_IS_X11_DISPLAY(d)) ++ return 0; ++#endif ++ + if (XGetWindowProperty(GDK_DISPLAY_XDISPLAY(d), GDK_WINDOW_XID(w), + gdk_x11_get_xatom_by_name_for_display(d, "_NET_WM_DESKTOP"), + 0, G_MAXLONG, False, XA_CARDINAL, &type_return, +@@ -254,18 +259,28 @@ int ca_gtk_proplist_set_for_widget(ca_proplist *p, GtkWidget *widget) { + + if (gtk_widget_get_realized(GTK_WIDGET(w))) { + GdkWindow *dw = NULL; ++#ifdef GDK_IS_X11_DISPLAY + GdkScreen *screen = NULL; ++#endif + GdkDisplay *display = NULL; + gint x = -1, y = -1, width = -1, height = -1, screen_width = -1, screen_height = -1; + +- if ((dw = gtk_widget_get_window(GTK_WIDGET(w)))) +- if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_X11_XID, "%lu", (unsigned long) GDK_WINDOW_XID(dw))) < 0) +- return ret; ++ if ((dw = gtk_widget_get_window(GTK_WIDGET(w)))) { ++#ifdef GDK_IS_X11_DISPLAY ++ if (GDK_IS_X11_DISPLAY(display)) { ++ if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_X11_XID, "%lu", (unsigned long) GDK_WINDOW_XID(dw))) < 0) ++ return ret; ++ } ++#endif ++ } + + if ((display = gtk_widget_get_display(GTK_WIDGET(w)))) { +- if ((t = gdk_display_get_name(display))) ++#ifdef GDK_IS_X11_DISPLAY ++ if (GDK_IS_X11_DISPLAY(display) && (t = gdk_display_get_name(display))) { + if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_X11_DISPLAY, t)) < 0) + return ret; ++ } ++#endif + + if (dw) { + gint desktop = window_get_desktop(display, dw); +@@ -276,7 +291,8 @@ int ca_gtk_proplist_set_for_widget(ca_proplist *p, GtkWidget *widget) { + } + } + +- if ((screen = gtk_widget_get_screen(GTK_WIDGET(w)))) { ++#ifdef GDK_IS_X11_DISPLAY ++ if (GDK_IS_X11_DISPLAY(display) && (screen = gtk_widget_get_screen(GTK_WIDGET(w)))) { + + if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_X11_SCREEN, "%i", gdk_screen_get_number(screen))) < 0) + return ret; +@@ -285,7 +301,7 @@ int ca_gtk_proplist_set_for_widget(ca_proplist *p, GtkWidget *widget) { + if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_X11_MONITOR, "%i", gdk_screen_get_monitor_at_window(screen, dw))) < 0) + return ret; + } +- ++#endif + /* FIXME, this might cause a round trip */ + + if (dw) { diff --git a/snapcraft.yaml b/snapcraft.yaml index fa7d504..3409146 100644 --- a/snapcraft.yaml +++ b/snapcraft.yaml @@ -956,6 +956,11 @@ parts: - --prefix=/usr - --with-builtin=pulse build-environment: *buildenv + override-pull: | + craftctl default + for p in $CRAFT_PROJECT_DIR/patches/libcanberra/*.patch; do + patch -p1 < "$p" + done override-build: | ./autogen.sh craftctl default