summaryrefslogtreecommitdiff
path: root/gio/gapplicationimpl-dbus.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2011-12-17 15:37:29 -0500
committerMatthias Clasen <mclasen@redhat.com>2011-12-17 20:33:26 -0500
commitdef83cd90925caf2137b5a2099f3eb17070e227d (patch)
treecf3c9777962547428705410cd29ee7b9ef4d5194 /gio/gapplicationimpl-dbus.c
parent0971d36e4b8338f4f3f96d751f5275517514d3b1 (diff)
downloadglib-wip/session.tar.gz
Add session supportwip/session
This is a port of the eggsmclient dbus implementation, plus an inhibit api.
Diffstat (limited to 'gio/gapplicationimpl-dbus.c')
-rw-r--r--gio/gapplicationimpl-dbus.c268
1 files changed, 266 insertions, 2 deletions
diff --git a/gio/gapplicationimpl-dbus.c b/gio/gapplicationimpl-dbus.c
index d8999d7c5..a0212e3c4 100644
--- a/gio/gapplicationimpl-dbus.c
+++ b/gio/gapplicationimpl-dbus.c
@@ -30,6 +30,7 @@
#include "gdbusconnection.h"
#include "gdbusintrospection.h"
#include "gdbuserror.h"
+#include "gdbusproxy.h"
#include "gmenuexporter.h"
#include <string.h>
@@ -103,6 +104,11 @@ struct _GApplicationImpl
gboolean properties_live;
gboolean primary;
gpointer app;
+
+ gchar *app_id;
+ GDBusProxy *sm_proxy;
+ gchar *client_path;
+ GDBusProxy *client_proxy;
};
@@ -467,11 +473,15 @@ g_application_impl_destroy (GApplicationImpl *impl)
{
g_application_impl_stop_primary (impl);
- if (impl->session_bus)
- g_object_unref (impl->session_bus);
+ g_clear_object (&impl->session_bus);
g_free (impl->object_path);
+ g_clear_object (&impl->sm_proxy);
+ g_clear_object (&impl->client_proxy);
+ g_free (impl->client_path);
+ g_free (impl->app_id);
+
g_slice_free (GApplicationImpl, impl);
}
@@ -817,6 +827,260 @@ g_dbus_command_line_new (GDBusMethodInvocation *invocation)
return G_APPLICATION_COMMAND_LINE (gdbcl);
}
+/* Session Management {{{1 */
+
+static void
+unregister_client (GApplicationImpl *impl)
+{
+ GError *error = NULL;
+
+ g_debug ("Unregistering client\n");
+
+ g_dbus_proxy_call_sync (impl->sm_proxy,
+ "UnregisterClient",
+ g_variant_new ("(o)", impl->client_path),
+ 0,
+ G_MAXINT,
+ NULL,
+ &error);
+
+ if (error)
+ {
+ g_warning ("Failed to unregister client: %s\n", error->message);
+ g_error_free (error);
+ }
+
+ g_clear_object (&impl->client_proxy);
+
+ g_free (impl->client_path);
+ impl->client_path = NULL;
+}
+
+static void
+client_proxy_signal (GDBusProxy *proxy,
+ const gchar *sender_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ GApplicationImpl *impl)
+{
+ if (strcmp (signal_name, "QueryEndSession") == 0)
+ {
+ g_debug ("Received QueryEndSession\n");
+ g_application_emit_quit_requested (impl->app);
+ }
+ else if (strcmp (signal_name, "EndSession") == 0)
+ {
+ g_debug ("Received EndSession\n");
+ g_application_impl_quit_response (impl, TRUE, NULL);
+ unregister_client (impl);
+ g_application_emit_quit (impl->app);
+ }
+ else if (strcmp (signal_name, "CancelEndSession") == 0)
+ {
+ g_debug ("Received CancelEndSession\n");
+ g_application_emit_quit_cancelled (impl->app);
+ }
+ else if (strcmp (signal_name, "Stop") == 0)
+ {
+ g_debug ("Received Stop\n");
+ unregister_client (impl);
+ g_application_emit_quit (impl->app);
+ }
+}
+
+void
+g_application_impl_session_startup (GApplicationImpl *impl)
+{
+ static gchar *client_id;
+ GError *error = NULL;
+ GVariant *res;
+
+ if (client_id == NULL)
+ {
+ const gchar *desktop_autostart_id;
+
+ desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
+ /* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to
+ * use the same client id.
+ */
+ g_unsetenv ("DESKTOP_AUTOSTART_ID");
+ client_id = g_strdup (desktop_autostart_id ? desktop_autostart_id : "");
+ }
+
+ g_debug ("Connecting to session manager\n");
+
+ impl->sm_proxy = g_dbus_proxy_new_sync (impl->session_bus, 0,
+ NULL, /* FIXME */
+ "org.gnome.SessionManager",
+ "/org/gnome/SessionManager",
+ "org.gnome.SessionManager",
+ NULL,
+ &error);
+ if (error)
+ {
+ g_warning ("Failed to get a session proxy: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ impl->app_id = g_strdup (g_get_prgname ());
+
+ g_debug ("Registering client '%s' '%s'\n", impl->app_id, client_id);
+
+ res = g_dbus_proxy_call_sync (impl->sm_proxy,
+ "RegisterClient",
+ g_variant_new ("(ss)", impl->app_id, client_id),
+ 0,
+ -1,
+ NULL,
+ &error);
+
+ if (error)
+ {
+ g_warning ("Failed to register client: %s\n", error->message);
+ g_error_free (error);
+ g_clear_object (&impl->sm_proxy);
+ return;
+ }
+
+ g_variant_get (res, "(o)", &impl->client_path);
+ g_variant_unref (res);
+
+ g_debug ("Registered client at '%s'\n", impl->client_path);
+
+ impl->client_proxy = g_dbus_proxy_new_sync (impl->session_bus, 0,
+ NULL, /* FIXME */
+ "org.gnome.SessionManager",
+ impl->client_path,
+ "org.gnome.SessionManager.ClientPrivate",
+ NULL,
+ &error);
+ if (error)
+ {
+ g_warning ("Failed to get client proxy: %s\n", error->message);
+ g_error_free (error);
+ g_clear_object (&impl->sm_proxy);
+ g_free (impl->client_path);
+ impl->client_path = NULL;
+ return;
+ }
+
+ g_signal_connect (impl->client_proxy, "g-signal", G_CALLBACK (client_proxy_signal), impl);
+}
+
+void
+g_application_impl_quit_response (GApplicationImpl *impl,
+ gboolean will_quit,
+ const gchar *reason)
+{
+ g_return_if_fail (impl->client_proxy != NULL);
+
+ g_debug ("Calling EndSessionResponse %d '%s'\n", will_quit, reason);
+
+ g_dbus_proxy_call (impl->client_proxy,
+ "EndSessionResponse",
+ g_variant_new ("(bs)", will_quit, reason ? reason : ""),
+ 0, G_MAXINT,
+ NULL, NULL, NULL);
+}
+
+guint
+g_application_impl_inhibit (GApplicationImpl *impl,
+ GApplicationInhibitFlags flags,
+ const gchar *reason)
+{
+ GVariant *res;
+ GError *error = NULL;
+ guint cookie;
+
+ g_return_val_if_fail (impl->sm_proxy != NULL, 0);
+
+ g_debug ("Calling Inhibit\n");
+
+ res = g_dbus_proxy_call_sync (impl->sm_proxy,
+ "Inhibit",
+ g_variant_new ("(susu)",
+ impl->app_id,
+ 0, /* toplevel XID */
+ reason,
+ flags),
+ 0,
+ -1,
+ NULL,
+ &error);
+ if (error)
+ {
+ g_warning ("Calling Inhibit failed: %s\n", error->message);
+ g_error_free (error);
+ return 0;
+ }
+
+ g_variant_get (res, "(u)", &cookie);
+ g_variant_unref (res);
+
+ return cookie;
+}
+
+void
+g_application_impl_uninhibit (GApplicationImpl *impl,
+ guint cookie)
+{
+ GVariant *res;
+ GError *error = NULL;
+
+ g_return_if_fail (impl->sm_proxy != NULL);
+
+ g_debug ("Calling Uninhibit\n");
+
+ res = g_dbus_proxy_call_sync (impl->sm_proxy,
+ "Uninhibit",
+ g_variant_new ("(u)", cookie),
+ 0,
+ -1,
+ NULL,
+ &error);
+ if (error)
+ {
+ g_warning ("Calling Uninhibit failed: %s\n", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ g_variant_unref (res);
+}
+
+gboolean
+g_application_impl_is_inhibited (GApplicationImpl *impl,
+ GApplicationInhibitFlags flags)
+{
+ GVariant *res;
+ GError *error = NULL;
+ gboolean inhibited;
+
+ g_return_val_if_fail (impl->sm_proxy != NULL, FALSE);
+
+ g_debug ("Calling IsInhibited\n");
+
+ res = g_dbus_proxy_call_sync (impl->sm_proxy,
+ "IsInhibited",
+ g_variant_new ("(u)", flags),
+ 0,
+ -1,
+ NULL,
+ &error);
+ if (error)
+ {
+ g_warning ("Calling IsInhibited failed: %s\n", error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ inhibited = g_variant_get_boolean (res);
+ g_variant_unref (res);
+
+ return inhibited;
+}
+
/* Epilogue {{{1 */
/* vim:set foldmethod=marker: */