Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

452 Commits   2 Branches   1 Tag
Index: Makefile
===================================================================
--- Makefile	(nonexistent)
+++ Makefile	(revision 233)
@@ -0,0 +1,56 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/packages/x/libcanberra
+
+versions    = 0.30
+pkgname     = libcanberra
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+patches     = $(CURDIR)/patches/libcanberra-0.30-wayland.patch
+
+.NOTPARALLEL: $(patches)
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s) $(patches)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+$(patches): $(sha1s)
+	@echo -e "\n======= Create Patches =======\n" ; \
+	 ( cd create-0.30-wayland-patch ; ./create.patch.sh ) ; \
+	 echo -e "\n"
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s) $(patches)
Index: create-0.30-wayland-patch/create.patch.sh
===================================================================
--- create-0.30-wayland-patch/create.patch.sh	(nonexistent)
+++ create-0.30-wayland-patch/create.patch.sh	(revision 233)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=0.30
+
+tar --files-from=file.list -xJvf ../libcanberra-$VERSION.tar.xz
+mv libcanberra-$VERSION libcanberra-$VERSION-orig
+
+cp -rf ./libcanberra-$VERSION-new ./libcanberra-$VERSION
+
+diff --unified -Nr  libcanberra-$VERSION-orig  libcanberra-$VERSION > libcanberra-$VERSION-wayland.patch
+
+mv libcanberra-$VERSION-wayland.patch ../patches
+
+rm -rf ./libcanberra-$VERSION
+rm -rf ./libcanberra-$VERSION-orig

Property changes on: create-0.30-wayland-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: create-0.30-wayland-patch/file.list
===================================================================
--- create-0.30-wayland-patch/file.list	(nonexistent)
+++ create-0.30-wayland-patch/file.list	(revision 233)
@@ -0,0 +1,2 @@
+libcanberra-0.30/src/canberra-gtk-module.c
+libcanberra-0.30/src/canberra-gtk.c
Index: create-0.30-wayland-patch/libcanberra-0.30-new/src/canberra-gtk-module.c
===================================================================
--- create-0.30-wayland-patch/libcanberra-0.30-new/src/canberra-gtk-module.c	(nonexistent)
+++ create-0.30-wayland-patch/libcanberra-0.30-new/src/canberra-gtk-module.c	(revision 233)
@@ -0,0 +1,1005 @@
+/*-*- Mode: C; c-basic-offset: 8 -*-*/
+
+/***
+  This file is part of libcanberra.
+
+  Copyright 2008 Lennart Poettering
+
+  libcanberra is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation, either version 2.1 of the
+  License, or (at your option) any later version.
+
+  libcanberra is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with libcanberra. If not, see
+  <http://www.gnu.org/licenses/>.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+
+#include "canberra-gtk.h"
+
+typedef struct {
+        guint signal_id;
+        gboolean arg1_is_set;
+        GObject *object;
+        GValue arg1;
+        GdkEvent *event;
+} SoundEventData;
+
+/*
+   We generate these sounds:
+
+   dialog-error
+   dialog-warning
+   dialog-information
+   dialog-question
+   window-new
+   window-close
+   window-minimized
+   window-unminimized
+   window-maximized
+   window-unmaximized
+   notebook-tab-changed
+   dialog-ok
+   dialog-cancel
+   item-selected
+   link-pressed
+   link-released
+   button-pressed
+   button-released
+   menu-click
+   button-toggle-on
+   button-toggle-off
+   menu-popup
+   menu-popdown
+   menu-replace
+   tooltip-popup
+   tooltip-popdown
+   drag-start
+   drag-accept
+   drag-fail
+   expander-toggle-on
+   expander-toggle-off
+
+   TODO:
+   scroll-xxx
+   window-switch
+   window-resize-xxx
+   window-move-xxx
+
+*/
+
+static gboolean disabled = FALSE;
+
+static GQueue sound_event_queue = G_QUEUE_INIT;
+
+static guint idle_id = 0;
+
+static guint
+        signal_id_dialog_response,
+        signal_id_widget_show,
+        signal_id_widget_hide,
+        signal_id_check_menu_item_toggled,
+        signal_id_menu_item_activate,
+        signal_id_toggle_button_toggled,
+        signal_id_button_pressed,
+        signal_id_button_released,
+        signal_id_widget_window_state_event,
+        signal_id_notebook_switch_page,
+        signal_id_tree_view_cursor_changed,
+        signal_id_icon_view_selection_changed,
+        signal_id_widget_drag_begin,
+        signal_id_widget_drag_failed,
+        signal_id_widget_drag_drop,
+        signal_id_expander_activate;
+
+static GQuark
+        disable_sound_quark,
+        was_iconized_quark,
+        is_xembed_quark;
+
+/* Make sure GCC doesn't warn us about a missing prototype for this
+ * exported function */
+void gtk_module_init(gint *argc, gchar ***argv[]);
+
+static const char *translate_message_tye(GtkMessageType mt) {
+        static const char *const message_type_table[] = {
+                [GTK_MESSAGE_INFO] = "dialog-information",
+                [GTK_MESSAGE_WARNING] = "dialog-warning",
+                [GTK_MESSAGE_QUESTION] = "dialog-question",
+                [GTK_MESSAGE_ERROR] = "dialog-error",
+                [GTK_MESSAGE_OTHER] = NULL
+        };
+
+        if (mt >= G_N_ELEMENTS(message_type_table))
+                return NULL;
+
+        return message_type_table[mt];
+}
+
+static const char *translate_response(int response) {
+        static const char *const response_table[] = {
+                [-GTK_RESPONSE_NONE] = NULL,
+                [-GTK_RESPONSE_REJECT] = "dialog-cancel",
+                [-GTK_RESPONSE_DELETE_EVENT] = "dialog-cancel",
+                [-GTK_RESPONSE_ACCEPT] = "dialog-ok",
+                [-GTK_RESPONSE_OK] = "dialog-ok",
+                [-GTK_RESPONSE_CANCEL] = "dialog-cancel",
+                [-GTK_RESPONSE_CLOSE] = "dialog-ok",
+                [-GTK_RESPONSE_YES] = "dialog-ok",
+                [-GTK_RESPONSE_NO] = "dialog-cancel",
+                [-GTK_RESPONSE_APPLY] = "dialog-ok",
+                [-GTK_RESPONSE_HELP] = NULL,
+        };
+
+        if (response >= 0)
+                return NULL;
+
+        if ((unsigned) -response >= G_N_ELEMENTS(response_table))
+                return NULL;
+
+        return response_table[-response];
+}
+
+static gboolean is_child_of_combo_box(GtkWidget *w) {
+
+        while (w) {
+
+                if (GTK_IS_COMBO_BOX(w))
+                        return TRUE;
+
+                w = gtk_widget_get_parent(w);
+        }
+
+        return FALSE;
+}
+
+static GtkDialog* find_parent_dialog(GtkWidget *w) {
+
+        while (w) {
+
+                if (GTK_IS_DIALOG(w))
+                        return GTK_DIALOG(w);
+
+                w = gtk_widget_get_parent(w);
+        }
+
+        return NULL;
+}
+
+static void free_sound_event(SoundEventData *d) {
+
+        g_object_unref(d->object);
+
+        if (d->arg1_is_set)
+                g_value_unset(&d->arg1);
+
+        if (d->event)
+                gdk_event_free(d->event);
+
+        g_slice_free(SoundEventData, d);
+}
+
+static gboolean is_menu_hint(GdkWindowTypeHint hint) {
+        return
+                hint == GDK_WINDOW_TYPE_HINT_POPUP_MENU ||
+                hint == GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU ||
+                hint == GDK_WINDOW_TYPE_HINT_MENU;
+}
+
+static SoundEventData* filter_sound_event(SoundEventData *d) {
+        GList *i, *n;
+
+        do {
+
+                for (i = sound_event_queue.head; i; i = n) {
+                        SoundEventData *j;
+
+                        j = i->data;
+                        n = i->next;
+
+                        if (d->object == j->object) {
+
+                                /* Let's drop a show event immediately followed by a
+                                 * hide event */
+
+                                if (d->signal_id == signal_id_widget_show &&
+                                    j->signal_id == signal_id_widget_hide) {
+
+                                        free_sound_event(d);
+                                        free_sound_event(j);
+                                        g_queue_delete_link(&sound_event_queue, i);
+
+                                        return NULL;
+                                }
+
+                                /* Let's drop widget hide events in favour of dialog
+                                 * response.
+                                 *
+                                 * Let's drop widget window state events in favour of
+                                 * widget hide/show.
+                                 *
+                                 * Let's drop double events */
+
+                                if ((d->signal_id == signal_id_widget_hide &&
+                                     j->signal_id == signal_id_dialog_response) ||
+
+                                    (d->signal_id == signal_id_widget_window_state_event &&
+                                     j->signal_id == signal_id_widget_hide) ||
+
+                                    (d->signal_id == signal_id_widget_window_state_event &&
+                                     j->signal_id == signal_id_widget_show)) {
+
+                                        free_sound_event(d);
+                                        d = j;
+                                        g_queue_delete_link(&sound_event_queue, i);
+                                        break;
+                                }
+
+                                if ((d->signal_id == signal_id_dialog_response &&
+                                     j->signal_id == signal_id_widget_hide) ||
+
+                                    (d->signal_id == signal_id_widget_show &&
+                                     j->signal_id == signal_id_widget_window_state_event) ||
+
+                                    (d->signal_id == signal_id_widget_hide &&
+                                     j->signal_id == signal_id_widget_window_state_event) ||
+
+                                    (d->signal_id == j->signal_id)) {
+
+                                        free_sound_event(j);
+                                        g_queue_delete_link(&sound_event_queue, i);
+                                }
+
+                        } else if (GTK_IS_WINDOW(d->object) && GTK_IS_WINDOW(j->object)) {
+
+                                GdkWindowTypeHint dhint, jhint;
+
+                                dhint = gtk_window_get_type_hint(GTK_WINDOW(d->object));
+                                jhint = gtk_window_get_type_hint(GTK_WINDOW(j->object));
+
+                                if (is_menu_hint(dhint) && is_menu_hint(jhint)) {
+
+                                        if (d->signal_id == signal_id_widget_hide &&
+                                            j->signal_id == signal_id_widget_show) {
+                                                free_sound_event(d);
+                                                d = j;
+                                                g_queue_delete_link(&sound_event_queue, i);
+                                                break;
+                                        }
+
+                                        if (d->signal_id == signal_id_widget_show &&
+                                            j->signal_id == signal_id_widget_hide) {
+
+                                                free_sound_event(j);
+                                                g_queue_delete_link(&sound_event_queue, i);
+                                        }
+                                }
+                        }
+                }
+
+                /* If we exited the iteration early, let's retry. */
+
+        } while (i);
+
+        /* FIXME: Filter menu hide on menu show */
+
+        return d;
+}
+
+static gint window_get_desktop(GdkDisplay *d, GdkWindow *w) {
+        Atom type_return;
+        gint format_return;
+        gulong nitems_return;
+        gulong bytes_after_return;
+        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,
+                               &format_return, &nitems_return, &bytes_after_return,
+                               &data) != Success)
+                return -1;
+
+        if (type_return == XA_CARDINAL && format_return == 32 && data) {
+                guint32 desktop = *(guint32*) data;
+
+                if (desktop != 0xFFFFFFFF)
+                        ret = (gint) desktop;
+        }
+
+        if (type_return != None && data != NULL)
+                XFree(data);
+
+        return ret;
+}
+
+static gint display_get_desktop(GdkDisplay *d) {
+        Atom type_return;
+        gint format_return;
+        gulong nitems_return;
+        gulong bytes_after_return;
+        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,
+                               &format_return, &nitems_return, &bytes_after_return,
+                               &data) != Success)
+                return -1;
+
+        if (type_return == XA_CARDINAL && format_return == 32 && data) {
+
+                guint32 desktop = *(guint32*) data;
+
+                if (desktop != 0xFFFFFFFF)
+                        ret = (gint) desktop;
+        }
+
+        if (type_return != None && data != NULL)
+                XFree(data);
+
+        return ret;
+}
+
+static gboolean window_is_xembed(GdkDisplay *d, GdkWindow *w) {
+        Atom type_return;
+        gint format_return;
+        gulong nitems_return;
+        gulong bytes_after_return;
+        guchar *data = NULL;
+        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 */
+
+        xembed = gdk_x11_get_xatom_by_name_for_display(d, "_XEMBED_INFO");
+
+        /* be robust against not existing XIDs (LP: #834403) */
+        gdk_error_trap_push();
+        if (XGetWindowProperty(GDK_DISPLAY_XDISPLAY(d), GDK_WINDOW_XID(w),
+                               xembed,
+                               0, 2, False, xembed, &type_return,
+                               &format_return, &nitems_return, &bytes_after_return,
+                               &data) != Success) {
+                return FALSE;
+        }
+
+#if GTK_CHECK_VERSION(3,0,0)
+        gdk_error_trap_pop_ignored();
+#else
+        gdk_flush();
+        gdk_error_trap_pop();
+#endif
+
+        if (type_return == xembed && format_return == 32 && data)
+                ret = TRUE;
+
+        if (type_return != None && data != NULL)
+                XFree(data);
+
+        return ret;
+}
+
+static void dispatch_sound_event(SoundEventData *d) {
+        int ret = CA_SUCCESS;
+        static gboolean menu_is_popped_up = FALSE;
+
+        if (g_object_get_qdata(d->object, disable_sound_quark))
+                return;
+
+        /* The GdkWindow of the the widget might have changed while this
+         * event was queued for us. Make sure to update it from the
+         * current one if necessary. */
+        if (d->event && d->event->any.window) {
+                GdkWindow *window;
+
+                g_object_unref(G_OBJECT(d->event->any.window));
+
+                if ((window = gtk_widget_get_window(GTK_WIDGET(d->object))))
+                        d->event->any.window = GDK_WINDOW(g_object_ref(G_OBJECT(window)));
+                else
+                        d->event->any.window = NULL;
+        }
+
+        if (d->signal_id == signal_id_widget_show) {
+                GdkWindowTypeHint hint;
+
+                /* Show/hide signals for non-windows have already been filtered out
+                 * by the emission hook! */
+
+                hint = gtk_window_get_type_hint(GTK_WINDOW(d->object));
+
+                if (is_menu_hint(hint)) {
+
+                        if (!menu_is_popped_up) {
+
+                                ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
+                                                             CA_PROP_EVENT_ID, "menu-popup",
+                                                             CA_PROP_EVENT_DESCRIPTION, "Menu popped up",
+                                                             CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                             NULL);
+                        } else {
+                                ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
+                                                             CA_PROP_EVENT_ID, "menu-replace",
+                                                             CA_PROP_EVENT_DESCRIPTION, "Menu replaced",
+                                                             CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                             NULL);
+                        }
+
+                        menu_is_popped_up = TRUE;
+
+                } else if (hint == GDK_WINDOW_TYPE_HINT_TOOLTIP) {
+
+                        ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
+                                                     CA_PROP_EVENT_ID, "tooltip-popup",
+                                                     CA_PROP_EVENT_DESCRIPTION, "Tooltip popped up",
+                                                     CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                     NULL);
+
+                } else if (hint == GDK_WINDOW_TYPE_HINT_NORMAL ||
+                           hint == GDK_WINDOW_TYPE_HINT_DIALOG) {
+
+                        gboolean played_sound = FALSE;
+                        gboolean is_xembed;
+
+                        is_xembed =
+                                gtk_widget_get_realized(GTK_WIDGET(d->object)) &&
+                                window_is_xembed(
+                                                gtk_widget_get_display(GTK_WIDGET(d->object)),
+                                                gtk_widget_get_window(GTK_WIDGET(d->object)));
+
+                        g_object_set_qdata(d->object, is_xembed_quark, GINT_TO_POINTER(is_xembed));
+
+                        if (GTK_IS_MESSAGE_DIALOG(d->object)) {
+                                GtkMessageType mt;
+                                const char *id;
+
+                                g_object_get(d->object, "message_type", &mt, NULL);
+
+                                if ((id = translate_message_tye(mt))) {
+
+                                        ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
+                                                                     CA_PROP_EVENT_ID, id,
+                                                                     CA_PROP_EVENT_DESCRIPTION, "Message dialog shown",
+                                                                     CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                                     NULL);
+                                        played_sound = TRUE;
+                                }
+
+                        }
+
+                        if (!played_sound &&
+                            !is_xembed &&
+                            gtk_window_get_decorated(GTK_WINDOW(d->object))) {
+
+                                ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
+                                                             CA_PROP_EVENT_ID, "window-new",
+                                                             CA_PROP_EVENT_DESCRIPTION, "Window shown",
+                                                             CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                             NULL);
+
+                        }
+                }
+        }
+
+        if (GTK_IS_DIALOG(d->object) && d->signal_id == signal_id_dialog_response) {
+
+                int response;
+                const char *id;
+
+                response = g_value_get_int(&d->arg1);
+
+                if ((id = translate_response(response))) {
+
+                        ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
+                                                     CA_PROP_EVENT_ID, id,
+                                                     CA_PROP_EVENT_DESCRIPTION, "Dialog closed",
+                                                     CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                     NULL);
+                } else {
+                        ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
+                                                     CA_PROP_EVENT_ID, "window-close",
+                                                     CA_PROP_EVENT_DESCRIPTION, "Window closed",
+                                                     CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                     NULL);
+                }
+
+        } else if (d->signal_id == signal_id_widget_hide) {
+                GdkWindowTypeHint hint;
+
+                hint = gtk_window_get_type_hint(GTK_WINDOW(d->object));
+
+                if (is_menu_hint(hint)) {
+
+                        if (GTK_IS_MENU(gtk_bin_get_child(GTK_BIN(d->object)))) {
+
+                                ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
+                                                             CA_PROP_EVENT_ID, "menu-popdown",
+                                                             CA_PROP_EVENT_DESCRIPTION, "Menu popped down",
+                                                             CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                             NULL);
+                        }
+
+                        menu_is_popped_up = FALSE;
+
+                } else if (hint == GDK_WINDOW_TYPE_HINT_TOOLTIP) {
+
+                        ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
+                                                     CA_PROP_EVENT_ID, "tooltip-popdown",
+                                                     CA_PROP_EVENT_DESCRIPTION, "Tooltip popped down",
+                                                     CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                     NULL);
+
+                } else if ((hint == GDK_WINDOW_TYPE_HINT_NORMAL ||
+                            hint == GDK_WINDOW_TYPE_HINT_DIALOG)) {
+
+                        gboolean is_xembed;
+
+                        is_xembed = !!g_object_get_qdata(d->object, is_xembed_quark);
+
+                        if (!is_xembed &&
+                            gtk_window_get_decorated(GTK_WINDOW(d->object)))
+                                ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
+                                                             CA_PROP_EVENT_ID, "window-close",
+                                                             CA_PROP_EVENT_DESCRIPTION, "Window closed",
+                                                             CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                             NULL);
+                }
+        }
+
+        if (GTK_IS_WINDOW(d->object) && d->signal_id == signal_id_widget_window_state_event) {
+                GdkEventWindowState *e;
+                gint w_desktop = -1, c_desktop = -1;
+
+                e = (GdkEventWindowState*) d->event;
+
+                /* Unfortunately GDK_WINDOW_STATE_ICONIFIED is used both for
+                 * proper minimizing and when a window becomes invisible
+                 * because the desktop was switched. To handle this we check
+                 * if the window becoming invisible is actually on the current
+                 * desktop, and only if that's the case we assume it is being
+                 * minimized. We then store this information, so that we know
+                 * later on when the window is unminimized again. */
+
+                if (gtk_widget_get_realized(GTK_WIDGET(d->object))) {
+                        GdkDisplay *display;
+
+                        display = gtk_widget_get_display(GTK_WIDGET(d->object));
+                        w_desktop = window_get_desktop(display, gtk_widget_get_window(GTK_WIDGET(d->object)));
+                        c_desktop = display_get_desktop(display);
+                }
+
+                if ((e->changed_mask & GDK_WINDOW_STATE_ICONIFIED) &&
+                    (e->new_window_state & GDK_WINDOW_STATE_ICONIFIED) &&
+                    (w_desktop == c_desktop || w_desktop < 0)) {
+
+                        ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
+                                                     CA_PROP_EVENT_ID, "window-minimized",
+                                                     CA_PROP_EVENT_DESCRIPTION, "Window minimized",
+                                                     CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                     NULL);
+
+                        g_object_set_qdata(d->object, was_iconized_quark, GINT_TO_POINTER(1));
+
+                } else if ((e->changed_mask & (GDK_WINDOW_STATE_MAXIMIZED|GDK_WINDOW_STATE_FULLSCREEN)) &&
+                           (e->new_window_state & (GDK_WINDOW_STATE_MAXIMIZED|GDK_WINDOW_STATE_FULLSCREEN))) {
+
+                        ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
+                                                     CA_PROP_EVENT_ID, "window-maximized",
+                                                     CA_PROP_EVENT_DESCRIPTION, "Window maximized",
+                                                     CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                     NULL);
+
+                        g_object_set_qdata(d->object, was_iconized_quark, GINT_TO_POINTER(0));
+
+                } else if ((e->changed_mask & GDK_WINDOW_STATE_ICONIFIED) &&
+                           !(e->new_window_state & GDK_WINDOW_STATE_ICONIFIED) &&
+                           g_object_get_qdata(d->object, was_iconized_quark)) {
+
+                        ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
+                                                     CA_PROP_EVENT_ID, "window-unminimized",
+                                                     CA_PROP_EVENT_DESCRIPTION, "Window unminimized",
+                                                     CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                     NULL);
+
+                        g_object_set_qdata(d->object, was_iconized_quark, GINT_TO_POINTER(0));
+
+                } else if ((e->changed_mask & (GDK_WINDOW_STATE_MAXIMIZED|GDK_WINDOW_STATE_FULLSCREEN)) &&
+                           !(e->new_window_state & (GDK_WINDOW_STATE_MAXIMIZED|GDK_WINDOW_STATE_FULLSCREEN))) {
+
+                        ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
+                                                     CA_PROP_EVENT_ID, "window-unmaximized",
+                                                     CA_PROP_EVENT_DESCRIPTION, "Window unmaximized",
+                                                     CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                     NULL);
+                }
+        }
+
+        if (GTK_IS_CHECK_MENU_ITEM(d->object) && d->signal_id == signal_id_check_menu_item_toggled) {
+
+                if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(d->object)))
+                        ret = ca_gtk_play_for_event(d->event, 0,
+                                                    CA_PROP_EVENT_ID, "button-toggle-on",
+                                                    CA_PROP_EVENT_DESCRIPTION, "Check menu item checked",
+                                                    CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                    NULL);
+                else
+                        ret = ca_gtk_play_for_event(d->event, 0,
+                                                    CA_PROP_EVENT_ID, "button-toggle-off",
+                                                    CA_PROP_EVENT_DESCRIPTION, "Check menu item unchecked",
+                                                    CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                    NULL);
+
+        } else if (GTK_IS_MENU_ITEM(d->object) && d->signal_id == signal_id_menu_item_activate) {
+
+                if (!gtk_menu_item_get_submenu(GTK_MENU_ITEM(d->object)))
+                        ret = ca_gtk_play_for_event(d->event, 0,
+                                                    CA_PROP_EVENT_ID, "menu-click",
+                                                    CA_PROP_EVENT_DESCRIPTION, "Menu item clicked",
+                                                    CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                    NULL);
+        }
+
+        if (GTK_IS_TOGGLE_BUTTON(d->object)) {
+
+                if (d->signal_id == signal_id_toggle_button_toggled) {
+
+                        if (!is_child_of_combo_box(GTK_WIDGET(d->object))) {
+
+                                /* We don't want to play this sound if this is a toggle
+                                 * button belonging to combo box. */
+
+                                if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(d->object)))
+                                        ret = ca_gtk_play_for_event(d->event, 0,
+                                                                    CA_PROP_EVENT_ID, "button-toggle-on",
+                                                                    CA_PROP_EVENT_DESCRIPTION, "Toggle button checked",
+                                                                    CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                                    NULL);
+                                else
+                                        ret = ca_gtk_play_for_event(d->event, 0,
+                                                                    CA_PROP_EVENT_ID, "button-toggle-off",
+                                                                    CA_PROP_EVENT_DESCRIPTION, "Toggle button unchecked",
+                                                                    CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                                    NULL);
+                        }
+                }
+
+        } else if (GTK_IS_LINK_BUTTON(d->object)) {
+
+                if (d->signal_id == signal_id_button_pressed) {
+                        ret = ca_gtk_play_for_event(d->event, 0,
+                                                    CA_PROP_EVENT_ID, "link-pressed",
+                                                    CA_PROP_EVENT_DESCRIPTION, "Link pressed",
+                                                    CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                    NULL);
+
+                } else if (d->signal_id == signal_id_button_released) {
+
+                        ret = ca_gtk_play_for_event(d->event, 0,
+                                                    CA_PROP_EVENT_ID, "link-released",
+                                                    CA_PROP_EVENT_DESCRIPTION, "Link released",
+                                                    CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                    NULL);
+                }
+
+        } else if (GTK_IS_BUTTON(d->object) && !GTK_IS_TOGGLE_BUTTON(d->object)) {
+
+                if (d->signal_id == signal_id_button_pressed) {
+                        ret = ca_gtk_play_for_event(d->event, 0,
+                                                    CA_PROP_EVENT_ID, "button-pressed",
+                                                    CA_PROP_EVENT_DESCRIPTION, "Button pressed",
+                                                    CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                    NULL);
+
+                } else if (d->signal_id == signal_id_button_released) {
+                        GtkDialog *dialog;
+                        gboolean dont_play = FALSE;
+
+                        if ((dialog = find_parent_dialog(GTK_WIDGET(d->object)))) {
+                                int response;
+
+                                /* Don't play the click sound if this is a response widget
+                                 * we will generate a dialog-xxx event sound anyway. */
+
+                                response = gtk_dialog_get_response_for_widget(dialog, GTK_WIDGET(d->object));
+                                dont_play = !!translate_response(response);
+                        }
+
+                        if (!dont_play)
+                                ret = ca_gtk_play_for_event(d->event, 0,
+                                                            CA_PROP_EVENT_ID, "button-released",
+                                                            CA_PROP_EVENT_DESCRIPTION, "Button released",
+                                                            CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                            NULL);
+                }
+        }
+
+        if (GTK_IS_NOTEBOOK(d->object) && d->signal_id == signal_id_notebook_switch_page) {
+                ret = ca_gtk_play_for_event(d->event, 0,
+                                            CA_PROP_EVENT_ID, "notebook-tab-changed",
+                                            CA_PROP_EVENT_DESCRIPTION, "Tab changed",
+                                            CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                            NULL);
+                goto finish;
+        }
+
+        if (GTK_IS_TREE_VIEW(d->object) && d->signal_id == signal_id_tree_view_cursor_changed) {
+                ret = ca_gtk_play_for_event(d->event, 0,
+                                            CA_PROP_EVENT_ID, "item-selected",
+                                            CA_PROP_EVENT_DESCRIPTION, "Item selected",
+                                            CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                            NULL);
+                goto finish;
+        }
+
+        if (GTK_IS_ICON_VIEW(d->object) && d->signal_id == signal_id_icon_view_selection_changed) {
+                ret = ca_gtk_play_for_event(d->event, 0,
+                                            CA_PROP_EVENT_ID, "item-selected",
+                                            CA_PROP_EVENT_DESCRIPTION, "Item selected",
+                                            CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                            NULL);
+                goto finish;
+        }
+
+        if (GTK_IS_EXPANDER(d->object) && d->signal_id == signal_id_expander_activate) {
+
+                if (gtk_expander_get_expanded(GTK_EXPANDER(d->object)))
+                        ret = ca_gtk_play_for_event(d->event, 0,
+                                                    CA_PROP_EVENT_ID, "expander-toggle-on",
+                                                    CA_PROP_EVENT_DESCRIPTION, "Expander expanded",
+                                                    CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                    NULL);
+                else
+                        ret = ca_gtk_play_for_event(d->event, 0,
+                                                    CA_PROP_EVENT_ID, "expander-toggle-off",
+                                                    CA_PROP_EVENT_DESCRIPTION, "Expander unexpanded",
+                                                    CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                    NULL);
+
+                goto finish;
+        }
+
+        if (GTK_IS_WIDGET(d->object)) {
+
+                if (d->signal_id == signal_id_widget_drag_begin) {
+
+                        ret = ca_gtk_play_for_event(d->event, 0,
+                                                    CA_PROP_EVENT_ID, "drag-start",
+                                                    CA_PROP_EVENT_DESCRIPTION, "Drag started",
+                                                    CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                    NULL);
+                        goto finish;
+
+                } else if (d->signal_id == signal_id_widget_drag_drop) {
+
+                        ret = ca_gtk_play_for_event(d->event, 0,
+                                                    CA_PROP_EVENT_ID, "drag-accept",
+                                                    CA_PROP_EVENT_DESCRIPTION, "Drag accepted",
+                                                    CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                    NULL);
+                        goto finish;
+
+                } else if (d->signal_id == signal_id_widget_drag_failed) {
+
+                        ret = ca_gtk_play_for_event(d->event, 0,
+                                                    CA_PROP_EVENT_ID, "drag-fail",
+                                                    CA_PROP_EVENT_DESCRIPTION, "Drag failed",
+                                                    CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                                                    NULL);
+                        goto finish;
+                }
+        }
+
+finish:
+
+        ;
+        /* if (ret != CA_SUCCESS) */
+        /*     g_warning("Failed to play event sound: %s", ca_strerror(ret)); */
+}
+
+static void dispatch_queue(void) {
+        SoundEventData *d;
+
+        while ((d = g_queue_pop_head(&sound_event_queue))) {
+
+                if (!(d = filter_sound_event(d)))
+                        continue;
+
+                dispatch_sound_event(d);
+                free_sound_event(d);
+        }
+}
+
+static gboolean idle_cb(void *userdata) {
+        idle_id = 0;
+
+        dispatch_queue();
+
+        return FALSE;
+}
+
+static void connect_settings(void);
+
+static gboolean emission_hook_cb(GSignalInvocationHint *hint, guint n_param_values, const GValue *param_values, gpointer data) {
+        static SoundEventData *d = NULL;
+        GdkEvent *e;
+        GObject *object;
+
+        connect_settings();
+
+        if (disabled)
+                return TRUE;
+
+        object = g_value_get_object(&param_values[0]);
+
+        /* g_message("signal '%s' on object of type '%s' with name '%s'", */
+        /*           g_signal_name(hint->signal_id), */
+        /*           G_OBJECT_TYPE_NAME(object), */
+        /*           gtk_widget_get_name(GTK_WIDGET(object))); */
+
+        /* if (GTK_IS_WINDOW(object)) */
+        /*     g_message("window role='%s' title='%s' type='%u'", */
+        /*               gtk_window_get_role(GTK_WINDOW(object)), */
+        /*               gtk_window_get_title(GTK_WINDOW(object)), */
+        /*               gtk_window_get_type_hint(GTK_WINDOW(object))); */
+
+        /* Filter a few very often occuring signals as quickly as possible */
+        if ((hint->signal_id == signal_id_widget_hide ||
+             hint->signal_id == signal_id_widget_show ||
+             hint->signal_id == signal_id_widget_window_state_event) &&
+            !GTK_IS_WINDOW(object))
+                return TRUE;
+
+        if (hint->signal_id != signal_id_widget_hide &&
+            hint->signal_id != signal_id_dialog_response &&
+            !gtk_widget_is_drawable(GTK_WIDGET (object)))
+                return TRUE;
+
+        d = g_slice_new0(SoundEventData);
+
+        d->object = g_object_ref(object);
+
+        d->signal_id = hint->signal_id;
+
+        if (d->signal_id == signal_id_widget_window_state_event) {
+                d->event = gdk_event_copy(g_value_peek_pointer(&param_values[1]));
+        } else if ((e = gtk_get_current_event()))
+                d->event = gdk_event_copy(e);
+
+        if (n_param_values > 1) {
+                g_value_init(&d->arg1, G_VALUE_TYPE(&param_values[1]));
+                g_value_copy(&param_values[1], &d->arg1);
+                d->arg1_is_set = TRUE;
+        }
+
+        g_queue_push_tail(&sound_event_queue, d);
+
+        if (idle_id == 0)
+                idle_id = gdk_threads_add_idle_full(GDK_PRIORITY_REDRAW-1, (GSourceFunc) idle_cb, NULL, NULL);
+
+        return TRUE;
+}
+
+static void install_hook(GType type, const char *sig, guint *sn) {
+        GTypeClass *type_class;
+
+        type_class = g_type_class_ref(type);
+
+        *sn = g_signal_lookup(sig, type);
+        g_signal_add_emission_hook(*sn, 0, emission_hook_cb, NULL, NULL);
+
+        g_type_class_unref(type_class);
+}
+
+static void read_enable_input_feedback_sounds(GtkSettings *s) {
+        gboolean enabled = !disabled;
+
+        if (g_getenv("CANBERRA_FORCE_INPUT_FEEDBACK_SOUNDS"))
+                disabled = FALSE;
+        else {
+                g_object_get(G_OBJECT(s), "gtk-enable-input-feedback-sounds", &enabled, NULL);
+                disabled = !enabled;
+        }
+}
+
+static void enable_input_feedback_sounds_changed(GtkSettings *s, GParamSpec *arg1, gpointer userdata) {
+        read_enable_input_feedback_sounds(s);
+}
+
+static void connect_settings(void) {
+        GtkSettings *s;
+        static gboolean connected = FALSE;
+
+        if (connected)
+                return;
+
+        if (!(s = gtk_settings_get_default()))
+                return;
+
+        if (g_object_class_find_property(G_OBJECT_GET_CLASS(s), "gtk-enable-input-feedback-sounds")) {
+                g_signal_connect(G_OBJECT(s), "notify::gtk-enable-input-feedback-sounds", G_CALLBACK(enable_input_feedback_sounds_changed), NULL);
+                read_enable_input_feedback_sounds(s);
+        } else
+                g_debug("This Gtk+ version doesn't have the GtkSettings::gtk-enable-input-feedback-sounds property.");
+
+        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"
+#else
+static gboolean quit_handler(gpointer data) {
+        dispatch_queue();
+        return FALSE;
+}
+#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");
+        is_xembed_quark = g_quark_from_string("canberra_is_xembed");
+
+        /* Hook up the gtk setting */
+        connect_settings();
+
+        install_hook(GTK_TYPE_WINDOW, "show", &signal_id_widget_show);
+        install_hook(GTK_TYPE_WINDOW, "hide", &signal_id_widget_hide);
+        install_hook(GTK_TYPE_DIALOG, "response", &signal_id_dialog_response);
+        install_hook(GTK_TYPE_MENU_ITEM, "activate", &signal_id_menu_item_activate);
+        install_hook(GTK_TYPE_CHECK_MENU_ITEM, "toggled", &signal_id_check_menu_item_toggled);
+        install_hook(GTK_TYPE_TOGGLE_BUTTON, "toggled", &signal_id_toggle_button_toggled);
+        install_hook(GTK_TYPE_BUTTON, "pressed", &signal_id_button_pressed);
+        install_hook(GTK_TYPE_BUTTON, "released", &signal_id_button_released);
+        install_hook(GTK_TYPE_WIDGET, "window-state-event", &signal_id_widget_window_state_event);
+        install_hook(GTK_TYPE_NOTEBOOK, "switch-page", &signal_id_notebook_switch_page);
+        install_hook(GTK_TYPE_TREE_VIEW, "cursor-changed", &signal_id_tree_view_cursor_changed);
+        install_hook(GTK_TYPE_ICON_VIEW, "selection-changed", &signal_id_icon_view_selection_changed);
+        install_hook(GTK_TYPE_WIDGET, "drag-begin", &signal_id_widget_drag_begin);
+        install_hook(GTK_TYPE_WIDGET, "drag-drop", &signal_id_widget_drag_drop);
+        install_hook(GTK_TYPE_WIDGET, "drag-failed", &signal_id_widget_drag_failed);
+        install_hook(GTK_TYPE_EXPANDER, "activate", &signal_id_expander_activate);
+
+#if !GTK_CHECK_VERSION(3,0,0)
+        gtk_quit_add(1, quit_handler, NULL);
+#endif
+}
+
+G_MODULE_EXPORT gchar* g_module_check_init(GModule *module);
+
+G_MODULE_EXPORT gchar* g_module_check_init(GModule *module) {
+        g_module_make_resident(module);
+        return NULL;
+}
Index: create-0.30-wayland-patch/libcanberra-0.30-new/src/canberra-gtk.c
===================================================================
--- create-0.30-wayland-patch/libcanberra-0.30-new/src/canberra-gtk.c	(nonexistent)
+++ create-0.30-wayland-patch/libcanberra-0.30-new/src/canberra-gtk.c	(revision 233)
@@ -0,0 +1,549 @@
+/*-*- Mode: C; c-basic-offset: 8 -*-*/
+
+/***
+  This file is part of libcanberra.
+
+  Copyright 2008 Lennart Poettering
+
+  libcanberra is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation, either version 2.1 of the
+  License, or (at your option) any later version.
+
+  libcanberra is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with libcanberra. If not, see
+  <http://www.gnu.org/licenses/>.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+
+#include "canberra.h"
+#include "canberra-gtk.h"
+#include "common.h"
+#include "malloc.h"
+#include "proplist.h"
+#include "fork-detect.h"
+
+/**
+ * SECTION:canberra-gtk
+ * @short_description: Gtk+ libcanberra Bindings
+ *
+ * libcanberra-gtk provides a few functions that simplify libcanberra
+ * usage from Gtk+ programs. It maintains a single ca_context object
+ * per #GdkScreen that is made accessible via
+ * ca_gtk_context_get_for_screen(), with a shortcut ca_gtk_context_get()
+ * to get the context for the default screen. More importantly, it provides
+ * a few functions
+ * to compile event sound property lists based on GtkWidget objects or
+ * GdkEvent events.
+ */
+
+static void read_sound_theme_name(ca_context *c, GtkSettings *s) {
+        gchar *theme_name = NULL;
+
+        g_object_get(G_OBJECT(s), "gtk-sound-theme-name", &theme_name, NULL);
+
+        if (theme_name) {
+                ca_context_change_props(c, CA_PROP_CANBERRA_XDG_THEME_NAME, theme_name, NULL);
+                g_free(theme_name);
+        }
+}
+
+static void read_enable_event_sounds(ca_context *c, GtkSettings *s) {
+        gboolean enable_event_sounds = TRUE;
+
+        if (!g_getenv("CANBERRA_FORCE_EVENT_SOUNDS"))
+                g_object_get(G_OBJECT(s), "gtk-enable-event-sounds", &enable_event_sounds, NULL);
+
+        ca_context_change_props(c, CA_PROP_CANBERRA_ENABLE, enable_event_sounds ? "1" : "0", NULL);
+}
+
+static void sound_theme_name_changed(GtkSettings *s, GParamSpec *arg1, ca_context *c) {
+        read_sound_theme_name(c, s);
+}
+
+static void enable_event_sounds_changed(GtkSettings *s, GParamSpec *arg1, ca_context *c) {
+        read_enable_event_sounds(c, s);
+}
+
+/**
+ * ca_gtk_context_get:
+ *
+ * Gets the single ca_context object for the default screen. See
+ * ca_gtk_context_get_for_screen().
+ *
+ * Returns: a ca_context object. The object is owned by libcanberra-gtk
+ *   and must not be destroyed
+ */
+ca_context *ca_gtk_context_get(void) {
+        return ca_gtk_context_get_for_screen(NULL);
+}
+
+/**
+ * ca_gtk_context_get_for_screen:
+ * @screen: the #GdkScreen to get the context for, or %NULL to use
+ *   the default screen
+ *
+ * libcanberra-gtk maintains a single ca_context object for each
+ * #GdkScreen. Use this function to access it. The
+ * %CA_PROP_CANBERRA_XDG_THEME_NAME of this context property is
+ * dynamically bound to the XSETTINGS setting for the XDG theme
+ * name. CA_PROP_APPLICATION_NAME is bound to
+ * g_get_application_name().
+ *
+ * Returns: a ca_context object. The object is owned by libcanberra-gtk
+ *   and must not be destroyed
+ *
+ * Since: 0.13
+ */
+ca_context *ca_gtk_context_get_for_screen(GdkScreen *screen) {
+        ca_context *c = NULL;
+        ca_proplist *p = NULL;
+        const char *name;
+        GtkSettings *s;
+
+        if (!screen)
+                screen = gdk_screen_get_default();
+
+        if ((c = g_object_get_data(G_OBJECT(screen), "canberra::gtk::context")))
+                return c;
+
+        if (ca_context_create(&c) != CA_SUCCESS)
+                return NULL;
+
+        if (ca_proplist_create(&p) != CA_SUCCESS) {
+                ca_context_destroy(c);
+                return NULL;
+        }
+
+        if ((name = g_get_application_name()))
+                ca_proplist_sets(p, CA_PROP_APPLICATION_NAME, name);
+        else {
+                ca_proplist_sets(p, CA_PROP_APPLICATION_NAME, "libcanberra-gtk");
+                ca_proplist_sets(p, CA_PROP_APPLICATION_VERSION, PACKAGE_VERSION);
+                ca_proplist_sets(p, CA_PROP_APPLICATION_ID, "org.freedesktop.libcanberra.gtk");
+        }
+
+        if ((name = gtk_window_get_default_icon_name()))
+                ca_proplist_sets(p, CA_PROP_APPLICATION_ICON_NAME, name);
+
+        if ((name = gdk_display_get_name(gdk_screen_get_display(screen))))
+                ca_proplist_sets(p, CA_PROP_WINDOW_X11_DISPLAY, name);
+
+        ca_proplist_setf(p, CA_PROP_WINDOW_X11_SCREEN, "%i", gdk_screen_get_number(screen));
+
+        ca_context_change_props_full(c, p);
+        ca_proplist_destroy(p);
+
+        if ((s = gtk_settings_get_for_screen(screen))) {
+
+                if (g_object_class_find_property(G_OBJECT_GET_CLASS(s), "gtk-sound-theme-name")) {
+                        g_signal_connect(G_OBJECT(s), "notify::gtk-sound-theme-name", G_CALLBACK(sound_theme_name_changed), c);
+                        read_sound_theme_name(c, s);
+                } else
+                        g_debug("This Gtk+ version doesn't have the GtkSettings::gtk-sound-theme-name property.");
+
+                if (g_object_class_find_property(G_OBJECT_GET_CLASS(s), "gtk-enable-event-sounds")) {
+                        g_signal_connect(G_OBJECT(s), "notify::gtk-enable-event-sounds", G_CALLBACK(enable_event_sounds_changed), c);
+                        read_enable_event_sounds(c, s);
+                } else
+                        g_debug("This Gtk+ version doesn't have the GtkSettings::gtk-enable-event-sounds property.");
+        }
+
+        g_object_set_data_full(G_OBJECT(screen), "canberra::gtk::context", c, (GDestroyNotify) ca_context_destroy);
+
+        return c;
+}
+
+static GtkWindow* get_toplevel(GtkWidget *w) {
+        if (!(w = gtk_widget_get_toplevel(w)))
+                return NULL;
+
+        if (!GTK_IS_WINDOW(w))
+                return NULL;
+
+        return GTK_WINDOW(w);
+}
+
+static gint window_get_desktop(GdkDisplay *d, GdkWindow *w) {
+        Atom type_return;
+        gint format_return;
+        gulong nitems_return;
+        gulong bytes_after_return;
+        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,
+                               &format_return, &nitems_return, &bytes_after_return,
+                               &data) != Success)
+                return -1;
+
+        if (type_return == XA_CARDINAL && format_return == 32 && data) {
+                guint32 desktop = *(guint32*) data;
+
+                if (desktop != 0xFFFFFFFF)
+                        ret = (gint) desktop;
+        }
+
+        if (type_return != None && data != NULL)
+                XFree(data);
+
+        return ret;
+}
+
+/**
+ * ca_gtk_proplist_set_for_widget:
+ * @p: The proplist to store these sound event properties in
+ * @w: The Gtk widget to base these sound event properties on
+ *
+ * Fill in a ca_proplist object for a sound event that shall originate
+ * from the specified Gtk Widget. This will fill in properties like
+ * %CA_PROP_WINDOW_NAME or %CA_PROP_WINDOW_X11_DISPLAY for you.
+ *
+ * Returns: 0 on success, negative error code on error.
+ */
+
+int ca_gtk_proplist_set_for_widget(ca_proplist *p, GtkWidget *widget) {
+        GtkWindow *w;
+        int ret;
+        const char *t, *role;
+
+        ca_return_val_if_fail(p, CA_ERROR_INVALID);
+        ca_return_val_if_fail(widget, CA_ERROR_INVALID);
+        ca_return_val_if_fail(!ca_detect_fork(), CA_ERROR_FORKED);
+
+        if (!(w = get_toplevel(widget)))
+                return CA_ERROR_INVALID;
+
+        if ((t = gtk_window_get_title(w)))
+                if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_NAME, t)) < 0)
+                        return ret;
+
+        if ((role = gtk_window_get_role(w))) {
+                if (role && t) {
+                        char *id = ca_sprintf_malloc("%s#%s", t, role);
+
+                        if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_ID, id)) < 0) {
+                                ca_free(id);
+                                return ret;
+                        }
+
+                        ca_free(id);
+                }
+        } else if (t)
+                if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_ID, t)) < 0)
+                        return ret;
+
+        if ((t = gtk_window_get_icon_name(w)))
+                if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_ICON_NAME, t)) < 0)
+                        return ret;
+
+        if (gtk_widget_get_realized(GTK_WIDGET(w))) {
+                GdkWindow *dw = NULL;
+                GdkScreen *screen = NULL;
+                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 ((display = gtk_widget_get_display(GTK_WIDGET(w)))) {
+                        if ((t = gdk_display_get_name(display)))
+                                if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_X11_DISPLAY, t)) < 0)
+                                        return ret;
+
+                        if (dw)  {
+                                gint desktop = window_get_desktop(display, dw);
+
+                                if (desktop >= 0)
+                                        if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_DESKTOP, "%i", desktop)) < 0)
+                                                return ret;
+                        }
+                }
+
+                if ((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;
+
+                        if (dw)
+                                if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_X11_MONITOR, "%i", gdk_screen_get_monitor_at_window(screen, dw))) < 0)
+                                        return ret;
+                }
+
+                /* FIXME, this might cause a round trip */
+
+                if (dw) {
+                        gdk_window_get_origin(dw, &x, &y);
+
+                        if (x >= 0)
+                                if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_X, "%i", x)) < 0)
+                                        return ret;
+                        if (y >= 0)
+                                if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_Y, "%i", y)) < 0)
+                                        return ret;
+                }
+
+                gtk_window_get_size(w, &width, &height);
+
+                if (width > 0)
+                        if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_WIDTH, "%i", width)) < 0)
+                                return ret;
+                if (height > 0)
+                        if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_HEIGHT, "%i", height)) < 0)
+                                return ret;
+
+                if (x >= 0 && width > 0) {
+                        screen_width = gdk_screen_get_width(gtk_widget_get_screen(GTK_WIDGET(w)));
+
+                        x += width/2;
+                        x = CA_CLAMP(x, 0, screen_width-1);
+
+                        /* We use these strange format strings here to avoid that libc
+                         * applies locale information on the formatting of floating
+                         * numbers. */
+
+                        if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_HPOS, "%i.%03i",
+                                                    (int) (x/(screen_width-1)), (int) (1000.0*x/(screen_width-1)) % 1000)) < 0)
+                                return ret;
+                }
+
+                if (y >= 0 && height > 0) {
+                        screen_height = gdk_screen_get_height(gtk_widget_get_screen(GTK_WIDGET(w)));
+
+                        y += height/2;
+                        y = CA_CLAMP(y, 0, screen_height-1);
+
+                        if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_VPOS, "%i.%03i",
+                                                    (int) (y/(screen_height-1)), (int) (1000.0*y/(screen_height-1)) % 1000)) < 0)
+                                return ret;
+                }
+        }
+
+        return CA_SUCCESS;
+}
+
+/**
+ * ca_gtk_proplist_set_for_event:
+ * @p: The proplist to store these sound event properties in
+ * @e: The Gdk event to base these sound event properties on
+ *
+ * Fill in a ca_proplist object for a sound event that is being
+ * triggered by the specified Gdk Event. This will fill in properties
+ * like %CA_PROP_EVENT_MOUSE_X or %CA_PROP_EVENT_MOUSE_BUTTON for
+ * you. This will internally also cal ca_gtk_proplist_set_for_widget()
+ * on the widget this event belongs to.
+ *
+ * Returns: 0 on success, negative error code on error.
+ */
+
+int ca_gtk_proplist_set_for_event(ca_proplist *p, GdkEvent *e) {
+        gdouble x, y;
+        GdkWindow *gw;
+        GtkWidget *w = NULL;
+        int ret;
+
+        ca_return_val_if_fail(p, CA_ERROR_INVALID);
+        ca_return_val_if_fail(e, CA_ERROR_INVALID);
+        ca_return_val_if_fail(!ca_detect_fork(), CA_ERROR_FORKED);
+
+        if ((gw = e->any.window)) {
+                gdk_window_get_user_data(gw, (gpointer*) &w);
+
+                if (w)
+                        if ((ret = ca_gtk_proplist_set_for_widget(p, w)) < 0)
+                                return ret;
+        }
+
+        if (gdk_event_get_root_coords(e, &x, &y)) {
+
+                if ((ret = ca_proplist_setf(p, CA_PROP_EVENT_MOUSE_X, "%0.0f", x)) < 0)
+                        return ret;
+
+                if ((ret = ca_proplist_setf(p, CA_PROP_EVENT_MOUSE_Y, "%0.0f", y)) < 0)
+                        return ret;
+
+                if (w)  {
+                        int width, height;
+
+                        width = gdk_screen_get_width(gtk_widget_get_screen(w));
+                        height = gdk_screen_get_height(gtk_widget_get_screen(w));
+
+                        /* We use these strange format strings here to avoid that
+                         * libc applies locale information on the formatting of
+                         * floating numbers. */
+
+                        if ((ret = ca_proplist_setf(p, CA_PROP_EVENT_MOUSE_HPOS, "%i.%03i",
+                                                    (int) (x/(width-1)), (int) (1000.0*x/(width-1)) % 1000)) < 0)
+                                return ret;
+
+                        if ((ret = ca_proplist_setf(p, CA_PROP_EVENT_MOUSE_VPOS, "%i.%03i",
+                                                    (int) (y/(height-1)), (int) (1000.0*y/(height-1)) % 1000)) < 0)
+                                return ret;
+                }
+        }
+
+        if (e->type == GDK_BUTTON_PRESS ||
+            e->type == GDK_2BUTTON_PRESS ||
+            e->type == GDK_3BUTTON_PRESS ||
+            e->type == GDK_BUTTON_RELEASE) {
+
+                if ((ret = ca_proplist_setf(p, CA_PROP_EVENT_MOUSE_BUTTON, "%u", e->button.button)) < 0)
+                        return ret;
+        }
+
+        return CA_SUCCESS;
+}
+
+/**
+ * ca_gtk_play_for_widget:
+ * @w: The Gtk widget to base these sound event properties on
+ * @id: The event id that can later be used to cancel this event sound
+ * using ca_context_cancel(). This can be any integer and shall be
+ * chosen be the client program. It is a good idea to pass 0 here if
+ * cancelling the sound later is not needed. If the same id is passed
+ * to multiple sounds they can be canceled with a single
+ * ca_context_cancel() call.
+ * @...: additional event properties as pairs of strings, terminated by NULL.
+ *
+ * Play a sound event for the specified widget. This will internally
+ * call ca_gtk_proplist_set_for_widget() and then merge them with the
+ * properties passed in via the NULL terminated argument
+ * list. Finally, it will call ca_context_play_full() to actually play
+ * the event sound.
+ *
+ * Returns: 0 on success, negative error code on error.
+ */
+
+int ca_gtk_play_for_widget(GtkWidget *w, uint32_t id, ...) {
+        va_list ap;
+        int ret;
+        ca_proplist *p;
+        GdkScreen *s;
+
+        ca_return_val_if_fail(w, CA_ERROR_INVALID);
+        ca_return_val_if_fail(!ca_detect_fork(), CA_ERROR_FORKED);
+
+        if ((ret = ca_proplist_create(&p)) < 0)
+                return ret;
+
+        if ((ret = ca_gtk_proplist_set_for_widget(p, w)) < 0)
+                goto fail;
+
+        va_start(ap, id);
+        ret = ca_proplist_merge_ap(p, ap);
+        va_end(ap);
+
+        if (ret < 0)
+                goto fail;
+
+        s = gtk_widget_get_screen(w);
+        ret = ca_context_play_full(ca_gtk_context_get_for_screen(s), id, p, NULL, NULL);
+
+fail:
+
+        ca_assert_se(ca_proplist_destroy(p) == 0);
+
+        return ret;
+}
+
+/**
+ * ca_gtk_play_for_event:
+ * @e: The Gdk event to base these sound event properties on
+ * @id: The event id that can later be used to cancel this event sound
+ * using ca_context_cancel(). This can be any integer and shall be
+ * chosen be the client program. It is a good idea to pass 0 here if
+ * cancelling the sound later is not needed. If the same id is passed
+ * to multiple sounds they can be canceled with a single
+ * ca_context_cancel() call.
+ * @...: additional event properties as pairs of strings, terminated by NULL.
+ *
+ * Play a sound event for the specified event. This will internally
+ * call ca_gtk_proplist_set_for_event() and then merge them with the
+ * properties passed in via the NULL terminated argument
+ * list. Finally, it will call ca_context_play_full() to actually play
+ * the event sound.
+ *
+ * Returns: 0 on success, negative error code on error.
+ */
+
+int ca_gtk_play_for_event(GdkEvent *e, uint32_t id, ...) {
+        va_list ap;
+        int ret;
+        ca_proplist *p;
+        GdkScreen *s;
+
+        ca_return_val_if_fail(e, CA_ERROR_INVALID);
+        ca_return_val_if_fail(!ca_detect_fork(), CA_ERROR_FORKED);
+
+        if ((ret = ca_proplist_create(&p)) < 0)
+                return ret;
+
+        if ((ret = ca_gtk_proplist_set_for_event(p, e)) < 0)
+                goto fail;
+
+        va_start(ap, id);
+        ret = ca_proplist_merge_ap(p, ap);
+        va_end(ap);
+
+        if (ret < 0)
+                goto fail;
+
+        if (e->any.window)
+#if GTK_CHECK_VERSION (2, 90, 7)
+                s = gdk_window_get_screen(e->any.window);
+#else
+                s = gdk_drawable_get_screen(GDK_DRAWABLE(e->any.window));
+#endif
+        else
+                s = gdk_screen_get_default();
+
+        ret = ca_context_play_full(ca_gtk_context_get_for_screen(s), id, p, NULL, NULL);
+
+fail:
+
+        ca_assert_se(ca_proplist_destroy(p) == 0);
+
+        return ret;
+}
+
+/**
+ * ca_gtk_widget_disable_sounds:
+ * @w: The Gtk widget to disable automatic event sounds for.
+ * @enable: Boolean specifying whether sound events shall be enabled or disabled for this widget.
+ *
+ * By default sound events are automatically generated for all kinds
+ * of input events. Use this function to disable this. This is
+ * intended to be used for widgets which directly generate sound
+ * events.
+ */
+
+void ca_gtk_widget_disable_sounds(GtkWidget *w, gboolean enable) {
+        static GQuark disable_sound_quark = 0;
+
+        /* This is the same quark used by libgnomeui! */
+        if (!disable_sound_quark)
+                disable_sound_quark = g_quark_from_static_string("gnome_disable_sound_events");
+
+        g_object_set_qdata(G_OBJECT(w), disable_sound_quark, GINT_TO_POINTER(!!enable));
+}
Index: patches/README
===================================================================
--- patches/README	(nonexistent)
+++ patches/README	(revision 233)
@@ -0,0 +1,6 @@
+
+/* begin *
+
+   TODO: Leave some comment here.
+
+ * end */
Index: patches
===================================================================
--- patches	(nonexistent)
+++ patches	(revision 233)

Property changes on: patches
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,74 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.rk358x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: .
===================================================================
--- .	(nonexistent)
+++ .	(revision 233)

Property changes on: .
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,74 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.rk358x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~