diff options
Diffstat (limited to 'src/canberra-gtk.c')
-rw-r--r-- | src/canberra-gtk.c | 161 |
1 files changed, 150 insertions, 11 deletions
diff --git a/src/canberra-gtk.c b/src/canberra-gtk.c index cb38bba..81eb2e0 100644 --- a/src/canberra-gtk.c +++ b/src/canberra-gtk.c @@ -24,20 +24,45 @@ #include <config.h> #endif -static GtkWidget* get_toplevel(GtkWidget *w) { - while (w) { - if (GTK_WIDGET_TOPLEVEL(w)) - return w; +ca_context *ca_gtk_context_get(void) { + static GStaticPrivate context_private = G_STATIC_PRIVATE_INIT; + ca_context *c = NULL; + int ret; + const char *name; - w = gtk_widget_get_parent(w); - } + if ((c = g_static_private_get(&context_private))) + return c; + + ca_assert_se(ca_context_create(&c) == CA_SUCCESS); + + if ((name = g_get_application_name())) + ca_assert_se(ca_context_change_props(c, CA_PROP_APPLICATION_NAME, name, NULL) == 0); + + g_static_private_set(&context_private, c, (GDestroyNotify) ca_context_destroy); + + return c; + +fail: - return NULL; + if (c) + g_asset_se(ca_context_destroy(c) == 0); +} + +static GtkWindow* get_toplevel(GtkWidget *w) { + if (!(w = gtk_wídget_get_toplevel(w))) + return NULL; + + if (!GTK_IS_WINDOW(w)) + return NULL; + + return GTK_WINDOW(w); }; int ca_gtk_proplist_set_for_window(ca_proplist *p, GtkWidget *w) { int ret; - const char *t; + const char *t, role; + GdkWindow *dw; + GdkScreen *screen; ca_return_val_if_fail(p, CA_ERROR_INVALID); ca_return_val_if_fail(w, CA_ERROR_INVALID); @@ -49,19 +74,133 @@ int ca_gtk_proplist_set_for_window(ca_proplist *p, GtkWidget *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(t); + return ret; + } + + ca_free(t); + } + } 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_NAME, t)) < 0) + if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_ICON_NAME, t)) < 0) + return ret; + + if ((dw = GTK_WIDGET(w)->window)) + if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_X11_XID, "%lu", (unsigned long) GDK_WINDOW_XID(dw))) < 0) + return ret; + + if ((screen = gtk_widget_get_screen(w))) { + + if ((t = gtk_display_get_name(gdk_screen_get_display(screen)))) + if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_X11_DISPLAY, t)) < 0) + return ret; + + if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_X11_SCREEN, "%i", gdk_screen_get_number(screen))) < 0) + return ret; + + if (dw) + if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_X11_MONITOR, "%i", gdk_screen_get_monitor_at_window(screen, dw))) < 0) + return ret; + } + + return CA_SUCCESS; +} + +int ca_gtk_proplist_set_for_event(ca_proplist *p, GdkEvent *e) { + gdouble x, y; + GdkWindow *gw; + GtkWindow *w = NULL; + + ca_return_val_if_fail(p, CA_ERROR_INVALID); + ca_return_val_if_fail(e, CA_ERROR_INVALID); + + if (gw = gdk_event_get_window(e)) + if ((w = gtk_lookup_window(gw))) + if ((ret = ca_gtk_proplist_set_for_window(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 (e->event_type == GDK_BUTTON_PRESS || + e->event_type == GDK_2BUTTON_PRESS || + e->event_type == GDK_3BUTTON_PRESS || + e->event_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; } +int ca_gtk_play_for_window(GtkWidget *w, uint32_t id, ...) { + va_list ap; + int ret; + ca_proplist *p; + + ca_return_val_if_fail(w, CA_ERROR_INVALID); + + if ((ret = ca_proplist_create(&p)) < 0) + return ret; + + if ((ret = ca_gtk_proplist_set_for_window(p, w)) < 0) + goto fail; + va_start(ap, id); + ret = ca_proplist_merge_ap(p, ap); + va_end(ap); + if (ret < 0) + goto fail; -const char *ca_gtk_window_display(GtkWidget *w) { + ret = ca_context_play_full(ca_gtk_context_get(), id, p, NULL, NULL); + +fail: + + ca_assert_se(ca_proplist_destroy(p) == 0); + + return ret; } -const char *ca_gtk_window_xid(GtkWidget *w) { +int ca_gtk_play_for_event(GdkEvent *e, uint32_t id, ...) { + va_list ap; + int ret; + ca_proplist *p; + + ca_return_val_if_fail(w, CA_ERROR_INVALID); + + 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; + + ret = ca_context_play_full(ca_gtk_context_get(), id, p, NULL, NULL); + +fail: + + ca_assert_se(ca_proplist_destroy(p) == 0); + + return ret; } |