Merge lp:~3v1n0/ubuntu/vivid/libcanberra/fix-mir-crash into lp:ubuntu/vivid/libcanberra

Proposed by Marco Trevisan (Treviño)
Status: Merged
Merge reported by: Sebastien Bacher
Merged at revision: not available
Proposed branch: lp:~3v1n0/ubuntu/vivid/libcanberra/fix-mir-crash
Merge into: lp:ubuntu/vivid/libcanberra
Diff against target: 1704 lines (+1628/-0)
8 files modified
.pc/05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch/src/canberra-gtk-module.c (+990/-0)
.pc/05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch/src/canberra-gtk.c (+544/-0)
.pc/applied-patches (+1/-0)
debian/changelog (+7/-0)
debian/patches/05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch (+65/-0)
debian/patches/series (+1/-0)
src/canberra-gtk-module.c (+15/-0)
src/canberra-gtk.c (+5/-0)
To merge this branch: bzr merge lp:~3v1n0/ubuntu/vivid/libcanberra/fix-mir-crash
Reviewer Review Type Date Requested Status
Sebastien Bacher Approve
Review via email: mp+244481@code.launchpad.net

Commit message

gtk: don't assume all GdkDisplay's are GdkX11Display's

Fixes crash on Mir.

Description of the change

Backporting upstream commit to ubuntu, to get canberra properly work in Mir.

http://git.0pointer.net/libcanberra.git/commit/?id=c0620e4326

To post a comment you must log in.
Revision history for this message
Sebastien Bacher (seb128) wrote :

Thanks, but isn't our package built with a version of GTK which has that define set?

Revision history for this message
Sebastien Bacher (seb128) wrote :

ignore previous comment, I focussed on the ifdef, the useful code is in between those ;-)

review: Approve
Revision history for this message
Sebastien Bacher (seb128) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory '.pc/05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch'
2=== added directory '.pc/05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch/src'
3=== added file '.pc/05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch/src/canberra-gtk-module.c'
4--- .pc/05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch/src/canberra-gtk-module.c 1970-01-01 00:00:00 +0000
5+++ .pc/05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch/src/canberra-gtk-module.c 2014-12-11 18:09:28 +0000
6@@ -0,0 +1,990 @@
7+/*-*- Mode: C; c-basic-offset: 8 -*-*/
8+
9+/***
10+ This file is part of libcanberra.
11+
12+ Copyright 2008 Lennart Poettering
13+
14+ libcanberra is free software; you can redistribute it and/or modify
15+ it under the terms of the GNU Lesser General Public License as
16+ published by the Free Software Foundation, either version 2.1 of the
17+ License, or (at your option) any later version.
18+
19+ libcanberra is distributed in the hope that it will be useful, but
20+ WITHOUT ANY WARRANTY; without even the implied warranty of
21+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22+ Lesser General Public License for more details.
23+
24+ You should have received a copy of the GNU Lesser General Public
25+ License along with libcanberra. If not, see
26+ <http://www.gnu.org/licenses/>.
27+***/
28+
29+#ifdef HAVE_CONFIG_H
30+#include <config.h>
31+#endif
32+
33+#include <gtk/gtk.h>
34+#include <gdk/gdkx.h>
35+#include <X11/Xatom.h>
36+
37+#include "canberra-gtk.h"
38+
39+typedef struct {
40+ guint signal_id;
41+ gboolean arg1_is_set;
42+ GObject *object;
43+ GValue arg1;
44+ GdkEvent *event;
45+} SoundEventData;
46+
47+/*
48+ We generate these sounds:
49+
50+ dialog-error
51+ dialog-warning
52+ dialog-information
53+ dialog-question
54+ window-new
55+ window-close
56+ window-minimized
57+ window-unminimized
58+ window-maximized
59+ window-unmaximized
60+ notebook-tab-changed
61+ dialog-ok
62+ dialog-cancel
63+ item-selected
64+ link-pressed
65+ link-released
66+ button-pressed
67+ button-released
68+ menu-click
69+ button-toggle-on
70+ button-toggle-off
71+ menu-popup
72+ menu-popdown
73+ menu-replace
74+ tooltip-popup
75+ tooltip-popdown
76+ drag-start
77+ drag-accept
78+ drag-fail
79+ expander-toggle-on
80+ expander-toggle-off
81+
82+ TODO:
83+ scroll-xxx
84+ window-switch
85+ window-resize-xxx
86+ window-move-xxx
87+
88+*/
89+
90+static gboolean disabled = FALSE;
91+
92+static GQueue sound_event_queue = G_QUEUE_INIT;
93+
94+static guint idle_id = 0;
95+
96+static guint
97+ signal_id_dialog_response,
98+ signal_id_widget_show,
99+ signal_id_widget_hide,
100+ signal_id_check_menu_item_toggled,
101+ signal_id_menu_item_activate,
102+ signal_id_toggle_button_toggled,
103+ signal_id_button_pressed,
104+ signal_id_button_released,
105+ signal_id_widget_window_state_event,
106+ signal_id_notebook_switch_page,
107+ signal_id_tree_view_cursor_changed,
108+ signal_id_icon_view_selection_changed,
109+ signal_id_widget_drag_begin,
110+ signal_id_widget_drag_failed,
111+ signal_id_widget_drag_drop,
112+ signal_id_expander_activate;
113+
114+static GQuark
115+ disable_sound_quark,
116+ was_iconized_quark,
117+ is_xembed_quark;
118+
119+/* Make sure GCC doesn't warn us about a missing prototype for this
120+ * exported function */
121+void gtk_module_init(gint *argc, gchar ***argv[]);
122+
123+static const char *translate_message_tye(GtkMessageType mt) {
124+ static const char *const message_type_table[] = {
125+ [GTK_MESSAGE_INFO] = "dialog-information",
126+ [GTK_MESSAGE_WARNING] = "dialog-warning",
127+ [GTK_MESSAGE_QUESTION] = "dialog-question",
128+ [GTK_MESSAGE_ERROR] = "dialog-error",
129+ [GTK_MESSAGE_OTHER] = NULL
130+ };
131+
132+ if (mt >= G_N_ELEMENTS(message_type_table))
133+ return NULL;
134+
135+ return message_type_table[mt];
136+}
137+
138+static const char *translate_response(int response) {
139+ static const char *const response_table[] = {
140+ [-GTK_RESPONSE_NONE] = NULL,
141+ [-GTK_RESPONSE_REJECT] = "dialog-cancel",
142+ [-GTK_RESPONSE_DELETE_EVENT] = "dialog-cancel",
143+ [-GTK_RESPONSE_ACCEPT] = "dialog-ok",
144+ [-GTK_RESPONSE_OK] = "dialog-ok",
145+ [-GTK_RESPONSE_CANCEL] = "dialog-cancel",
146+ [-GTK_RESPONSE_CLOSE] = "dialog-ok",
147+ [-GTK_RESPONSE_YES] = "dialog-ok",
148+ [-GTK_RESPONSE_NO] = "dialog-cancel",
149+ [-GTK_RESPONSE_APPLY] = "dialog-ok",
150+ [-GTK_RESPONSE_HELP] = NULL,
151+ };
152+
153+ if (response >= 0)
154+ return NULL;
155+
156+ if ((unsigned) -response >= G_N_ELEMENTS(response_table))
157+ return NULL;
158+
159+ return response_table[-response];
160+}
161+
162+static gboolean is_child_of_combo_box(GtkWidget *w) {
163+
164+ while (w) {
165+
166+ if (GTK_IS_COMBO_BOX(w))
167+ return TRUE;
168+
169+ w = gtk_widget_get_parent(w);
170+ }
171+
172+ return FALSE;
173+}
174+
175+static GtkDialog* find_parent_dialog(GtkWidget *w) {
176+
177+ while (w) {
178+
179+ if (GTK_IS_DIALOG(w))
180+ return GTK_DIALOG(w);
181+
182+ w = gtk_widget_get_parent(w);
183+ }
184+
185+ return NULL;
186+}
187+
188+static void free_sound_event(SoundEventData *d) {
189+
190+ g_object_unref(d->object);
191+
192+ if (d->arg1_is_set)
193+ g_value_unset(&d->arg1);
194+
195+ if (d->event)
196+ gdk_event_free(d->event);
197+
198+ g_slice_free(SoundEventData, d);
199+}
200+
201+static gboolean is_menu_hint(GdkWindowTypeHint hint) {
202+ return
203+ hint == GDK_WINDOW_TYPE_HINT_POPUP_MENU ||
204+ hint == GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU ||
205+ hint == GDK_WINDOW_TYPE_HINT_MENU;
206+}
207+
208+static SoundEventData* filter_sound_event(SoundEventData *d) {
209+ GList *i, *n;
210+
211+ do {
212+
213+ for (i = sound_event_queue.head; i; i = n) {
214+ SoundEventData *j;
215+
216+ j = i->data;
217+ n = i->next;
218+
219+ if (d->object == j->object) {
220+
221+ /* Let's drop a show event immediately followed by a
222+ * hide event */
223+
224+ if (d->signal_id == signal_id_widget_show &&
225+ j->signal_id == signal_id_widget_hide) {
226+
227+ free_sound_event(d);
228+ free_sound_event(j);
229+ g_queue_delete_link(&sound_event_queue, i);
230+
231+ return NULL;
232+ }
233+
234+ /* Let's drop widget hide events in favour of dialog
235+ * response.
236+ *
237+ * Let's drop widget window state events in favour of
238+ * widget hide/show.
239+ *
240+ * Let's drop double events */
241+
242+ if ((d->signal_id == signal_id_widget_hide &&
243+ j->signal_id == signal_id_dialog_response) ||
244+
245+ (d->signal_id == signal_id_widget_window_state_event &&
246+ j->signal_id == signal_id_widget_hide) ||
247+
248+ (d->signal_id == signal_id_widget_window_state_event &&
249+ j->signal_id == signal_id_widget_show)) {
250+
251+ free_sound_event(d);
252+ d = j;
253+ g_queue_delete_link(&sound_event_queue, i);
254+ break;
255+ }
256+
257+ if ((d->signal_id == signal_id_dialog_response &&
258+ j->signal_id == signal_id_widget_hide) ||
259+
260+ (d->signal_id == signal_id_widget_show &&
261+ j->signal_id == signal_id_widget_window_state_event) ||
262+
263+ (d->signal_id == signal_id_widget_hide &&
264+ j->signal_id == signal_id_widget_window_state_event) ||
265+
266+ (d->signal_id == j->signal_id)) {
267+
268+ free_sound_event(j);
269+ g_queue_delete_link(&sound_event_queue, i);
270+ }
271+
272+ } else if (GTK_IS_WINDOW(d->object) && GTK_IS_WINDOW(j->object)) {
273+
274+ GdkWindowTypeHint dhint, jhint;
275+
276+ dhint = gtk_window_get_type_hint(GTK_WINDOW(d->object));
277+ jhint = gtk_window_get_type_hint(GTK_WINDOW(j->object));
278+
279+ if (is_menu_hint(dhint) && is_menu_hint(jhint)) {
280+
281+ if (d->signal_id == signal_id_widget_hide &&
282+ j->signal_id == signal_id_widget_show) {
283+ free_sound_event(d);
284+ d = j;
285+ g_queue_delete_link(&sound_event_queue, i);
286+ break;
287+ }
288+
289+ if (d->signal_id == signal_id_widget_show &&
290+ j->signal_id == signal_id_widget_hide) {
291+
292+ free_sound_event(j);
293+ g_queue_delete_link(&sound_event_queue, i);
294+ }
295+ }
296+ }
297+ }
298+
299+ /* If we exited the iteration early, let's retry. */
300+
301+ } while (i);
302+
303+ /* FIXME: Filter menu hide on menu show */
304+
305+ return d;
306+}
307+
308+static gint window_get_desktop(GdkDisplay *d, GdkWindow *w) {
309+ Atom type_return;
310+ gint format_return;
311+ gulong nitems_return;
312+ gulong bytes_after_return;
313+ guchar *data = NULL;
314+ gint ret = -1;
315+
316+ if (XGetWindowProperty(GDK_DISPLAY_XDISPLAY(d), GDK_WINDOW_XID(w),
317+ gdk_x11_get_xatom_by_name_for_display(d, "_NET_WM_DESKTOP"),
318+ 0, G_MAXLONG, False, XA_CARDINAL, &type_return,
319+ &format_return, &nitems_return, &bytes_after_return,
320+ &data) != Success)
321+ return -1;
322+
323+ if (type_return == XA_CARDINAL && format_return == 32 && data) {
324+ guint32 desktop = *(guint32*) data;
325+
326+ if (desktop != 0xFFFFFFFF)
327+ ret = (gint) desktop;
328+ }
329+
330+ if (type_return != None && data != NULL)
331+ XFree(data);
332+
333+ return ret;
334+}
335+
336+static gint display_get_desktop(GdkDisplay *d) {
337+ Atom type_return;
338+ gint format_return;
339+ gulong nitems_return;
340+ gulong bytes_after_return;
341+ guchar *data = NULL;
342+ gint ret = -1;
343+
344+ if (XGetWindowProperty(GDK_DISPLAY_XDISPLAY(d), DefaultRootWindow(GDK_DISPLAY_XDISPLAY(d)),
345+ gdk_x11_get_xatom_by_name_for_display(d, "_NET_CURRENT_DESKTOP"),
346+ 0, G_MAXLONG, False, XA_CARDINAL, &type_return,
347+ &format_return, &nitems_return, &bytes_after_return,
348+ &data) != Success)
349+ return -1;
350+
351+ if (type_return == XA_CARDINAL && format_return == 32 && data) {
352+
353+ guint32 desktop = *(guint32*) data;
354+
355+ if (desktop != 0xFFFFFFFF)
356+ ret = (gint) desktop;
357+ }
358+
359+ if (type_return != None && data != NULL)
360+ XFree(data);
361+
362+ return ret;
363+}
364+
365+static gboolean window_is_xembed(GdkDisplay *d, GdkWindow *w) {
366+ Atom type_return;
367+ gint format_return;
368+ gulong nitems_return;
369+ gulong bytes_after_return;
370+ guchar *data = NULL;
371+ gboolean ret = FALSE;
372+ Atom xembed;
373+
374+ /* Gnome Panel applets are XEMBED windows. We need to make sure we
375+ * ignore them */
376+
377+ xembed = gdk_x11_get_xatom_by_name_for_display(d, "_XEMBED_INFO");
378+
379+ /* be robust against not existing XIDs (LP: #834403) */
380+ gdk_error_trap_push();
381+ if (XGetWindowProperty(GDK_DISPLAY_XDISPLAY(d), GDK_WINDOW_XID(w),
382+ xembed,
383+ 0, 2, False, xembed, &type_return,
384+ &format_return, &nitems_return, &bytes_after_return,
385+ &data) != Success) {
386+ return FALSE;
387+ }
388+
389+#if GTK_CHECK_VERSION(3,0,0)
390+ gdk_error_trap_pop_ignored();
391+#else
392+ gdk_flush();
393+ gdk_error_trap_pop();
394+#endif
395+
396+ if (type_return == xembed && format_return == 32 && data)
397+ ret = TRUE;
398+
399+ if (type_return != None && data != NULL)
400+ XFree(data);
401+
402+ return ret;
403+}
404+
405+static void dispatch_sound_event(SoundEventData *d) {
406+ int ret = CA_SUCCESS;
407+ static gboolean menu_is_popped_up = FALSE;
408+
409+ if (g_object_get_qdata(d->object, disable_sound_quark))
410+ return;
411+
412+ /* The GdkWindow of the the widget might have changed while this
413+ * event was queued for us. Make sure to update it from the
414+ * current one if necessary. */
415+ if (d->event && d->event->any.window) {
416+ GdkWindow *window;
417+
418+ g_object_unref(G_OBJECT(d->event->any.window));
419+
420+ if ((window = gtk_widget_get_window(GTK_WIDGET(d->object))))
421+ d->event->any.window = GDK_WINDOW(g_object_ref(G_OBJECT(window)));
422+ else
423+ d->event->any.window = NULL;
424+ }
425+
426+ if (d->signal_id == signal_id_widget_show) {
427+ GdkWindowTypeHint hint;
428+
429+ /* Show/hide signals for non-windows have already been filtered out
430+ * by the emission hook! */
431+
432+ hint = gtk_window_get_type_hint(GTK_WINDOW(d->object));
433+
434+ if (is_menu_hint(hint)) {
435+
436+ if (!menu_is_popped_up) {
437+
438+ ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
439+ CA_PROP_EVENT_ID, "menu-popup",
440+ CA_PROP_EVENT_DESCRIPTION, "Menu popped up",
441+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
442+ NULL);
443+ } else {
444+ ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
445+ CA_PROP_EVENT_ID, "menu-replace",
446+ CA_PROP_EVENT_DESCRIPTION, "Menu replaced",
447+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
448+ NULL);
449+ }
450+
451+ menu_is_popped_up = TRUE;
452+
453+ } else if (hint == GDK_WINDOW_TYPE_HINT_TOOLTIP) {
454+
455+ ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
456+ CA_PROP_EVENT_ID, "tooltip-popup",
457+ CA_PROP_EVENT_DESCRIPTION, "Tooltip popped up",
458+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
459+ NULL);
460+
461+ } else if (hint == GDK_WINDOW_TYPE_HINT_NORMAL ||
462+ hint == GDK_WINDOW_TYPE_HINT_DIALOG) {
463+
464+ gboolean played_sound = FALSE;
465+ gboolean is_xembed;
466+
467+ is_xembed =
468+ gtk_widget_get_realized(GTK_WIDGET(d->object)) &&
469+ window_is_xembed(
470+ gtk_widget_get_display(GTK_WIDGET(d->object)),
471+ gtk_widget_get_window(GTK_WIDGET(d->object)));
472+
473+ g_object_set_qdata(d->object, is_xembed_quark, GINT_TO_POINTER(is_xembed));
474+
475+ if (GTK_IS_MESSAGE_DIALOG(d->object)) {
476+ GtkMessageType mt;
477+ const char *id;
478+
479+ g_object_get(d->object, "message_type", &mt, NULL);
480+
481+ if ((id = translate_message_tye(mt))) {
482+
483+ ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
484+ CA_PROP_EVENT_ID, id,
485+ CA_PROP_EVENT_DESCRIPTION, "Message dialog shown",
486+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
487+ NULL);
488+ played_sound = TRUE;
489+ }
490+
491+ }
492+
493+ if (!played_sound &&
494+ !is_xembed &&
495+ gtk_window_get_decorated(GTK_WINDOW(d->object))) {
496+
497+ ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
498+ CA_PROP_EVENT_ID, "window-new",
499+ CA_PROP_EVENT_DESCRIPTION, "Window shown",
500+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
501+ NULL);
502+
503+ }
504+ }
505+ }
506+
507+ if (GTK_IS_DIALOG(d->object) && d->signal_id == signal_id_dialog_response) {
508+
509+ int response;
510+ const char *id;
511+
512+ response = g_value_get_int(&d->arg1);
513+
514+ if ((id = translate_response(response))) {
515+
516+ ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
517+ CA_PROP_EVENT_ID, id,
518+ CA_PROP_EVENT_DESCRIPTION, "Dialog closed",
519+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
520+ NULL);
521+ } else {
522+ ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
523+ CA_PROP_EVENT_ID, "window-close",
524+ CA_PROP_EVENT_DESCRIPTION, "Window closed",
525+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
526+ NULL);
527+ }
528+
529+ } else if (d->signal_id == signal_id_widget_hide) {
530+ GdkWindowTypeHint hint;
531+
532+ hint = gtk_window_get_type_hint(GTK_WINDOW(d->object));
533+
534+ if (is_menu_hint(hint)) {
535+
536+ if (GTK_IS_MENU(gtk_bin_get_child(GTK_BIN(d->object)))) {
537+
538+ ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
539+ CA_PROP_EVENT_ID, "menu-popdown",
540+ CA_PROP_EVENT_DESCRIPTION, "Menu popped down",
541+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
542+ NULL);
543+ }
544+
545+ menu_is_popped_up = FALSE;
546+
547+ } else if (hint == GDK_WINDOW_TYPE_HINT_TOOLTIP) {
548+
549+ ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
550+ CA_PROP_EVENT_ID, "tooltip-popdown",
551+ CA_PROP_EVENT_DESCRIPTION, "Tooltip popped down",
552+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
553+ NULL);
554+
555+ } else if ((hint == GDK_WINDOW_TYPE_HINT_NORMAL ||
556+ hint == GDK_WINDOW_TYPE_HINT_DIALOG)) {
557+
558+ gboolean is_xembed;
559+
560+ is_xembed = !!g_object_get_qdata(d->object, is_xembed_quark);
561+
562+ if (!is_xembed &&
563+ gtk_window_get_decorated(GTK_WINDOW(d->object)))
564+ ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
565+ CA_PROP_EVENT_ID, "window-close",
566+ CA_PROP_EVENT_DESCRIPTION, "Window closed",
567+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
568+ NULL);
569+ }
570+ }
571+
572+ if (GTK_IS_WINDOW(d->object) && d->signal_id == signal_id_widget_window_state_event) {
573+ GdkEventWindowState *e;
574+ gint w_desktop = -1, c_desktop = -1;
575+
576+ e = (GdkEventWindowState*) d->event;
577+
578+ /* Unfortunately GDK_WINDOW_STATE_ICONIFIED is used both for
579+ * proper minimizing and when a window becomes invisible
580+ * because the desktop was switched. To handle this we check
581+ * if the window becoming invisible is actually on the current
582+ * desktop, and only if that's the case we assume it is being
583+ * minimized. We then store this information, so that we know
584+ * later on when the window is unminimized again. */
585+
586+ if (gtk_widget_get_realized(GTK_WIDGET(d->object))) {
587+ GdkDisplay *display;
588+
589+ display = gtk_widget_get_display(GTK_WIDGET(d->object));
590+ w_desktop = window_get_desktop(display, gtk_widget_get_window(GTK_WIDGET(d->object)));
591+ c_desktop = display_get_desktop(display);
592+ }
593+
594+ if ((e->changed_mask & GDK_WINDOW_STATE_ICONIFIED) &&
595+ (e->new_window_state & GDK_WINDOW_STATE_ICONIFIED) &&
596+ (w_desktop == c_desktop || w_desktop < 0)) {
597+
598+ ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
599+ CA_PROP_EVENT_ID, "window-minimized",
600+ CA_PROP_EVENT_DESCRIPTION, "Window minimized",
601+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
602+ NULL);
603+
604+ g_object_set_qdata(d->object, was_iconized_quark, GINT_TO_POINTER(1));
605+
606+ } else if ((e->changed_mask & (GDK_WINDOW_STATE_MAXIMIZED|GDK_WINDOW_STATE_FULLSCREEN)) &&
607+ (e->new_window_state & (GDK_WINDOW_STATE_MAXIMIZED|GDK_WINDOW_STATE_FULLSCREEN))) {
608+
609+ ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
610+ CA_PROP_EVENT_ID, "window-maximized",
611+ CA_PROP_EVENT_DESCRIPTION, "Window maximized",
612+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
613+ NULL);
614+
615+ g_object_set_qdata(d->object, was_iconized_quark, GINT_TO_POINTER(0));
616+
617+ } else if ((e->changed_mask & GDK_WINDOW_STATE_ICONIFIED) &&
618+ !(e->new_window_state & GDK_WINDOW_STATE_ICONIFIED) &&
619+ g_object_get_qdata(d->object, was_iconized_quark)) {
620+
621+ ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
622+ CA_PROP_EVENT_ID, "window-unminimized",
623+ CA_PROP_EVENT_DESCRIPTION, "Window unminimized",
624+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
625+ NULL);
626+
627+ g_object_set_qdata(d->object, was_iconized_quark, GINT_TO_POINTER(0));
628+
629+ } else if ((e->changed_mask & (GDK_WINDOW_STATE_MAXIMIZED|GDK_WINDOW_STATE_FULLSCREEN)) &&
630+ !(e->new_window_state & (GDK_WINDOW_STATE_MAXIMIZED|GDK_WINDOW_STATE_FULLSCREEN))) {
631+
632+ ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
633+ CA_PROP_EVENT_ID, "window-unmaximized",
634+ CA_PROP_EVENT_DESCRIPTION, "Window unmaximized",
635+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
636+ NULL);
637+ }
638+ }
639+
640+ if (GTK_IS_CHECK_MENU_ITEM(d->object) && d->signal_id == signal_id_check_menu_item_toggled) {
641+
642+ if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(d->object)))
643+ ret = ca_gtk_play_for_event(d->event, 0,
644+ CA_PROP_EVENT_ID, "button-toggle-on",
645+ CA_PROP_EVENT_DESCRIPTION, "Check menu item checked",
646+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
647+ NULL);
648+ else
649+ ret = ca_gtk_play_for_event(d->event, 0,
650+ CA_PROP_EVENT_ID, "button-toggle-off",
651+ CA_PROP_EVENT_DESCRIPTION, "Check menu item unchecked",
652+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
653+ NULL);
654+
655+ } else if (GTK_IS_MENU_ITEM(d->object) && d->signal_id == signal_id_menu_item_activate) {
656+
657+ if (!gtk_menu_item_get_submenu(GTK_MENU_ITEM(d->object)))
658+ ret = ca_gtk_play_for_event(d->event, 0,
659+ CA_PROP_EVENT_ID, "menu-click",
660+ CA_PROP_EVENT_DESCRIPTION, "Menu item clicked",
661+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
662+ NULL);
663+ }
664+
665+ if (GTK_IS_TOGGLE_BUTTON(d->object)) {
666+
667+ if (d->signal_id == signal_id_toggle_button_toggled) {
668+
669+ if (!is_child_of_combo_box(GTK_WIDGET(d->object))) {
670+
671+ /* We don't want to play this sound if this is a toggle
672+ * button belonging to combo box. */
673+
674+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(d->object)))
675+ ret = ca_gtk_play_for_event(d->event, 0,
676+ CA_PROP_EVENT_ID, "button-toggle-on",
677+ CA_PROP_EVENT_DESCRIPTION, "Toggle button checked",
678+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
679+ NULL);
680+ else
681+ ret = ca_gtk_play_for_event(d->event, 0,
682+ CA_PROP_EVENT_ID, "button-toggle-off",
683+ CA_PROP_EVENT_DESCRIPTION, "Toggle button unchecked",
684+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
685+ NULL);
686+ }
687+ }
688+
689+ } else if (GTK_IS_LINK_BUTTON(d->object)) {
690+
691+ if (d->signal_id == signal_id_button_pressed) {
692+ ret = ca_gtk_play_for_event(d->event, 0,
693+ CA_PROP_EVENT_ID, "link-pressed",
694+ CA_PROP_EVENT_DESCRIPTION, "Link pressed",
695+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
696+ NULL);
697+
698+ } else if (d->signal_id == signal_id_button_released) {
699+
700+ ret = ca_gtk_play_for_event(d->event, 0,
701+ CA_PROP_EVENT_ID, "link-released",
702+ CA_PROP_EVENT_DESCRIPTION, "Link released",
703+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
704+ NULL);
705+ }
706+
707+ } else if (GTK_IS_BUTTON(d->object) && !GTK_IS_TOGGLE_BUTTON(d->object)) {
708+
709+ if (d->signal_id == signal_id_button_pressed) {
710+ ret = ca_gtk_play_for_event(d->event, 0,
711+ CA_PROP_EVENT_ID, "button-pressed",
712+ CA_PROP_EVENT_DESCRIPTION, "Button pressed",
713+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
714+ NULL);
715+
716+ } else if (d->signal_id == signal_id_button_released) {
717+ GtkDialog *dialog;
718+ gboolean dont_play = FALSE;
719+
720+ if ((dialog = find_parent_dialog(GTK_WIDGET(d->object)))) {
721+ int response;
722+
723+ /* Don't play the click sound if this is a response widget
724+ * we will generate a dialog-xxx event sound anyway. */
725+
726+ response = gtk_dialog_get_response_for_widget(dialog, GTK_WIDGET(d->object));
727+ dont_play = !!translate_response(response);
728+ }
729+
730+ if (!dont_play)
731+ ret = ca_gtk_play_for_event(d->event, 0,
732+ CA_PROP_EVENT_ID, "button-released",
733+ CA_PROP_EVENT_DESCRIPTION, "Button released",
734+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
735+ NULL);
736+ }
737+ }
738+
739+ if (GTK_IS_NOTEBOOK(d->object) && d->signal_id == signal_id_notebook_switch_page) {
740+ ret = ca_gtk_play_for_event(d->event, 0,
741+ CA_PROP_EVENT_ID, "notebook-tab-changed",
742+ CA_PROP_EVENT_DESCRIPTION, "Tab changed",
743+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
744+ NULL);
745+ goto finish;
746+ }
747+
748+ if (GTK_IS_TREE_VIEW(d->object) && d->signal_id == signal_id_tree_view_cursor_changed) {
749+ ret = ca_gtk_play_for_event(d->event, 0,
750+ CA_PROP_EVENT_ID, "item-selected",
751+ CA_PROP_EVENT_DESCRIPTION, "Item selected",
752+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
753+ NULL);
754+ goto finish;
755+ }
756+
757+ if (GTK_IS_ICON_VIEW(d->object) && d->signal_id == signal_id_icon_view_selection_changed) {
758+ ret = ca_gtk_play_for_event(d->event, 0,
759+ CA_PROP_EVENT_ID, "item-selected",
760+ CA_PROP_EVENT_DESCRIPTION, "Item selected",
761+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
762+ NULL);
763+ goto finish;
764+ }
765+
766+ if (GTK_IS_EXPANDER(d->object) && d->signal_id == signal_id_expander_activate) {
767+
768+ if (gtk_expander_get_expanded(GTK_EXPANDER(d->object)))
769+ ret = ca_gtk_play_for_event(d->event, 0,
770+ CA_PROP_EVENT_ID, "expander-toggle-on",
771+ CA_PROP_EVENT_DESCRIPTION, "Expander expanded",
772+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
773+ NULL);
774+ else
775+ ret = ca_gtk_play_for_event(d->event, 0,
776+ CA_PROP_EVENT_ID, "expander-toggle-off",
777+ CA_PROP_EVENT_DESCRIPTION, "Expander unexpanded",
778+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
779+ NULL);
780+
781+ goto finish;
782+ }
783+
784+ if (GTK_IS_WIDGET(d->object)) {
785+
786+ if (d->signal_id == signal_id_widget_drag_begin) {
787+
788+ ret = ca_gtk_play_for_event(d->event, 0,
789+ CA_PROP_EVENT_ID, "drag-start",
790+ CA_PROP_EVENT_DESCRIPTION, "Drag started",
791+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
792+ NULL);
793+ goto finish;
794+
795+ } else if (d->signal_id == signal_id_widget_drag_drop) {
796+
797+ ret = ca_gtk_play_for_event(d->event, 0,
798+ CA_PROP_EVENT_ID, "drag-accept",
799+ CA_PROP_EVENT_DESCRIPTION, "Drag accepted",
800+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
801+ NULL);
802+ goto finish;
803+
804+ } else if (d->signal_id == signal_id_widget_drag_failed) {
805+
806+ ret = ca_gtk_play_for_event(d->event, 0,
807+ CA_PROP_EVENT_ID, "drag-fail",
808+ CA_PROP_EVENT_DESCRIPTION, "Drag failed",
809+ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
810+ NULL);
811+ goto finish;
812+ }
813+ }
814+
815+finish:
816+
817+ ;
818+ /* if (ret != CA_SUCCESS) */
819+ /* g_warning("Failed to play event sound: %s", ca_strerror(ret)); */
820+}
821+
822+static void dispatch_queue(void) {
823+ SoundEventData *d;
824+
825+ while ((d = g_queue_pop_head(&sound_event_queue))) {
826+
827+ if (!(d = filter_sound_event(d)))
828+ continue;
829+
830+ dispatch_sound_event(d);
831+ free_sound_event(d);
832+ }
833+}
834+
835+static gboolean idle_cb(void *userdata) {
836+ idle_id = 0;
837+
838+ dispatch_queue();
839+
840+ return FALSE;
841+}
842+
843+static void connect_settings(void);
844+
845+static gboolean emission_hook_cb(GSignalInvocationHint *hint, guint n_param_values, const GValue *param_values, gpointer data) {
846+ static SoundEventData *d = NULL;
847+ GdkEvent *e;
848+ GObject *object;
849+
850+ connect_settings();
851+
852+ if (disabled)
853+ return TRUE;
854+
855+ object = g_value_get_object(&param_values[0]);
856+
857+ /* g_message("signal '%s' on object of type '%s' with name '%s'", */
858+ /* g_signal_name(hint->signal_id), */
859+ /* G_OBJECT_TYPE_NAME(object), */
860+ /* gtk_widget_get_name(GTK_WIDGET(object))); */
861+
862+ /* if (GTK_IS_WINDOW(object)) */
863+ /* g_message("window role='%s' title='%s' type='%u'", */
864+ /* gtk_window_get_role(GTK_WINDOW(object)), */
865+ /* gtk_window_get_title(GTK_WINDOW(object)), */
866+ /* gtk_window_get_type_hint(GTK_WINDOW(object))); */
867+
868+ /* Filter a few very often occuring signals as quickly as possible */
869+ if ((hint->signal_id == signal_id_widget_hide ||
870+ hint->signal_id == signal_id_widget_show ||
871+ hint->signal_id == signal_id_widget_window_state_event) &&
872+ !GTK_IS_WINDOW(object))
873+ return TRUE;
874+
875+ if (hint->signal_id != signal_id_widget_hide &&
876+ hint->signal_id != signal_id_dialog_response &&
877+ !gtk_widget_is_drawable(GTK_WIDGET (object)))
878+ return TRUE;
879+
880+ d = g_slice_new0(SoundEventData);
881+
882+ d->object = g_object_ref(object);
883+
884+ d->signal_id = hint->signal_id;
885+
886+ if (d->signal_id == signal_id_widget_window_state_event) {
887+ d->event = gdk_event_copy(g_value_peek_pointer(&param_values[1]));
888+ } else if ((e = gtk_get_current_event()))
889+ d->event = gdk_event_copy(e);
890+
891+ if (n_param_values > 1) {
892+ g_value_init(&d->arg1, G_VALUE_TYPE(&param_values[1]));
893+ g_value_copy(&param_values[1], &d->arg1);
894+ d->arg1_is_set = TRUE;
895+ }
896+
897+ g_queue_push_tail(&sound_event_queue, d);
898+
899+ if (idle_id == 0)
900+ idle_id = gdk_threads_add_idle_full(GDK_PRIORITY_REDRAW-1, (GSourceFunc) idle_cb, NULL, NULL);
901+
902+ return TRUE;
903+}
904+
905+static void install_hook(GType type, const char *sig, guint *sn) {
906+ GTypeClass *type_class;
907+
908+ type_class = g_type_class_ref(type);
909+
910+ *sn = g_signal_lookup(sig, type);
911+ g_signal_add_emission_hook(*sn, 0, emission_hook_cb, NULL, NULL);
912+
913+ g_type_class_unref(type_class);
914+}
915+
916+static void read_enable_input_feedback_sounds(GtkSettings *s) {
917+ gboolean enabled = !disabled;
918+
919+ if (g_getenv("CANBERRA_FORCE_INPUT_FEEDBACK_SOUNDS"))
920+ disabled = FALSE;
921+ else {
922+ g_object_get(G_OBJECT(s), "gtk-enable-input-feedback-sounds", &enabled, NULL);
923+ disabled = !enabled;
924+ }
925+}
926+
927+static void enable_input_feedback_sounds_changed(GtkSettings *s, GParamSpec *arg1, gpointer userdata) {
928+ read_enable_input_feedback_sounds(s);
929+}
930+
931+static void connect_settings(void) {
932+ GtkSettings *s;
933+ static gboolean connected = FALSE;
934+
935+ if (connected)
936+ return;
937+
938+ if (!(s = gtk_settings_get_default()))
939+ return;
940+
941+ if (g_object_class_find_property(G_OBJECT_GET_CLASS(s), "gtk-enable-input-feedback-sounds")) {
942+ g_signal_connect(G_OBJECT(s), "notify::gtk-enable-input-feedback-sounds", G_CALLBACK(enable_input_feedback_sounds_changed), NULL);
943+ read_enable_input_feedback_sounds(s);
944+ } else
945+ g_debug("This Gtk+ version doesn't have the GtkSettings::gtk-enable-input-feedback-sounds property.");
946+
947+ connected = TRUE;
948+}
949+
950+#if GTK_CHECK_VERSION(3,0,0)
951+#warning "We really need a quit handler in Gtk 3.0, https://bugzilla.gnome.org/show_bug.cgi?id=639770"
952+#else
953+static gboolean quit_handler(gpointer data) {
954+ dispatch_queue();
955+ return FALSE;
956+}
957+#endif
958+
959+G_MODULE_EXPORT void gtk_module_init(gint *argc, gchar ***argv[]) {
960+
961+ /* This is the same quark libgnomeui uses! */
962+ disable_sound_quark = g_quark_from_string("gnome_disable_sound_events");
963+ was_iconized_quark = g_quark_from_string("canberra_was_iconized");
964+ is_xembed_quark = g_quark_from_string("canberra_is_xembed");
965+
966+ /* Hook up the gtk setting */
967+ connect_settings();
968+
969+ install_hook(GTK_TYPE_WINDOW, "show", &signal_id_widget_show);
970+ install_hook(GTK_TYPE_WINDOW, "hide", &signal_id_widget_hide);
971+ install_hook(GTK_TYPE_DIALOG, "response", &signal_id_dialog_response);
972+ install_hook(GTK_TYPE_MENU_ITEM, "activate", &signal_id_menu_item_activate);
973+ install_hook(GTK_TYPE_CHECK_MENU_ITEM, "toggled", &signal_id_check_menu_item_toggled);
974+ install_hook(GTK_TYPE_TOGGLE_BUTTON, "toggled", &signal_id_toggle_button_toggled);
975+ install_hook(GTK_TYPE_BUTTON, "pressed", &signal_id_button_pressed);
976+ install_hook(GTK_TYPE_BUTTON, "released", &signal_id_button_released);
977+ install_hook(GTK_TYPE_WIDGET, "window-state-event", &signal_id_widget_window_state_event);
978+ install_hook(GTK_TYPE_NOTEBOOK, "switch-page", &signal_id_notebook_switch_page);
979+ install_hook(GTK_TYPE_TREE_VIEW, "cursor-changed", &signal_id_tree_view_cursor_changed);
980+ install_hook(GTK_TYPE_ICON_VIEW, "selection-changed", &signal_id_icon_view_selection_changed);
981+ install_hook(GTK_TYPE_WIDGET, "drag-begin", &signal_id_widget_drag_begin);
982+ install_hook(GTK_TYPE_WIDGET, "drag-drop", &signal_id_widget_drag_drop);
983+ install_hook(GTK_TYPE_WIDGET, "drag-failed", &signal_id_widget_drag_failed);
984+ install_hook(GTK_TYPE_EXPANDER, "activate", &signal_id_expander_activate);
985+
986+#if !GTK_CHECK_VERSION(3,0,0)
987+ gtk_quit_add(1, quit_handler, NULL);
988+#endif
989+}
990+
991+G_MODULE_EXPORT gchar* g_module_check_init(GModule *module);
992+
993+G_MODULE_EXPORT gchar* g_module_check_init(GModule *module) {
994+ g_module_make_resident(module);
995+ return NULL;
996+}
997
998=== added file '.pc/05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch/src/canberra-gtk.c'
999--- .pc/05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch/src/canberra-gtk.c 1970-01-01 00:00:00 +0000
1000+++ .pc/05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch/src/canberra-gtk.c 2014-12-11 18:09:28 +0000
1001@@ -0,0 +1,544 @@
1002+/*-*- Mode: C; c-basic-offset: 8 -*-*/
1003+
1004+/***
1005+ This file is part of libcanberra.
1006+
1007+ Copyright 2008 Lennart Poettering
1008+
1009+ libcanberra is free software; you can redistribute it and/or modify
1010+ it under the terms of the GNU Lesser General Public License as
1011+ published by the Free Software Foundation, either version 2.1 of the
1012+ License, or (at your option) any later version.
1013+
1014+ libcanberra is distributed in the hope that it will be useful, but
1015+ WITHOUT ANY WARRANTY; without even the implied warranty of
1016+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1017+ Lesser General Public License for more details.
1018+
1019+ You should have received a copy of the GNU Lesser General Public
1020+ License along with libcanberra. If not, see
1021+ <http://www.gnu.org/licenses/>.
1022+***/
1023+
1024+#ifdef HAVE_CONFIG_H
1025+#include <config.h>
1026+#endif
1027+
1028+#include <gtk/gtk.h>
1029+#include <gdk/gdk.h>
1030+#include <gdk/gdkx.h>
1031+#include <X11/Xatom.h>
1032+
1033+#include "canberra.h"
1034+#include "canberra-gtk.h"
1035+#include "common.h"
1036+#include "malloc.h"
1037+#include "proplist.h"
1038+#include "fork-detect.h"
1039+
1040+/**
1041+ * SECTION:canberra-gtk
1042+ * @short_description: Gtk+ libcanberra Bindings
1043+ *
1044+ * libcanberra-gtk provides a few functions that simplify libcanberra
1045+ * usage from Gtk+ programs. It maintains a single ca_context object
1046+ * per #GdkScreen that is made accessible via
1047+ * ca_gtk_context_get_for_screen(), with a shortcut ca_gtk_context_get()
1048+ * to get the context for the default screen. More importantly, it provides
1049+ * a few functions
1050+ * to compile event sound property lists based on GtkWidget objects or
1051+ * GdkEvent events.
1052+ */
1053+
1054+static void read_sound_theme_name(ca_context *c, GtkSettings *s) {
1055+ gchar *theme_name = NULL;
1056+
1057+ g_object_get(G_OBJECT(s), "gtk-sound-theme-name", &theme_name, NULL);
1058+
1059+ if (theme_name) {
1060+ ca_context_change_props(c, CA_PROP_CANBERRA_XDG_THEME_NAME, theme_name, NULL);
1061+ g_free(theme_name);
1062+ }
1063+}
1064+
1065+static void read_enable_event_sounds(ca_context *c, GtkSettings *s) {
1066+ gboolean enable_event_sounds = TRUE;
1067+
1068+ if (!g_getenv("CANBERRA_FORCE_EVENT_SOUNDS"))
1069+ g_object_get(G_OBJECT(s), "gtk-enable-event-sounds", &enable_event_sounds, NULL);
1070+
1071+ ca_context_change_props(c, CA_PROP_CANBERRA_ENABLE, enable_event_sounds ? "1" : "0", NULL);
1072+}
1073+
1074+static void sound_theme_name_changed(GtkSettings *s, GParamSpec *arg1, ca_context *c) {
1075+ read_sound_theme_name(c, s);
1076+}
1077+
1078+static void enable_event_sounds_changed(GtkSettings *s, GParamSpec *arg1, ca_context *c) {
1079+ read_enable_event_sounds(c, s);
1080+}
1081+
1082+/**
1083+ * ca_gtk_context_get:
1084+ *
1085+ * Gets the single ca_context object for the default screen. See
1086+ * ca_gtk_context_get_for_screen().
1087+ *
1088+ * Returns: a ca_context object. The object is owned by libcanberra-gtk
1089+ * and must not be destroyed
1090+ */
1091+ca_context *ca_gtk_context_get(void) {
1092+ return ca_gtk_context_get_for_screen(NULL);
1093+}
1094+
1095+/**
1096+ * ca_gtk_context_get_for_screen:
1097+ * @screen: the #GdkScreen to get the context for, or %NULL to use
1098+ * the default screen
1099+ *
1100+ * libcanberra-gtk maintains a single ca_context object for each
1101+ * #GdkScreen. Use this function to access it. The
1102+ * %CA_PROP_CANBERRA_XDG_THEME_NAME of this context property is
1103+ * dynamically bound to the XSETTINGS setting for the XDG theme
1104+ * name. CA_PROP_APPLICATION_NAME is bound to
1105+ * g_get_application_name().
1106+ *
1107+ * Returns: a ca_context object. The object is owned by libcanberra-gtk
1108+ * and must not be destroyed
1109+ *
1110+ * Since: 0.13
1111+ */
1112+ca_context *ca_gtk_context_get_for_screen(GdkScreen *screen) {
1113+ ca_context *c = NULL;
1114+ ca_proplist *p = NULL;
1115+ const char *name;
1116+ GtkSettings *s;
1117+
1118+ if (!screen)
1119+ screen = gdk_screen_get_default();
1120+
1121+ if ((c = g_object_get_data(G_OBJECT(screen), "canberra::gtk::context")))
1122+ return c;
1123+
1124+ if (ca_context_create(&c) != CA_SUCCESS)
1125+ return NULL;
1126+
1127+ if (ca_proplist_create(&p) != CA_SUCCESS) {
1128+ ca_context_destroy(c);
1129+ return NULL;
1130+ }
1131+
1132+ if ((name = g_get_application_name()))
1133+ ca_proplist_sets(p, CA_PROP_APPLICATION_NAME, name);
1134+ else {
1135+ ca_proplist_sets(p, CA_PROP_APPLICATION_NAME, "libcanberra-gtk");
1136+ ca_proplist_sets(p, CA_PROP_APPLICATION_VERSION, PACKAGE_VERSION);
1137+ ca_proplist_sets(p, CA_PROP_APPLICATION_ID, "org.freedesktop.libcanberra.gtk");
1138+ }
1139+
1140+ if ((name = gtk_window_get_default_icon_name()))
1141+ ca_proplist_sets(p, CA_PROP_APPLICATION_ICON_NAME, name);
1142+
1143+ if ((name = gdk_display_get_name(gdk_screen_get_display(screen))))
1144+ ca_proplist_sets(p, CA_PROP_WINDOW_X11_DISPLAY, name);
1145+
1146+ ca_proplist_setf(p, CA_PROP_WINDOW_X11_SCREEN, "%i", gdk_screen_get_number(screen));
1147+
1148+ ca_context_change_props_full(c, p);
1149+ ca_proplist_destroy(p);
1150+
1151+ if ((s = gtk_settings_get_for_screen(screen))) {
1152+
1153+ if (g_object_class_find_property(G_OBJECT_GET_CLASS(s), "gtk-sound-theme-name")) {
1154+ g_signal_connect(G_OBJECT(s), "notify::gtk-sound-theme-name", G_CALLBACK(sound_theme_name_changed), c);
1155+ read_sound_theme_name(c, s);
1156+ } else
1157+ g_debug("This Gtk+ version doesn't have the GtkSettings::gtk-sound-theme-name property.");
1158+
1159+ if (g_object_class_find_property(G_OBJECT_GET_CLASS(s), "gtk-enable-event-sounds")) {
1160+ g_signal_connect(G_OBJECT(s), "notify::gtk-enable-event-sounds", G_CALLBACK(enable_event_sounds_changed), c);
1161+ read_enable_event_sounds(c, s);
1162+ } else
1163+ g_debug("This Gtk+ version doesn't have the GtkSettings::gtk-enable-event-sounds property.");
1164+ }
1165+
1166+ g_object_set_data_full(G_OBJECT(screen), "canberra::gtk::context", c, (GDestroyNotify) ca_context_destroy);
1167+
1168+ return c;
1169+}
1170+
1171+static GtkWindow* get_toplevel(GtkWidget *w) {
1172+ if (!(w = gtk_widget_get_toplevel(w)))
1173+ return NULL;
1174+
1175+ if (!GTK_IS_WINDOW(w))
1176+ return NULL;
1177+
1178+ return GTK_WINDOW(w);
1179+}
1180+
1181+static gint window_get_desktop(GdkDisplay *d, GdkWindow *w) {
1182+ Atom type_return;
1183+ gint format_return;
1184+ gulong nitems_return;
1185+ gulong bytes_after_return;
1186+ guchar *data = NULL;
1187+ gint ret = -1;
1188+
1189+ if (XGetWindowProperty(GDK_DISPLAY_XDISPLAY(d), GDK_WINDOW_XID(w),
1190+ gdk_x11_get_xatom_by_name_for_display(d, "_NET_WM_DESKTOP"),
1191+ 0, G_MAXLONG, False, XA_CARDINAL, &type_return,
1192+ &format_return, &nitems_return, &bytes_after_return,
1193+ &data) != Success)
1194+ return -1;
1195+
1196+ if (type_return == XA_CARDINAL && format_return == 32 && data) {
1197+ guint32 desktop = *(guint32*) data;
1198+
1199+ if (desktop != 0xFFFFFFFF)
1200+ ret = (gint) desktop;
1201+ }
1202+
1203+ if (type_return != None && data != NULL)
1204+ XFree(data);
1205+
1206+ return ret;
1207+}
1208+
1209+/**
1210+ * ca_gtk_proplist_set_for_widget:
1211+ * @p: The proplist to store these sound event properties in
1212+ * @w: The Gtk widget to base these sound event properties on
1213+ *
1214+ * Fill in a ca_proplist object for a sound event that shall originate
1215+ * from the specified Gtk Widget. This will fill in properties like
1216+ * %CA_PROP_WINDOW_NAME or %CA_PROP_WINDOW_X11_DISPLAY for you.
1217+ *
1218+ * Returns: 0 on success, negative error code on error.
1219+ */
1220+
1221+int ca_gtk_proplist_set_for_widget(ca_proplist *p, GtkWidget *widget) {
1222+ GtkWindow *w;
1223+ int ret;
1224+ const char *t, *role;
1225+
1226+ ca_return_val_if_fail(p, CA_ERROR_INVALID);
1227+ ca_return_val_if_fail(widget, CA_ERROR_INVALID);
1228+ ca_return_val_if_fail(!ca_detect_fork(), CA_ERROR_FORKED);
1229+
1230+ if (!(w = get_toplevel(widget)))
1231+ return CA_ERROR_INVALID;
1232+
1233+ if ((t = gtk_window_get_title(w)))
1234+ if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_NAME, t)) < 0)
1235+ return ret;
1236+
1237+ if ((role = gtk_window_get_role(w))) {
1238+ if (role && t) {
1239+ char *id = ca_sprintf_malloc("%s#%s", t, role);
1240+
1241+ if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_ID, id)) < 0) {
1242+ ca_free(id);
1243+ return ret;
1244+ }
1245+
1246+ ca_free(id);
1247+ }
1248+ } else if (t)
1249+ if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_ID, t)) < 0)
1250+ return ret;
1251+
1252+ if ((t = gtk_window_get_icon_name(w)))
1253+ if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_ICON_NAME, t)) < 0)
1254+ return ret;
1255+
1256+ if (gtk_widget_get_realized(GTK_WIDGET(w))) {
1257+ GdkWindow *dw = NULL;
1258+ GdkScreen *screen = NULL;
1259+ GdkDisplay *display = NULL;
1260+ gint x = -1, y = -1, width = -1, height = -1, screen_width = -1, screen_height = -1;
1261+
1262+ if ((dw = gtk_widget_get_window(GTK_WIDGET(w))))
1263+ if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_X11_XID, "%lu", (unsigned long) GDK_WINDOW_XID(dw))) < 0)
1264+ return ret;
1265+
1266+ if ((display = gtk_widget_get_display(GTK_WIDGET(w)))) {
1267+ if ((t = gdk_display_get_name(display)))
1268+ if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_X11_DISPLAY, t)) < 0)
1269+ return ret;
1270+
1271+ if (dw) {
1272+ gint desktop = window_get_desktop(display, dw);
1273+
1274+ if (desktop >= 0)
1275+ if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_DESKTOP, "%i", desktop)) < 0)
1276+ return ret;
1277+ }
1278+ }
1279+
1280+ if ((screen = gtk_widget_get_screen(GTK_WIDGET(w)))) {
1281+
1282+ if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_X11_SCREEN, "%i", gdk_screen_get_number(screen))) < 0)
1283+ return ret;
1284+
1285+ if (dw)
1286+ if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_X11_MONITOR, "%i", gdk_screen_get_monitor_at_window(screen, dw))) < 0)
1287+ return ret;
1288+ }
1289+
1290+ /* FIXME, this might cause a round trip */
1291+
1292+ if (dw) {
1293+ gdk_window_get_origin(dw, &x, &y);
1294+
1295+ if (x >= 0)
1296+ if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_X, "%i", x)) < 0)
1297+ return ret;
1298+ if (y >= 0)
1299+ if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_Y, "%i", y)) < 0)
1300+ return ret;
1301+ }
1302+
1303+ gtk_window_get_size(w, &width, &height);
1304+
1305+ if (width > 0)
1306+ if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_WIDTH, "%i", width)) < 0)
1307+ return ret;
1308+ if (height > 0)
1309+ if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_HEIGHT, "%i", height)) < 0)
1310+ return ret;
1311+
1312+ if (x >= 0 && width > 0) {
1313+ screen_width = gdk_screen_get_width(gtk_widget_get_screen(GTK_WIDGET(w)));
1314+
1315+ x += width/2;
1316+ x = CA_CLAMP(x, 0, screen_width-1);
1317+
1318+ /* We use these strange format strings here to avoid that libc
1319+ * applies locale information on the formatting of floating
1320+ * numbers. */
1321+
1322+ if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_HPOS, "%i.%03i",
1323+ (int) (x/(screen_width-1)), (int) (1000.0*x/(screen_width-1)) % 1000)) < 0)
1324+ return ret;
1325+ }
1326+
1327+ if (y >= 0 && height > 0) {
1328+ screen_height = gdk_screen_get_height(gtk_widget_get_screen(GTK_WIDGET(w)));
1329+
1330+ y += height/2;
1331+ y = CA_CLAMP(y, 0, screen_height-1);
1332+
1333+ if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_VPOS, "%i.%03i",
1334+ (int) (y/(screen_height-1)), (int) (1000.0*y/(screen_height-1)) % 1000)) < 0)
1335+ return ret;
1336+ }
1337+ }
1338+
1339+ return CA_SUCCESS;
1340+}
1341+
1342+/**
1343+ * ca_gtk_proplist_set_for_event:
1344+ * @p: The proplist to store these sound event properties in
1345+ * @e: The Gdk event to base these sound event properties on
1346+ *
1347+ * Fill in a ca_proplist object for a sound event that is being
1348+ * triggered by the specified Gdk Event. This will fill in properties
1349+ * like %CA_PROP_EVENT_MOUSE_X or %CA_PROP_EVENT_MOUSE_BUTTON for
1350+ * you. This will internally also cal ca_gtk_proplist_set_for_widget()
1351+ * on the widget this event belongs to.
1352+ *
1353+ * Returns: 0 on success, negative error code on error.
1354+ */
1355+
1356+int ca_gtk_proplist_set_for_event(ca_proplist *p, GdkEvent *e) {
1357+ gdouble x, y;
1358+ GdkWindow *gw;
1359+ GtkWidget *w = NULL;
1360+ int ret;
1361+
1362+ ca_return_val_if_fail(p, CA_ERROR_INVALID);
1363+ ca_return_val_if_fail(e, CA_ERROR_INVALID);
1364+ ca_return_val_if_fail(!ca_detect_fork(), CA_ERROR_FORKED);
1365+
1366+ if ((gw = e->any.window)) {
1367+ gdk_window_get_user_data(gw, (gpointer*) &w);
1368+
1369+ if (w)
1370+ if ((ret = ca_gtk_proplist_set_for_widget(p, w)) < 0)
1371+ return ret;
1372+ }
1373+
1374+ if (gdk_event_get_root_coords(e, &x, &y)) {
1375+
1376+ if ((ret = ca_proplist_setf(p, CA_PROP_EVENT_MOUSE_X, "%0.0f", x)) < 0)
1377+ return ret;
1378+
1379+ if ((ret = ca_proplist_setf(p, CA_PROP_EVENT_MOUSE_Y, "%0.0f", y)) < 0)
1380+ return ret;
1381+
1382+ if (w) {
1383+ int width, height;
1384+
1385+ width = gdk_screen_get_width(gtk_widget_get_screen(w));
1386+ height = gdk_screen_get_height(gtk_widget_get_screen(w));
1387+
1388+ /* We use these strange format strings here to avoid that
1389+ * libc applies locale information on the formatting of
1390+ * floating numbers. */
1391+
1392+ if ((ret = ca_proplist_setf(p, CA_PROP_EVENT_MOUSE_HPOS, "%i.%03i",
1393+ (int) (x/(width-1)), (int) (1000.0*x/(width-1)) % 1000)) < 0)
1394+ return ret;
1395+
1396+ if ((ret = ca_proplist_setf(p, CA_PROP_EVENT_MOUSE_VPOS, "%i.%03i",
1397+ (int) (y/(height-1)), (int) (1000.0*y/(height-1)) % 1000)) < 0)
1398+ return ret;
1399+ }
1400+ }
1401+
1402+ if (e->type == GDK_BUTTON_PRESS ||
1403+ e->type == GDK_2BUTTON_PRESS ||
1404+ e->type == GDK_3BUTTON_PRESS ||
1405+ e->type == GDK_BUTTON_RELEASE) {
1406+
1407+ if ((ret = ca_proplist_setf(p, CA_PROP_EVENT_MOUSE_BUTTON, "%u", e->button.button)) < 0)
1408+ return ret;
1409+ }
1410+
1411+ return CA_SUCCESS;
1412+}
1413+
1414+/**
1415+ * ca_gtk_play_for_widget:
1416+ * @w: The Gtk widget to base these sound event properties on
1417+ * @id: The event id that can later be used to cancel this event sound
1418+ * using ca_context_cancel(). This can be any integer and shall be
1419+ * chosen be the client program. It is a good idea to pass 0 here if
1420+ * cancelling the sound later is not needed. If the same id is passed
1421+ * to multiple sounds they can be canceled with a single
1422+ * ca_context_cancel() call.
1423+ * @...: additional event properties as pairs of strings, terminated by NULL.
1424+ *
1425+ * Play a sound event for the specified widget. This will internally
1426+ * call ca_gtk_proplist_set_for_widget() and then merge them with the
1427+ * properties passed in via the NULL terminated argument
1428+ * list. Finally, it will call ca_context_play_full() to actually play
1429+ * the event sound.
1430+ *
1431+ * Returns: 0 on success, negative error code on error.
1432+ */
1433+
1434+int ca_gtk_play_for_widget(GtkWidget *w, uint32_t id, ...) {
1435+ va_list ap;
1436+ int ret;
1437+ ca_proplist *p;
1438+ GdkScreen *s;
1439+
1440+ ca_return_val_if_fail(w, CA_ERROR_INVALID);
1441+ ca_return_val_if_fail(!ca_detect_fork(), CA_ERROR_FORKED);
1442+
1443+ if ((ret = ca_proplist_create(&p)) < 0)
1444+ return ret;
1445+
1446+ if ((ret = ca_gtk_proplist_set_for_widget(p, w)) < 0)
1447+ goto fail;
1448+
1449+ va_start(ap, id);
1450+ ret = ca_proplist_merge_ap(p, ap);
1451+ va_end(ap);
1452+
1453+ if (ret < 0)
1454+ goto fail;
1455+
1456+ s = gtk_widget_get_screen(w);
1457+ ret = ca_context_play_full(ca_gtk_context_get_for_screen(s), id, p, NULL, NULL);
1458+
1459+fail:
1460+
1461+ ca_assert_se(ca_proplist_destroy(p) == 0);
1462+
1463+ return ret;
1464+}
1465+
1466+/**
1467+ * ca_gtk_play_for_event:
1468+ * @e: The Gdk event to base these sound event properties on
1469+ * @id: The event id that can later be used to cancel this event sound
1470+ * using ca_context_cancel(). This can be any integer and shall be
1471+ * chosen be the client program. It is a good idea to pass 0 here if
1472+ * cancelling the sound later is not needed. If the same id is passed
1473+ * to multiple sounds they can be canceled with a single
1474+ * ca_context_cancel() call.
1475+ * @...: additional event properties as pairs of strings, terminated by NULL.
1476+ *
1477+ * Play a sound event for the specified event. This will internally
1478+ * call ca_gtk_proplist_set_for_event() and then merge them with the
1479+ * properties passed in via the NULL terminated argument
1480+ * list. Finally, it will call ca_context_play_full() to actually play
1481+ * the event sound.
1482+ *
1483+ * Returns: 0 on success, negative error code on error.
1484+ */
1485+
1486+int ca_gtk_play_for_event(GdkEvent *e, uint32_t id, ...) {
1487+ va_list ap;
1488+ int ret;
1489+ ca_proplist *p;
1490+ GdkScreen *s;
1491+
1492+ ca_return_val_if_fail(e, CA_ERROR_INVALID);
1493+ ca_return_val_if_fail(!ca_detect_fork(), CA_ERROR_FORKED);
1494+
1495+ if ((ret = ca_proplist_create(&p)) < 0)
1496+ return ret;
1497+
1498+ if ((ret = ca_gtk_proplist_set_for_event(p, e)) < 0)
1499+ goto fail;
1500+
1501+ va_start(ap, id);
1502+ ret = ca_proplist_merge_ap(p, ap);
1503+ va_end(ap);
1504+
1505+ if (ret < 0)
1506+ goto fail;
1507+
1508+ if (e->any.window)
1509+#if GTK_CHECK_VERSION (2, 90, 7)
1510+ s = gdk_window_get_screen(e->any.window);
1511+#else
1512+ s = gdk_drawable_get_screen(GDK_DRAWABLE(e->any.window));
1513+#endif
1514+ else
1515+ s = gdk_screen_get_default();
1516+
1517+ ret = ca_context_play_full(ca_gtk_context_get_for_screen(s), id, p, NULL, NULL);
1518+
1519+fail:
1520+
1521+ ca_assert_se(ca_proplist_destroy(p) == 0);
1522+
1523+ return ret;
1524+}
1525+
1526+/**
1527+ * ca_gtk_widget_disable_sounds:
1528+ * @w: The Gtk widget to disable automatic event sounds for.
1529+ * @enable: Boolean specifying whether sound events shall be enabled or disabled for this widget.
1530+ *
1531+ * By default sound events are automatically generated for all kinds
1532+ * of input events. Use this function to disable this. This is
1533+ * intended to be used for widgets which directly generate sound
1534+ * events.
1535+ */
1536+
1537+void ca_gtk_widget_disable_sounds(GtkWidget *w, gboolean enable) {
1538+ static GQuark disable_sound_quark = 0;
1539+
1540+ /* This is the same quark used by libgnomeui! */
1541+ if (!disable_sound_quark)
1542+ disable_sound_quark = g_quark_from_static_string("gnome_disable_sound_events");
1543+
1544+ g_object_set_qdata(G_OBJECT(w), disable_sound_quark, GINT_TO_POINTER(!!enable));
1545+}
1546
1547=== modified file '.pc/applied-patches'
1548--- .pc/applied-patches 2014-05-07 14:51:25 +0000
1549+++ .pc/applied-patches 2014-12-11 18:09:28 +0000
1550@@ -2,3 +2,4 @@
1551 02_disable_login_sound.patch
1552 03_onlyshowin_unity.patch
1553 04_nodisplay_autostart.patch
1554+05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch
1555
1556=== modified file 'debian/changelog'
1557--- debian/changelog 2014-05-07 14:51:25 +0000
1558+++ debian/changelog 2014-12-11 18:09:28 +0000
1559@@ -1,3 +1,10 @@
1560+libcanberra (0.30-2ubuntu2) UNRELEASED; urgency=medium
1561+
1562+ * debian/patches/05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch:
1563+ - Import patch from upstream, to fix crashes on non X11 Gdk backends
1564+
1565+ -- Marco Trevisan (Treviño) <marco@ubuntu.com> Thu, 11 Dec 2014 18:53:30 +0100
1566+
1567 libcanberra (0.30-2ubuntu1) utopic; urgency=low
1568
1569 * Merge from Debian unstable. Remaining changes:
1570
1571=== added file 'debian/patches/05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch'
1572--- debian/patches/05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch 1970-01-01 00:00:00 +0000
1573+++ debian/patches/05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch 2014-12-11 18:09:28 +0000
1574@@ -0,0 +1,65 @@
1575+Description: gtk: Don't assume all GdkDisplays are GdkX11Displays
1576+Author: Michael Meeks <michael.meeks@suse.com>
1577+Origin: http://git.0pointer.net/libcanberra.git/commit/?id=c0620e43265
1578+Bug-Ubuntu: https://launchpad.net/bugs/1401622
1579+Applied-Upstream: commit:c0620e432650e81062c1967cc669829dbd29b310
1580+
1581+---
1582+diff --git a/src/canberra-gtk-module.c b/src/canberra-gtk-module.c
1583+index 67791f0..c1532ab 100644
1584+--- a/src/canberra-gtk-module.c
1585++++ b/src/canberra-gtk-module.c
1586+@@ -307,6 +307,11 @@ static gint window_get_desktop(GdkDisplay *d, GdkWindow *w) {
1587+ guchar *data = NULL;
1588+ gint ret = -1;
1589+
1590++#ifdef GDK_IS_X11_DISPLAY
1591++ if (!GDK_IS_X11_DISPLAY(d))
1592++ return 0;
1593++#endif
1594++
1595+ if (XGetWindowProperty(GDK_DISPLAY_XDISPLAY(d), GDK_WINDOW_XID(w),
1596+ gdk_x11_get_xatom_by_name_for_display(d, "_NET_WM_DESKTOP"),
1597+ 0, G_MAXLONG, False, XA_CARDINAL, &type_return,
1598+@@ -335,6 +340,11 @@ static gint display_get_desktop(GdkDisplay *d) {
1599+ guchar *data = NULL;
1600+ gint ret = -1;
1601+
1602++#ifdef GDK_IS_X11_DISPLAY
1603++ if (!GDK_IS_X11_DISPLAY(d))
1604++ return 0;
1605++#endif
1606++
1607+ if (XGetWindowProperty(GDK_DISPLAY_XDISPLAY(d), DefaultRootWindow(GDK_DISPLAY_XDISPLAY(d)),
1608+ gdk_x11_get_xatom_by_name_for_display(d, "_NET_CURRENT_DESKTOP"),
1609+ 0, G_MAXLONG, False, XA_CARDINAL, &type_return,
1610+@@ -365,6 +375,11 @@ static gboolean window_is_xembed(GdkDisplay *d, GdkWindow *w) {
1611+ gboolean ret = FALSE;
1612+ Atom xembed;
1613+
1614++#ifdef GDK_IS_X11_DISPLAY
1615++ if (!GDK_IS_X11_DISPLAY(d))
1616++ return FALSE;
1617++#endif
1618++
1619+ /* Gnome Panel applets are XEMBED windows. We need to make sure we
1620+ * ignore them */
1621+
1622+diff --git a/src/canberra-gtk.c b/src/canberra-gtk.c
1623+index 34446f5..08cb668 100644
1624+--- a/src/canberra-gtk.c
1625++++ b/src/canberra-gtk.c
1626+@@ -185,6 +185,11 @@ static gint window_get_desktop(GdkDisplay *d, GdkWindow *w) {
1627+ guchar *data = NULL;
1628+ gint ret = -1;
1629+
1630++#ifdef GDK_IS_X11_DISPLAY
1631++ if (!GDK_IS_X11_DISPLAY(d))
1632++ return 0;
1633++#endif
1634++
1635+ if (XGetWindowProperty(GDK_DISPLAY_XDISPLAY(d), GDK_WINDOW_XID(w),
1636+ gdk_x11_get_xatom_by_name_for_display(d, "_NET_WM_DESKTOP"),
1637+ 0, G_MAXLONG, False, XA_CARDINAL, &type_return,
1638+--
1639+cgit v0.9.2
1640
1641=== modified file 'debian/patches/series'
1642--- debian/patches/series 2014-05-07 14:51:25 +0000
1643+++ debian/patches/series 2014-12-11 18:09:28 +0000
1644@@ -2,3 +2,4 @@
1645 02_disable_login_sound.patch
1646 03_onlyshowin_unity.patch
1647 04_nodisplay_autostart.patch
1648+05_gtk_dont_assume_all_gdkdisplays_are_gdkx11displays.patch
1649
1650=== modified file 'src/canberra-gtk-module.c'
1651--- src/canberra-gtk-module.c 2014-05-07 14:51:25 +0000
1652+++ src/canberra-gtk-module.c 2014-12-11 18:09:28 +0000
1653@@ -307,6 +307,11 @@
1654 guchar *data = NULL;
1655 gint ret = -1;
1656
1657+#ifdef GDK_IS_X11_DISPLAY
1658+ if (!GDK_IS_X11_DISPLAY(d))
1659+ return 0;
1660+#endif
1661+
1662 if (XGetWindowProperty(GDK_DISPLAY_XDISPLAY(d), GDK_WINDOW_XID(w),
1663 gdk_x11_get_xatom_by_name_for_display(d, "_NET_WM_DESKTOP"),
1664 0, G_MAXLONG, False, XA_CARDINAL, &type_return,
1665@@ -335,6 +340,11 @@
1666 guchar *data = NULL;
1667 gint ret = -1;
1668
1669+#ifdef GDK_IS_X11_DISPLAY
1670+ if (!GDK_IS_X11_DISPLAY(d))
1671+ return 0;
1672+#endif
1673+
1674 if (XGetWindowProperty(GDK_DISPLAY_XDISPLAY(d), DefaultRootWindow(GDK_DISPLAY_XDISPLAY(d)),
1675 gdk_x11_get_xatom_by_name_for_display(d, "_NET_CURRENT_DESKTOP"),
1676 0, G_MAXLONG, False, XA_CARDINAL, &type_return,
1677@@ -365,6 +375,11 @@
1678 gboolean ret = FALSE;
1679 Atom xembed;
1680
1681+#ifdef GDK_IS_X11_DISPLAY
1682+ if (!GDK_IS_X11_DISPLAY(d))
1683+ return FALSE;
1684+#endif
1685+
1686 /* Gnome Panel applets are XEMBED windows. We need to make sure we
1687 * ignore them */
1688
1689
1690=== modified file 'src/canberra-gtk.c'
1691--- src/canberra-gtk.c 2010-12-08 11:28:26 +0000
1692+++ src/canberra-gtk.c 2014-12-11 18:09:28 +0000
1693@@ -185,6 +185,11 @@
1694 guchar *data = NULL;
1695 gint ret = -1;
1696
1697+#ifdef GDK_IS_X11_DISPLAY
1698+ if (!GDK_IS_X11_DISPLAY(d))
1699+ return 0;
1700+#endif
1701+
1702 if (XGetWindowProperty(GDK_DISPLAY_XDISPLAY(d), GDK_WINDOW_XID(w),
1703 gdk_x11_get_xatom_by_name_for_display(d, "_NET_WM_DESKTOP"),
1704 0, G_MAXLONG, False, XA_CARDINAL, &type_return,

Subscribers

People subscribed via source and target branches