From 367a69006a115bcd209c7498af708d433591cce9 Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Tue, 11 Jan 2011 10:48:07 -0600 Subject: port to gdbus and dbusmenu 0.4 --- src/Makefile.am | 32 ++++------ src/indicator-session.c | 143 ++++++++++++++++++++++++++++------------- src/session-dbus.c | 166 +++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 256 insertions(+), 85 deletions(-) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 24e00e4..190d012 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,7 +11,7 @@ sessionlibdir = $(INDICATORDIR) sessionlib_LTLIBRARIES = libsession.la libsession_la_SOURCES = \ indicator-session.c \ - session-dbus-client.h \ + gen-session-dbus.xml.h \ dbus-shared-names.h \ dbusmenu-shared.h \ users-service-client.h @@ -54,20 +54,6 @@ upower-client.h: $(srcdir)/upower.xml --output=upower-client.h \ $(srcdir)/upower.xml -session-dbus-client.h: $(srcdir)/session-dbus.xml - dbus-binding-tool \ - --prefix=_session_dbus_client \ - --mode=glib-client \ - --output=session-dbus-client.h \ - $(srcdir)/session-dbus.xml - -session-dbus-server.h: $(srcdir)/session-dbus.xml - dbus-binding-tool \ - --prefix=_session_dbus_server \ - --mode=glib-server \ - --output=session-dbus-server.h \ - $(srcdir)/session-dbus.xml - users-service-marshal.h: $(srcdir)/users-service.list glib-genmarshal --header \ --prefix=_users_service_marshal $(srcdir)/users-service.list \ @@ -78,6 +64,16 @@ users-service-marshal.c: $(srcdir)/users-service.list --prefix=_users_service_marshal $(srcdir)/users-service.list \ > users-service-marshal.c +gen-%.xml.c: %.xml + @echo "Building $@ from $<" + @echo "const char * _$(subst -,_,$(subst .,_,$(basename $<))) = " > $@ + @sed -e "s:\":\\\\\":g" -e s:^:\": -e s:\$$:\\\\n\": $< >> $@ + @echo ";" >> $@ + +gen-%.xml.h: %.xml + @echo "Building $@ from $<" + @echo "extern const char * _$(subst -,_,$(subst .,_,$(basename $<)));" > $@ + ################# # Session Stuff ################# @@ -88,7 +84,7 @@ indicator_session_service_SOURCES = \ session-service.c \ session-dbus.c \ session-dbus.h \ - session-dbus-server.h \ + gen-session-dbus.xml.c \ dbusmenu-shared.h \ gconf-helper.c \ users-service-dbus.h \ @@ -129,8 +125,8 @@ BUILT_SOURCES = \ consolekit-manager-client.h \ consolekit-session-client.h \ gdm-local-display-factory-client.h \ - session-dbus-client.h \ - session-dbus-server.h \ + gen-session-dbus.xml.c \ + gen-session-dbus.xml.h \ upower-client.h \ users-service-client.h \ users-service-marshal.h \ diff --git a/src/indicator-session.c b/src/indicator-session.c index a1f1667..d98bd1f 100644 --- a/src/indicator-session.c +++ b/src/indicator-session.c @@ -31,9 +31,6 @@ with this program. If not, see . #include #include -#include -#include - #include #include #include @@ -41,7 +38,6 @@ with this program. If not, see . #include "dbus-shared-names.h" #include "dbusmenu-shared.h" -#include "session-dbus-client.h" #define INDICATOR_SESSION_TYPE (indicator_session_get_type ()) #define INDICATOR_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_SESSION_TYPE, IndicatorSession)) @@ -62,7 +58,8 @@ struct _IndicatorSession { IndicatorServiceManager * service; GtkImage * status_image; DbusmenuGtkMenu * menu; - DBusGProxy * service_proxy; + GCancellable * service_proxy_cancel; + GDBusProxy * service_proxy; }; GType indicator_session_get_type (void); @@ -77,9 +74,11 @@ static GtkImage * get_icon (IndicatorObject * io); static GtkMenu * get_menu (IndicatorObject * io); static gboolean build_menu_switch (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); static gboolean new_user_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); -static void icon_changed (DBusGProxy * proxy, gchar * icon_name, gpointer user_data); +static void icon_changed (IndicatorSession * session, const gchar * icon_name); static void service_connection_cb (IndicatorServiceManager * sm, gboolean connected, gpointer user_data); static gboolean build_restart_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); +static void receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, GVariant * parameters, gpointer user_data); +static void service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data); static void indicator_session_class_init (IndicatorSessionClass *klass); static void indicator_session_init (IndicatorSession *self); @@ -109,6 +108,8 @@ indicator_session_init (IndicatorSession *self) { /* Set good defaults */ self->service = NULL; + self->service_proxy_cancel = NULL; + self->service_proxy = NULL; /* Now let's fire these guys up. */ self->service = indicator_service_manager_new_version(INDICATOR_SESSION_DBUS_NAME, INDICATOR_SESSION_DBUS_VERSION); @@ -125,19 +126,50 @@ indicator_session_init (IndicatorSession *self) GtkAccelGroup * agroup = gtk_accel_group_new(); dbusmenu_gtkclient_set_accel_group(DBUSMENU_GTKCLIENT(client), agroup); - DBusGConnection * session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); - self->service_proxy = dbus_g_proxy_new_for_name(session_bus, - INDICATOR_SESSION_DBUS_NAME, - INDICATOR_SESSION_SERVICE_DBUS_OBJECT, - INDICATOR_SESSION_SERVICE_DBUS_IFACE); + self->service_proxy_cancel = g_cancellable_new(); - dbus_g_proxy_add_signal(self->service_proxy, "IconUpdated", - G_TYPE_STRING, G_TYPE_INVALID); - dbus_g_proxy_connect_signal(self->service_proxy, - "IconUpdated", - G_CALLBACK(icon_changed), - self, - NULL); + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + INDICATOR_SESSION_DBUS_NAME, + INDICATOR_SESSION_SERVICE_DBUS_OBJECT, + INDICATOR_SESSION_SERVICE_DBUS_IFACE, + self->service_proxy_cancel, + service_proxy_cb, + self); + + return; +} + +/* Callback from trying to create the proxy for the serivce, this + could include starting the service. Sometime it'll fail and + we'll try to start that dang service again! */ +static void +service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data) +{ + GError * error = NULL; + + IndicatorSession * self = INDICATOR_SESSION(user_data); + g_return_if_fail(self != NULL); + + GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error); + + if (self->service_proxy_cancel != NULL) { + g_object_unref(self->service_proxy_cancel); + self->service_proxy_cancel = NULL; + } + + if (error != NULL) { + g_error("Could not grab DBus proxy for %s: %s", INDICATOR_SESSION_DBUS_NAME, error->message); + g_error_free(error); + return; + } + + /* Okay, we're good to grab the proxy at this point, we're + sure that it's ours. */ + self->service_proxy = proxy; + + g_signal_connect(proxy, "g-signal", G_CALLBACK(receive_signal), self); return; } @@ -170,18 +202,26 @@ indicator_session_finalize (GObject *object) } static void -icon_name_get_cb (DBusGProxy *proxy, char * OUT_name, GError *error, gpointer userdata) +icon_name_get_cb (GObject * obj, GAsyncResult * res, gpointer user_data) { + IndicatorSession * self = INDICATOR_SESSION(user_data); + GError * error = NULL; + gchar * name; + GVariant * result; + + result = g_dbus_proxy_call_finish(self->service_proxy, res, &error); + if (error != NULL) { return; } - if (OUT_name == NULL || OUT_name[0] == '\0') { + g_variant_get(result, "(&s)", &name); + + if (name == NULL || name[0] == '\0') { return; } - IndicatorSession * self = INDICATOR_SESSION(userdata); - indicator_image_helper_update(self->status_image, OUT_name); + indicator_image_helper_update(self->status_image, name); return; } @@ -191,7 +231,9 @@ service_connection_cb (IndicatorServiceManager * sm, gboolean connected, gpointe IndicatorSession * self = INDICATOR_SESSION(user_data); if (connected) { - org_ayatana_indicator_session_service_get_icon_async(self->service_proxy, icon_name_get_cb, user_data); + g_dbus_proxy_call(self->service_proxy, "GetIcon", NULL, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, + icon_name_get_cb, user_data); } else { indicator_image_helper_update(self->status_image, ICON_DEFAULT); } @@ -206,13 +248,28 @@ get_label (IndicatorObject * io) } static void -icon_changed (DBusGProxy * proxy, gchar * icon_name, gpointer user_data) +icon_changed (IndicatorSession * session, const gchar * icon_name) { - IndicatorSession * session = INDICATOR_SESSION(user_data); indicator_image_helper_update(session->status_image, icon_name); return; } +/* Receives all signals from the service, routed to the appropriate functions */ +static void +receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, + GVariant * parameters, gpointer user_data) +{ + IndicatorSession * self = INDICATOR_SESSION(user_data); + + if (g_strcmp0(signal_name, "IconUpdated") == 0) { + const gchar *name; + g_variant_get (parameters, "(&s)", &name); + icon_changed(self, name); + } + + return; +} + static GtkImage * get_icon (IndicatorObject * io) { @@ -221,10 +278,10 @@ get_icon (IndicatorObject * io) } static void -user_property_change (DbusmenuMenuitem * item, const gchar * property, const GValue * value, gpointer user_data) +user_property_change (DbusmenuMenuitem * item, const gchar * property, GVariant * variant, gpointer user_data) { if (g_strcmp0(property, USER_ITEM_PROP_LOGGED_IN) == 0) { - if (g_value_get_boolean(value)) { + if (g_variant_get_boolean(variant)) { gtk_widget_show(GTK_WIDGET(user_data)); } else { gtk_widget_hide(GTK_WIDGET(user_data)); @@ -308,7 +365,7 @@ get_menu (IndicatorObject * io) } static void -switch_property_change (DbusmenuMenuitem * item, const gchar * property, const GValue * value, gpointer user_data) +switch_property_change (DbusmenuMenuitem * item, const gchar * property, GVariant * variant, gpointer user_data) { if (g_strcmp0(property, MENU_SWITCH_USER) != 0) { return; @@ -330,13 +387,13 @@ switch_property_change (DbusmenuMenuitem * item, const gchar * property, const G /* If there's a NULL string of some type, then we want to go back to our old 'Switch User' which isn't great but eh, this error condition should never happen. */ - if (value == NULL || g_value_get_string(value) == NULL || g_value_get_string(value)[0] == '\0' || no_name_in_lang) { + if (variant == NULL || g_variant_get_string(variant, NULL) == NULL || g_variant_get_string(variant, NULL)[0] == '\0' || no_name_in_lang) { finalstring = _("Switch User..."); set_ellipsize = FALSE; } if (finalstring == NULL) { - const gchar * username = g_value_get_string(value); + const gchar * username = g_variant_get_string(variant, NULL); GtkStyle * style = gtk_widget_get_style(GTK_WIDGET(gmi)); PangoLayout * layout = pango_layout_new(gtk_widget_get_pango_context(GTK_WIDGET(gmi))); @@ -387,17 +444,17 @@ static const gchar * dbusmenu_item_data = "dbusmenu-item"; /* IF the label or icon changes we need to grab that and update the menu item */ static void -restart_property_change (DbusmenuMenuitem * item, const gchar * property, const GValue * value, gpointer user_data) +restart_property_change (DbusmenuMenuitem * item, const gchar * property, GVariant * variant, gpointer user_data) { DbusmenuGtkClient * client = DBUSMENU_GTKCLIENT(user_data); GtkMenuItem * gmi = dbusmenu_gtkclient_menuitem_get(client, item); if (g_strcmp0(property, RESTART_ITEM_LABEL) == 0) { - gtk_menu_item_set_label(gmi, g_value_get_string(value)); + gtk_menu_item_set_label(gmi, g_variant_get_string(variant, NULL)); } else if (g_strcmp0(property, RESTART_ITEM_ICON) == 0) { GtkWidget * image = gtk_image_menu_item_get_image(GTK_IMAGE_MENU_ITEM(gmi)); - GIcon * gicon = g_themed_icon_new_with_default_fallbacks(g_value_get_string(value)); + GIcon * gicon = g_themed_icon_new_with_default_fallbacks(g_variant_get_string(variant, NULL)); if (image == NULL) { image = gtk_image_new_from_gicon(gicon, GTK_ICON_SIZE_MENU); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(gmi), image); @@ -424,16 +481,16 @@ build_restart_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusm g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(restart_property_change), client); - /* Grab the inital values and put them into the item */ - const GValue * value; - value = dbusmenu_menuitem_property_get_value(newitem, RESTART_ITEM_LABEL); - if (value != NULL) { - restart_property_change(newitem, RESTART_ITEM_LABEL, value, client); + /* Grab the inital variants and put them into the item */ + GVariant * variant; + variant = dbusmenu_menuitem_property_get_variant(newitem, RESTART_ITEM_LABEL); + if (variant != NULL) { + restart_property_change(newitem, RESTART_ITEM_LABEL, variant, client); } - value = dbusmenu_menuitem_property_get_value(newitem, RESTART_ITEM_ICON); - if (value != NULL) { - restart_property_change(newitem, RESTART_ITEM_ICON, value, client); + variant = dbusmenu_menuitem_property_get_variant(newitem, RESTART_ITEM_ICON); + if (variant != NULL) { + restart_property_change(newitem, RESTART_ITEM_ICON, variant, client); } return TRUE; @@ -448,7 +505,7 @@ switch_style_set (GtkWidget * widget, GtkStyle * prev_style, gpointer user_data) DbusmenuGtkClient * client = DBUSMENU_GTKCLIENT(user_data); DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(g_object_get_data(G_OBJECT(widget), dbusmenu_item_data)); - switch_property_change(mi, MENU_SWITCH_USER, dbusmenu_menuitem_property_get_value(mi, MENU_SWITCH_USER), client); + switch_property_change(mi, MENU_SWITCH_USER, dbusmenu_menuitem_property_get_variant(mi, MENU_SWITCH_USER), client); return; } @@ -468,7 +525,7 @@ build_menu_switch (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusme g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(switch_property_change), client); g_signal_connect(G_OBJECT(gmi), "style-set", G_CALLBACK(switch_style_set), client); - switch_property_change(newitem, MENU_SWITCH_USER, dbusmenu_menuitem_property_get_value(newitem, MENU_SWITCH_USER), client); + switch_property_change(newitem, MENU_SWITCH_USER, dbusmenu_menuitem_property_get_variant(newitem, MENU_SWITCH_USER), client); return TRUE; } diff --git a/src/session-dbus.c b/src/session-dbus.c index 20a0fa0..3c60a4e 100644 --- a/src/session-dbus.c +++ b/src/session-dbus.c @@ -23,26 +23,34 @@ with this program. If not, see . #include "config.h" #endif +#include + #include "session-dbus.h" #include "dbus-shared-names.h" -static gboolean _session_dbus_server_get_icon (SessionDbus * service, gchar ** icon, GError ** error); +static GVariant * get_icon (SessionDbus * service); +static void bus_get_cb (GObject * object, GAsyncResult * res, gpointer user_data); +static void bus_method_call (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * method, GVariant * params, GDBusMethodInvocation * invocation, gpointer user_data); -#include "session-dbus-server.h" +#include "gen-session-dbus.xml.h" typedef struct _SessionDbusPrivate SessionDbusPrivate; struct _SessionDbusPrivate { gchar * name; + GDBusConnection * bus; + GCancellable * bus_cancel; + guint dbus_registration; }; -/* Signals */ -enum { - ICON_UPDATED, - LAST_SIGNAL +/* GDBus Stuff */ +static GDBusNodeInfo * node_info = NULL; +static GDBusInterfaceInfo * interface_info = NULL; +static GDBusInterfaceVTable interface_table = { + method_call: bus_method_call, + get_property: NULL, /* No properties */ + set_property: NULL /* No properties */ }; -static guint signals[LAST_SIGNAL] = { 0 }; - #define SESSION_DBUS_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), SESSION_DBUS_TYPE, SessionDbusPrivate)) @@ -63,15 +71,24 @@ session_dbus_class_init (SessionDbusClass *klass) object_class->dispose = session_dbus_dispose; object_class->finalize = session_dbus_finalize; - signals[ICON_UPDATED] = g_signal_new ("icon-updated", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (SessionDbusClass, icon_updated), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); + /* Setting up the DBus interfaces */ + if (node_info == NULL) { + GError * error = NULL; + + node_info = g_dbus_node_info_new_for_xml(_session_dbus, &error); + if (error != NULL) { + g_error("Unable to parse Session Service Interface description: %s", error->message); + g_error_free(error); + } + } + + if (interface_info == NULL) { + interface_info = g_dbus_node_info_lookup_interface(node_info, INDICATOR_SESSION_SERVICE_DBUS_IFACE); - dbus_g_object_type_install_info(SESSION_DBUS_TYPE, &dbus_glib__session_dbus_server_object_info); + if (interface_info == NULL) { + g_error("Unable to find interface '" INDICATOR_SESSION_SERVICE_DBUS_IFACE "'"); + } + } return; } @@ -79,19 +96,104 @@ session_dbus_class_init (SessionDbusClass *klass) static void session_dbus_init (SessionDbus *self) { - DBusGConnection * session = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); - dbus_g_connection_register_g_object(session, INDICATOR_SESSION_SERVICE_DBUS_OBJECT, G_OBJECT(self)); - SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(self); priv->name = g_strdup(ICON_DEFAULT); + priv->bus = NULL; + priv->bus_cancel = NULL; + priv->dbus_registration = 0; + + priv->bus_cancel = g_cancellable_new(); + g_bus_get(G_BUS_TYPE_SESSION, + priv->bus_cancel, + bus_get_cb, + self); return; } +static void +bus_get_cb (GObject * object, GAsyncResult * res, gpointer user_data) +{ + GError * error = NULL; + GDBusConnection * connection = g_bus_get_finish(res, &error); + + if (error != NULL) { + g_error("OMG! Unable to get a connection to DBus: %s", error->message); + g_error_free(error); + return; + } + + SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(user_data); + + g_warn_if_fail(priv->bus == NULL); + priv->bus = connection; + + if (priv->bus_cancel != NULL) { + g_object_unref(priv->bus_cancel); + priv->bus_cancel = NULL; + } + + /* Now register our object on our new connection */ + priv->dbus_registration = g_dbus_connection_register_object(priv->bus, + INDICATOR_SESSION_SERVICE_DBUS_OBJECT, + interface_info, + &interface_table, + user_data, + NULL, + &error); + + if (error != NULL) { + g_error("Unable to register the object to DBus: %s", error->message); + g_error_free(error); + return; + } + + return; +} + +/* A method has been called from our dbus inteface. Figure out what it + is and dispatch it. */ +static void +bus_method_call (GDBusConnection * connection, const gchar * sender, + const gchar * path, const gchar * interface, + const gchar * method, GVariant * params, + GDBusMethodInvocation * invocation, gpointer user_data) +{ + SessionDbus * service = SESSION_DBUS(user_data); + GVariant * retval = NULL; + + if (g_strcmp0(method, "GetIcon") == 0) { + retval = get_icon(service); + } else { + g_warning("Calling method '%s' on the indicator service and it's unknown", method); + } + + g_dbus_method_invocation_return_value(invocation, retval); + return; +} + static void session_dbus_dispose (GObject *object) { + SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(object); + + if (priv->dbus_registration != 0) { + g_dbus_connection_unregister_object(priv->bus, priv->dbus_registration); + /* Don't care if it fails, there's nothing we can do */ + priv->dbus_registration = 0; + } + + if (priv->bus != NULL) { + g_object_unref(priv->bus); + priv->bus = NULL; + } + + if (priv->bus_cancel != NULL) { + g_cancellable_cancel(priv->bus_cancel); + g_object_unref(priv->bus_cancel); + priv->bus_cancel = NULL; + } G_OBJECT_CLASS (session_dbus_parent_class)->dispose (object); return; @@ -111,12 +213,11 @@ session_dbus_finalize (GObject *object) return; } -static gboolean -_session_dbus_server_get_icon (SessionDbus * service, gchar ** icon, GError ** error) +static GVariant * +get_icon (SessionDbus * service) { SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(service); - *icon = g_strdup(priv->name); - return TRUE; + return g_variant_new("(s)", priv->name); } SessionDbus * @@ -129,11 +230,28 @@ void session_dbus_set_name (SessionDbus * session, const gchar * name) { SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(session); + GError * error = NULL; if (priv->name != NULL) { g_free(priv->name); priv->name = NULL; } priv->name = g_strdup(name); - g_signal_emit(G_OBJECT(session), signals[ICON_UPDATED], 0, priv->name, TRUE); + + if (priv->bus != NULL) { + g_dbus_connection_emit_signal (priv->bus, + NULL, + INDICATOR_SESSION_SERVICE_DBUS_OBJECT, + INDICATOR_SESSION_SERVICE_DBUS_IFACE, + "IconUpdated", + g_variant_new ("(s)", priv->name, NULL), + &error); + + if (error != NULL) { + g_error("Unable to send IconUpdated signal: %s", error->message); + g_error_free(error); + return; + } + } + return; } -- cgit v1.2.3