gnome-session r4732 - in trunk: . gnome-session



Author: lucasr
Date: Thu Jun 12 23:13:33 2008
New Revision: 4732
URL: http://svn.gnome.org/viewvc/gnome-session?rev=4732&view=rev

Log:
2008-06-13  Lucas Rocha  <lucasr gnome org>

	Add support for ConsoleKit reboot and shutdown. #511881, William Jon
	McCann. Patch by William Jon McCann and Matthias Clasen.

	* configure.in: check for optional dependency on polkit-gnome.
	* gnome-session/Makefile.am: use polkit-gnome flags and libs
	on session manager build.
	* gnome-session/consolekit.[ch]: interface to abstract the
	communication with ConsoleKit and PolicyKit.
	* gnome-session/logout-dialog.c (gsm_logout_supports_reboot,
	gsm_logout_supports_shutdown): first check if ConsoleKit can
	shutdown/restart system. If not, try GDM directly.
	* gnome-session/session.c (do_request_reboot, do_request_shutdown,
	session_shutdown): use ConsoleKit to shutdown/restart system after
	logout. If not possible, use GDM directly.


Added:
   trunk/gnome-session/consolekit.c
   trunk/gnome-session/consolekit.h
Modified:
   trunk/ChangeLog
   trunk/configure.in
   trunk/gnome-session/Makefile.am
   trunk/gnome-session/app-autostart.c
   trunk/gnome-session/logout-dialog.c
   trunk/gnome-session/session.c

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Thu Jun 12 23:13:33 2008
@@ -57,6 +57,7 @@
 GLADE_REQUIRED=2.3.6
 DBUS_GLIB_REQUIRED=0.35
 GNOME_KEYRING_REQUIRED=2.21.92
+POLKIT_GNOME_REQUIRED=0.7
 
 dnl ====================================================================
 dnl Dependency Checks 
@@ -76,6 +77,12 @@
 PKG_CHECK_MODULES(EGG_SMCLIENT, gtk+-2.0)
 PKG_CHECK_MODULES(EGG_LIBGNOMEUI, libgnomeui-2.0)
 
+PKG_CHECK_MODULES(POLKIT_GNOME, polkit-gnome >= $POLKIT_GNOME_REQUIRED, have_polkit=yes, have_polkit=no)
+
+if test "$have_polkit" = "yes"; then
+  AC_DEFINE(HAVE_POLKIT_GNOME, [1], [whether PolKit GNOME was found])
+fi
+
 AC_CHECK_LIB(gdk-x11-2.0, gdk_x11_display_broadcast_startup_message, have_startup_message=yes, have_startup_message=no, "$GTK_LIBS")
 if test "x$have_startup_message" = "xyes"; then
   AC_DEFINE([HAVE_GDK_X11_DISPLAY_BROADCAST_STARTUP_MESSAGE],[1],[Define to compile with broadcast startup message support])

Modified: trunk/gnome-session/Makefile.am
==============================================================================
--- trunk/gnome-session/Makefile.am	(original)
+++ trunk/gnome-session/Makefile.am	Thu Jun 12 23:13:33 2008
@@ -8,6 +8,7 @@
 	$(DBUS_GLIB_CFLAGS)			\
 	$(GCONF_CFLAGS)				\
 	$(GTK_CFLAGS)				\
+	$(POLKIT_GNOME_CFLAGS)			\
 	-I$(top_srcdir)/egg			\
 	-DLOCALE_DIR=\""$(datadir)/locale"\"	\
 	-DDATA_DIR=\""$(datadir)/gnome-session"\" \
@@ -21,7 +22,8 @@
 	$(top_builddir)/egg/libeggdesktopfile.la \
 	$(GNOME_SESSION_LIBS)			\
 	$(DBUS_GLIB_LIBS)			\
-	$(GCONF_LIBS)
+	$(GCONF_LIBS)				\
+	$(POLKIT_GNOME_LIBS)
 
 gnome_session_SOURCES =				\
 	app-autostart.c				\
@@ -34,6 +36,8 @@
 	client-xsmp.h				\
 	client.c				\
 	client.h				\
+	consolekit.c				\
+	consolekit.h				\
 	dbus.c					\
 	dbus.h					\
 	gconf.c					\

Modified: trunk/gnome-session/app-autostart.c
==============================================================================
--- trunk/gnome-session/app-autostart.c	(original)
+++ trunk/gnome-session/app-autostart.c	Thu Jun 12 23:13:33 2008
@@ -33,7 +33,8 @@
   LAST_SIGNAL
 };
 
-struct _GsmAppAutostartPrivate {
+struct _GsmAppAutostartPrivate 
+{
   GFileMonitor         *monitor;
   gboolean              condition;
 };

Added: trunk/gnome-session/consolekit.c
==============================================================================
--- (empty file)
+++ trunk/gnome-session/consolekit.c	Thu Jun 12 23:13:33 2008
@@ -0,0 +1,683 @@
+/* console-kit.c
+ * Copyright (C) 2008 Jon McCann <jmccann redhat com>
+ *
+ * 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, 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include <dbus/dbus-glib.h>
+
+#ifdef HAVE_POLKIT_GNOME
+#include <polkit-gnome/polkit-gnome.h>
+#endif
+
+#include "consolekit.h"
+
+#define CK_NAME      "org.freedesktop.ConsoleKit"
+#define CK_PATH      "/org/freedesktop/ConsoleKit"
+#define CK_INTERFACE "org.freedesktop.ConsoleKit"
+
+#define CK_MANAGER_PATH      "/org/freedesktop/ConsoleKit/Manager"
+#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
+#define CK_SEAT_INTERFACE    "org.freedesktop.ConsoleKit.Seat"
+#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
+
+#define GSM_CONSOLEKIT_GET_PRIVATE(o) \
+        (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_CONSOLEKIT, GsmConsolekitPrivate))
+
+struct _GsmConsolekitPrivate 
+{
+  DBusGConnection *dbus_connection;
+  DBusGProxy      *bus_proxy;
+  DBusGProxy      *ck_proxy;
+  guint32          is_connected : 1;
+};
+
+enum 
+{
+  PROP_0,
+  PROP_IS_CONNECTED
+};
+
+enum 
+{
+  REQUEST_COMPLETED = 0,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void     gsm_consolekit_class_init   (GsmConsolekitClass *klass);
+static void     gsm_consolekit_init         (GsmConsolekit      *ck);
+static void     gsm_consolekit_finalize     (GObject              *object);
+
+static void     gsm_consolekit_on_name_owner_changed (DBusGProxy        *bus_proxy,
+                                                        const char        *name,
+                                                        const char        *prev_owner,
+                                                        const char        *new_owner,
+                                                        GsmConsolekit   *manager);
+
+G_DEFINE_TYPE (GsmConsolekit, gsm_consolekit, G_TYPE_OBJECT);
+
+static void
+gsm_consolekit_get_property (GObject    *object,
+                             guint       prop_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
+{
+  GsmConsolekit *manager = GSM_CONSOLEKIT (object);
+  
+  switch (prop_id) {
+  case PROP_IS_CONNECTED:
+    g_value_set_boolean (value,
+                             manager->priv->is_connected);
+    break;
+  
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+                                           prop_id,
+                                           pspec);
+  }
+}
+
+static void
+gsm_consolekit_class_init (GsmConsolekitClass *manager_class)
+{
+  GObjectClass *object_class;
+  GParamSpec *param_spec;
+  
+  object_class = G_OBJECT_CLASS (manager_class);
+  
+  object_class->finalize = gsm_consolekit_finalize;
+  object_class->get_property = gsm_consolekit_get_property;
+  
+  param_spec = g_param_spec_boolean ("is-connected",
+                                     "Is connected",
+                                     "Whether the session is connected to ConsoleKit",
+                                     FALSE,
+                                     G_PARAM_READABLE);
+
+  g_object_class_install_property (object_class, PROP_IS_CONNECTED,
+                                   param_spec);
+  
+  signals [REQUEST_COMPLETED] =
+          g_signal_new ("request-completed",
+                        G_OBJECT_CLASS_TYPE (object_class),
+                        G_SIGNAL_RUN_LAST,
+                        G_STRUCT_OFFSET (GsmConsolekitClass, request_completed),
+                        NULL,
+                        NULL,
+                        g_cclosure_marshal_VOID__POINTER,
+                        G_TYPE_NONE,
+                        1, G_TYPE_POINTER);
+  
+  g_type_class_add_private (manager_class, sizeof (GsmConsolekitPrivate));
+}
+
+static gboolean
+gsm_consolekit_ensure_ck_connection (GsmConsolekit  *manager,
+                                       GError          **error)
+{
+  GError *connection_error;
+  gboolean is_connected;
+  
+  connection_error = NULL;
+
+  if (manager->priv->dbus_connection == NULL) 
+    {
+      manager->priv->dbus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM,
+                                                       &connection_error);
+      
+      if (manager->priv->dbus_connection == NULL) 
+        {
+                g_propagate_error (error, connection_error);
+                is_connected = FALSE;
+                goto out;
+        }
+    }
+  
+  if (manager->priv->bus_proxy == NULL) 
+    {
+      manager->priv->bus_proxy =
+              dbus_g_proxy_new_for_name_owner (manager->priv->dbus_connection,
+                                               DBUS_SERVICE_DBUS,
+                                               DBUS_PATH_DBUS,
+                                               DBUS_INTERFACE_DBUS,
+                                               &connection_error);
+      
+      if (manager->priv->bus_proxy == NULL) 
+        {
+          g_propagate_error (error, connection_error);
+          is_connected = FALSE;
+          goto out;
+        }
+ 
+      dbus_g_proxy_add_signal (manager->priv->bus_proxy,
+                               "NameOwnerChanged",
+                               G_TYPE_STRING,
+                               G_TYPE_STRING,
+                               G_TYPE_STRING,
+                               G_TYPE_INVALID);
+
+      dbus_g_proxy_connect_signal (manager->priv->bus_proxy,
+                                   "NameOwnerChanged",
+                                   G_CALLBACK (gsm_consolekit_on_name_owner_changed),
+                                   manager, NULL);
+    }
+  
+  if (manager->priv->ck_proxy == NULL) 
+    {
+      manager->priv->ck_proxy =
+              dbus_g_proxy_new_for_name_owner (manager->priv->dbus_connection,
+                                               "org.freedesktop.ConsoleKit",
+                                               "/org/freedesktop/ConsoleKit/Manager",
+                                               "org.freedesktop.ConsoleKit.Manager",
+                                               &connection_error);
+      
+      if (manager->priv->ck_proxy == NULL)  
+        {
+          g_propagate_error (error, connection_error);
+          is_connected = FALSE;
+          goto out;
+        }
+    }
+
+  is_connected = TRUE;
+
+out:
+  if (manager->priv->is_connected != is_connected) 
+    {
+      manager->priv->is_connected = is_connected;
+      g_object_notify (G_OBJECT (manager), "is-connected");
+    }
+  
+  if (!is_connected) 
+    {
+      if (manager->priv->dbus_connection == NULL) 
+        {
+          if (manager->priv->bus_proxy != NULL) 
+            {
+              g_object_unref (manager->priv->bus_proxy);
+              manager->priv->bus_proxy = NULL;
+            }
+          
+          if (manager->priv->ck_proxy != NULL) 
+            {
+              g_object_unref (manager->priv->ck_proxy);
+              manager->priv->ck_proxy = NULL;
+            }
+        } 
+      else if (manager->priv->bus_proxy == NULL) 
+        {
+          if (manager->priv->ck_proxy != NULL) 
+            {
+              g_object_unref (manager->priv->ck_proxy);
+              manager->priv->ck_proxy = NULL;
+            }
+        }
+    }
+  
+  return is_connected;
+}
+
+static void
+gsm_consolekit_on_name_owner_changed (DBusGProxy        *bus_proxy,
+                                      const char        *name,
+                                      const char        *prev_owner,
+                                      const char        *new_owner,
+                                      GsmConsolekit *manager)
+{
+  if (name != NULL && strcmp (name, "org.freedesktop.ConsoleKit") != 0)
+    return;
+
+  if (manager->priv->ck_proxy != NULL) 
+    {
+      g_object_unref (manager->priv->ck_proxy);
+      manager->priv->ck_proxy = NULL;
+    }
+
+  gsm_consolekit_ensure_ck_connection (manager, NULL);
+}
+
+static void
+gsm_consolekit_init (GsmConsolekit *manager)
+{
+  GError *error;
+
+  manager->priv = GSM_CONSOLEKIT_GET_PRIVATE (manager);
+
+  error = NULL;
+
+  if (!gsm_consolekit_ensure_ck_connection (manager, &error)) 
+    {
+      g_message ("Could not connect to ConsoleKit: %s",
+                 error->message);
+      g_error_free (error);
+    }
+}
+
+static void
+gsm_consolekit_finalize (GObject *object)
+{
+  GsmConsolekit *manager;
+  GObjectClass *parent_class;
+  
+  manager = GSM_CONSOLEKIT (object);
+  
+  parent_class = G_OBJECT_CLASS (gsm_consolekit_parent_class);
+  
+  if (manager->priv->bus_proxy != NULL) 
+    g_object_unref (manager->priv->bus_proxy);
+  
+  if (manager->priv->ck_proxy != NULL) 
+    g_object_unref (manager->priv->ck_proxy);
+  
+  if (parent_class->finalize != NULL)
+    parent_class->finalize (object);
+}
+
+GQuark
+gsm_consolekit_error_quark (void)
+{
+  static GQuark error_quark = 0;
+
+  if (error_quark == 0)
+    error_quark = g_quark_from_static_string ("gsm-consolekit-error");
+
+  return error_quark;
+}
+
+GsmConsolekit *
+gsm_consolekit_new (void)
+{
+  GsmConsolekit *manager;
+
+  manager = g_object_new (GSM_TYPE_CONSOLEKIT, NULL);
+
+  return manager;
+}
+
+static gboolean
+try_system_stop (DBusGConnection *connection,
+                 GError                **error)
+{
+  DBusGProxy *proxy;
+  gboolean res;
+
+  proxy = dbus_g_proxy_new_for_name (connection,
+                                     CK_NAME,
+                                     CK_MANAGER_PATH,
+                                     CK_MANAGER_INTERFACE);
+
+  res = dbus_g_proxy_call_with_timeout (proxy,
+                                        "Stop",
+                                        INT_MAX,
+                                        error,
+                                        /* parameters: */
+                                        G_TYPE_INVALID,
+                                        /* return values: */
+                                        G_TYPE_INVALID);
+  return res;
+}
+
+static gboolean
+try_system_restart (DBusGConnection *connection,
+                    GError           **error)
+{
+  DBusGProxy *proxy;
+  gboolean res;
+  
+  proxy = dbus_g_proxy_new_for_name (connection,
+                                     CK_NAME,
+                                     CK_MANAGER_PATH,
+                                     CK_MANAGER_INTERFACE);
+
+  res = dbus_g_proxy_call_with_timeout (proxy,
+                                        "Restart",
+                                        INT_MAX,
+                                        error,
+                                        /* parameters: */
+                                        G_TYPE_INVALID,
+                                        /* return values: */
+                                        G_TYPE_INVALID);
+  return res;
+}
+
+static void
+emit_restart_complete (GsmConsolekit *manager,
+                       const char    *error_message)
+{
+  GError *call_error;
+
+  call_error = NULL;
+
+  if (error_message != NULL) 
+    {
+      call_error = g_error_new_literal (GSM_CONSOLEKIT_ERROR,
+                                        GSM_CONSOLEKIT_ERROR_RESTARTING,
+                                        error_message);
+    }
+
+  g_signal_emit (G_OBJECT (manager),
+                 signals [REQUEST_COMPLETED],
+                 0, call_error);
+
+  if (call_error != NULL)
+    g_error_free (call_error);
+}
+
+static void
+emit_stop_complete (GsmConsolekit *manager,
+                    GError        *error)
+{
+  GError *call_error;
+  
+  call_error = NULL;
+  
+  if (error != NULL) 
+    {
+      call_error = g_error_new_literal (GSM_CONSOLEKIT_ERROR,
+                                        GSM_CONSOLEKIT_ERROR_STOPPING,
+                                        error->message);
+    }
+  
+  g_signal_emit (G_OBJECT (manager),
+                 signals [REQUEST_COMPLETED],
+                 0, call_error);
+
+  if (call_error != NULL)
+    g_error_free (call_error);
+}
+
+#ifdef HAVE_POLKIT_GNOME
+static void
+system_restart_auth_cb (PolKitAction  *action,
+                        gboolean       gained_privilege,
+                        GError        *error,
+                        GsmConsolekit *manager)
+{
+  GError *local_error;
+  gboolean res;
+  
+  if (!gained_privilege) 
+    {
+      if (error != NULL)
+        emit_restart_complete (manager, error->message);
+
+      return;
+    }
+  
+  local_error = NULL;
+
+  res = try_system_restart (manager->priv->dbus_connection, &local_error);
+
+  if (!res) 
+    {
+      g_warning ("Unable to restart system: %s", local_error->message);
+      emit_restart_complete (manager, local_error->message);
+      g_error_free (local_error);
+
+      return;
+    }
+}
+
+static void
+system_stop_auth_cb (PolKitAction  *action,
+                     gboolean       gained_privilege,
+                     GError        *error,
+                     GsmConsolekit *manager)
+{
+  GError *local_error;
+  gboolean res;
+
+  if (!gained_privilege) 
+    {
+      if (error != NULL)
+        emit_stop_complete (manager, error);
+
+      return;
+    }
+
+  local_error = NULL;
+
+  res = try_system_stop (manager->priv->dbus_connection, &local_error);
+
+  if (!res) 
+    {
+      g_warning ("Unable to stop system: %s", local_error->message);
+      emit_stop_complete (manager, local_error);
+      g_error_free (local_error);
+
+      return;
+    }
+}
+
+static PolKitAction *
+get_action_from_error (GError *error)
+{
+  PolKitAction *action;
+  const char *paction;
+
+  action = polkit_action_new ();
+
+  paction = NULL;
+
+  if (g_str_has_prefix (error->message, "Not privileged for action: ")) 
+    {
+      paction = error->message + strlen ("Not privileged for action: ");
+    }
+
+  polkit_action_set_action_id (action, paction);
+
+  return action;
+}
+#endif /* HAVE_POLKIT_GNOME */
+
+static void
+request_restart_priv (GsmConsolekit *manager,
+                      GError        *error)
+{
+#ifdef HAVE_POLKIT_GNOME
+  PolKitAction *action;
+  pid_t pid;
+  char *error_message = NULL;
+  gboolean res = FALSE;
+  guint xid;
+  GError *local_error;
+
+  action = get_action_from_error (error);
+
+  xid = 0;
+  pid = getpid ();
+
+  local_error = NULL;
+  res = polkit_gnome_auth_obtain (action,
+                                  xid,
+                                  pid,
+                                  (PolKitGnomeAuthCB) system_restart_auth_cb,
+                                  manager,
+                                  &local_error);
+
+  polkit_action_unref (action);
+
+  if (local_error != NULL) 
+    {
+      error_message = g_strdup (local_error->message);
+      g_error_free (local_error);
+    }
+
+  if (!res) 
+    {
+      emit_restart_complete (manager, error_message);
+      g_free (error_message);
+    }
+#else
+  g_assert_not_reached ();
+#endif /* HAVE POLKIT */
+}
+
+static void
+request_stop_priv (GsmConsolekit *manager,
+                   GError          *error)
+{
+#ifdef HAVE_POLKIT_GNOME
+  PolKitAction *action;
+  pid_t pid;
+  gboolean res = FALSE;
+  guint xid;
+  GError *local_error;
+  
+  action = get_action_from_error (error);
+  
+  xid = 0;
+  pid = getpid ();
+  
+  local_error = NULL;
+  res = polkit_gnome_auth_obtain (action,
+                                  xid,
+                                  pid,
+                                  (PolKitGnomeAuthCB) system_stop_auth_cb,
+                                  manager,
+                                  &local_error);
+
+  polkit_action_unref (action);
+
+  if (!res) 
+    {
+      if (local_error != NULL)
+        {
+          g_warning ("Unable to obtain auth to stop system: %s", 
+                     local_error->message);
+
+          emit_stop_complete (manager, local_error);
+          g_error_free (local_error);
+        }
+    }
+#else
+  g_assert_not_reached ();
+#endif /* HAVE POLKIT */
+}
+
+void
+gsm_consolekit_attempt_restart (GsmConsolekit *manager)
+{
+  gboolean res;
+  GError *error;
+
+  error = NULL;
+
+  if (!gsm_consolekit_ensure_ck_connection (manager, &error)) 
+    {
+      g_warning ("Could not connect to ConsoleKit: %s",
+                 error->message);
+      g_error_free (error);
+      return;
+    }
+
+  res = try_system_restart (manager->priv->dbus_connection, &error);
+
+  if (!res) 
+    {
+      if (dbus_g_error_has_name (error, "org.freedesktop.ConsoleKit.Manager.NotPrivileged")) 
+        {
+          request_restart_priv (manager, error);
+        }
+      else 
+        {
+          emit_restart_complete (manager, error->message);
+        }
+
+      g_error_free (error);
+    }
+}
+
+void
+gsm_consolekit_attempt_stop (GsmConsolekit *manager)
+{
+  gboolean res;
+  GError *error;
+  
+  error = NULL;
+  
+  if (!gsm_consolekit_ensure_ck_connection (manager, &error)) 
+    {
+      g_warning ("Could not connect to ConsoleKit: %s",
+                 error->message);
+      g_error_free (error);
+      return;
+    }
+  
+  res = try_system_stop (manager->priv->dbus_connection, &error);
+
+  if (!res) 
+    {
+      g_warning ("Unable to stop system: %s", error->message);
+      if (dbus_g_error_has_name (error, "org.freedesktop.ConsoleKit.Manager.NotPrivileged")) 
+        {
+          request_stop_priv (manager, error);
+        } 
+      else 
+        {
+          emit_stop_complete (manager, error);
+        }
+
+      g_error_free (error);
+    }
+}
+
+gboolean
+gsm_consolekit_can_restart (GsmConsolekit *manager)
+{
+#ifdef HAVE_POLKIT_GNOME
+  return gsm_consolekit_ensure_ck_connection (manager, NULL);
+#else
+  return FALSE;
+#endif
+}
+
+gboolean
+gsm_consolekit_can_stop (GsmConsolekit *manager)
+{
+#ifdef HAVE_POLKIT_GNOME
+  return gsm_consolekit_ensure_ck_connection (manager, NULL);
+#else
+  return FALSE;
+#endif
+}
+
+GsmConsolekit *
+gsm_get_consolekit (void)
+{
+  static GsmConsolekit *manager = NULL;
+
+  if (manager == NULL) 
+    {
+      manager = gsm_consolekit_new ();
+    }
+
+  return g_object_ref (manager);
+}

Added: trunk/gnome-session/consolekit.h
==============================================================================
--- (empty file)
+++ trunk/gnome-session/consolekit.h	Thu Jun 12 23:13:33 2008
@@ -0,0 +1,83 @@
+/* console-kit.h
+ * Copyright (C) 2008 Jon McCann <jmccann redhat com>
+ *
+ * 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.
+ *
+ * Authors:
+ *	Jon McCann <jmccann redhat com>
+ */
+
+#ifndef __GSM_CONSOLEKIT_H__
+#define __GSM_CONSOLEKIT_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GSM_TYPE_CONSOLEKIT             (gsm_consolekit_get_type ())
+#define GSM_CONSOLEKIT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_CONSOLEKIT, GsmConsolekit))
+#define GSM_CONSOLEKIT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_CONSOLEKIT, GsmConsolekitClass))
+#define GSM_IS_CONSOLEKIT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_CONSOLEKIT))
+#define GSM_IS_CONSOLEKIT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_CONSOLEKIT))
+#define GSM_CONSOLEKIT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), GSM_TYPE_CONSOLEKIT, GsmConsolekitClass))
+#define GSM_CONSOLEKIT_ERROR            (gsm_consolekit_error_quark ())
+
+typedef struct _GsmConsolekit        GsmConsolekit;
+typedef struct _GsmConsolekitClass   GsmConsolekitClass;
+typedef struct _GsmConsolekitPrivate GsmConsolekitPrivate;
+typedef enum   _GsmConsolekitError   GsmConsolekitError;
+
+struct _GsmConsolekit 
+{
+  GObject parent;
+
+  GsmConsolekitPrivate *priv;
+};
+
+struct _GsmConsolekitClass 
+{
+  GObjectClass parent_class;
+  
+  void (* request_completed) (GsmConsolekit *manager,
+                              GError        *error);
+};
+
+enum _GsmConsolekitError 
+{
+  GSM_CONSOLEKIT_ERROR_RESTARTING = 0,
+  GSM_CONSOLEKIT_ERROR_STOPPING
+};
+
+GType            gsm_consolekit_get_type        (void);
+
+GQuark           gsm_consolekit_error_quark     (void);
+
+GsmConsolekit   *gsm_consolekit_new             (void) G_GNUC_MALLOC;
+
+gboolean         gsm_consolekit_can_stop        (GsmConsolekit *manager);
+
+gboolean         gsm_consolekit_can_restart     (GsmConsolekit *manager);
+
+void             gsm_consolekit_attempt_stop    (GsmConsolekit *manager);
+
+void             gsm_consolekit_attempt_restart (GsmConsolekit *manager);
+
+GsmConsolekit   *gsm_get_consolekit             (void);
+
+G_END_DECLS
+
+#endif /* __GSM_CONSOLEKIT_H__ */

Modified: trunk/gnome-session/logout-dialog.c
==============================================================================
--- trunk/gnome-session/logout-dialog.c	(original)
+++ trunk/gnome-session/logout-dialog.c	Thu Jun 12 23:13:33 2008
@@ -17,7 +17,7 @@
  * 02111-1307, USA.
  *
  * Authors:
- *	Vincent Untz <vuntz gnome org>
+ *      Vincent Untz <vuntz gnome org>
  */
 
 #ifdef HAVE_CONFIG_H
@@ -33,6 +33,7 @@
 #include "session.h"
 #include "logout-dialog.h"
 #include "power-manager.h"
+#include "consolekit.h"
 #include "gdm.h"
 
 #define GSM_LOGOUT_DIALOG_GET_PRIVATE(o) \
@@ -48,6 +49,7 @@
   GsmSessionLogoutType type;
   
   GsmPowerManager     *power_manager;
+  GsmConsolekit       *consolekit;
   
   int                  timeout;
   unsigned int         timeout_id;
@@ -60,10 +62,10 @@
 static void gsm_logout_dialog_set_timeout  (GsmLogoutDialog *logout_dialog);
 
 static void gsm_logout_dialog_destroy  (GsmLogoutDialog *logout_dialog,
-				        gpointer         data);
+                                        gpointer         data);
 
 static void gsm_logout_dialog_show     (GsmLogoutDialog *logout_dialog,
-				        gpointer         data);
+                                        gpointer         data);
 
 enum {
   PROP_0,
@@ -74,9 +76,9 @@
 
 static void 
 gsm_logout_dialog_set_property (GObject      *object,
-			        guint         prop_id,
-			        const GValue *value,
-			        GParamSpec   *pspec)
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
 {
   switch (prop_id) 
     {
@@ -90,9 +92,9 @@
 
 static void 
 gsm_logout_dialog_get_property (GObject     *object,
-			        guint        prop_id,
-			        GValue      *value,
-			        GParamSpec  *pspec)
+                                guint        prop_id,
+                                GValue      *value,
+                                GParamSpec  *pspec)
 {
   switch (prop_id) 
     {
@@ -121,13 +123,24 @@
   gobject_class->get_property = gsm_logout_dialog_get_property;
   
   g_object_class_override_property (gobject_class,
-  				    PROP_MESSAGE_TYPE,
-  				    "message-type");
+                                    PROP_MESSAGE_TYPE,
+                                    "message-type");
   
   g_type_class_add_private (klass, sizeof (GsmLogoutDialogPrivate));
 }
 
 static void
+on_ck_request_completed (GsmConsolekit *gsm_consolekit,
+                         GError          *error)
+{
+  if (error == NULL) 
+    {
+      /* request was successful */
+      return;
+    }
+}
+
+static void
 gsm_logout_dialog_init (GsmLogoutDialog *logout_dialog)
 {
   logout_dialog->priv = GSM_LOGOUT_DIALOG_GET_PRIVATE (logout_dialog);
@@ -141,21 +154,28 @@
   gtk_window_stick (GTK_WINDOW (logout_dialog));
   
   logout_dialog->priv->power_manager = gsm_get_power_manager ();
+
+  logout_dialog->priv->consolekit = gsm_get_consolekit ();
+
+  g_signal_connect (logout_dialog->priv->consolekit,
+                    "request-completed",
+                    G_CALLBACK (on_ck_request_completed), 
+                    NULL);
   
   g_signal_connect (logout_dialog, 
                     "destroy",
-  		    G_CALLBACK (gsm_logout_dialog_destroy), 
+                    G_CALLBACK (gsm_logout_dialog_destroy), 
                     NULL);
 
   g_signal_connect (logout_dialog, 
                     "show",
-  		    G_CALLBACK (gsm_logout_dialog_show), 
+                      G_CALLBACK (gsm_logout_dialog_show), 
                     NULL);
 }
 
 static void
 gsm_logout_dialog_destroy (GsmLogoutDialog *logout_dialog,
-		           gpointer         data)
+                           gpointer         data)
 {
   if (logout_dialog->priv->timeout_id != 0)
     {
@@ -169,9 +189,44 @@
       logout_dialog->priv->power_manager = NULL;
     }  
 
+  if (logout_dialog->priv->consolekit)
+    {
+      g_object_unref (logout_dialog->priv->consolekit);
+      logout_dialog->priv->consolekit = NULL;
+    }  
+
   current_dialog = NULL;
 }
 
+static gboolean
+gsm_logout_supports_reboot (GsmLogoutDialog *logout_dialog)
+{
+  gboolean ret;
+
+  ret = gsm_consolekit_can_restart (logout_dialog->priv->consolekit);
+  if (!ret) 
+    {
+      ret = gdm_supports_logout_action (GDM_LOGOUT_ACTION_REBOOT);
+    }
+
+  return ret;
+}
+
+static gboolean
+gsm_logout_supports_shutdown (GsmLogoutDialog *logout_dialog)
+{
+  gboolean ret;
+
+  ret = gsm_consolekit_can_stop (logout_dialog->priv->consolekit);
+
+  if (!ret) 
+    {
+      ret = gdm_supports_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN);
+    }
+
+  return ret;
+}
+
 static void
 gsm_logout_dialog_show (GsmLogoutDialog *logout_dialog, gpointer user_data)
 {
@@ -191,7 +246,7 @@
   if (!logout_dialog->priv->timeout) 
   {
     gtk_dialog_response (GTK_DIALOG (logout_dialog),
-    		         logout_dialog->priv->default_response);
+                         logout_dialog->priv->default_response);
     
     return FALSE;
   }
@@ -212,26 +267,26 @@
     {
     case GSM_SESSION_LOGOUT_TYPE_LOGOUT:
       secondary_text = ngettext ("You are currently logged in as "
-      			         "\"%s\".\n"
-      			         "You will be automatically logged "
-      			         "out in %d second.",
-      			         "You are currently logged in as "
-      			         "\"%s\".\n"
-      			         "You will be automatically logged "
-      			         "out in %d seconds.",
-      			         seconds_to_show);
+                                 "\"%s\".\n"
+                                 "You will be automatically logged "
+                                 "out in %d second.",
+                                 "You are currently logged in as "
+                                 "\"%s\".\n"
+                                 "You will be automatically logged "
+                                 "out in %d seconds.",
+                                 seconds_to_show);
       break;
 
     case GSM_SESSION_LOGOUT_TYPE_SHUTDOWN:
       secondary_text = ngettext ("You are currently logged in as "
-      			         "\"%s\".\n"
-      			         "This system will be automatically "
-      			         "shut down in %d second.",
-      			         "You are currently logged in as "
-      			         "\"%s\".\n"
-      			         "This system will be automatically "
-      			         "shut down in %d seconds.",
-      			         seconds_to_show);
+                                 "\"%s\".\n"
+                                 "This system will be automatically "
+                                 "shut down in %d second.",
+                                 "You are currently logged in as "
+                                 "\"%s\".\n"
+                                 "This system will be automatically "
+                                 "shut down in %d seconds.",
+                                 seconds_to_show);
       break;
 
     default:
@@ -244,10 +299,10 @@
     name = g_get_user_name ();
   
   gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (logout_dialog),
-  					    secondary_text,
-  					    name,
-  					    seconds_to_show,
-  					    NULL);
+                                            secondary_text,
+                                            name,
+                                            seconds_to_show,
+                                            NULL);
   
   logout_dialog->priv->timeout--;
   
@@ -266,14 +321,14 @@
     g_source_remove (logout_dialog->priv->timeout_id);
   
   logout_dialog->priv->timeout_id = g_timeout_add (1000,
-  						   gsm_logout_dialog_timeout,
-  						   logout_dialog);
+                                                   gsm_logout_dialog_timeout,
+                                                   logout_dialog);
 }
 
 GtkWidget *
 gsm_get_logout_dialog (GsmSessionLogoutType  type,
-		       GdkScreen            *screen,
-		       guint32               activate_time)
+                       GdkScreen            *screen,
+                       guint32               activate_time)
 {
   GsmLogoutDialog *logout_dialog;
   char *icon_name;
@@ -301,21 +356,20 @@
       icon_name    = GSM_ICON_LOGOUT;
       primary_text = N_("Log out of this system now?");
 
-      //FIXME need to verify that this response can be used
       logout_dialog->priv->default_response = GSM_LOGOUT_RESPONSE_LOGOUT;
       
       //FIXME is gdm running?
       gtk_dialog_add_button (GTK_DIALOG (logout_dialog),
-      		             _("_Switch User"),
-      		             GSM_LOGOUT_RESPONSE_SWITCH_USER);
+                             _("_Switch User"),
+                             GSM_LOGOUT_RESPONSE_SWITCH_USER);
 
       gtk_dialog_add_button (GTK_DIALOG (logout_dialog),
-      		       GTK_STOCK_CANCEL,
-      		       GTK_RESPONSE_CANCEL);
+                             GTK_STOCK_CANCEL,
+                             GTK_RESPONSE_CANCEL);
 
       gtk_dialog_add_button (GTK_DIALOG (logout_dialog),
-      		       _("_Log Out"),
-      		       GSM_LOGOUT_RESPONSE_LOGOUT);
+                             _("_Log Out"),
+                             GSM_LOGOUT_RESPONSE_LOGOUT);
 
       break;
     case GSM_SESSION_LOGOUT_TYPE_SHUTDOWN:
@@ -325,41 +379,41 @@
       logout_dialog->priv->default_response = GSM_LOGOUT_RESPONSE_SHUTDOWN;
 
       if (gsm_power_manager_can_suspend (logout_dialog->priv->power_manager))
-      	gtk_dialog_add_button (GTK_DIALOG (logout_dialog),
-      			       _("S_uspend"),
-      			       GSM_LOGOUT_RESPONSE_STR);
+        gtk_dialog_add_button (GTK_DIALOG (logout_dialog),
+                               _("S_uspend"),
+                               GSM_LOGOUT_RESPONSE_STR);
  
       if (gsm_power_manager_can_hibernate (logout_dialog->priv->power_manager))
-      	gtk_dialog_add_button (GTK_DIALOG (logout_dialog),
-      			       _("_Hibernate"),
-      			       GSM_LOGOUT_RESPONSE_STD);
+        gtk_dialog_add_button (GTK_DIALOG (logout_dialog),
+                               _("_Hibernate"),
+                               GSM_LOGOUT_RESPONSE_STD);
       
-      if (gdm_supports_logout_action (GDM_LOGOUT_ACTION_REBOOT))
-      	gtk_dialog_add_button (GTK_DIALOG (logout_dialog),
-      			       _("_Restart"),
-      			       GSM_LOGOUT_RESPONSE_REBOOT);
+      if (gsm_logout_supports_reboot (logout_dialog))
+        gtk_dialog_add_button (GTK_DIALOG (logout_dialog),
+                               _("_Restart"),
+                               GSM_LOGOUT_RESPONSE_REBOOT);
       
       gtk_dialog_add_button (GTK_DIALOG (logout_dialog),
-      		             GTK_STOCK_CANCEL,
-      		             GTK_RESPONSE_CANCEL);
+                             GTK_STOCK_CANCEL,
+                             GTK_RESPONSE_CANCEL);
   
-      if (gdm_supports_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN))
-      	gtk_dialog_add_button (GTK_DIALOG (logout_dialog),
-      			       _("_Shut Down"),
-      			       GSM_LOGOUT_RESPONSE_SHUTDOWN);
+      if (gsm_logout_supports_shutdown (logout_dialog))
+        gtk_dialog_add_button (GTK_DIALOG (logout_dialog),
+                               _("_Shut Down"),
+                               GSM_LOGOUT_RESPONSE_SHUTDOWN);
       break;
     default:
       g_assert_not_reached ();
     }
   
   gtk_image_set_from_icon_name (GTK_IMAGE (GTK_MESSAGE_DIALOG (logout_dialog)->image),
-  			        icon_name, GTK_ICON_SIZE_DIALOG);
+                                icon_name, GTK_ICON_SIZE_DIALOG);
   
   gtk_label_set_text (GTK_LABEL (GTK_MESSAGE_DIALOG (logout_dialog)->label),
-  		      primary_text);
+                      primary_text);
   
   gtk_dialog_set_default_response (GTK_DIALOG (logout_dialog),
-  				   logout_dialog->priv->default_response);
+                                   logout_dialog->priv->default_response);
   
   gtk_window_set_screen (GTK_WINDOW (logout_dialog), screen);
 

Modified: trunk/gnome-session/session.c
==============================================================================
--- trunk/gnome-session/session.c	(original)
+++ trunk/gnome-session/session.c	Thu Jun 12 23:13:33 2008
@@ -25,6 +25,7 @@
 #include "app-autostart.h"
 #include "app-resumed.h"
 #include "logout-dialog.h"
+#include "consolekit.h"
 #include "power-manager.h"
 #include "gdm.h"
 #include "gconf.h"
@@ -880,8 +881,37 @@
 }
 
 static void
+do_request_reboot (GsmConsolekit *consolekit)
+{
+  if (gsm_consolekit_can_restart (consolekit)) 
+    {
+      gdm_set_logout_action (GDM_LOGOUT_ACTION_NONE);
+      gsm_consolekit_attempt_restart (consolekit);
+    } 
+  else 
+    {
+      gdm_set_logout_action (GDM_LOGOUT_ACTION_REBOOT);
+    }
+}
+
+static void
+do_request_shutdown (GsmConsolekit *consolekit)
+{
+  if (gsm_consolekit_can_stop (consolekit)) 
+    {
+      gdm_set_logout_action (GDM_LOGOUT_ACTION_NONE);
+      gsm_consolekit_attempt_stop (consolekit);
+    } 
+  else 
+    {
+      gdm_set_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN);
+    }
+}
+
+static void
 session_shutdown (GsmSession *session)
 {
+  GsmConsolekit *consolekit;
   GSList *cl;
 
   /* Emit session over signal */
@@ -894,11 +924,19 @@
   switch (session->logout_response_id) 
     {
     case GSM_LOGOUT_RESPONSE_SHUTDOWN:
-      gdm_set_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN);
+      consolekit = gsm_get_consolekit ();
+
+      do_request_shutdown (consolekit);
+
+      g_object_unref (consolekit);
       break;
 
     case GSM_LOGOUT_RESPONSE_REBOOT:
-      gdm_set_logout_action (GDM_LOGOUT_ACTION_REBOOT);
+      consolekit = gsm_get_consolekit ();
+
+      do_request_reboot (consolekit);
+
+      g_object_unref (consolekit);
       break;
 
     default:



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