summaryrefslogtreecommitdiffstats
path: root/src/canberra-gtk-module.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2008-06-10 13:00:58 +0000
committerLennart Poettering <lennart@poettering.net>2008-06-10 13:00:58 +0000
commitf7081c9e82c7dea2887bb5e23f8c20c01aa703b0 (patch)
tree1b32762c13c06ea9cc0ab61a26001b3f9be2f8c6 /src/canberra-gtk-module.c
parentb1dccb6dfdab87e5e7d84e7e687eef93319aa332 (diff)
extend the the gtk module
git-svn-id: file:///home/lennart/svn/public/libcanberra/trunk@60 01b60673-d06a-42c0-afdd-89cb8e0f78ac
Diffstat (limited to 'src/canberra-gtk-module.c')
-rw-r--r--src/canberra-gtk-module.c261
1 files changed, 210 insertions, 51 deletions
diff --git a/src/canberra-gtk-module.c b/src/canberra-gtk-module.c
index c241f1f..783d04d 100644
--- a/src/canberra-gtk-module.c
+++ b/src/canberra-gtk-module.c
@@ -25,6 +25,8 @@
#endif
#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
#include "canberra-gtk.h"
@@ -63,11 +65,15 @@ typedef struct {
menu-popup
menu-popdown
menu-replace
+ tooltip-popup
+ tooltip-popdown
TODO:
drag-start
drag-accept
drag-fail
+ expander-toggle-on
+ expander-toggle-off
*/
@@ -86,9 +92,12 @@ static guint
signal_id_button_released,
signal_id_widget_window_state_event,
signal_id_notebook_switch_page,
- signal_id_tree_view_move_cursor;
+ signal_id_tree_view_cursor_changed,
+ signal_id_icon_view_selection_changed;
-static GQuark disable_sound_quark;
+static GQuark
+ disable_sound_quark,
+ was_hidden_quark;
/* Make sure GCC doesn't warn us about a missing prototype for this
* exported function */
@@ -172,21 +181,55 @@ static void free_sound_event(SoundEventData *d) {
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;
+ GList *i, *n;
do {
- for (i = sound_event_queue.head; i; i = i->next) {
- SoundEventData *j = i->data;
+ 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 */
+ * 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) ||
- 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;
@@ -194,13 +237,45 @@ static SoundEventData* filter_sound_event(SoundEventData *d) {
break;
}
+ if ((d->signal_id == signal_id_dialog_response &&
+ j->signal_id == signal_id_widget_hide) ||
- 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);
+ }
+ }
}
}
@@ -213,38 +288,56 @@ static SoundEventData* filter_sound_event(SoundEventData *d) {
return d;
}
+static gboolean is_hidden(GdkDisplay *d, GdkWindow *w) {
+ Atom type_return;
+ gint format_return;
+ gulong nitems_return;
+ gulong bytes_after_return;
+ guchar *data = NULL;
+ gboolean r = FALSE;
+
+ if (XGetWindowProperty(GDK_DISPLAY_XDISPLAY(d), GDK_WINDOW_XID(w),
+ gdk_x11_get_xatom_by_name_for_display(d, "_NET_WM_STATE"),
+ 0, G_MAXLONG, False, XA_ATOM, &type_return,
+ &format_return, &nitems_return, &bytes_after_return,
+ &data) != Success)
+ return FALSE;
+
+ if (type_return == XA_ATOM && format_return == 32 && data) {
+ unsigned i;
+
+ for (i = 0; i < nitems_return; i++) {
+ Atom atom = ((Atom*) data)[i];
+
+ if (atom == gdk_x11_get_xatom_by_name_for_display(d, "_NET_WM_STATE_HIDDEN")) {
+ r = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (type_return != None && data != NULL)
+ XFree (data);
+
+ return r;
+}
+
static void dispatch_sound_event(SoundEventData *d) {
int ret = CA_SUCCESS;
- static gboolean menu_is_popped_up = FALSE;
-
- if (!GTK_WIDGET_DRAWABLE(d->object))
- return;
+ static gboolean menu_is_popped_up = TRUE;
if (g_object_get_qdata(d->object, disable_sound_quark))
return;
if (d->signal_id == signal_id_widget_show) {
- gboolean played_sound = FALSE;
+ GdkWindowTypeHint hint;
- /* Show signals for non-windows have already been filtered out
+ /* Show/hide signals for non-windows have already been filtered out
* by the emission hook! */
- 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;
- }
+ hint = gtk_window_get_type_hint(GTK_WINDOW(d->object));
- } else if (GTK_IS_MENU(gtk_bin_get_child(GTK_BIN(d->object)))) {
+ if (is_menu_hint(hint)) {
if (menu_is_popped_up) {
ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
@@ -260,16 +353,46 @@ static void dispatch_sound_event(SoundEventData *d) {
NULL);
}
- played_sound = TRUE;
menu_is_popped_up = TRUE;
- }
- if (!played_sound)
+ } else if (hint == GDK_WINDOW_TYPE_HINT_TOOLTIP) {
+
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_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;
+
+ 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)
+ 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) {
@@ -295,34 +418,53 @@ static void dispatch_sound_event(SoundEventData *d) {
}
} else if (d->signal_id == signal_id_widget_hide) {
- gboolean played_sound = FALSE;
+ 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;
- if (GTK_IS_MENU(gtk_bin_get_child(GTK_BIN(d->object)))) {
+ } else if (hint == GDK_WINDOW_TYPE_HINT_TOOLTIP) {
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_EVENT_ID, "tooltip-popdown",
+ CA_PROP_EVENT_DESCRIPTION, "Tooltip popped down",
CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
NULL);
- played_sound = TRUE;
- menu_is_popped_up = FALSE;
- }
+ } else if (hint == GDK_WINDOW_TYPE_HINT_NORMAL ||
+ hint == GDK_WINDOW_TYPE_HINT_DIALOG) {
- if (!played_sound)
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;
+ gboolean h, ph;
e = (GdkEventWindowState*) d->event;
- if ((e->changed_mask & GDK_WINDOW_STATE_ICONIFIED) && (e->new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
+ h = is_hidden(gdk_screen_get_display(gdk_event_get_screen(d->event)), e->window);
+ ph = !!g_object_get_qdata(d->object, was_hidden_quark);
+ g_object_set_qdata(d->object, was_hidden_quark, GINT_TO_POINTER(h));
+
+ if ((e->changed_mask & GDK_WINDOW_STATE_ICONIFIED) && (e->new_window_state & GDK_WINDOW_STATE_ICONIFIED) && h && !ph) {
ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
CA_PROP_EVENT_ID, "window-minimized",
@@ -338,7 +480,7 @@ static void dispatch_sound_event(SoundEventData *d) {
CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
NULL);
- } else if ((e->changed_mask & GDK_WINDOW_STATE_ICONIFIED) && !(e->new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
+ } else if ((e->changed_mask & GDK_WINDOW_STATE_ICONIFIED) && !(e->new_window_state & GDK_WINDOW_STATE_ICONIFIED) && ph) {
ret = ca_gtk_play_for_widget(GTK_WIDGET(d->object), 0,
CA_PROP_EVENT_ID, "window-unminimized",
@@ -357,7 +499,7 @@ static void dispatch_sound_event(SoundEventData *d) {
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)))
+ 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",
@@ -462,7 +604,15 @@ static void dispatch_sound_event(SoundEventData *d) {
NULL);
}
- if (GTK_IS_TREE_VIEW(d->object) && d->signal_id == signal_id_tree_view_move_cursor) {
+ 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);
+ }
+
+ 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",
@@ -482,7 +632,9 @@ static gboolean idle_cb(void *userdata) {
g_message("idle_cb()");
while ((d = g_queue_pop_head(&sound_event_queue))) {
- d = filter_sound_event(d);
+
+ if (!(d = filter_sound_event(d)))
+ continue;
g_message("Dispatching signal %s on %s", g_signal_name(d->signal_id), g_type_name(G_OBJECT_TYPE(d->object)));
@@ -508,6 +660,11 @@ static gboolean emission_hook_cb(GSignalInvocationHint *hint, guint n_param_valu
!GTK_IS_WINDOW(object))
return TRUE;
+ if (hint->signal_id != signal_id_widget_hide &&
+ hint->signal_id != signal_id_dialog_response &&
+ !GTK_WIDGET_DRAWABLE(object))
+ return TRUE;
+
g_message("signal %s on %s", g_signal_name(hint->signal_id), g_type_name(G_OBJECT_TYPE(object)));
d = g_slice_new0(SoundEventData);
@@ -527,7 +684,7 @@ static gboolean emission_hook_cb(GSignalInvocationHint *hint, guint n_param_valu
d->arg1_is_set = TRUE;
}
- g_queue_push_tail(&sound_event_queue, e);
+ g_queue_push_tail(&sound_event_queue, d);
g_message("enqueuing");
@@ -551,6 +708,7 @@ static void install_hook(GType type, const char *signal, guint *sn) {
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_hidden_quark = g_quark_from_string("canberra_was_hidden");
install_hook(GTK_TYPE_WINDOW, "show", &signal_id_widget_show);
install_hook(GTK_TYPE_WINDOW, "hide", &signal_id_widget_hide);
@@ -562,5 +720,6 @@ void gtk_module_init(gint *argc, gchar ***argv[]) {
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, "move-cursor", &signal_id_tree_view_move_cursor);
+ 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);
}