diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/app-indicator.c | 151 |
1 files changed, 113 insertions, 38 deletions
diff --git a/src/app-indicator.c b/src/app-indicator.c index 9715817..2a8eb2f 100644 --- a/src/app-indicator.c +++ b/src/app-indicator.c @@ -92,10 +92,11 @@ struct _AppIndicatorPrivate { gint fallback_timer; /* Fun stuff */ - DBusGProxy *watcher_proxy; + GDBusProxy *watcher_proxy; GDBusConnection *connection; DBusGProxy * dbus_proxy; guint dbus_registration; + gchar * path; /* Might be used */ IndicatorDesktopShortcuts * shorties; @@ -198,6 +199,7 @@ static void submenu_changed (GtkWidget *widget, GtkWidget *child, gpointer data) static void theme_changed_cb (GtkIconTheme * theme, gpointer user_data); static GVariant * bus_get_prop (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * property, GError ** error, gpointer user_data); static void bus_creation (GObject * obj, GAsyncResult * res, gpointer user_data); +static void bus_watcher_ready (GObject * obj, GAsyncResult * res, gpointer user_data); static const GDBusInterfaceVTable item_interface_table = { method_call: NULL, /* No methods on this object */ @@ -619,6 +621,7 @@ app_indicator_init (AppIndicator *self) priv->connection = NULL; priv->dbus_proxy = NULL; priv->dbus_registration = 0; + priv->path = NULL; priv->status_icon = NULL; priv->fallback_timer = 0; @@ -694,7 +697,6 @@ app_indicator_dispose (GObject *object) } if (priv->watcher_proxy != NULL) { - dbus_g_connection_flush(priv->connection); g_signal_handlers_disconnect_by_func(G_OBJECT(priv->watcher_proxy), watcher_proxy_destroyed, self); g_object_unref(G_OBJECT(priv->watcher_proxy)); priv->watcher_proxy = NULL; @@ -704,7 +706,7 @@ app_indicator_dispose (GObject *object) } if (priv->connection != NULL) { - dbus_g_connection_unref(priv->connection); + g_object_unref(G_OBJECT(priv->connection)); priv->connection = NULL; } @@ -717,8 +719,8 @@ app_indicator_dispose (GObject *object) static void app_indicator_finalize (GObject *object) { - AppIndicator * self = APP_INDICATOR(object); - AppIndicatorPrivate *priv = self->priv; + AppIndicator * self = APP_INDICATOR(object); + AppIndicatorPrivate *priv = self->priv; if (priv->status != APP_INDICATOR_STATUS_PASSIVE) { g_warning("Finalizing Application Status with the status set to: %d", priv->status); @@ -759,9 +761,9 @@ app_indicator_finalize (GObject *object) priv->label_guide = NULL; } - if (priv->connection != NULL) { - g_object_unref(G_OBJECT(priv->connection)); - priv->connection = NULL; + if (priv->path != NULL) { + g_free(priv->path); + priv->path = NULL; } G_OBJECT_CLASS (app_indicator_parent_class)->finalize (object); @@ -938,9 +940,20 @@ app_indicator_get_property (GObject * object, guint prop_id, GValue * value, GPa } break; - case PROP_CONNECTED: - g_value_set_boolean (value, priv->watcher_proxy != NULL ? TRUE : FALSE); - break; + case PROP_CONNECTED: { + gboolean connected = FALSE; + + if (priv->watcher_proxy != NULL) { + gchar * name = g_dbus_proxy_get_name_owner(priv->watcher_proxy); + if (name != NULL) { + connected = TRUE; + g_free(name); + } + } + + g_value_set_boolean (value, connected); + break; + } case PROP_X_LABEL: case PROP_LABEL: @@ -1043,50 +1056,109 @@ check_connect (AppIndicator *self) /* We're alreadying connecting or trying to connect. */ if (priv->watcher_proxy != NULL) return; + gchar * name = g_dbus_proxy_get_name_owner(priv->watcher_proxy); + if (name == NULL) { + return; + } + g_free(name); + /* Do we have enough information? */ if (priv->menu == NULL) return; if (priv->icon_name == NULL) return; if (priv->id == NULL) return; - gchar * path = g_strdup_printf(DEFAULT_ITEM_PATH "/%s", priv->clean_id); + if (priv->path == NULL) { + priv->path = g_strdup_printf(DEFAULT_ITEM_PATH "/%s", priv->clean_id); + } + if (priv->dbus_registration == 0) { + GError * error = NULL; + priv->dbus_registration = g_dbus_connection_register_object(priv->connection, + priv->path, + item_interface_info, + &item_interface_table, + self, + NULL, + &error); + if (error != NULL) { + g_warning("Unable to register object on path '%s': %s", priv->path, error->message); + g_error_free(error); + return; + } + } + + /* NOTE: It's really important the order here. We make sure to *publish* + the object on the bus and *then* get the proxy. The reason is that we + want to ensure all the filters are setup before talking to the watcher + and that's where the order is important. */ + + if (priv->watcher_proxy == NULL) { + /* Build Watcher Proxy */ + g_dbus_proxy_new(priv->connection, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, /* We don't use these, don't bother with them */ + watcher_interface_info, + NOTIFICATION_WATCHER_DBUS_ADDR, + NOTIFICATION_WATCHER_DBUS_OBJ, + NOTIFICATION_WATCHER_DBUS_IFACE, + NULL, /* cancellable */ + bus_watcher_ready, + self); + } else { + bus_watcher_ready(NULL, NULL, self); + } + + return; +} + +/* Callback for when the watcher proxy has been created, or not + but we got called none-the-less. */ +static void +bus_watcher_ready (GObject * obj, GAsyncResult * res, gpointer user_data) +{ GError * error = NULL; - priv->dbus_registration = g_dbus_connection_register_object(priv->connection, - path, - item_interface_info, - &item_interface_table, - self, - NULL, - &error); - if (error != NULL) { - g_warning("Unable to register object on path '%s': %s", path, error->message); - g_error_free(error); - g_free(path); - return; + + GDBusProxy * proxy = NULL; + if (res != NULL) { + proxy = g_dbus_proxy_new_finish(res, &error); } - priv->watcher_proxy = dbus_g_proxy_new_for_name_owner(priv->connection, - NOTIFICATION_WATCHER_DBUS_ADDR, - NOTIFICATION_WATCHER_DBUS_OBJ, - NOTIFICATION_WATCHER_DBUS_IFACE, - &error); if (error != NULL) { /* Unable to get proxy, but we're handling that now so it's not a warning anymore. */ g_error_free(error); - dbus_g_connection_unregister_g_object(priv->connection, - G_OBJECT(self)); - start_fallback_timer(self, FALSE); - g_free(path); + + if (IS_APP_INDICATOR(user_data)) { + start_fallback_timer(APP_INDICATOR(user_data), FALSE); + } return; } - g_signal_connect(G_OBJECT(priv->watcher_proxy), "destroy", G_CALLBACK(watcher_proxy_destroyed), self); - org_kde_StatusNotifierWatcher_register_status_notifier_item_async(priv->watcher_proxy, path, register_service_cb, self); - g_free(path); + AppIndicator * app = APP_INDICATOR(user_data); - /* Emit the AppIndicator::connection-changed signal*/ - g_signal_emit (self, signals[CONNECTION_CHANGED], 0, TRUE); + if (res != NULL) { + app->priv->watcher_proxy = proxy; + + /* Setting up a signal to watch when the unique name + changes */ + g_signal_connect(G_OBJECT(app->priv->watcher_proxy), "destroy", G_CALLBACK(watcher_proxy_destroyed), user_data); + } + + /* Let's insure that someone is on the other side, else we're + still in a fallback scenario. */ + gchar * name = g_dbus_proxy_get_name_owner(app->priv->watcher_proxy); + if (name == NULL) { + start_fallback_timer(APP_INDICATOR(user_data), FALSE); + return; + } + + g_dbus_proxy_call(app->priv->watcher_proxy, + "RegisterStatusNotifierItem", + g_variant_new("(s)", app->priv->path), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, /* cancelable */ + register_service_cb, + user_data); return; } @@ -1129,6 +1201,9 @@ register_service_cb (DBusGProxy * proxy, GError * error, gpointer data) start_fallback_timer(APP_INDICATOR(data), TRUE); } + /* Emit the AppIndicator::connection-changed signal*/ + g_signal_emit (self, signals[CONNECTION_CHANGED], 0, TRUE); + if (priv->status_icon) { AppIndicatorClass * class = APP_INDICATOR_GET_CLASS(data); if (class->unfallback != NULL) { |