[gnome-packagekit] Connect to gnome-session to get the idle status, not gnome-screensaver



commit 63b611682b517e601ef4aec8953ffcfebc149746
Author: Richard Hughes <richard hughsie com>
Date:   Tue Jun 16 08:47:49 2009 +0100

    Connect to gnome-session to get the idle status, not gnome-screensaver

 src/Makefile.am        |    2 +
 src/gpk-auto-refresh.c |   80 +-------
 src/gpk-common.c       |   42 ----
 src/gpk-common.h       |    1 -
 src/gpk-session.c      |  502 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/gpk-session.h      |   77 ++++++++
 src/gpk-watch.c        |    8 +-
 7 files changed, 598 insertions(+), 114 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 4f8c70e..2b8965e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -64,6 +64,8 @@ shared_SOURCES =					\
 	gpk-x11.h					\
 	gpk-marshal.c					\
 	gpk-marshal.h					\
+	gpk-session.c					\
+	gpk-session.h					\
 	gpk-desktop.c					\
 	gpk-desktop.h					\
 	gpk-animated-icon.c				\
diff --git a/src/gpk-auto-refresh.c b/src/gpk-auto-refresh.c
index 24fc6f7..47ce381 100644
--- a/src/gpk-auto-refresh.c
+++ b/src/gpk-auto-refresh.c
@@ -33,16 +33,15 @@
 #include <unistd.h>
 #endif /* HAVE_UNISTD_H */
 #include <glib/gi18n.h>
-#include <dbus/dbus-glib.h>
 #include <gconf/gconf-client.h>
 #include <packagekit-glib/packagekit.h>
 #include <devkit-power-gobject/devicekit-power.h>
 
 #include "egg-debug.h"
 #include "egg-string.h"
-#include "egg-dbus-monitor.h"
 
 #include "gpk-common.h"
+#include "gpk-session.h"
 #include "gpk-auto-refresh.h"
 #include "gpk-enum.h"
 
@@ -52,10 +51,6 @@ static void     gpk_auto_refresh_finalize	(GObject            *object);
 #define GPK_AUTO_REFRESH_PERIODIC_CHECK		60*60	/* force check for updates every this much time */
 #define GPK_UPDATES_LOGIN_TIMEOUT		3	/* seconds */
 
-#define GS_DBUS_SERVICE				"org.gnome.ScreenSaver"
-#define GS_DBUS_PATH				"/org/gnome/ScreenSaver"
-#define GS_DBUS_INTERFACE			"org.gnome.ScreenSaver"
-
 /*
  * at startup, after a small delay, force a GetUpdates call
  * every hour (or any event) check:
@@ -71,11 +66,9 @@ struct GpkAutoRefreshPrivate
 	gboolean		 force_get_updates_login;
 	guint			 force_get_updates_login_timeout_id;
 	guint			 timeout_id;
-	EggDbusMonitor		*monitor_gs;
 	DkpClient		*client;
 	GConfClient		*gconf_client;
-	DBusGProxy		*proxy_gs;
-	DBusGConnection		*connection;
+	GpkSession		*session;
 	PkControl		*control;
 };
 
@@ -400,10 +393,10 @@ gpk_auto_refresh_gconf_key_changed_cb (GConfClient *client, guint cnxn_id, GConf
 }
 
 /**
- * gpk_auto_refresh_idle_cb:
+ * gpk_auto_refresh_session_idle_changed_cb:
  **/
 static void
-gpk_auto_refresh_idle_cb (DBusGProxy *proxy, gboolean is_idle, GpkAutoRefresh *arefresh)
+gpk_auto_refresh_session_idle_changed_cb (GpkSession *session, gboolean is_idle, GpkAutoRefresh *arefresh)
 {
 	g_return_if_fail (GPK_IS_AUTO_REFRESH (arefresh));
 
@@ -486,44 +479,6 @@ gpk_auto_refresh_timeout_cb (gpointer user_data)
 }
 
 /**
- * pk_connection_gs_changed_cb:
- **/
-static void
-pk_connection_gs_changed_cb (EggDbusMonitor *egg_dbus_monitor, gboolean connected, GpkAutoRefresh *arefresh)
-{
-	GError *error = NULL;
-
-	g_return_if_fail (GPK_IS_AUTO_REFRESH (arefresh));
-
-	egg_debug ("gnome-screensaver connection-changed: %i", connected);
-
-	/* is this valid? */
-	if (!connected) {
-		if (arefresh->priv->proxy_gs != NULL) {
-			g_object_unref (arefresh->priv->proxy_gs);
-			arefresh->priv->proxy_gs = NULL;
-		}
-		return;
-	}
-
-	/* use gnome-screensaver for the idle detection */
-	arefresh->priv->proxy_gs = dbus_g_proxy_new_for_name_owner (arefresh->priv->connection,
-					  GS_DBUS_SERVICE, GS_DBUS_PATH, GS_DBUS_INTERFACE, &error);
-	if (error != NULL) {
-		egg_warning ("Cannot connect to gnome-screensaver: %s", error->message);
-		g_error_free (error);
-		return;
-	}
-	/* get SessionIdleChanged */
-	dbus_g_proxy_add_signal (arefresh->priv->proxy_gs, "SessionIdleChanged",
-				 G_TYPE_BOOLEAN, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (arefresh->priv->proxy_gs, "SessionIdleChanged",
-				     G_CALLBACK (gpk_auto_refresh_idle_cb),
-				     arefresh, NULL);
-
-}
-
-/**
  * gpk_auto_refresh_client_changed_cb:
  **/
 static void
@@ -554,17 +509,14 @@ gpk_auto_refresh_client_changed_cb (DkpClient *client, GpkAutoRefresh *arefresh)
 static void
 gpk_auto_refresh_init (GpkAutoRefresh *arefresh)
 {
-	GError *error = NULL;
 	PkNetworkEnum state;
 
 	arefresh->priv = GPK_AUTO_REFRESH_GET_PRIVATE (arefresh);
 	arefresh->priv->on_battery = FALSE;
-	arefresh->priv->session_idle = FALSE;
 	arefresh->priv->network_active = FALSE;
 	arefresh->priv->force_get_updates_login = FALSE;
 	arefresh->priv->timeout_id = 0;
 	arefresh->priv->force_get_updates_login_timeout_id = 0;
-	arefresh->priv->proxy_gs = NULL;
 
 	/* we need to know the updates frequency */
 	arefresh->priv->gconf_client = gconf_client_get_default ();
@@ -583,14 +535,6 @@ gpk_auto_refresh_init (GpkAutoRefresh *arefresh)
 	state = pk_control_get_network_state (arefresh->priv->control, NULL);
 	arefresh->priv->network_active = gpk_auto_refresh_convert_network_state (arefresh, state);
 
-	/* connect to session bus */
-	arefresh->priv->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
-	if (error != NULL) {
-		egg_warning ("Cannot connect to session bus: %s", error->message);
-		g_error_free (error);
-		return;
-	}
-
 	/* use a DkpClient */
 	arefresh->priv->client = dkp_client_new ();
 	g_signal_connect (arefresh->priv->client, "changed",
@@ -600,11 +544,11 @@ gpk_auto_refresh_init (GpkAutoRefresh *arefresh)
 	arefresh->priv->on_battery = dkp_client_on_battery (arefresh->priv->client);
 	egg_debug ("setting on battery %i", arefresh->priv->on_battery);
 
-	/* watch gnome-screensaver */
-	arefresh->priv->monitor_gs = egg_dbus_monitor_new ();
-	g_signal_connect (arefresh->priv->monitor_gs, "connection-changed",
-			  G_CALLBACK (pk_connection_gs_changed_cb), arefresh);
-	egg_dbus_monitor_assign (arefresh->priv->monitor_gs, EGG_DBUS_MONITOR_SESSION, GS_DBUS_SERVICE);
+	/* use gnome-session for the idle detection */
+	arefresh->priv->session = gpk_session_new ();
+	g_signal_connect (arefresh->priv->session, "idle_changed",
+			  G_CALLBACK (gpk_auto_refresh_session_idle_changed_cb), arefresh);
+	arefresh->priv->session_idle = gpk_session_get_idle (arefresh->priv->session);
 
 	/* we check this in case we miss one of the async signals */
 	g_timeout_add_seconds (GPK_AUTO_REFRESH_PERIODIC_CHECK, gpk_auto_refresh_timeout_cb, arefresh);
@@ -633,13 +577,9 @@ gpk_auto_refresh_finalize (GObject *object)
 		g_source_remove (arefresh->priv->force_get_updates_login_timeout_id);
 
 	g_object_unref (arefresh->priv->control);
-	g_object_unref (arefresh->priv->monitor_gs);
 	g_object_unref (arefresh->priv->gconf_client);
 	g_object_unref (arefresh->priv->client);
-
-	/* only unref the proxies if they were ever set */
-	if (arefresh->priv->proxy_gs != NULL)
-		g_object_unref (arefresh->priv->proxy_gs);
+	g_object_unref (arefresh->priv->session);
 
 	G_OBJECT_CLASS (gpk_auto_refresh_parent_class)->finalize (object);
 }
diff --git a/src/gpk-common.c b/src/gpk-common.c
index 40004e6..e5561a9 100644
--- a/src/gpk-common.c
+++ b/src/gpk-common.c
@@ -170,48 +170,6 @@ gtk_text_buffer_insert_markup (GtkTextBuffer *buffer, GtkTextIter *iter, const g
 }
 
 /**
- * gpk_session_logout:
- **/
-gboolean
-gpk_session_logout (void)
-{
-	DBusGConnection *connection;
-	DBusGProxy *proxy = NULL;
-	gboolean ret = FALSE;
-	GError *error = NULL;
-
-	/* connect to DBus */
-	connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
-	if (connection == NULL) {
-		egg_warning ("Failed to connect to DBus: %s", error->message);
-		g_error_free (error);
-		goto out;
-	}
-
-	/* connect to SessionManager */
-	proxy = dbus_g_proxy_new_for_name (connection, GNOME_SESSION_MANAGER_NAME,
-					   GNOME_SESSION_MANAGER_PATH,
-					   GNOME_SESSION_MANAGER_INTERFACE);
-	if (proxy == NULL) {
-		egg_warning ("cannot connect to session manager");
-		goto out;
-	}
-	ret = dbus_g_proxy_call (proxy, "Logout", &error,
-				 G_TYPE_UINT, 0,
-				 G_TYPE_INVALID,
-				 G_TYPE_INVALID);
-	if (!ret) {
-		egg_warning ("Failed to logout: %s", error->message);
-		g_error_free (error);
-		goto out;
-	}
-out:
-	if (proxy != NULL)
-		g_object_unref (proxy);
-	return ret;
-}
-
-/**
  * gpk_window_set_size_request:
  **/
 gboolean
diff --git a/src/gpk-common.h b/src/gpk-common.h
index 19a840a..d250173 100644
--- a/src/gpk-common.h
+++ b/src/gpk-common.h
@@ -104,7 +104,6 @@ GtkEntryCompletion *gpk_package_entry_completion_new	(void);
 gboolean	 gpk_window_set_size_request		(GtkWindow	*window,
 							 guint		 width,
 							 guint		 height);
-gboolean	 gpk_session_logout			(void);
 gboolean	 gpk_ignore_session_error		(GError		*error);
 
 G_END_DECLS
diff --git a/src/gpk-session.c b/src/gpk-session.c
new file mode 100644
index 0000000..5d94b5c
--- /dev/null
+++ b/src/gpk-session.c
@@ -0,0 +1,502 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008-2009 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <dbus/dbus-glib.h>
+
+#include "gpk-session.h"
+#include "gpk-common.h"
+#include "egg-debug.h"
+
+static void     gpk_session_finalize   (GObject		*object);
+
+#define GPK_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPK_TYPE_SESSION, GpkSessionPrivate))
+
+#define GPK_SESSION_MANAGER_SERVICE			"org.gnome.SessionManager"
+#define GPK_SESSION_MANAGER_PATH			"/org/gnome/SessionManager"
+#define GPK_SESSION_MANAGER_INTERFACE			"org.gnome.SessionManager"
+#define GPK_SESSION_MANAGER_PRESENCE_PATH		"/org/gnome/SessionManager/Presence"
+#define GPK_SESSION_MANAGER_PRESENCE_INTERFACE		"org.gnome.SessionManager.Presence"
+#define GPK_SESSION_MANAGER_CLIENT_PRIVATE_INTERFACE	"org.gnome.SessionManager.ClientPrivate"
+#define GPK_DBUS_PROPERTIES_INTERFACE			"org.freedesktop.DBus.Properties"
+
+typedef enum {
+	GPK_SESSION_STATUS_ENUM_AVAILABLE = 0,
+	GPK_SESSION_STATUS_ENUM_INVISIBLE,
+	GPK_SESSION_STATUS_ENUM_BUSY,
+	GPK_SESSION_STATUS_ENUM_IDLE,
+	GPK_SESSION_STATUS_ENUM_UNKNOWN
+} GpkSessionStatusEnum;
+
+typedef enum {
+	GPK_SESSION_INHIBIT_MASK_LOGOUT = 1,
+	GPK_SESSION_INHIBIT_MASK_SWITCH = 2,
+	GPK_SESSION_INHIBIT_MASK_SUSPEND = 4,
+	GPK_SESSION_INHIBIT_MASK_IDLE = 8
+} GpkSessionInhibitMask;
+
+struct GpkSessionPrivate
+{
+	DBusGProxy		*proxy;
+	DBusGProxy		*proxy_presence;
+	DBusGProxy		*proxy_client_private;
+	DBusGProxy		*proxy_prop;
+	gboolean		 is_idle_old;
+	gboolean		 is_inhibited_old;
+};
+
+enum {
+	IDLE_CHANGED,
+	INHIBITED_CHANGED,
+	STOP,
+	QUERY_END_SESSION,
+	END_SESSION,
+	CANCEL_END_SESSION,
+	LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+static gpointer gpk_session_object = NULL;
+
+G_DEFINE_TYPE (GpkSession, gpk_session, G_TYPE_OBJECT)
+
+/**
+ * gpk_session_logout:
+ **/
+gboolean
+gpk_session_logout (GpkSession *session)
+{
+	g_return_val_if_fail (GPK_IS_SESSION (session), FALSE);
+
+	/* no gnome-session */
+	if (session->priv->proxy == NULL) {
+		egg_warning ("no gnome-session");
+		return FALSE;
+	}
+
+	/* we have to use no reply, as the SM calls into g-p-m to get the can_suspend property */
+	dbus_g_proxy_call_no_reply (session->priv->proxy, "Shutdown", G_TYPE_INVALID);
+	return TRUE;
+}
+
+/**
+ * gpk_session_get_idle:
+ **/
+gboolean
+gpk_session_get_idle (GpkSession *session)
+{
+	g_return_val_if_fail (GPK_IS_SESSION (session), FALSE);
+	return session->priv->is_idle_old;
+}
+
+/**
+ * gpk_session_get_inhibited:
+ **/
+gboolean
+gpk_session_get_inhibited (GpkSession *session)
+{
+	g_return_val_if_fail (GPK_IS_SESSION (session), FALSE);
+	return session->priv->is_inhibited_old;
+}
+
+/**
+ * gpk_session_presence_status_changed_cb:
+ **/
+static void
+gpk_session_presence_status_changed_cb (DBusGProxy *proxy, guint status, GpkSession *session)
+{
+	gboolean is_idle;
+	is_idle = (status == GPK_SESSION_STATUS_ENUM_IDLE);
+	if (is_idle != session->priv->is_idle_old) {
+		egg_debug ("emitting idle-changed : (%i)", is_idle);
+		g_signal_emit (session, signals [IDLE_CHANGED], 0, is_idle);
+		session->priv->is_idle_old = is_idle;
+	}
+}
+
+/**
+ * gpk_session_is_idle:
+ **/
+static gboolean
+gpk_session_is_idle (GpkSession *session)
+{
+	gboolean ret;
+	gboolean is_idle = FALSE;
+	GError *error = NULL;
+	GValue *value;
+
+	/* no gnome-session */
+	if (session->priv->proxy_prop == NULL) {
+		egg_warning ("no gnome-session");
+		goto out;
+	}
+
+	value = g_new0(GValue, 1);
+	/* find out if this change altered the inhibited state */
+	ret = dbus_g_proxy_call (session->priv->proxy_prop, "Get", &error,
+				 G_TYPE_STRING, GPK_SESSION_MANAGER_PRESENCE_INTERFACE,
+				 G_TYPE_STRING, "status",
+				 G_TYPE_INVALID,
+				 G_TYPE_VALUE, value,
+				 G_TYPE_INVALID);
+	if (!ret) {
+		egg_warning ("failed to get idle status: %s", error->message);
+		g_error_free (error);
+		is_idle = FALSE;
+		goto out;
+	}
+	is_idle = (g_value_get_uint (value) == GPK_SESSION_STATUS_ENUM_IDLE);
+	g_free (value);
+out:
+	return is_idle;
+}
+
+/**
+ * gpk_session_is_inhibited:
+ **/
+static gboolean
+gpk_session_is_inhibited (GpkSession *session)
+{
+	gboolean ret;
+	gboolean is_inhibited = FALSE;
+	GError *error = NULL;
+
+	/* no gnome-session */
+	if (session->priv->proxy == NULL) {
+		egg_warning ("no gnome-session");
+		goto out;
+	}
+
+	/* find out if this change altered the inhibited state */
+	ret = dbus_g_proxy_call (session->priv->proxy, "IsInhibited", &error,
+				 G_TYPE_UINT, GPK_SESSION_INHIBIT_MASK_IDLE,
+				 G_TYPE_INVALID,
+				 G_TYPE_BOOLEAN, &is_inhibited,
+				 G_TYPE_INVALID);
+	if (!ret) {
+		egg_warning ("failed to get inhibit status: %s", error->message);
+		g_error_free (error);
+		is_inhibited = FALSE;
+	}
+out:
+	return is_inhibited;
+}
+
+/**
+ * gpk_session_stop_cb:
+ **/
+static void
+gpk_session_stop_cb (DBusGProxy *proxy, GpkSession *session)
+{
+	egg_debug ("emitting ::stop()");
+	g_signal_emit (session, signals [STOP], 0);
+}
+
+/**
+ * gpk_session_query_end_session_cb:
+ **/
+static void
+gpk_session_query_end_session_cb (DBusGProxy *proxy, guint flags, GpkSession *session)
+{
+	egg_debug ("emitting ::query-end-session(%i)", flags);
+	g_signal_emit (session, signals [QUERY_END_SESSION], 0, flags);
+}
+
+/**
+ * gpk_session_end_session_cb:
+ **/
+static void
+gpk_session_end_session_cb (DBusGProxy *proxy, guint flags, GpkSession *session)
+{
+	egg_debug ("emitting ::end-session(%i)", flags);
+	g_signal_emit (session, signals [END_SESSION], 0, flags);
+}
+
+/**
+ * gpk_session_end_session_response:
+ **/
+gboolean
+gpk_session_end_session_response (GpkSession *session, gboolean is_okay, const gchar *reason)
+{
+	gboolean ret = FALSE;
+	GError *error = NULL;
+
+	g_return_val_if_fail (GPK_IS_SESSION (session), FALSE);
+	g_return_val_if_fail (session->priv->proxy_client_private != NULL, FALSE);
+
+	/* no gnome-session */
+	if (session->priv->proxy_client_private == NULL) {
+		egg_warning ("no gnome-session proxy");
+		goto out;
+	}
+
+	/* send response */
+	ret = dbus_g_proxy_call (session->priv->proxy_client_private, "EndSessionResponse", &error,
+				 G_TYPE_BOOLEAN, is_okay,
+				 G_TYPE_STRING, reason,
+				 G_TYPE_INVALID,
+				 G_TYPE_INVALID);
+	if (!ret) {
+		egg_warning ("failed to send session response: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+out:
+	return ret;
+}
+
+/**
+ * gpk_session_register_client:
+ **/
+gboolean
+gpk_session_register_client (GpkSession *session, const gchar *app_id, const gchar *client_startup_id)
+{
+	gboolean ret = FALSE;
+	gchar *client_id = NULL;
+	GError *error = NULL;
+	DBusGConnection *connection;
+
+	g_return_val_if_fail (GPK_IS_SESSION (session), FALSE);
+
+	/* no gnome-session */
+	if (session->priv->proxy == NULL) {
+		egg_warning ("no gnome-session");
+		goto out;
+	}
+
+	/* find out if this change altered the inhibited state */
+	ret = dbus_g_proxy_call (session->priv->proxy, "RegisterClient", &error,
+				 G_TYPE_STRING, app_id,
+				 G_TYPE_STRING, client_startup_id,
+				 G_TYPE_INVALID,
+				 DBUS_TYPE_G_OBJECT_PATH, &client_id,
+				 G_TYPE_INVALID);
+	if (!ret) {
+		egg_warning ("failed to register client '%s': %s", client_startup_id, error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* get org.gnome.Session.ClientPrivate interface */
+	connection = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
+	session->priv->proxy_client_private = dbus_g_proxy_new_for_name_owner (connection, GPK_SESSION_MANAGER_SERVICE,
+									       client_id, GPK_SESSION_MANAGER_CLIENT_PRIVATE_INTERFACE, &error);
+	if (session->priv->proxy_client_private == NULL) {
+		egg_warning ("DBUS error: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* get Stop */
+	dbus_g_proxy_add_signal (session->priv->proxy_client_private, "Stop", G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (session->priv->proxy_client_private, "Stop", G_CALLBACK (gpk_session_stop_cb), session, NULL);
+
+	/* get QueryEndSession */
+	dbus_g_proxy_add_signal (session->priv->proxy_client_private, "QueryEndSession", G_TYPE_UINT, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (session->priv->proxy_client_private, "QueryEndSession", G_CALLBACK (gpk_session_query_end_session_cb), session, NULL);
+
+	/* get EndSession */
+	dbus_g_proxy_add_signal (session->priv->proxy_client_private, "EndSession", G_TYPE_UINT, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (session->priv->proxy_client_private, "EndSession", G_CALLBACK (gpk_session_end_session_cb), session, NULL);
+
+	egg_debug ("registered startup '%s' to client id '%s'", client_startup_id, client_id);
+out:
+	g_free (client_id);
+	return ret;
+}
+
+/**
+ * gpk_session_inhibit_changed_cb:
+ **/
+static void
+gpk_session_inhibit_changed_cb (DBusGProxy *proxy, const gchar *id, GpkSession *session)
+{
+	gboolean is_inhibited;
+
+	is_inhibited = gpk_session_is_inhibited (session);
+	if (is_inhibited != session->priv->is_inhibited_old) {
+		egg_debug ("emitting inhibited-changed : (%i)", is_inhibited);
+		g_signal_emit (session, signals [INHIBITED_CHANGED], 0, is_inhibited);
+		session->priv->is_inhibited_old = is_inhibited;
+	}
+}
+
+/**
+ * gpk_session_class_init:
+ * @klass: This class instance
+ **/
+static void
+gpk_session_class_init (GpkSessionClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = gpk_session_finalize;
+	g_type_class_add_private (klass, sizeof (GpkSessionPrivate));
+
+	signals [IDLE_CHANGED] =
+		g_signal_new ("idle-changed",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GpkSessionClass, idle_changed),
+			      NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN,
+			      G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+	signals [INHIBITED_CHANGED] =
+		g_signal_new ("inhibited-changed",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GpkSessionClass, inhibited_changed),
+			      NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN,
+			      G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+	signals [STOP] =
+		g_signal_new ("stop",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GpkSessionClass, stop),
+			      NULL, NULL, g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
+	signals [QUERY_END_SESSION] =
+		g_signal_new ("query-end-session",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GpkSessionClass, query_end_session),
+			      NULL, NULL, g_cclosure_marshal_VOID__UINT,
+			      G_TYPE_NONE, 1, G_TYPE_UINT);
+	signals [END_SESSION] =
+		g_signal_new ("end-session",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GpkSessionClass, end_session),
+			      NULL, NULL, g_cclosure_marshal_VOID__UINT,
+			      G_TYPE_NONE, 1, G_TYPE_UINT);
+	signals [CANCEL_END_SESSION] =
+		g_signal_new ("cancel-end-session",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GpkSessionClass, cancel_end_session),
+			      NULL, NULL, g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
+}
+
+/**
+ * gpk_session_init:
+ * @session: This class instance
+ **/
+static void
+gpk_session_init (GpkSession *session)
+{
+	DBusGConnection *connection;
+	GError *error = NULL;
+
+	session->priv = GPK_SESSION_GET_PRIVATE (session);
+	session->priv->is_idle_old = FALSE;
+	session->priv->is_inhibited_old = FALSE;
+	session->priv->proxy_client_private = NULL;
+
+	connection = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
+
+	/* get org.gnome.Session interface */
+	session->priv->proxy = dbus_g_proxy_new_for_name_owner (connection, GPK_SESSION_MANAGER_SERVICE,
+								GPK_SESSION_MANAGER_PATH,
+								GPK_SESSION_MANAGER_INTERFACE, &error);
+	if (session->priv->proxy == NULL) {
+		egg_warning ("DBUS error: %s", error->message);
+		g_error_free (error);
+		return;
+	}
+
+	/* get org.gnome.Session.Presence interface */
+	session->priv->proxy_presence = dbus_g_proxy_new_for_name_owner (connection, GPK_SESSION_MANAGER_SERVICE,
+									 GPK_SESSION_MANAGER_PRESENCE_PATH,
+									 GPK_SESSION_MANAGER_PRESENCE_INTERFACE, &error);
+	if (session->priv->proxy_presence == NULL) {
+		egg_warning ("DBUS error: %s", error->message);
+		g_error_free (error);
+		return;
+	}
+
+	/* get properties interface */
+	session->priv->proxy_prop = dbus_g_proxy_new_for_name_owner (connection, GPK_SESSION_MANAGER_SERVICE,
+								     GPK_SESSION_MANAGER_PRESENCE_PATH,
+								     GPK_DBUS_PROPERTIES_INTERFACE, &error);
+	if (session->priv->proxy_prop == NULL) {
+		egg_warning ("DBUS error: %s", error->message);
+		g_error_free (error);
+		return;
+	}
+
+	/* get StatusChanged */
+	dbus_g_proxy_add_signal (session->priv->proxy_presence, "StatusChanged", G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (session->priv->proxy_presence, "StatusChanged", G_CALLBACK (gpk_session_presence_status_changed_cb), session, NULL);
+
+	/* get InhibitorAdded */
+	dbus_g_proxy_add_signal (session->priv->proxy, "InhibitorAdded", G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (session->priv->proxy, "InhibitorAdded", G_CALLBACK (gpk_session_inhibit_changed_cb), session, NULL);
+
+	/* get InhibitorRemoved */
+	dbus_g_proxy_add_signal (session->priv->proxy, "InhibitorRemoved", G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (session->priv->proxy, "InhibitorRemoved", G_CALLBACK (gpk_session_inhibit_changed_cb), session, NULL);
+
+	/* coldplug */
+	session->priv->is_inhibited_old = gpk_session_is_inhibited (session);
+	session->priv->is_idle_old = gpk_session_is_idle (session);
+	egg_debug ("idle: %i, inhibited: %i", session->priv->is_idle_old, session->priv->is_inhibited_old);
+}
+
+/**
+ * gpk_session_finalize:
+ * @object: This class instance
+ **/
+static void
+gpk_session_finalize (GObject *object)
+{
+	GpkSession *session;
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (GPK_IS_SESSION (object));
+
+	session = GPK_SESSION (object);
+	session->priv = GPK_SESSION_GET_PRIVATE (session);
+
+	g_object_unref (session->priv->proxy);
+	g_object_unref (session->priv->proxy_presence);
+	g_object_unref (session->priv->proxy_client_private);
+	g_object_unref (session->priv->proxy_prop);
+
+	G_OBJECT_CLASS (gpk_session_parent_class)->finalize (object);
+}
+
+/**
+ * gpk_session_new:
+ * Return value: new GpkSession instance.
+ **/
+GpkSession *
+gpk_session_new (void)
+{
+	if (gpk_session_object != NULL) {
+		g_object_ref (gpk_session_object);
+	} else {
+		gpk_session_object = g_object_new (GPK_TYPE_SESSION, NULL);
+		g_object_add_weak_pointer (gpk_session_object, &gpk_session_object);
+	}
+	return GPK_SESSION (gpk_session_object);
+}
diff --git a/src/gpk-session.h b/src/gpk-session.h
new file mode 100644
index 0000000..6dfcf43
--- /dev/null
+++ b/src/gpk-session.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008-2009 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GPK_SESSION_H
+#define __GPK_SESSION_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GPK_TYPE_SESSION		(gpk_session_get_type ())
+#define GPK_SESSION(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), GPK_TYPE_SESSION, GpkSession))
+#define GPK_SESSION_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), GPK_TYPE_SESSION, GpkSessionClass))
+#define GPK_IS_SESSION(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GPK_TYPE_SESSION))
+#define GPK_IS_SESSION_CLASS(k)		(G_TYPE_CHECK_CLASS_TYPE ((k), GPK_TYPE_SESSION))
+#define GPK_SESSION_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GPK_TYPE_SESSION, GpkSessionClass))
+
+typedef struct GpkSessionPrivate GpkSessionPrivate;
+
+typedef struct
+{
+	GObject			 parent;
+	GpkSessionPrivate	*priv;
+} GpkSession;
+
+typedef struct
+{
+	GObjectClass	parent_class;
+	void		(* idle_changed)		(GpkSession	*session,
+							 gboolean	 is_idle);
+	void		(* inhibited_changed)		(GpkSession	*session,
+							 gboolean	 is_inhibited);
+	/* just exit */
+	void		(* stop)			(GpkSession	*session);
+	/* reply with EndSessionResponse */
+	void		(* query_end_session)		(GpkSession	*session,
+							 guint		 flags);
+	/* reply with EndSessionResponse */
+	void		(* end_session)			(GpkSession	*session,
+							 guint		 flags);
+	void		(* cancel_end_session)		(GpkSession	*session);
+} GpkSessionClass;
+
+GType		 gpk_session_get_type			(void);
+GpkSession	*gpk_session_new			(void);
+
+gboolean	 gpk_session_logout			(GpkSession	*session);
+gboolean	 gpk_session_get_idle			(GpkSession	*session);
+gboolean	 gpk_session_get_inhibited		(GpkSession	*session);
+gboolean	 gpk_session_register_client		(GpkSession	*session,
+							 const gchar	*app_id,
+							 const gchar	*client_startup_id);
+gboolean	 gpk_session_end_session_response	(GpkSession	*session,
+							 gboolean	 is_okay,
+							 const gchar	*reason);
+
+G_END_DECLS
+
+#endif	/* __GPK_SESSION_H */
diff --git a/src/gpk-watch.c b/src/gpk-watch.c
index 42e2bc3..cfbbac5 100644
--- a/src/gpk-watch.c
+++ b/src/gpk-watch.c
@@ -44,6 +44,7 @@
 #include "egg-string.h"
 
 #include "gpk-common.h"
+#include "gpk-session.h"
 #include "gpk-error.h"
 #include "gpk-watch.h"
 #include "gpk-modal-dialog.h"
@@ -1222,8 +1223,13 @@ static void
 gpk_watch_menu_log_out_cb (GtkMenuItem *item, gpointer data)
 {
 	GpkWatch *watch = GPK_WATCH (data);
+	GpkSession *session;
 	g_return_if_fail (GPK_IS_WATCH (watch));
-	gpk_session_logout ();
+
+	/* just ask for logout */
+	session = gpk_session_new ();
+	gpk_session_logout (session);
+	g_object_unref (session);
 }
 
 /**



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]