[Xfce4-commits] <xfce4-session:master> Remove suspend/hibernate, split consolekit and rebuild dialog.

Nick Schermer noreply at xfce.org
Sat Mar 24 22:50:03 CET 2012


Updating branch refs/heads/master
         to 4002e8d4ef3905e878e44633c076f8e7d42fd91b (commit)
       from e90852df0f772184546320871c69d3358699d182 (commit)

commit 4002e8d4ef3905e878e44633c076f8e7d42fd91b
Author: Nick Schermer <nick at xfce.org>
Date:   Sun Nov 6 21:59:43 2011 +0100

    Remove suspend/hibernate, split consolekit and rebuild dialog.
    
    Way too many changes in 1 commit, but it's all related.

 configure.in.in                      |   14 +-
 libxfsm/xfsm-util.c                  |   19 +-
 libxfsm/xfsm-util.h                  |    2 -
 scripts/xinitrc.in.in                |    2 +-
 xfce4-session/Makefile.am            |    7 +-
 xfce4-session/main.c                 |   28 +-
 xfce4-session/xfsm-consolekit.c      |  337 ++++++
 xfce4-session/xfsm-consolekit.h      |   54 +
 xfce4-session/xfsm-error.h           |    2 +
 xfce4-session/xfsm-fadeout.c         |    9 +
 xfce4-session/xfsm-fadeout.h         |    1 +
 xfce4-session/xfsm-global.c          |   19 +-
 xfce4-session/xfsm-global.h          |   10 -
 xfce4-session/xfsm-logout-dialog.c   | 1321 +++++++++++++-----------
 xfce4-session/xfsm-logout-dialog.h   |   20 +-
 xfce4-session/xfsm-manager.c         |   20 +-
 xfce4-session/xfsm-manager.h         |    1 +
 xfce4-session/xfsm-shutdown-helper.c | 1862 ----------------------------------
 xfce4-session/xfsm-shutdown-helper.h |   64 --
 xfce4-session/xfsm-shutdown.c        |  716 ++++++++++++-
 xfce4-session/xfsm-shutdown.h        |   73 ++-
 21 files changed, 1927 insertions(+), 2654 deletions(-)

diff --git a/configure.in.in b/configure.in.in
index 980bc35..c80e5e5 100644
--- a/configure.in.in
+++ b/configure.in.in
@@ -62,7 +62,7 @@ AC_HEADER_STDC
 AC_CHECK_HEADERS([asm/unistd.h errno.h fcntl.h limits.h \
                   netdb.h pwd.h signal.h stdarg.h sys/param.h sys/resource.h \
                   sys/socket.h sys/time.h sys/wait.h sys/utsname.h time.h \
-                  unistd.h sys/param.h sys/user.h sys/sysctl.h])
+                  unistd.h sys/param.h sys/user.h sys/sysctl.h math.h])
 AC_CHECK_FUNCS([getaddrinfo gethostbyname gethostname getpwuid setsid \
                 sigaction strdup sync vfork])
 
@@ -142,18 +142,6 @@ else
   AC_MSG_RESULT([yes])
 fi
 
-dnl Check whether to create session screenshots
-AC_ARG_ENABLE([session-screenshots],
-AC_HELP_STRING([--enable-session-screenshots], [Create screenshots of sessions on logout]),
-  [], [enable_session_screenshots=no])
-AC_MSG_CHECKING([whether to create screenshots of sessions on logout])
-if test x"$enable_session_screenshots" != x"yes"; then
-  AC_MSG_RESULT([no])
-else
-  AC_DEFINE([SESSION_SCREENSHOTS], [1], [Define for session screenshots])
-  AC_MSG_RESULT([yes])
-fi
-
 dnl
 dnl        D-Bus RUNTIME Dependencies
 dnl
diff --git a/libxfsm/xfsm-util.c b/libxfsm/xfsm-util.c
index e766c25..ddd9d2a 100644
--- a/libxfsm/xfsm-util.c
+++ b/libxfsm/xfsm-util.c
@@ -175,23 +175,14 @@ xfsm_window_add_border (GtkWindow *window)
   gtk_container_add (GTK_CONTAINER (window), box1);
 }
 
-
-void
-xfsm_window_grab_input (GtkWindow *window)
-{
-  GdkWindow *xwindow = GTK_WIDGET (window)->window;
-
-  gdk_pointer_grab (xwindow, TRUE, 0, NULL, NULL, GDK_CURRENT_TIME);
-  gdk_keyboard_grab (xwindow, FALSE, GDK_CURRENT_TIME);
-  XSetInputFocus (GDK_DISPLAY (), GDK_WINDOW_XWINDOW (xwindow),
-                  RevertToParent, CurrentTime);
-}
-
-
 XfconfChannel*
 xfsm_open_config (void)
 {
-  return xfconf_channel_get ("xfce4-session");
+  static XfconfChannel *channel = NULL;
+
+  if (G_UNLIKELY (channel == NULL))
+    channel = xfconf_channel_get ("xfce4-session");
+  return channel;
 }
 
 gchar*
diff --git a/libxfsm/xfsm-util.h b/libxfsm/xfsm-util.h
index b215b54..8ca9fc2 100644
--- a/libxfsm/xfsm-util.h
+++ b/libxfsm/xfsm-util.h
@@ -47,8 +47,6 @@ gboolean xfsm_strv_equal (gchar **a, gchar **b);
 
 void xfsm_window_add_border (GtkWindow *window);
 
-void xfsm_window_grab_input (GtkWindow *window);
-
 XfconfChannel *xfsm_open_config (void);
 
 gchar *xfsm_gdk_display_get_fullname (GdkDisplay *display);
diff --git a/scripts/xinitrc.in.in b/scripts/xinitrc.in.in
index e63eac1..1395fb5 100755
--- a/scripts/xinitrc.in.in
+++ b/scripts/xinitrc.in.in
@@ -212,7 +212,7 @@ fi
 
 # Run xfce4-session if installed
 if which xfce4-session >/dev/null 2>&1; then
-    xfce4-session
+    ck-launch-session xfce4-session
 
     if test "$ssh_agent_kill_cmd"; then
         echo "running '$ssh_agent_kill_cmd'"
diff --git a/xfce4-session/Makefile.am b/xfce4-session/Makefile.am
index 9c845b9..089d3c5 100644
--- a/xfce4-session/Makefile.am
+++ b/xfce4-session/Makefile.am
@@ -37,6 +37,8 @@ xfce4_session_SOURCES =							\
 	xfsm-compat-gnome.h						\
 	xfsm-compat-kde.c						\
 	xfsm-compat-kde.h						\
+	xfsm-consolekit.c						\
+	xfsm-consolekit.h						\
 	xfsm-dns.c							\
 	xfsm-dns.h							\
 	xfsm-error.c							\
@@ -55,8 +57,6 @@ xfce4_session_SOURCES =							\
 	xfsm-properties.h						\
 	xfsm-shutdown.c							\
 	xfsm-shutdown.h							\
-	xfsm-shutdown-helper.c						\
-	xfsm-shutdown-helper.h						\
 	xfsm-splash-screen.c						\
 	xfsm-splash-screen.h						\
 	xfsm-startup.c							\
@@ -95,7 +95,8 @@ xfce4_session_LDADD =							\
 	$(DBUS_GLIB_LIBS)						\
 	$(LIBWNCK_LIBS)							\
 	$(XFCONF_LIBS)							\
-	$(GNOME_KEYRING_LIBS)
+	$(GNOME_KEYRING_LIBS)						\
+	-lm
 
 xfce4_session_DEPENDENCIES =						\
 	$(top_builddir)/libxfsm/libxfsm-4.6.la
diff --git a/xfce4-session/main.c b/xfce4-session/main.c
index e88b895..ddac407 100644
--- a/xfce4-session/main.c
+++ b/xfce4-session/main.c
@@ -195,11 +195,13 @@ xfsm_dbus_cleanup (void)
 int
 main (int argc, char **argv)
 {
-  XfsmManager     *manager;
-  XfsmShutdownType shutdown_type;
-  GError          *error = NULL;
-  GdkDisplay      *dpy;
-  XfconfChannel   *channel;
+  XfsmManager      *manager;
+  GError           *error = NULL;
+  GdkDisplay       *dpy;
+  XfconfChannel    *channel;
+  XfsmShutdownType  shutdown_type;
+  XfsmShutdown     *shutdown;
+  gboolean          succeed;
 
   xfce_textdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");
 
@@ -261,13 +263,25 @@ main (int argc, char **argv)
   xfsm_manager_restart (manager);
 
   gtk_main ();
-
+  
   shutdown_type = xfsm_manager_get_shutdown_type (manager);
+
   g_object_unref (manager);
   g_object_unref (channel);
 
   xfsm_dbus_cleanup ();
   ice_cleanup ();
 
-  return xfsm_shutdown (shutdown_type);
+  if (shutdown_type == XFSM_SHUTDOWN_SHUTDOWN
+      || shutdown_type == XFSM_SHUTDOWN_RESTART)
+    {
+      shutdown = xfsm_shutdown_get ();
+      succeed = xfsm_shutdown_try_type (shutdown, shutdown_type, &error);
+      if (!succeed)
+        g_warning ("Failed to shutdown/restart: %s", ERROR_MSG (error));
+      g_object_unref (shutdown);
+      return succeed ? EXIT_SUCCESS : EXIT_FAILURE;
+    }
+
+  return EXIT_SUCCESS;
 }
diff --git a/xfce4-session/xfsm-consolekit.c b/xfce4-session/xfsm-consolekit.c
new file mode 100644
index 0000000..d11c810
--- /dev/null
+++ b/xfce4-session/xfsm-consolekit.c
@@ -0,0 +1,337 @@
+/*-
+ * Copyright (c) 2010 Ali Abdallah <aliov at xfce.org>
+ * Copyright (c) 2011 Nick Schermer <nick at xfce.org>
+ * All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
+ */
+
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <xfce4-session/xfsm-consolekit.h>
+
+
+
+#define CK_NAME         "org.freedesktop.ConsoleKit"
+#define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager"
+#define CK_MANAGER_NAME CK_NAME ".Manager"
+
+
+
+static void     xfsm_consolekit_finalize     (GObject         *object);
+static gboolean xfsm_consolekit_proxy_ensure (XfsmConsolekit  *consolekit,
+                                              GError         **error);
+static void     xfsm_consolekit_proxy_free   (XfsmConsolekit *consolekit);
+
+
+
+struct _XfsmConsolekitClass
+{
+  GObjectClass __parent__;
+};
+
+struct _XfsmConsolekit
+{
+  GObject __parent__;
+
+  DBusGConnection *dbus_conn;
+  DBusGProxy      *ck_proxy;
+  DBusGProxy      *dbus_proxy;
+};
+
+
+
+G_DEFINE_TYPE (XfsmConsolekit, xfsm_consolekit, G_TYPE_OBJECT)
+
+
+
+static void
+xfsm_consolekit_class_init (XfsmConsolekitClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = xfsm_consolekit_finalize;
+}
+
+
+
+static void
+xfsm_consolekit_init (XfsmConsolekit *consolekit)
+{
+}
+
+
+
+static void
+xfsm_consolekit_finalize (GObject *object)
+{
+  xfsm_consolekit_proxy_free (XFSM_CONSOLEKIT (object));
+
+  (*G_OBJECT_CLASS (xfsm_consolekit_parent_class)->finalize) (object);
+}
+
+
+
+static DBusHandlerResult
+xfsm_consolekit_dbus_filter (DBusConnection *connection,
+                             DBusMessage    *message,
+                             gpointer        data)
+{
+  g_return_val_if_fail (XFSM_IS_CONSOLEKIT (data), DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+
+  if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")
+      && g_strcmp0 (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0)
+    {
+      xfsm_consolekit_proxy_free (XFSM_CONSOLEKIT (data));
+    }
+
+  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
+
+static void
+xfsm_consolekit_name_owner_changed (DBusGProxy     *dbus_proxy,
+                                    const gchar    *name,
+                                    const gchar    *prev_owner,
+                                    const gchar    *new_owner,
+                                    XfsmConsolekit *consolekit)
+{
+  GError *err = NULL;
+
+  g_return_if_fail (XFSM_IS_CONSOLEKIT (consolekit));
+  g_return_if_fail (consolekit->dbus_proxy == dbus_proxy);
+
+  if (g_strcmp0 (name, CK_NAME) == 0)
+    {
+      /* only reconnect the consolekit proxy */
+      if (consolekit->ck_proxy != NULL)
+        {
+          g_object_unref (G_OBJECT (consolekit->ck_proxy));
+          consolekit->ck_proxy = NULL;
+        }
+
+      if (!xfsm_consolekit_proxy_ensure (consolekit, &err))
+        {
+          g_warning ("Failed to reconnect to consolekit: %s", err->message);
+          g_error_free (err);
+        }
+    }
+}
+
+
+
+static gboolean
+xfsm_consolekit_proxy_ensure (XfsmConsolekit  *consolekit,
+                              GError         **error)
+{
+  GError         *err = NULL;
+  DBusConnection *connection;
+
+  if (consolekit->dbus_conn == NULL)
+    {
+      consolekit->dbus_conn = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
+      if (consolekit->dbus_conn == NULL)
+        goto error1;
+
+      connection = dbus_g_connection_get_connection (consolekit->dbus_conn);
+      dbus_connection_set_exit_on_disconnect (connection, FALSE);
+      dbus_connection_add_filter (connection, xfsm_consolekit_dbus_filter, consolekit, NULL);
+    }
+
+  if (consolekit->dbus_proxy == NULL)
+    {
+      consolekit->dbus_proxy = dbus_g_proxy_new_for_name_owner (consolekit->dbus_conn,
+                                                                DBUS_SERVICE_DBUS,
+                                                                DBUS_PATH_DBUS,
+                                                                DBUS_INTERFACE_DBUS,
+                                                                &err);
+      if (consolekit->dbus_proxy == NULL)
+        goto error1;
+
+      /* (dis)connect to consolekit if stopped/started */
+      dbus_g_proxy_add_signal (consolekit->dbus_proxy,
+                               "NameOwnerChanged",
+                               G_TYPE_STRING,
+                               G_TYPE_STRING,
+                               G_TYPE_STRING,
+                               G_TYPE_INVALID);
+
+      dbus_g_proxy_connect_signal (consolekit->dbus_proxy,
+                                   "NameOwnerChanged",
+                                   G_CALLBACK (xfsm_consolekit_name_owner_changed),
+                                   consolekit, NULL);
+    }
+
+  if (consolekit->ck_proxy == NULL)
+    {
+      consolekit->ck_proxy = dbus_g_proxy_new_for_name_owner (consolekit->dbus_conn,
+                                                              CK_NAME,
+                                                              CK_MANAGER_PATH,
+                                                              CK_MANAGER_NAME,
+                                                              &err);
+      if (consolekit->ck_proxy == NULL)
+        goto error1;
+    }
+
+  return TRUE;
+
+  error1:
+
+  g_propagate_error (error, err);
+  xfsm_consolekit_proxy_free (consolekit);
+
+  return FALSE;
+}
+
+
+
+static void
+xfsm_consolekit_proxy_free (XfsmConsolekit *consolekit)
+{
+  DBusConnection *connection;
+
+  if (consolekit->ck_proxy != NULL)
+    {
+      g_object_unref (G_OBJECT (consolekit->ck_proxy));
+      consolekit->ck_proxy = NULL;
+    }
+
+  if (consolekit->dbus_proxy != NULL)
+    {
+      g_object_unref (G_OBJECT (consolekit->dbus_proxy));
+      consolekit->dbus_proxy = NULL;
+    }
+
+  if (consolekit->dbus_conn != NULL)
+    {
+      connection = dbus_g_connection_get_connection (consolekit->dbus_conn);
+      dbus_connection_remove_filter (connection,
+                                     xfsm_consolekit_dbus_filter,
+                                     consolekit);
+
+      dbus_g_connection_unref (consolekit->dbus_conn);
+      consolekit->dbus_conn = NULL;
+    }
+}
+
+
+
+static gboolean
+xfsm_consolekit_can_method (XfsmConsolekit  *consolekit,
+                            const gchar     *method,
+                            gboolean        *can_method,
+                            GError         **error)
+{
+  g_return_val_if_fail (can_method != NULL, FALSE);
+
+  /* never return true if something fails */
+  *can_method = FALSE;
+
+  if (!xfsm_consolekit_proxy_ensure (consolekit, error))
+    return FALSE;
+
+  return dbus_g_proxy_call (consolekit->ck_proxy, method,
+                            error, G_TYPE_INVALID,
+                            G_TYPE_BOOLEAN, can_method,
+                            G_TYPE_INVALID);
+}
+
+
+
+static gboolean
+xfsm_consolekit_try_method (XfsmConsolekit  *consolekit,
+                            const gchar     *method,
+                            GError         **error)
+{
+  if (!xfsm_consolekit_proxy_ensure (consolekit, error))
+    return FALSE;
+
+  return dbus_g_proxy_call (consolekit->ck_proxy, method, error,
+                            G_TYPE_INVALID, G_TYPE_INVALID);
+}
+
+
+
+XfsmConsolekit *
+xfsm_consolekit_get (void)
+{
+  static XfsmConsolekit *object = NULL;
+
+  if (G_LIKELY (object != NULL))
+    {
+      g_object_ref (G_OBJECT (object));
+    }
+  else
+    {
+      object = g_object_new (XFSM_TYPE_CONSOLEKIT, NULL);
+      g_object_add_weak_pointer (G_OBJECT (object), (gpointer) &object);
+    }
+
+  return object;
+}
+
+
+
+gboolean
+xfsm_consolekit_try_restart (XfsmConsolekit  *consolekit,
+                             GError         **error)
+{
+  g_return_val_if_fail (XFSM_IS_CONSOLEKIT (consolekit), FALSE);
+
+  return xfsm_consolekit_try_method (consolekit, "Restart", error);
+}
+
+
+
+gboolean
+xfsm_consolekit_try_shutdown (XfsmConsolekit  *consolekit,
+                              GError         **error)
+{
+  g_return_val_if_fail (XFSM_IS_CONSOLEKIT (consolekit), FALSE);
+
+  return xfsm_consolekit_try_method (consolekit, "Stop", error);
+}
+
+
+
+gboolean
+xfsm_consolekit_can_restart (XfsmConsolekit  *consolekit,
+                             gboolean        *can_restart,
+                             GError         **error)
+{
+  g_return_val_if_fail (XFSM_IS_CONSOLEKIT (consolekit), FALSE);
+
+
+  return xfsm_consolekit_can_method (consolekit, "CanRestart",
+                                     can_restart, error);
+}
+
+
+
+gboolean
+xfsm_consolekit_can_shutdown (XfsmConsolekit  *consolekit,
+                              gboolean        *can_shutdown,
+                              GError         **error)
+{
+  g_return_val_if_fail (XFSM_IS_CONSOLEKIT (consolekit), FALSE);
+
+  return xfsm_consolekit_can_method (consolekit, "CanStop",
+                                     can_shutdown, error);
+}
diff --git a/xfce4-session/xfsm-consolekit.h b/xfce4-session/xfsm-consolekit.h
new file mode 100644
index 0000000..17dbe42
--- /dev/null
+++ b/xfce4-session/xfsm-consolekit.h
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2003-2006 Benedikt Meurer <benny at xfce.org>
+ * Copyright (c) 2010      Ali Abdallah    <aliov at xfce.org>
+ * Copyright (c) 2011      Nick Schermer <nick at xfce.org>
+ * All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
+ */
+
+#ifndef __XFSM_SHUTDOWN_HELPER_H__
+#define __XFSM_SHUTDOWN_HELPER_H__
+
+typedef struct _XfsmConsolekitClass XfsmConsolekitClass;
+typedef struct _XfsmConsolekit      XfsmConsolekit;
+
+#define XFSM_TYPE_CONSOLEKIT            (xfsm_consolekit_get_type ())
+#define XFSM_CONSOLEKIT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFSM_TYPE_CONSOLEKIT, XfsmConsolekit))
+#define XFSM_CONSOLEKIT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFSM_TYPE_CONSOLEKIT, XfsmConsolekitClass))
+#define XFSM_IS_CONSOLEKIT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFSM_TYPE_CONSOLEKIT))
+#define XFSM_IS_CONSOLEKIT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFSM_TYPE_CONSOLEKIT))
+#define XFSM_CONSOLEKIT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFSM_TYPE_CONSOLEKIT, XfsmConsolekitClass))
+
+GType           xfsm_consolekit_get_type     (void) G_GNUC_CONST;
+
+XfsmConsolekit *xfsm_consolekit_get          (void);
+
+gboolean        xfsm_consolekit_try_restart  (XfsmConsolekit  *consolekit,
+                                              GError         **error);
+
+gboolean        xfsm_consolekit_try_shutdown (XfsmConsolekit  *consolekit,
+                                              GError         **error);
+
+gboolean        xfsm_consolekit_can_restart  (XfsmConsolekit  *consolekit,
+                                              gboolean        *can_restart,
+                                              GError         **error);
+
+gboolean        xfsm_consolekit_can_shutdown (XfsmConsolekit  *consolekit,
+                                              gboolean        *can_shutdown,
+                                              GError         **error);
+
+#endif /* !__XFSM_SHUTDOWN_HELPER_H__ */
diff --git a/xfce4-session/xfsm-error.h b/xfce4-session/xfsm-error.h
index f2bedf9..22ff710 100644
--- a/xfce4-session/xfsm-error.h
+++ b/xfce4-session/xfsm-error.h
@@ -23,6 +23,8 @@
 #define XFSM_TYPE_ERROR  (xfsm_error_get_type ())
 #define XFSM_ERROR       (xfsm_error_get_quark ())
 
+#define ERROR_MSG(err)   ((err) != NULL ? (err)->message : "Error not set")
+
 G_BEGIN_DECLS
 
 typedef enum
diff --git a/xfce4-session/xfsm-fadeout.c b/xfce4-session/xfsm-fadeout.c
index 9ee4691..91af5b6 100644
--- a/xfce4-session/xfsm-fadeout.c
+++ b/xfce4-session/xfsm-fadeout.c
@@ -120,6 +120,15 @@ xfsm_fadeout_new (GdkDisplay *display)
 
 
 void
+xfsm_fadeout_clear (XfsmFadeout *fadeout)
+{
+  if (fadeout != NULL)
+    g_slist_foreach (fadeout->windows, (GFunc) gdk_window_clear, NULL);
+}
+
+
+
+void
 xfsm_fadeout_destroy (XfsmFadeout *fadeout)
 {
   g_slist_foreach (fadeout->windows, (GFunc) gdk_window_hide, NULL);
diff --git a/xfce4-session/xfsm-fadeout.h b/xfce4-session/xfsm-fadeout.h
index 9b31af2..6cc80fe 100644
--- a/xfce4-session/xfsm-fadeout.h
+++ b/xfce4-session/xfsm-fadeout.h
@@ -30,6 +30,7 @@ G_BEGIN_DECLS;
 typedef struct _XfsmFadeout XfsmFadeout;
 
 XfsmFadeout *xfsm_fadeout_new     (GdkDisplay  *display);
+void         xfsm_fadeout_clear   (XfsmFadeout *fadeout);
 void         xfsm_fadeout_destroy (XfsmFadeout *fadeout);
 
 G_END_DECLS;
diff --git a/xfce4-session/xfsm-global.c b/xfce4-session/xfsm-global.c
index 1d5ed37..05f8d80 100644
--- a/xfce4-session/xfsm-global.c
+++ b/xfce4-session/xfsm-global.c
@@ -142,30 +142,25 @@ xfsm_generate_client_id (SmsConn sms_conn)
 GdkPixbuf *
 xfsm_load_session_preview (const gchar *name)
 {
-#ifdef SESSION_SCREENSHOTS
   GdkDisplay *display;
-  GdkPixbuf  *pb;
+  GdkPixbuf  *pb = NULL;
   gchar *display_name;
-  gchar *resource;
   gchar *filename;
+  gchar *path;
 
   /* determine thumb file */
   display = gdk_display_get_default ();
   display_name = xfsm_gdk_display_get_fullname (display);
-  resource = g_strconcat ("sessions/thumbs-", display_name,
-                          "/", name, ".png", NULL);
-  filename = xfce_resource_save_location (XFCE_RESOURCE_CACHE, resource, TRUE);
+  path = g_strconcat ("sessions/thumbs-", display_name, "/", name, ".png", NULL);
+  filename = xfce_resource_lookup (XFCE_RESOURCE_CACHE, path);
   g_free (display_name);
-  g_free (resource);
-
-  pb = gdk_pixbuf_new_from_file (filename, NULL);
+  g_free (path);
 
+  if (filename != NULL)
+    pb = gdk_pixbuf_new_from_file (filename, NULL);
   g_free (filename);
 
   return pb;
-#else
-  return NULL;
-#endif
 }
 
 
diff --git a/xfce4-session/xfsm-global.h b/xfce4-session/xfsm-global.h
index 1fdfe8c..273361f 100644
--- a/xfce4-session/xfsm-global.h
+++ b/xfce4-session/xfsm-global.h
@@ -29,16 +29,6 @@
 #include <xfce4-session/xfsm-splash-screen.h>
 #include <dbus/dbus.h>
 
-typedef enum
-{
-  XFSM_SHUTDOWN_ASK = 0,
-  XFSM_SHUTDOWN_LOGOUT,
-  XFSM_SHUTDOWN_HALT,
-  XFSM_SHUTDOWN_REBOOT,
-  XFSM_SHUTDOWN_SUSPEND,
-  XFSM_SHUTDOWN_HIBERNATE,
-} XfsmShutdownType;
-
 typedef struct _FailsafeClient FailsafeClient;
 struct _FailsafeClient
 {
diff --git a/xfce4-session/xfsm-logout-dialog.c b/xfce4-session/xfsm-logout-dialog.c
index 8b2fc15..32c92c2 100644
--- a/xfce4-session/xfsm-logout-dialog.c
+++ b/xfce4-session/xfsm-logout-dialog.c
@@ -1,29 +1,6 @@
 /*-
  * Copyright (c) 2003-2004 Benedikt Meurer <benny at xfce.org>
- * All rights reserved.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA.
- *
- * Parts of this file where taken from gnome-session/logout.c, which
- * was written by Owen Taylor <otaylor at redhat.com>.
- */
-
-/* $Id$ */
-/*-
- * Copyright (c) 2003-2004 Benedikt Meurer <benny at xfce.org>
+ * Copyright (c) 2011      Nick Schermer <nick at xfce.org>
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -62,18 +39,8 @@
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
-
-#ifdef HAVE_GETPWUID
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-#endif
-
-#ifdef HAVE_ASM_UNISTD_H
-#include <asm/unistd.h>  /* for __NR_ioprio_set */
+#ifdef HAVE_MATH_H
+#include <math.h>
 #endif
 
 #include <libxfce4util/libxfce4util.h>
@@ -82,177 +49,122 @@
 #include <libxfsm/xfsm-util.h>
 
 #include <xfce4-session/xfsm-logout-dialog.h>
-#include <xfce4-session/xfsm-compat-gnome.h>
-#include <xfce4-session/xfsm-compat-kde.h>
 #include <xfce4-session/xfsm-fadeout.h>
 #include <xfce4-session/xfsm-global.h>
 #include <xfce4-session/xfsm-legacy.h>
-#include <xfce4-session/xfsm-shutdown-helper.h>
+#include <xfce4-session/xfsm-error.h>
 
-#define BORDER    6
+#ifdef GDK_WINDOWING_X11
+#include <X11/Xlib.h>
+#include <gdk/gdkx.h>
+#endif
 
 
-static XfsmShutdownHelper *shutdown_helper = NULL;
 
-static GtkWidget *shutdown_dialog = NULL;
+#define BORDER   6
+#define SHOTSIZE 64
 
-#ifdef SESSION_SCREENSHOTS
-static void
-screenshot_save (const gchar *session_name, GdkPixmap *pm, GdkRectangle *area)
-{
-  gchar *display_name;
-  gchar *resource;
-  gchar *filename;
-  GdkDisplay *dpy;
-  GdkPixbuf *spb;
-  GdkPixbuf *pb;
 
-  pb = gdk_pixbuf_get_from_drawable (NULL, GDK_DRAWABLE (pm), NULL,
-                                     0, 0, 0, 0, area->width, area->height);
 
-  if (pb != NULL)
-    {
-      /* scale down the pixbuf */
-      spb = gdk_pixbuf_scale_simple (pb, 52, 43, GDK_INTERP_HYPER);
+static void       xfsm_logout_dialog_finalize (GObject          *object);
+static GtkWidget *xfsm_logout_dialog_button   (const gchar      *title,
+                                               const gchar      *icon_name,
+                                               const gchar      *icon_name_fallback,
+                                               XfsmShutdownType  type,
+                                               XfsmLogoutDialog *dialog);
+static void       xfsm_logout_dialog_activate (XfsmLogoutDialog *dialog);
 
-      if (spb != NULL)
-        {
-          /* determine thumb file */
-          dpy = gdk_drawable_get_display (GDK_DRAWABLE (pm));
-          display_name = xfsm_gdk_display_get_fullname (dpy);
-          resource = g_strconcat ("sessions/thumbs-", display_name,
-                                  "/", session_name, ".png", NULL);
-          filename = xfce_resource_save_location (XFCE_RESOURCE_CACHE,
-                                                  resource, TRUE);
-          g_free (display_name);
-          g_free (resource);
-
-          gdk_pixbuf_save (spb, filename, "png", NULL, NULL);
-
-          g_object_unref (G_OBJECT (spb));
-          g_free (filename);
-        }
 
-      g_object_unref (G_OBJECT (pb));
-    }
-}
-#endif
 
+enum
+{
+  MODE_LOGOUT_BUTTONS,
+  MODE_ASK_PASSWORD,
+  MODE_SHOW_ERROR,
+  N_MODES
+};
 
-static void
-entry_activate_cb (GtkWidget *entry, GtkDialog *dialog)
+struct _XfsmLogoutDialogClass
 {
-  gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-}
+  GtkDialogClass __parent__;
+};
 
-static void
-logout_button_clicked (GtkWidget *b, gint *shutdown_type)
+struct _XfsmLogoutDialog
 {
-    *shutdown_type = XFSM_SHUTDOWN_LOGOUT;
+  GtkDialog __parent__;
 
-    gtk_dialog_response (GTK_DIALOG (shutdown_dialog), GTK_RESPONSE_OK);
-}
+  /* set when a button is clicked */
+  XfsmShutdownType  type_clicked;
 
-static void
-reboot_button_clicked (GtkWidget *b, gint *shutdown_type)
-{
-    *shutdown_type = XFSM_SHUTDOWN_REBOOT;
+  /* save session checkbox */
+  GtkWidget        *save_session;
 
-    gtk_dialog_response (GTK_DIALOG (shutdown_dialog), GTK_RESPONSE_OK);
-}
+  /* mode widgets */
+  GtkWidget        *box[N_MODES];
 
-static void
-halt_button_clicked (GtkWidget *b, gint *shutdown_type)
-{
-    *shutdown_type = XFSM_SHUTDOWN_HALT;
+  /* dialog buttons */
+  GtkWidget        *button_cancel;
+  GtkWidget        *button_ok;
+  GtkWidget        *button_close;
 
-    gtk_dialog_response (GTK_DIALOG (shutdown_dialog), GTK_RESPONSE_OK);
-}
+  /* password entry */
+  GtkWidget        *password_entry;
+
+  /* error label */
+  GtkWidget        *error_label;
+
+  /* pm instance */
+  XfsmShutdown     *shutdown;
+};
+
+
+
+G_DEFINE_TYPE (XfsmLogoutDialog, xfsm_logout_dialog, GTK_TYPE_DIALOG)
 
-static void
-suspend_button_clicked (GtkWidget *b, gint *shutdown_type)
-{
-    *shutdown_type = XFSM_SHUTDOWN_SUSPEND;
 
-    gtk_dialog_response (GTK_DIALOG (shutdown_dialog), GTK_RESPONSE_OK);
-}
 
 static void
-hibernate_button_clicked (GtkWidget *b, gint *shutdown_type)
+xfsm_logout_dialog_class_init (XfsmLogoutDialogClass *klass)
 {
-    *shutdown_type = XFSM_SHUTDOWN_HIBERNATE;
+  GObjectClass *gobject_class;
 
-    gtk_dialog_response (GTK_DIALOG (shutdown_dialog), GTK_RESPONSE_OK);
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = xfsm_logout_dialog_finalize;
 }
 
-/*
- */
-gboolean
-xfsm_logout_dialog (const gchar      *session_name,
-                    XfsmShutdownType *shutdown_type,
-                    gboolean         *save_session)
+
+
+static void
+xfsm_logout_dialog_init (XfsmLogoutDialog *dialog)
 {
-  gboolean accessibility;
-  GtkIconTheme *icon_theme;
-  XfsmFadeout *fadeout = NULL;
-  GdkScreen *screen;
-  GtkWidget *dialog;
-  GtkWidget *label;
-  GtkWidget *dbox;
-  GtkWidget *hbox;
-  GtkWidget *vbox;
-  GtkWidget *vbox2;
-  GtkWidget *image;
-  GtkWidget *checkbox;
-  GtkWidget *entry_vbox;
-  GtkWidget *entry;
-  GtkWidget *hidden;
-  GtkWidget *logout_button;
-  GtkWidget *reboot_button;
-  GtkWidget *halt_button;
-  GtkWidget *suspend_button = NULL;
-  GtkWidget *hibernate_button = NULL;
-  GtkWidget *cancel_button;
-  GtkWidget *ok_button;
-  GdkPixbuf *icon;
-  gboolean saveonexit;
-  gboolean autosave;
-  gboolean prompt;
-  gboolean show_suspend;
-  gboolean show_hibernate;
-
-  gboolean show_restart;
-  gboolean show_shutdown;
-
-  gboolean require_password;
-
-  gint monitor;
-  gint result;
-  XfceKiosk *kiosk;
-  gboolean kiosk_can_shutdown;
-  gboolean kiosk_can_save_session;
+  const gchar   *username;
+  GtkWidget     *label;
+  gchar         *label_str;
+  PangoAttrList *attrs;
+  GtkWidget     *vbox;
+  GtkWidget     *main_vbox;
+  GtkWidget     *hbox;
+  GtkWidget     *button;
+  XfceKiosk     *kiosk;
+  gboolean       can_shutdown;
+  gboolean       kiosk_can_shutdown;
+  gboolean       kiosk_can_save_session;
+  gboolean       save_session = FALSE;
+  gboolean       can_restart;
+  gboolean       can_suspend = FALSE;
+  gboolean       can_hibernate = FALSE;
+  GError        *error = NULL;
   XfconfChannel *channel;
-#ifdef SESSION_SCREENSHOTS
-  GdkRectangle screenshot_area;
-  GdkWindow *root;
-  GdkPixmap *screenshot_pm = NULL;
-  GdkGC *screenshot_gc;
-#endif
-#ifdef HAVE_GETPWUID
-  struct passwd *pw;
-#endif
+  GtkWidget     *entry;
+  GtkWidget     *image;
+  GtkWidget     *separator;
 
-  g_return_val_if_fail(save_session != NULL, FALSE);
-  g_return_val_if_fail(shutdown_type != NULL, FALSE);
+  dialog->type_clicked = XFSM_SHUTDOWN_LOGOUT;
 
-  icon_theme = gtk_icon_theme_get_default ();
-
-  /* destroy any previously running shutdown helper first */
-  if (shutdown_helper != NULL)
-    {
-      g_object_unref (shutdown_helper);
-      shutdown_helper = NULL;
-    }
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+  gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
+  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
 
   /* load kiosk settings */
   kiosk = xfce_kiosk_new ("xfce4-session");
@@ -260,549 +172,744 @@ xfsm_logout_dialog (const gchar      *session_name,
   kiosk_can_save_session = xfce_kiosk_query (kiosk, "SaveSession");
   xfce_kiosk_free (kiosk);
 
-  /* load configuration */
+  /* load xfconf settings */
   channel = xfsm_open_config ();
-  channel = xfconf_channel_get ("xfce4-session");
-  saveonexit = xfconf_channel_get_bool (channel, "/general/SaveOnExit", TRUE);
-  autosave = xfconf_channel_get_bool (channel, "/general/AutoSave", FALSE);
-  prompt = xfconf_channel_get_bool (channel, "/general/PromptOnLogout", TRUE);
-  show_suspend = xfconf_channel_get_bool (channel, "/shutdown/ShowSuspend", TRUE);
-  show_hibernate = xfconf_channel_get_bool (channel, "/shutdown/ShowHibernate", TRUE);
-
-  /* make the session-save settings obey the kiosk settings */
-  if (!kiosk_can_save_session)
-    {
-      saveonexit = FALSE;
-      autosave = FALSE;
-    }
+  if (kiosk_can_save_session)
+    save_session = xfconf_channel_get_bool (channel, "/general/SaveOnExit", TRUE);
+
+  main_vbox = gtk_vbox_new (FALSE, BORDER);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), main_vbox, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (main_vbox), BORDER);
+  gtk_widget_show (main_vbox);
+
+  /* label showing the users' name */
+  username = g_get_real_name ();
+  if (username == NULL || *username == '\0')
+    username = g_get_user_name ();
+
+  label_str = g_strdup_printf (_("Log out %s"), username);
+  label = gtk_label_new (label_str);
+  gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
+  gtk_box_pack_start (GTK_BOX (main_vbox), label, FALSE, TRUE, 0);
+  gtk_widget_show (label);
+  g_free (label_str);
+
+  attrs = pango_attr_list_new ();
+  pango_attr_list_insert (attrs, pango_attr_scale_new (PANGO_SCALE_LARGE));
+  pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
+  gtk_label_set_attributes (GTK_LABEL (label), attrs);
+  pango_attr_list_unref (attrs);
+
+  separator = gtk_hseparator_new ();
+  gtk_box_pack_start (GTK_BOX (main_vbox), separator, FALSE, TRUE, 0);
+  gtk_widget_show (separator);
+
+  /**
+   * Start mode MODE_LOGOUT_BUTTONS
+   **/
+  dialog->box[MODE_LOGOUT_BUTTONS] = vbox = gtk_vbox_new (FALSE, BORDER);
+  gtk_box_pack_start (GTK_BOX (main_vbox), vbox, TRUE, TRUE, 0);
 
-  /* if PromptOnLogout is off, saving depends on AutoSave */
-  if (!prompt)
+  hbox = gtk_hbox_new (TRUE, BORDER);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
+  gtk_widget_show (hbox);
+
+  dialog->shutdown = xfsm_shutdown_get ();
+
+  /**
+   * Cancel
+   **/
+  dialog->button_cancel = gtk_dialog_add_button (GTK_DIALOG (dialog),
+                                                 GTK_STOCK_CANCEL,
+                                                 GTK_RESPONSE_CANCEL);
+
+  /**
+   * Ok, for password mode
+   **/
+  dialog->button_ok = gtk_dialog_add_button (GTK_DIALOG (dialog),
+                                             GTK_STOCK_OK,
+                                             GTK_RESPONSE_OK);
+  gtk_widget_hide (dialog->button_ok);
+
+  /**
+   * Close, for password error
+   **/
+  dialog->button_close = gtk_dialog_add_button (GTK_DIALOG (dialog),
+                                                GTK_STOCK_CLOSE,
+                                                GTK_RESPONSE_CANCEL);
+  gtk_widget_hide (dialog->button_close);
+
+  /**
+   * Logout
+   **/
+  button = xfsm_logout_dialog_button (_("_Log Out"), "system-log-out",
+                                      "xfsm-logout", XFSM_SHUTDOWN_LOGOUT,
+                                      dialog);
+
+  gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+  gtk_widget_show (button);
+  gtk_widget_grab_focus (button);
+
+  /**
+   * Reboot
+   **/
+  can_restart = kiosk_can_shutdown;
+  if (can_restart)
     {
-      *shutdown_type = XFSM_SHUTDOWN_LOGOUT;
-      *save_session = autosave;
+      if (!xfsm_shutdown_can_restart (dialog->shutdown, &can_restart, &error))
+        {
+          g_printerr ("%s: Querying CanRestart failed, %s\n\n",
+                      PACKAGE_NAME, ERROR_MSG (error));
+          g_clear_error (&error);
 
-      return TRUE;
+          can_restart = FALSE;
+        }
     }
 
-  /* spawn the helper early so we know what it supports when
-   * constructing the dialog */
-  shutdown_helper = xfsm_shutdown_helper_new ();
+  button = xfsm_logout_dialog_button (_("_Restart"), "system-reboot",
+                                      "xfsm-reboot", XFSM_SHUTDOWN_RESTART,
+                                      dialog);
 
-  /* It's really bad here if someone else has the pointer
-   * grabbed, so we first grab the pointer and keyboard
-   * to an offscreen window, and then once we have the
-   * server grabbed, move that to our dialog.
-   */
-  gtk_rc_reparse_all ();
+  gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+  gtk_widget_set_sensitive (button, can_restart);
+  gtk_widget_show (button);
 
-  /* get screen with pointer */
-  screen = xfce_gdk_screen_get_active (&monitor);
-  if (screen == NULL)
+  /**
+   * Shutdown
+   **/
+  can_shutdown = kiosk_can_shutdown;
+  if (can_shutdown)
     {
-      screen = gdk_screen_get_default ();
-      monitor = 0;
+      if (!xfsm_shutdown_can_shutdown (dialog->shutdown, &can_shutdown, &error))
+        {
+          g_printerr ("%s: Querying CanShutdown failed. %s\n\n",
+                      PACKAGE_NAME, ERROR_MSG (error));
+          g_clear_error (&error);
+
+          can_shutdown = FALSE;
+        }
     }
 
-  /* Try to grab Input on a hidden window first */
-  hidden = gtk_invisible_new_for_screen (screen);
-  gtk_widget_show_now (hidden);
+  button = xfsm_logout_dialog_button (_("Shut _Down"), "system-shutdown",
+                                      "xfsm-shutdown", XFSM_SHUTDOWN_SHUTDOWN,
+                                      dialog);
 
-  accessibility = GTK_IS_ACCESSIBLE (gtk_widget_get_accessible (hidden));
+  gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+  gtk_widget_set_sensitive (button, can_shutdown);
+  gtk_widget_show (button);
 
-  if (!accessibility)
+  /**
+   * Suspend and Hibernate
+   **/
+  if (kiosk_can_shutdown)
     {
-      for (;;)
+      /**
+       * Suspend
+       *
+       * Hide the button if Xfpm is not installed
+       **/
+      if (xfconf_channel_get_bool (channel, "/shutdown/ShowSuspend", TRUE))
         {
-          if (gdk_pointer_grab (hidden->window, TRUE, 0, NULL, NULL,
-                                GDK_CURRENT_TIME) == GDK_GRAB_SUCCESS)
+          if (xfsm_shutdown_can_suspend (dialog->shutdown, &can_suspend, &error))
             {
-              if (gdk_keyboard_grab (hidden->window, FALSE, GDK_CURRENT_TIME)
-                  == GDK_GRAB_SUCCESS)
-                {
-                  break;
-                }
+              button = xfsm_logout_dialog_button (_("Sus_pend"), "system-suspend",
+                                                  "xfsm-suspend", XFSM_SHUTDOWN_SUSPEND,
+                                                  dialog);
 
-              gdk_pointer_ungrab (GDK_CURRENT_TIME);
+              gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+              gtk_widget_set_sensitive (button, can_suspend);
+              gtk_widget_show (button);
+            }
+          else
+            {
+              g_printerr ("%s: Querying CanSuspend failed. %s\n\n",
+                          PACKAGE_NAME, ERROR_MSG (error));
+              g_clear_error (&error);
             }
-
-          g_usleep (50 * 1000);
         }
 
-#ifdef SESSION_SCREENSHOTS
-      /* grab a screenshot */
-      root = gdk_screen_get_root_window (screen);
-      gdk_screen_get_monitor_geometry (screen, monitor, &screenshot_area);
-      screenshot_pm = gdk_pixmap_new (GDK_DRAWABLE (root),
-                                      screenshot_area.width,
-                                      screenshot_area.height,
-                                      -1);
-      screenshot_gc = gdk_gc_new (GDK_DRAWABLE (screenshot_pm));
-      gdk_gc_set_function (screenshot_gc, GDK_COPY);
-      gdk_gc_set_subwindow (screenshot_gc, TRUE);
-      gdk_draw_drawable (GDK_DRAWABLE (screenshot_pm),
-                         screenshot_gc,
-                         GDK_DRAWABLE (root),
-                         screenshot_area.x,
-                         screenshot_area.y,
-                         0,
-                         0,
-                         screenshot_area.width,
-                         screenshot_area.height);
-      g_object_unref (G_OBJECT (screenshot_gc));
-#endif
-
-      /* display fadeout */
-      fadeout = xfsm_fadeout_new (gtk_widget_get_display (hidden));
-      gdk_flush ();
+      /**
+       * Hibernate
+       *
+       * Hide the button if Xfpm is not installed
+       **/
+      if (xfconf_channel_get_bool (channel, "/shutdown/ShowHibernate", TRUE))
+        {
+          if (xfsm_shutdown_can_hibernate (dialog->shutdown, &can_hibernate, &error))
+            {
+              button = xfsm_logout_dialog_button (_("_Hibernate"), "system-hibernate",
+                                                  "xfsm-hibernate", XFSM_SHUTDOWN_HIBERNATE,
+                                                  dialog);
 
-      /* create confirm dialog */
-      dialog = g_object_new (GTK_TYPE_DIALOG,
-                             "type", GTK_WINDOW_POPUP,
-                             NULL);
+              gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+              gtk_widget_set_sensitive (button, can_hibernate);
+              gtk_widget_show (button);
+            }
+          else
+            {
+              g_printerr ("%s: Querying CanHibernate failed. %s\n\n",
+                          PACKAGE_NAME, ERROR_MSG (error));
+              g_clear_error (&error);
+            }
+        }
     }
-  else
+
+  /**
+   * Save session
+   **/
+  if (kiosk_can_save_session
+      && !xfconf_channel_get_bool (channel, "/general/AutoSave", FALSE))
     {
-      dialog = gtk_dialog_new ();
-      atk_object_set_role (gtk_widget_get_accessible (dialog), ATK_ROLE_ALERT);
-      gtk_window_set_decorated (GTK_WINDOW (dialog), FALSE);
+      dialog->save_session = gtk_check_button_new_with_mnemonic (_("_Save session for future logins"));
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->save_session), save_session);
+      gtk_box_pack_start (GTK_BOX (vbox), dialog->save_session, FALSE, TRUE, BORDER);
+      gtk_widget_show (dialog->save_session);
     }
 
-  shutdown_dialog = dialog;
-
-  cancel_button = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL,
-                                         GTK_RESPONSE_CANCEL);
+  attrs = pango_attr_list_new ();
+  pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
 
-  ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK,
-                                     GTK_RESPONSE_OK);
+  /**
+   * Start mode MODE_ASK_PASSWORD
+   **/
+  dialog->box[MODE_ASK_PASSWORD] = vbox = gtk_vbox_new (FALSE, BORDER);
+  gtk_box_pack_start (GTK_BOX (main_vbox), vbox, TRUE, TRUE, 0);
 
-  gtk_widget_hide (ok_button);
-
-  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
-  gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
-  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
-  gtk_window_set_screen (GTK_WINDOW (dialog), screen);
+  hbox = gtk_hbox_new (FALSE, BORDER * 2);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
+  gtk_widget_show (hbox);
 
-  dbox = GTK_DIALOG(dialog)->vbox;
+  image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION, GTK_ICON_SIZE_DIALOG);
+  gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+  gtk_widget_show (image);
 
-  vbox = gtk_vbox_new(FALSE, BORDER);
-  gtk_box_pack_start(GTK_BOX(dbox), vbox, TRUE, TRUE, 0);
-  gtk_container_set_border_width (GTK_CONTAINER (vbox), BORDER);
-  gtk_widget_show(vbox);
+  vbox = gtk_vbox_new (FALSE, BORDER);
+  gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
+  gtk_widget_show (vbox);
 
-#ifdef HAVE_GETPWUID
-  pw = getpwuid (getuid ());
-  if (G_LIKELY(pw && pw->pw_name && *pw->pw_name))
-    {
-      gchar *text = g_strdup_printf (_("<span size='large'><b>Log out %s</b></span>"), pw->pw_name);
-      GtkWidget *logout_label = g_object_new (GTK_TYPE_LABEL,
-                                             "label", text,
-                                             "use-markup", TRUE,
-                                             "justify", GTK_JUSTIFY_CENTER,
-                                             "xalign", 0.5,
-                                             "yalign", 0.5,
-                                             NULL);
-
-      gtk_widget_show (logout_label);
-      gtk_box_pack_start (GTK_BOX (vbox), logout_label, FALSE, FALSE, 0);
-
-      g_free (text);
-    }
-#endif
+  label = gtk_label_new (_("Please enter your password"));
+  gtk_misc_set_alignment (GTK_MISC (label), 0.00, 0.50);
+  gtk_label_set_attributes (GTK_LABEL (label), attrs);
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+  gtk_widget_show (label);
 
-  hbox = gtk_hbox_new (TRUE, BORDER);
+  dialog->password_entry = entry = gtk_entry_new ();
+  gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
+  gtk_entry_set_width_chars (GTK_ENTRY (entry), 30);
+  gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
+  g_signal_connect_swapped (G_OBJECT (entry), "activate",
+                            G_CALLBACK (xfsm_logout_dialog_activate), dialog);
+  gtk_widget_show (entry);
+
+  /**
+   * Start mode MODE_SHOW_ERROR
+   **/
+  dialog->box[MODE_SHOW_ERROR] = vbox = gtk_vbox_new (FALSE, BORDER);
+  gtk_box_pack_start (GTK_BOX (main_vbox), vbox, TRUE, TRUE, 0);
+
+  hbox = gtk_hbox_new (FALSE, BORDER * 2);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
   gtk_widget_show (hbox);
-  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
-
-  /* logout */
-  logout_button = gtk_button_new ();
-  gtk_widget_show (logout_button);
-  gtk_box_pack_start (GTK_BOX (hbox), logout_button, TRUE, TRUE, 0);
-
-  g_signal_connect (logout_button, "clicked",
-                    G_CALLBACK (logout_button_clicked), shutdown_type);
-
-  vbox2 = gtk_vbox_new (FALSE, BORDER);
-  gtk_container_set_border_width (GTK_CONTAINER (vbox2), BORDER);
-  gtk_widget_show (vbox2);
-  gtk_container_add (GTK_CONTAINER (logout_button), vbox2);
-
-  icon = gtk_icon_theme_load_icon (icon_theme,
-                                   "system-log-out",
-                                   32,
-                                   0,
-                                   NULL);
-  if (!icon)
-    icon = gtk_icon_theme_load_icon (icon_theme,
-                                     "xfsm-logout",
-                                     32,
-                                     GTK_ICON_LOOKUP_GENERIC_FALLBACK,
-                                     NULL);
-
-  image = gtk_image_new_from_pixbuf (icon);
-  gtk_widget_show (image);
-  gtk_box_pack_start (GTK_BOX (vbox2), image, FALSE, FALSE, 0);
-  g_object_unref (icon);
 
-  label = gtk_label_new_with_mnemonic (_("_Log Out"));
-  gtk_widget_show (label);
-  gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
-
-  /* reboot */
-  reboot_button = gtk_button_new ();
-  gtk_widget_show (reboot_button);
-  gtk_box_pack_start (GTK_BOX (hbox), reboot_button, TRUE, TRUE, 0);
-
-  g_signal_connect (reboot_button, "clicked",
-                    G_CALLBACK (reboot_button_clicked), shutdown_type);
-
-  vbox2 = gtk_vbox_new (FALSE, BORDER);
-  gtk_container_set_border_width (GTK_CONTAINER (vbox2), BORDER);
-  gtk_widget_show (vbox2);
-  gtk_container_add (GTK_CONTAINER (reboot_button), vbox2);
-
-  icon = gtk_icon_theme_load_icon (icon_theme,
-                                   "system-reboot",
-                                   32,
-                                   0,
-                                   NULL);
-
-  if (!icon)
-    icon = gtk_icon_theme_load_icon (icon_theme,
-                                     "xfsm-reboot",
-                                     32,
-                                     GTK_ICON_LOOKUP_GENERIC_FALLBACK,
-                                     NULL);
-
-  image = gtk_image_new_from_pixbuf (icon);
+  image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG);
+  gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
   gtk_widget_show (image);
-  gtk_box_pack_start (GTK_BOX (vbox2), image, FALSE, FALSE, 0);
-  g_object_unref (icon);
 
-  label = gtk_label_new_with_mnemonic (_("_Restart"));
+  vbox = gtk_vbox_new (FALSE, BORDER);
+  gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
+  gtk_widget_show (vbox);
+
+  label = gtk_label_new (_("An error occurred"));
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+  gtk_misc_set_alignment (GTK_MISC (label), 0.00, 0.50);
+  gtk_label_set_attributes (GTK_LABEL (label), attrs);
   gtk_widget_show (label);
-  gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
-
-  g_object_get (shutdown_helper,
-                "user-can-restart", &show_restart,
-                NULL);
-
-  if (!kiosk_can_shutdown || !show_restart )
-    gtk_widget_set_sensitive (reboot_button, FALSE);
-
-  /* halt */
-  halt_button = gtk_button_new ();
-  gtk_widget_show (halt_button);
-  gtk_box_pack_start (GTK_BOX (hbox), halt_button, TRUE, TRUE, 0);
-
-  g_signal_connect (halt_button, "clicked",
-                    G_CALLBACK (halt_button_clicked), shutdown_type);
-
-  vbox2 = gtk_vbox_new (FALSE, BORDER);
-  gtk_container_set_border_width (GTK_CONTAINER (vbox2), BORDER);
-  gtk_widget_show (vbox2);
-  gtk_container_add (GTK_CONTAINER (halt_button), vbox2);
-
-  icon = gtk_icon_theme_load_icon (icon_theme,
-                                   "system-shutdown",
-                                   32,
-                                   0,
-                                   NULL);
-
-  if (!icon)
-    icon = gtk_icon_theme_load_icon (icon_theme,
-                                     "xfsm-shutdown",
-                                     32,
-                                     GTK_ICON_LOOKUP_GENERIC_FALLBACK,
-                                     NULL);
-
-  image = gtk_image_new_from_pixbuf (icon);
-  gtk_widget_show (image);
-  gtk_box_pack_start (GTK_BOX (vbox2), image, FALSE, FALSE, 0);
-  g_object_unref (icon);
 
-  label = gtk_label_new_with_mnemonic (_("Shut _Down"));
+  label = gtk_label_new (_("Either the password you entered is "
+                           "invalid, or the system administrator "
+                           "disallows shutting down this computer "
+                           "with your user account."));
+  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+  gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
   gtk_widget_show (label);
-  gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
 
-  g_object_get (shutdown_helper,
-                "user-can-shutdown", &show_shutdown,
-                NULL);
+  pango_attr_list_unref (attrs);
+}
 
-  if (!kiosk_can_shutdown || !show_shutdown)
-    gtk_widget_set_sensitive (halt_button, FALSE);
 
-  if (show_suspend)
-    g_object_get (shutdown_helper,
-                  "user-can-suspend", &show_suspend,
-                  NULL);
 
-  if (show_hibernate)
-    g_object_get (shutdown_helper,
-                  "user-can-hibernate", &show_hibernate,
-                  NULL);
+static void
+xfsm_logout_dialog_finalize (GObject *object)
+{
+  XfsmLogoutDialog *dialog = XFSM_LOGOUT_DIALOG (object);
 
+  g_object_unref (G_OBJECT (dialog->shutdown));
 
-  if (kiosk_can_shutdown && (show_suspend || show_hibernate))
+  (*G_OBJECT_CLASS (xfsm_logout_dialog_parent_class)->finalize) (object);
+}
+
+
+
+static void
+xfsm_logout_dialog_set_mode (XfsmLogoutDialog *dialog,
+                             gint              mode)
+{
+  gint i;
+
+  for (i = 0; i < N_MODES; i++)
+    gtk_widget_set_visible (dialog->box[i], i == mode);
+
+  gtk_widget_set_visible (dialog->button_cancel, mode != MODE_SHOW_ERROR);
+  gtk_widget_set_visible (dialog->button_ok, mode == MODE_ASK_PASSWORD);
+  gtk_widget_set_visible (dialog->button_close, mode == MODE_SHOW_ERROR);
+}
+
+
+
+static void
+xfsm_logout_dialog_button_clicked (GtkWidget        *button,
+                                   XfsmLogoutDialog *dialog)
+{
+  gint *val;
+
+  val = g_object_get_data (G_OBJECT (button), "shutdown-type");
+  g_assert (val != NULL);
+  dialog->type_clicked = *val;
+
+  gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+}
+
+
+
+static GtkWidget *
+xfsm_logout_dialog_button (const gchar      *title,
+                           const gchar      *icon_name,
+                           const gchar      *icon_name_fallback,
+                           XfsmShutdownType  type,
+                           XfsmLogoutDialog *dialog)
+{
+  GtkWidget    *button;
+  GtkWidget    *vbox;
+  GdkPixbuf    *pixbuf;
+  GtkWidget    *image;
+  GtkWidget    *label;
+  static gint   icon_size = 0;
+  gint          w, h;
+  gint         *val;
+  GtkIconTheme *icon_theme;
+
+  g_return_val_if_fail (XFSM_IS_LOGOUT_DIALOG (dialog), NULL);
+
+  val = g_new0 (gint, 1);
+  *val = type;
+
+  button = gtk_button_new ();
+  g_object_set_data_full (G_OBJECT (button), "shutdown-type", val, g_free);
+  g_signal_connect (G_OBJECT (button), "clicked",
+      G_CALLBACK (xfsm_logout_dialog_button_clicked), dialog);
+
+  vbox = gtk_vbox_new (FALSE, BORDER);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), BORDER);
+  gtk_container_add (GTK_CONTAINER (button), vbox);
+  gtk_widget_show (vbox);
+
+  if (G_UNLIKELY (icon_size == 0))
     {
-      hbox = gtk_hbox_new (FALSE, BORDER);
-      gtk_widget_show (hbox);
-      gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+      if (gtk_icon_size_lookup (GTK_ICON_SIZE_DND, &w, &h))
+        icon_size = MAX (w, h);
+      else
+        icon_size = 32;
     }
 
-  /* suspend */
-  if (kiosk_can_shutdown && show_suspend)
+  icon_theme = gtk_icon_theme_get_for_screen (gtk_window_get_screen (GTK_WINDOW (dialog)));
+  pixbuf = gtk_icon_theme_load_icon (icon_theme, icon_name, icon_size, 0, NULL);
+  if (G_UNLIKELY (pixbuf == NULL))
     {
-      suspend_button = gtk_button_new ();
-      gtk_widget_show (suspend_button);
-      gtk_box_pack_start (GTK_BOX (hbox), suspend_button, TRUE, TRUE, 0);
-
-      g_signal_connect (suspend_button, "clicked",
-                        G_CALLBACK (suspend_button_clicked), shutdown_type);
-
-      vbox2 = gtk_vbox_new (FALSE, BORDER);
-      gtk_container_set_border_width (GTK_CONTAINER (vbox2), BORDER);
-      gtk_widget_show (vbox2);
-      gtk_container_add (GTK_CONTAINER (suspend_button), vbox2);
-
-      icon = gtk_icon_theme_load_icon (icon_theme,
-                                       "system-suspend",
-                                       32,
-                                       0,
-                                       NULL);
-
-      if (!icon)
-        icon = gtk_icon_theme_load_icon (icon_theme,
-                                         "xfsm-suspend",
-                                         32,
-                                         GTK_ICON_LOOKUP_GENERIC_FALLBACK,
+      pixbuf = gtk_icon_theme_load_icon (icon_theme, icon_name_fallback,
+                                         icon_size, GTK_ICON_LOOKUP_GENERIC_FALLBACK,
                                          NULL);
+    }
 
-      image = gtk_image_new_from_pixbuf (icon);
-      gtk_widget_show (image);
-      gtk_box_pack_start (GTK_BOX (vbox2), image, FALSE, FALSE, 0);
-      g_object_unref (icon);
+  image = gtk_image_new_from_pixbuf (pixbuf);
+  gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0);
+  gtk_widget_show (image);
 
-      label = gtk_label_new_with_mnemonic (_("Sus_pend"));
-      gtk_widget_show (label);
-      gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
-    }
+  label = gtk_label_new_with_mnemonic (title);
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+  gtk_widget_show (label);
 
-  /* hibernate */
-  if (kiosk_can_shutdown && show_hibernate)
-    {
-      hibernate_button = gtk_button_new ();
-      gtk_widget_show (hibernate_button);
-      gtk_box_pack_start (GTK_BOX (hbox), hibernate_button, TRUE, TRUE, 0);
-
-      g_signal_connect (hibernate_button, "clicked",
-                        G_CALLBACK (hibernate_button_clicked), shutdown_type);
-
-      vbox2 = gtk_vbox_new (FALSE, BORDER);
-      gtk_container_set_border_width (GTK_CONTAINER (vbox2), BORDER);
-      gtk_widget_show (vbox2);
-      gtk_container_add (GTK_CONTAINER (hibernate_button), vbox2);
-
-      icon = gtk_icon_theme_load_icon (icon_theme,
-                                       "system-hibernate",
-                                       32,
-                                       0,
-                                       NULL);
-
-      if (!icon)
-        icon = gtk_icon_theme_load_icon (icon_theme,
-                                         "xfsm-hibernate",
-                                         32,
-                                         GTK_ICON_LOOKUP_GENERIC_FALLBACK,
-                                         NULL);
+  return button;
+}
 
-      image = gtk_image_new_from_pixbuf (icon);
-      gtk_widget_show (image);
-      gtk_box_pack_start (GTK_BOX (vbox2), image, FALSE, FALSE, 0);
-      g_object_unref (icon);
 
-      label = gtk_label_new_with_mnemonic (_("_Hibernate"));
-      gtk_widget_show (label);
-      gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
-  }
 
-  /* save session */
-  if (!autosave && kiosk_can_save_session)
+static void
+xfsm_logout_dialog_activate (XfsmLogoutDialog *dialog)
+{
+  g_return_if_fail (XFSM_IS_LOGOUT_DIALOG (dialog));
+  gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+}
+
+
+
+static GdkPixbuf *
+xfsm_logout_dialog_screenshot_new (GdkScreen *screen)
+{
+  GdkRectangle  rect, screen_rect;
+  GdkWindow    *window;
+  GdkPixbuf    *screenshot;
+  gint          x, y;
+
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  screen_rect.x = 0;
+  screen_rect.y = 0;
+  screen_rect.width = gdk_screen_get_width (screen);
+  screen_rect.height = gdk_screen_get_height (screen);
+
+  window = gdk_screen_get_root_window (screen);
+  gdk_drawable_get_size (GDK_DRAWABLE (window), &rect.width, &rect.height);
+  gdk_window_get_origin (window, &x, &y);
+
+  rect.x = x;
+  rect.y = y;
+
+  if (!gdk_rectangle_intersect (&rect, &screen_rect, &rect))
+    return NULL;
+
+  screenshot = gdk_pixbuf_get_from_drawable  (NULL,
+                                             GDK_DRAWABLE (window),
+                                             NULL,
+                                             0, 0,
+                                             0, 0,
+                                             rect.width,
+                                             rect.height);
+
+  gdk_display_beep (gdk_screen_get_display (screen));
+
+  return screenshot;
+}
+
+
+
+static GdkPixbuf *
+exo_gdk_pixbuf_scale_ratio (GdkPixbuf *source,
+                            gint       dest_size)
+{
+  gdouble wratio;
+  gdouble hratio;
+  gint    source_width;
+  gint    source_height;
+  gint    dest_width;
+  gint    dest_height;
+
+  g_return_val_if_fail (GDK_IS_PIXBUF (source), NULL);
+  g_return_val_if_fail (dest_size > 0, NULL);
+
+  source_width  = gdk_pixbuf_get_width  (source);
+  source_height = gdk_pixbuf_get_height (source);
+
+  wratio = (gdouble) source_width  / (gdouble) dest_size;
+  hratio = (gdouble) source_height / (gdouble) dest_size;
+
+  if (hratio > wratio)
     {
-      checkbox = gtk_check_button_new_with_mnemonic(
-          _("_Save session for future logins"));
-      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox), saveonexit);
-      gtk_box_pack_start(GTK_BOX(vbox), checkbox, FALSE, TRUE, BORDER);
-      gtk_widget_show(checkbox);
+      dest_width  = rint (source_width / hratio);
+      dest_height = dest_size;
     }
   else
     {
-      checkbox = NULL;
+      dest_width  = dest_size;
+      dest_height = rint (source_height / wratio);
     }
 
-  /* create small border */
-  if (!accessibility)
-    xfsm_window_add_border (GTK_WINDOW (dialog));
+  return gdk_pixbuf_scale_simple (source, MAX (dest_width, 1),
+                                  MAX (dest_height, 1), GDK_INTERP_BILINEAR);
+}
 
-  /* center dialog on target monitor */
-  gtk_window_set_screen (GTK_WINDOW (dialog), screen);
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
 
-  /* save portion of the root window covered by the dialog */
-  if (!accessibility && shutdown_helper != NULL)
+
+static void
+xfsm_logout_dialog_screenshot_save (GdkPixbuf   *screenshot,
+                                    GdkScreen   *screen,
+                                    const gchar *session_name)
+{
+  GdkPixbuf  *scaled;
+  gchar      *path;
+  gchar      *display_name;
+  GdkDisplay *dpy;
+  GError     *error = NULL;
+  gchar      *filename;
+
+  g_return_if_fail (GDK_IS_PIXBUF (screenshot));
+  g_return_if_fail (GDK_IS_SCREEN (screen));
+
+  scaled = exo_gdk_pixbuf_scale_ratio (screenshot, SHOTSIZE);
+  if (G_LIKELY (scaled != NULL))
     {
-      gtk_widget_realize (dialog);
-      gdk_window_set_override_redirect (dialog->window, TRUE);
-      gdk_window_raise (dialog->window);
+      dpy = gdk_screen_get_display (screen);
+      display_name = xfsm_gdk_display_get_fullname (dpy);
+      path = g_strconcat ("sessions/thumbs-", display_name, "/", session_name, ".png", NULL);
+      filename = xfce_resource_save_location (XFCE_RESOURCE_CACHE, path, TRUE);
+      g_free (display_name);
+      g_free (path);
+
+      if (!gdk_pixbuf_save (scaled, filename, "png", &error, NULL))
+        {
+          g_warning ("Failed to save session screenshot: %s", error->message);
+          g_error_free (error);
+        }
+
+      g_free (filename);
+      g_object_unref (G_OBJECT (scaled));
     }
+}
 
-  /* need to realize the dialog first! */
-  gtk_widget_show_now (dialog);
-  gtk_widget_grab_focus (logout_button);
 
-  /* Grab Keyboard and Mouse pointer */
-  if (!accessibility)
-    xfsm_window_grab_input (GTK_WINDOW (dialog));
 
-  /* run the logout dialog */
-  result = gtk_dialog_run (GTK_DIALOG(dialog));
+static gint
+xfsm_logout_dialog_run (GtkDialog *dialog,
+                        gboolean   grab_input)
+{
+  GdkWindow *window;
+  gint       ret;
 
-  if (result == GTK_RESPONSE_OK) {
-    *save_session = autosave ? autosave :
-            gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox));
-  }
+  if (grab_input)
+    {
+      gtk_widget_show_now (GTK_WIDGET (dialog));
+
+      window = gtk_widget_get_window (GTK_WIDGET (dialog));
+      if (gdk_keyboard_grab (window, FALSE, GDK_CURRENT_TIME) != GDK_GRAB_SUCCESS)
+        g_critical ("Failed to grab the keyboard for logout window");
+
+#ifdef GDK_WINDOWING_X11
+      /* force input to the dialog */
+      gdk_error_trap_push ();
+      XSetInputFocus (GDK_DISPLAY (),
+                      GDK_WINDOW_XWINDOW (window),
+                      RevertToParent, CurrentTime);
+      gdk_error_trap_pop ();
+#endif
+    }
 
-  gtk_widget_hide (dialog);
+  ret = gtk_dialog_run (dialog);
+
+  if (grab_input)
+    gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+
+  return ret;
+}
+
+
+
+gboolean
+xfsm_logout_dialog (const gchar      *session_name,
+                    XfsmShutdownType *return_type,
+                    gboolean         *return_save_session)
+{
+  gint              result;
+  GtkWidget        *hidden;
+  gboolean          a11y;
+  GtkWidget        *dialog;
+  GdkScreen        *screen;
+  gint              monitor;
+  GdkPixbuf        *screenshot = NULL;
+  XfsmFadeout      *fadeout = NULL;
+  XfsmLogoutDialog *xfsm_dialog;
+  XfconfChannel    *channel = xfsm_open_config ();
+  XfceKiosk        *kiosk;
+  gboolean          autosave;
+  gboolean          kiosk_can_save_session;
+  const gchar      *text;
+  XfsmPassState     state;
+
+  g_return_val_if_fail (return_type != NULL, FALSE);
+  g_return_val_if_fail (return_save_session != NULL, FALSE);
+
+  /* get autosave state */
+  kiosk = xfce_kiosk_new ("xfce4-session");
+  kiosk_can_save_session = xfce_kiosk_query (kiosk, "SaveSession");
+  xfce_kiosk_free (kiosk);
 
-  g_object_get (shutdown_helper,
-                "require-password", &require_password,
-                NULL);
+  if (kiosk_can_save_session)
+    autosave = xfconf_channel_get_bool (channel, "/general/AutoSave", FALSE);
+  else
+    autosave = FALSE;
 
-  /* ask password */
-  if (result == GTK_RESPONSE_OK && *shutdown_type != XFSM_SHUTDOWN_LOGOUT
-      && require_password )
+  /* check if we need to bother the user */
+  if (!xfconf_channel_get_bool (channel, "/general/PromptOnLogout", TRUE))
     {
-      gtk_widget_show (ok_button);
+      *return_type = XFSM_SHUTDOWN_LOGOUT;
+      *return_save_session = autosave;
 
-      gtk_widget_destroy (vbox);
+      return TRUE;
+    }
 
-      entry_vbox = gtk_vbox_new (FALSE, BORDER);
-      gtk_box_pack_start (GTK_BOX (dbox), entry_vbox, TRUE, TRUE, BORDER);
-      gtk_widget_show (entry_vbox);
+  /* decide on which screen we should show the dialog */
+  screen = xfce_gdk_screen_get_active (&monitor);
+  if (G_UNLIKELY (screen == NULL))
+    {
+      screen = gdk_screen_get_default ();
+      monitor = 0;
+    }
 
-      label = gtk_label_new (_("Please enter your password:"));
-      gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-      gtk_widget_show (label);
-      gtk_box_pack_start (GTK_BOX (entry_vbox), label, FALSE, FALSE, 0);
+  /* check if accessibility is enabled */
+  hidden = gtk_invisible_new_for_screen (screen);
+  gtk_widget_show (hidden);
+  a11y = GTK_IS_ACCESSIBLE (gtk_widget_get_accessible (hidden));
 
-      entry = gtk_entry_new ();
-      gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
-      gtk_box_pack_start (GTK_BOX (entry_vbox), entry, TRUE, TRUE, 0);
-      g_signal_connect (G_OBJECT (entry), "activate",
-                        G_CALLBACK (entry_activate_cb), dialog);
-      gtk_widget_show (entry);
+  if (G_LIKELY (!a11y))
+    {
+      /* wait until we can grab the keyboard, we need this for
+       * the dialog when running it */
+      for (;;)
+        {
+          if (gdk_keyboard_grab (gtk_widget_get_window (hidden), FALSE,
+                                 GDK_CURRENT_TIME) == GDK_GRAB_SUCCESS)
+            {
+              gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+              break;
+            }
 
-      /* center dialog on target monitor */
-      gtk_window_set_screen (GTK_WINDOW (dialog), screen);
-      gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
+          g_usleep (G_USEC_PER_SEC / 20);
+        }
+
+      /* make a screenshot */
+      if (xfconf_channel_get_bool (channel, "/general/ShowScreenshots", TRUE))
+        screenshot = xfsm_logout_dialog_screenshot_new (screen);
 
-      gtk_widget_show_now (dialog);
-      gtk_widget_grab_focus (entry);
+      /* display fadeout */
+      fadeout = xfsm_fadeout_new (gdk_screen_get_display (screen));
+      gdk_flush ();
 
-      /* Grab Keyboard and Mouse pointer */
-      if (!accessibility)
-        xfsm_window_grab_input (GTK_WINDOW (dialog));
+      dialog = g_object_new (XFSM_TYPE_LOGOUT_DIALOG,
+                             "type", GTK_WINDOW_POPUP,
+                             "screen", screen, NULL);
 
-      result = gtk_dialog_run (GTK_DIALOG (dialog));
+      xfsm_window_add_border (GTK_WINDOW (dialog));
 
-      if (result == GTK_RESPONSE_OK)
+      gtk_widget_realize (dialog);
+      gdk_window_set_override_redirect (dialog->window, TRUE);
+      gdk_window_raise (dialog->window);
+    }
+  else
+    {
+      dialog = g_object_new (XFSM_TYPE_LOGOUT_DIALOG,
+                             "decorated", !a11y,
+                             "screen", screen, NULL);
+
+      gtk_window_set_keep_above (GTK_WINDOW (dialog), TRUE);
+      atk_object_set_role (gtk_widget_get_accessible (dialog), ATK_ROLE_ALERT);
+    }
+
+  gtk_widget_destroy (hidden);
+
+  xfsm_dialog = XFSM_LOGOUT_DIALOG (dialog);
+
+  /* set mode */
+  xfsm_logout_dialog_set_mode (xfsm_dialog, MODE_LOGOUT_BUTTONS);
+
+  result = xfsm_logout_dialog_run (GTK_DIALOG (dialog), !a11y);
+
+  gtk_widget_hide (dialog);
+
+  if (result == GTK_RESPONSE_OK)
+    {
+      /* check if the sudo helper needs a password */
+      if (xfsm_shutdown_password_require (xfsm_dialog->shutdown, xfsm_dialog->type_clicked))
         {
-          const gchar *password = gtk_entry_get_text (GTK_ENTRY (entry));
+          /* switch mode */
+          xfsm_logout_dialog_set_mode (xfsm_dialog, MODE_ASK_PASSWORD);
 
-          if (!xfsm_shutdown_helper_send_password (shutdown_helper, password))
+          /* don't leave artifacts on the background window */
+          xfsm_fadeout_clear (fadeout);
+
+          /* loop for sudo password tries */
+          for (;;)
             {
-              gtk_label_set_text (GTK_LABEL (label),
-                                  _("<b>An error occurred</b>"));
-              gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+              gtk_widget_grab_focus (xfsm_dialog->password_entry);
+              gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+              result = xfsm_logout_dialog_run (GTK_DIALOG (dialog), !a11y);
 
-              gtk_container_remove (GTK_CONTAINER (
-                    GTK_DIALOG (dialog)->action_area), cancel_button);
-              gtk_container_remove (GTK_CONTAINER (
-                    GTK_DIALOG (dialog)->action_area), ok_button);
+              if (result == GTK_RESPONSE_OK)
+                {
+                  /* bit of visual feedback we're processing the password */
+                  gtk_widget_set_sensitive (xfsm_dialog->button_cancel, FALSE);
+                  gtk_widget_set_sensitive (xfsm_dialog->button_ok, FALSE);
 
-              gtk_container_remove (GTK_CONTAINER (entry_vbox), entry);
+                  /* update the widgets before we lock the loop */
+                  while (gtk_events_pending ())
+                    g_main_context_iteration (NULL, FALSE);
 
-              gtk_dialog_add_button (GTK_DIALOG (dialog),
-                                     GTK_STOCK_CLOSE,
-                                     GTK_RESPONSE_CANCEL);
+                  /* send the password to the helper */
+                  text = gtk_entry_get_text (GTK_ENTRY (xfsm_dialog->password_entry));
+                  state = xfsm_shutdown_password_send (xfsm_dialog->shutdown, xfsm_dialog->type_clicked, text);
+                  gtk_entry_set_text (GTK_ENTRY (xfsm_dialog->password_entry), "");
 
-              label = gtk_label_new (_("Either the password you entered is "
-                                       "invalid, or the system administrator "
-                                       "disallows shutting down this computer "
-                                       "with your user account."));
-              gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
-              gtk_box_pack_start (GTK_BOX (entry_vbox), label, TRUE, TRUE, 0);
-              gtk_widget_show (label);
+                  gtk_widget_set_sensitive (xfsm_dialog->button_cancel, TRUE);
+                  gtk_widget_set_sensitive (xfsm_dialog->button_ok, TRUE);
 
-              /* center dialog on target monitor */
-              gtk_window_set_screen (GTK_WINDOW (dialog), screen);
-              gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
+                  if (state == PASSWORD_RETRY)
+                    continue;
 
-              gtk_widget_show_now (dialog);
+                  if (state == PASSWORD_FAILED)
+                    {
+                      gtk_widget_hide (dialog);
 
-              /* Grab Keyboard and Mouse pointer */
-              if (!accessibility)
-                xfsm_window_grab_input (GTK_WINDOW (dialog));
+                      xfsm_logout_dialog_set_mode (xfsm_dialog, MODE_SHOW_ERROR);
+                      gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
 
-              gtk_dialog_run (GTK_DIALOG (dialog));
+                      /* don't leave artifacts on the background window */
+                      xfsm_fadeout_clear (fadeout);
 
-              result = GTK_RESPONSE_CANCEL;
-            }
-        }
-    }
+                      /* show error */
+                      xfsm_logout_dialog_run (GTK_DIALOG (dialog), !a11y);
 
-  gtk_widget_destroy(dialog);
-  gtk_widget_destroy(hidden);
+                      result = GTK_RESPONSE_CANCEL;
+                    }
+                }
 
-  shutdown_dialog = NULL;
+              /* cancel clicked, succeeded or helper killed */
+              break;
+            }
 
-  /* Release Keyboard/Mouse pointer grab */
-  if (!accessibility)
-    {
-      xfsm_fadeout_destroy (fadeout);
+          gtk_widget_hide (dialog);
+        }
 
-      gdk_pointer_ungrab (GDK_CURRENT_TIME);
-      gdk_keyboard_ungrab (GDK_CURRENT_TIME);
-      gdk_flush ();
+      if (result == GTK_RESPONSE_OK)
+        {
+          /* store autosave state */
+          if (autosave)
+            *return_save_session = TRUE;
+          else if (xfsm_dialog->save_session != NULL)
+            *return_save_session = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (xfsm_dialog->save_session));
+          else
+            *return_save_session = FALSE;
+
+          /* return the clicked action */
+          *return_type = xfsm_dialog->type_clicked;
+        }
     }
 
-  /* process all pending events first */
-  while (gtk_events_pending ())
-    g_main_context_iteration (NULL, FALSE);
+  if (fadeout != NULL)
+    xfsm_fadeout_destroy (fadeout);
 
-  /*
-   * remember the current settings.
-   */
+  gtk_widget_destroy (dialog);
+
+  /* store channel settings if everything worked fine */
   if (result == GTK_RESPONSE_OK)
     {
       xfconf_channel_set_string (channel, "/general/SessionName", session_name);
-      xfconf_channel_set_bool (channel, "/general/SaveOnExit", *save_session);
-    }
-  else
-    {
-      g_object_unref (shutdown_helper);
-      shutdown_helper = NULL;
+      xfconf_channel_set_bool (channel, "/general/SaveOnExit", *return_save_session);
     }
 
-#ifdef SESSION_SCREENSHOTS
-  if (screenshot_pm != NULL)
+  /* save the screenshot */
+  if (screenshot != NULL)
     {
       if (result == GTK_RESPONSE_OK)
-        screenshot_save (session_name, screenshot_pm, &screenshot_area);
-
-      g_object_unref (G_OBJECT (screenshot_pm));
+        xfsm_logout_dialog_screenshot_save (screenshot, screen, session_name);
+      g_object_unref (G_OBJECT (screenshot));
     }
-#endif
 
   return (result == GTK_RESPONSE_OK);
 }
diff --git a/xfce4-session/xfsm-logout-dialog.h b/xfce4-session/xfsm-logout-dialog.h
index ed348b7..2cb0882 100644
--- a/xfce4-session/xfsm-logout-dialog.h
+++ b/xfce4-session/xfsm-logout-dialog.h
@@ -22,10 +22,22 @@
 #ifndef __XFSM_LOGOUT_DIALOG_H__
 #define __XFSM_LOGOUT_DIALOG_H__
 
-#include <xfce4-session/xfsm-global.h>
+#include <xfce4-session/xfsm-shutdown.h>
 
-gboolean xfsm_logout_dialog (const gchar      *session_name,
-                             XfsmShutdownType *shutdown_type,
-                             gboolean         *save_session);
+typedef struct _XfsmLogoutDialogClass XfsmLogoutDialogClass;
+typedef struct _XfsmLogoutDialog      XfsmLogoutDialog;
+
+#define XFSM_TYPE_LOGOUT_DIALOG            (xfsm_logout_dialog_get_type ())
+#define XFSM_LOGOUT_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFSM_TYPE_LOGOUT_DIALOG, XfsmLogoutDialog))
+#define XFSM_LOGOUT_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFSM_TYPE_LOGOUT_DIALOG, XfsmLogoutDialogClass))
+#define XFSM_IS_LOGOUT_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFSM_TYPE_LOGOUT_DIALOG))
+#define XFSM_IS_LOGOUT_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFSM_TYPE_LOGOUT_DIALOG))
+#define XFSM_LOGOUT_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFSM_TYPE_LOGOUT_DIALOG, XfsmLogoutDialogClass))
+
+GType      xfsm_logout_dialog_get_type (void) G_GNUC_CONST;
+
+gboolean   xfsm_logout_dialog          (const gchar      *session_name,
+                                        XfsmShutdownType *return_type,
+                                        gboolean         *return_save_session);
 
 #endif
diff --git a/xfce4-session/xfsm-manager.c b/xfce4-session/xfsm-manager.c
index 9f87c48..367c11c 100644
--- a/xfce4-session/xfsm-manager.c
+++ b/xfce4-session/xfsm-manager.c
@@ -71,7 +71,6 @@
 
 #include <libwnck/libwnck.h>
 
-#include <xfce4-session/xfsm-shutdown-helper.h>
 #include <libxfce4ui/libxfce4ui.h>
 
 #include <libxfsm/xfsm-splash-engine.h>
@@ -1085,8 +1084,10 @@ xfsm_manager_save_yourself_global (XfsmManager     *manager,
                                    XfsmShutdownType shutdown_type,
                                    gboolean         allow_shutdown_save)
 {
-  gboolean shutdown_save = allow_shutdown_save;
-  GList *lp;
+  gboolean      shutdown_save = allow_shutdown_save;
+  GList        *lp;
+  XfsmShutdown *shutdown_helper;
+  GError       *error = NULL;
 
   if (shutdown)
     {
@@ -1111,14 +1112,11 @@ xfsm_manager_save_yourself_global (XfsmManager     *manager,
       if (manager->shutdown_type == XFSM_SHUTDOWN_SUSPEND
           || manager->shutdown_type == XFSM_SHUTDOWN_HIBERNATE)
         {
-          XfsmShutdownHelper *shutdown_helper;
-          GError *error = NULL;
-
-          shutdown_helper = xfsm_shutdown_helper_new ();
+          shutdown_helper = xfsm_shutdown_get ();
 
-          if (!xfsm_shutdown_helper_send_command (shutdown_helper,
-                                                  manager->shutdown_type,
-                                                  &error))
+          if (!xfsm_shutdown_try_type (shutdown_helper,
+                                       manager->shutdown_type,
+                                       &error))
             {
               xfce_message_dialog (NULL, _("Shutdown Failed"),
                                    GTK_STOCK_DIALOG_ERROR,
@@ -1131,10 +1129,8 @@ xfsm_manager_save_yourself_global (XfsmManager     *manager,
               g_error_free (error);
             }
 
-          /* clean up and return */
           g_object_unref (shutdown_helper);
 
-
           /* at this point, either we failed to suspend/hibernate, or we
            * successfully suspended/hibernated, and we've been woken back
            * up, so return control to the user */
diff --git a/xfce4-session/xfsm-manager.h b/xfce4-session/xfsm-manager.h
index b12b143..521bacc 100644
--- a/xfce4-session/xfsm-manager.h
+++ b/xfce4-session/xfsm-manager.h
@@ -30,6 +30,7 @@
 
 #include <xfce4-session/xfsm-client.h>
 #include <xfce4-session/xfsm-global.h>
+#include <xfce4-session/xfsm-shutdown.h>
 
 G_BEGIN_DECLS
 
diff --git a/xfce4-session/xfsm-shutdown-helper.c b/xfce4-session/xfsm-shutdown-helper.c
deleted file mode 100644
index ef29f4f..0000000
--- a/xfce4-session/xfsm-shutdown-helper.c
+++ /dev/null
@@ -1,1862 +0,0 @@
-/* $Id$ */
-/*-
- * Copyright (c) 2003-2006 Benedikt Meurer <benny at xfce.org>
- * Copyright (c) 2010      Ali Abdallah    <aliov at xfce.org>
- * All rights reserved.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifdef HAVE_SYS_USER_H
-#include <sys/user.h>
-#endif
-#ifdef HAVE_SYS_SYSCTL_H
-#include <sys/sysctl.h>
-#endif
-
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib-lowlevel.h>
-
-#include <libxfce4util/libxfce4util.h>
-
-#include <xfce4-session/xfsm-shutdown-helper.h>
-#include <xfce4-session/xfsm-global.h>
-
-static void xfsm_shutdown_helper_finalize     (GObject *object);
-
-static void xfsm_shutdown_helper_set_property (GObject *object,
-                                               guint prop_id,
-                                               const GValue *value,
-                                               GParamSpec *pspec);
-
-static void xfsm_shutdown_helper_get_property (GObject *object,
-                                               guint prop_id,
-                                               GValue *value,
-                                               GParamSpec *pspec);
-
-/**
- * Suspend/Hibernate backend to use.
- *
- * upower, HAL, pmutils via sudo.
- *
- **/
-typedef enum
-{
-  XFSM_SLEEP_BACKEND_NOT_SUPPORTED,
-  XFSM_SLEEP_BACKEND_UPOWER,
-  XFSM_SLEEP_BACKEND_HAL,
-  XFSM_SLEEP_BACKEND_SUDO /*sudo pm-suspend ?*/
-
-} XfsmSleepBackend;
-
-/**
- * Shutdown/Reboot backend to use
- *
- * ConsoleKit, HAL, sudo
- **/
-typedef enum
-{
-  XFSM_SHUTDOWN_BACKEND_NOT_SUPPORTED,
-  XFSM_SHUTDOWN_BACKEND_CONSOLE_KIT,
-  XFSM_SHUTDOWN_BACKEND_HAL,
-  XFSM_SHUTDOWN_BACKEND_SUDO
-
-} XfsmShutdownBackend;
-
-#ifdef ENABLE_POLKIT
-/*DBus GTypes for polkit calls*/
-static GType      polkit_subject_gtype   = G_TYPE_INVALID;
-static GType      polkit_details_gtype   = G_TYPE_INVALID;
-static GType      polkit_result_gtype    = G_TYPE_INVALID;
-#endif /*ENABLE_POLKIT*/
-
-struct _XfsmShutdownHelper
-{
-  GObject              parent;
-
-  DBusGConnection     *system_bus;
-
-#ifdef ENABLE_POLKIT
-  DBusGProxy          *polkit_proxy;
-  GValueArray         *polkit_subject;
-  GHashTable          *polkit_details;
-  GHashTable          *polkit_subject_hash;
-#endif
-
-  XfsmShutdownBackend  shutdown_backend;
-  XfsmSleepBackend     sleep_backend;
-
-  gboolean             auth_shutdown;
-  gboolean             auth_restart;
-  gboolean             auth_suspend;
-  gboolean             auth_hibernate;
-  gboolean             can_shutdown;
-  gboolean             can_restart;
-  gboolean             can_suspend;
-  gboolean             can_hibernate;
-
-  gboolean             devkit_is_upower;
-
-  /* Sudo data */
-  gchar               *sudo;
-  FILE                *infile;
-  FILE                *outfile;
-  pid_t                pid;
-  gboolean             require_password;
-
-};
-
-struct _XfsmShutdownHelperClass
-{
-  GObjectClass parent_class;
-};
-
-enum
-{
-  PROP_0,
-  PROP_AUTHORIZED_TO_SHUTDOWN,
-  PROP_AUTHORIZED_TO_RESTART,
-  PROP_AUTHORIZED_TO_SUSPEND,
-  PROP_AUTHORIZED_TO_HIBERNATE,
-  PROP_CAN_SHUTDOWN,
-  PROP_CAN_RESTART,
-  PROP_CAN_SUSPEND,
-  PROP_CAN_HIBERNATE,
-  PROP_USER_CAN_SHUTDOWN,
-  PROP_USER_CAN_RESTART,
-  PROP_USER_CAN_SUSPEND,
-  PROP_USER_CAN_HIBERNATE,
-  PROP_REQUIRE_PASSWORD
-};
-
-G_DEFINE_TYPE (XfsmShutdownHelper, xfsm_shutdown_helper, G_TYPE_OBJECT)
-
-#ifdef ENABLE_POLKIT
-
-#if defined(__FreeBSD__)
-/**
- * Taken from polkitunixprocess.c code to get process start
- * time from pid.
- *
- * Copyright (C) 2008 Red Hat, Inc.
- *
- **/
-static gboolean
-get_kinfo_proc (pid_t pid, struct kinfo_proc *p)
-{
-  int mib[4];
-  size_t len;
-
-  len = 4;
-  sysctlnametomib ("kern.proc.pid", mib, &len);
-
-  len = sizeof (struct kinfo_proc);
-  mib[3] = pid;
-
-  if (sysctl (mib, 4, p, &len, NULL, 0) == -1)
-    return FALSE;
-
-  return TRUE;
-}
-#endif /*if defined(__FreeBSD__)*/
-
-static guint64
-get_start_time_for_pid (pid_t pid)
-{
-  guint64 start_time;
-#if !defined(__FreeBSD__)
-  gchar *filename;
-  gchar *contents;
-  size_t length;
-  gchar **tokens;
-  guint num_tokens;
-  gchar *p;
-  gchar *endp;
-
-  start_time = 0;
-  contents = NULL;
-
-  filename = g_strdup_printf ("/proc/%d/stat", pid);
-
-  if (!g_file_get_contents (filename, &contents, &length, NULL))
-    goto out;
-
-  /* start time is the token at index 19 after the '(process name)' entry - since only this
-   * field can contain the ')' character, search backwards for this to avoid malicious
-   * processes trying to fool us
-   */
-  p = strrchr (contents, ')');
-  if (p == NULL)
-    {
-      goto out;
-    }
-  p += 2; /* skip ') ' */
-
-  if (p - contents >= (int) length)
-    {
-      g_warning ("Error parsing file %s", filename);
-      goto out;
-    }
-
-  tokens = g_strsplit (p, " ", 0);
-
-  num_tokens = g_strv_length (tokens);
-
-  if (num_tokens < 20)
-    {
-      g_warning ("Error parsing file %s", filename);
-      goto out;
-    }
-
-  start_time = strtoull (tokens[19], &endp, 10);
-  if (endp == tokens[19])
-    {
-      g_warning ("Error parsing file %s", filename);
-      goto out;
-    }
-
-  g_strfreev (tokens);
-
- out:
-  g_free (filename);
-  g_free (contents);
-
-#else /*if !defined(__FreeBSD__)*/
-
-  struct kinfo_proc p;
-
-  start_time = 0;
-
-  if (! get_kinfo_proc (pid, &p))
-    {
-      g_warning ("Error obtaining start time for %d (%s)",
-                 (gint) pid,
-                 g_strerror (errno));
-      goto out;
-    }
-
-  start_time = (guint64) p.ki_start.tv_sec;
-
-out:
-#endif
-
-  return start_time;
-}
-
-static void
-init_dbus_gtypes (void)
-{
-  if (G_UNLIKELY (polkit_subject_gtype == G_TYPE_INVALID ) )
-    {
-      polkit_subject_gtype =
-        dbus_g_type_get_struct ("GValueArray",
-                                G_TYPE_STRING,
-                                dbus_g_type_get_map ("GHashTable",
-                                                     G_TYPE_STRING,
-                                                     G_TYPE_VALUE),
-                                G_TYPE_INVALID);
-    }
-
-  if (G_UNLIKELY (polkit_details_gtype == G_TYPE_INVALID ))
-    {
-      polkit_details_gtype = dbus_g_type_get_map ("GHashTable",
-                                                  G_TYPE_STRING,
-                                                  G_TYPE_STRING);
-    }
-
-  if (G_UNLIKELY (polkit_result_gtype == G_TYPE_INVALID ) )
-    {
-      polkit_result_gtype =
-        dbus_g_type_get_struct ("GValueArray",
-                                G_TYPE_BOOLEAN,
-                                G_TYPE_BOOLEAN,
-                                dbus_g_type_get_map ("GHashTable",
-                                                     G_TYPE_STRING,
-                                                     G_TYPE_STRING),
-                                G_TYPE_INVALID);
-    }
-}
-
-/**
- * xfsm_shutdown_helper_init_polkit_data:
- *
- * Check for Pokit and
- * Init the neccarry Polkit data an GTypes.
- *
- **/
-static gboolean
-xfsm_shutdown_helper_init_polkit_data (XfsmShutdownHelper *helper)
-{
-  GValue hash_elem = { 0 };
-  guint64 start_time;
-  gint pid;
-
-  helper->polkit_proxy =
-    dbus_g_proxy_new_for_name (helper->system_bus,
-                               "org.freedesktop.PolicyKit1",
-                               "/org/freedesktop/PolicyKit1/Authority",
-                               "org.freedesktop.PolicyKit1.Authority");
-
-  if (!helper->polkit_proxy)
-    return FALSE;
-
-  pid = getpid ();
-
-  start_time = get_start_time_for_pid (pid);
-
-  if (G_LIKELY (start_time != 0))
-    {
-      GValue val = { 0 }, pid_val = { 0 }, start_time_val = { 0 };
-
-      helper->polkit_subject = g_value_array_new (2);
-      helper->polkit_subject_hash = g_hash_table_new_full (g_str_hash,
-                                                           g_str_equal,
-                                                           g_free, NULL);
-      g_value_init (&val, G_TYPE_STRING);
-      g_value_set_string (&val, "unix-process");
-      g_value_array_append (helper->polkit_subject, &val);
-
-      g_value_unset (&val);
-
-      g_value_init (&pid_val, G_TYPE_UINT);
-      g_value_set_uint (&pid_val, pid);
-      g_hash_table_insert (helper->polkit_subject_hash, g_strdup ("pid"), &pid_val);
-
-      g_value_init (&start_time_val, G_TYPE_UINT64);
-      g_value_set_uint64 (&start_time_val, start_time);
-      g_hash_table_insert (helper->polkit_subject_hash, g_strdup ("start-time"), &start_time_val);
-    }
-  else
-    {
-      g_warning ("Unable to create Polkit subject");
-      return FALSE;
-    }
-
-
-  g_value_init (&hash_elem,
-                dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE));
-
-  g_value_set_static_boxed (&hash_elem, helper->polkit_subject_hash);
-  g_value_array_append (helper->polkit_subject, &hash_elem);
-
-  /**
-   * Polkit details, will leave it empty.
-   **/
-  helper->polkit_details = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-
-  return TRUE;
-}
-#endif /*ENABLE_POLKIT*/
-
-/**
- * xfsm_shutdown_helper_check_sudo:
- *
- * Check if we can use sudo backend.
- * Method is called if HAL, upower, consolekit are missing
- * or the session was compiled without those services.
- *
- **/
-static gboolean
-xfsm_shutdown_helper_check_sudo (XfsmShutdownHelper *helper)
-{
-  struct  rlimit rlp;
-  gchar   buf[15];
-  gint    parent_pipe[2];
-  gint    child_pipe[2];
-  gint    result;
-  gint    n;
-
-  helper->sudo = g_find_program_in_path ("sudo");
-
-  if ( G_UNLIKELY (helper->sudo == NULL ) )
-    {
-      g_warning ("Program 'sudo' was not found.");
-      return FALSE;
-    }
-
-  result = pipe (parent_pipe);
-
-  if (result < 0)
-    {
-      g_warning ("Unable to create parent pipe: %s", strerror (errno));
-      return FALSE;
-    }
-
-  result = pipe (child_pipe);
-  if (result < 0)
-    {
-      g_warning ("Unable to create child pipe: %s", strerror (errno));
-      goto error0;
-    }
-
-  helper->pid = fork ();
-
-  if (helper->pid < 0)
-    {
-      g_warning ("Unable to fork sudo helper: %s", strerror (errno));
-      goto error1;
-    }
-  else if (helper->pid == 0)
-    {
-      /* setup signals */
-      signal (SIGPIPE, SIG_IGN);
-
-      /* setup environment */
-      xfce_setenv ("LC_ALL", "C", TRUE);
-      xfce_setenv ("LANG", "C", TRUE);
-      xfce_setenv ("LANGUAGE", "C", TRUE);
-
-      /* setup the 3 standard file handles */
-      dup2 (child_pipe[0], STDIN_FILENO);
-      dup2 (parent_pipe[1], STDOUT_FILENO);
-      dup2 (parent_pipe[1], STDERR_FILENO);
-
-      /* Close all other file handles */
-      getrlimit (RLIMIT_NOFILE, &rlp);
-      for (n = 0; n < (gint) rlp.rlim_cur; ++n)
-        {
-          if (n != STDIN_FILENO && n != STDOUT_FILENO && n != STDERR_FILENO)
-            close (n);
-        }
-
-      /* execute sudo with the helper */
-      execl (helper->sudo, "sudo", "-H", "-S", "-p",
-             "XFSM_SUDO_PASS ", "--", XFSM_SHUTDOWN_HELPER_CMD, NULL);
-      _exit (127);
-    }
-
-  close (parent_pipe[1]);
-
-  /* read sudo/helper answer */
-  n = read (parent_pipe[0], buf, 15);
-  if (n < 15)
-    {
-      g_warning ("Unable to read response from sudo helper: %s",
-                 n < 0 ? strerror (errno) : "Unknown error");
-      goto error1;
-    }
-
-  helper->infile = fdopen (parent_pipe[0], "r");
-
-  if (helper->infile == NULL)
-    {
-      g_warning ("Unable to open parent pipe: %s", strerror (errno));
-      goto error1;
-    }
-
-  helper->outfile = fdopen (child_pipe[1], "w");
-
-  if (helper->outfile == NULL)
-    {
-      g_warning ("Unable to open child pipe: %s", strerror (errno));
-      goto error2;
-    }
-
-  if (memcmp (buf, "XFSM_SUDO_PASS ", 15) == 0)
-    {
-      helper->require_password = TRUE;
-    }
-  else if (memcmp (buf, "XFSM_SUDO_DONE ", 15) == 0)
-    {
-      helper->require_password = FALSE;
-    }
-  else
-    {
-      g_warning ("Got unexpected reply from sudo shutdown helper");
-      goto error2;
-    }
-
-  close (parent_pipe[1]);
-  close (child_pipe[0]);
-
-  return TRUE;
-
-error2:
-  if (helper->infile != NULL)
-    {
-      fclose (helper->infile);
-      helper->infile = NULL;
-    }
-
-  if (helper->outfile != NULL)
-    {
-      fclose (helper->outfile);
-      helper->outfile = NULL;
-    }
-
-error1:
-  close (child_pipe[0]);
-  close (child_pipe[1]);
-
-error0:
-  close (parent_pipe[0]);
-  close (parent_pipe[1]);
-
-  return FALSE;
-}
-
-#ifdef ENABLE_UPOWER
-/**
- * xfsm_shutdown_helper_get_power_props:
- *
- **/
-static GHashTable *
-xfsm_shutdown_helper_get_power_props (XfsmShutdownHelper *helper,
-                                      const gchar *name,
-                                      const gchar *path,
-                                      const gchar *iface)
-{
-  DBusGProxy *proxy_prop;
-  GHashTable *props;
-  GType g_type_hash_map;
-  GError *error = NULL;
-
-  proxy_prop = dbus_g_proxy_new_for_name (helper->system_bus,
-                                          name,
-                                          path,
-                                          DBUS_INTERFACE_PROPERTIES);
-
-  if (!proxy_prop)
-    {
-      g_warning ("Unable to create proxy for %s", name);
-      return NULL;
-    }
-
-  /* The Hash table is a pair of (strings, GValues) */
-  g_type_hash_map = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE);
-
-  dbus_g_proxy_call (proxy_prop, "GetAll", &error,
-                     G_TYPE_STRING, iface,
-                     G_TYPE_INVALID,
-                     g_type_hash_map, &props,
-                     G_TYPE_INVALID);
-
-  g_object_unref (proxy_prop);
-
-  if (error)
-    {
-      g_warning ("Method 'GetAll' failed : %s", error->message);
-      g_error_free (error);
-      return NULL;
-    }
-
-  return props;
-}
-
-
-/**
- * xfsm_shutdown_helper_check_devkit_upower:
- *
- * Check upower (formely devicekit-power)
- * for hibernate and suspend availability.
- *
- * Returns: FALSE if failed to contact upower, TRUE otherwise.
- **/
-static gboolean
-xfsm_shutdown_helper_check_devkit_upower (XfsmShutdownHelper *helper)
-{
-  /**
-   * Get the properties on 'org.freedesktop.UPower'
-   *                    or 'org.freedesktop.DeviceKit.Power'
-   *
-   * DaemonVersion      's'
-   * CanSuspend'        'b'
-   * CanHibernate'      'b'
-   * OnBattery'         'b'
-   * OnLowBattery'      'b'
-   * LidIsClosed'       'b'
-   * LidIsPresent'      'b'
-   **/
-
-  GHashTable *props;
-  GValue *value;
-  const gchar *name, *path, *iface;
-
-  /* Check for upower first */
-  name = "org.freedesktop.UPower";
-  path = "/org/freedesktop/UPower";
-  iface = "org.freedesktop.UPower";
-
-  helper->devkit_is_upower = TRUE;
-
-  props = xfsm_shutdown_helper_get_power_props (helper,
-                                                name,
-                                                path,
-                                                iface);
-  if (!props)
-    {
-      g_message ("UPower not found, trying DevKitPower");
-
-      name = "org.freedesktop.DeviceKit.Power";
-      path = "/org/freedesktop/DeviceKit/Power";
-      iface = "org.freedesktop.DeviceKit.Power";
-
-      helper->devkit_is_upower = FALSE;
-
-      props = xfsm_shutdown_helper_get_power_props (helper,
-                                                    name,
-                                                    path,
-                                                    iface);
-      if (!props)
-        {
-          g_message ("Devkit Power is not running or not installed");
-          return FALSE;
-        }
-    }
-
-  /*Get The CanSuspend bit*/
-  value = g_hash_table_lookup (props, "CanSuspend");
-
-  if (G_LIKELY (value))
-    {
-      helper->can_suspend = g_value_get_boolean (value);
-    }
-  else
-    {
-      g_warning ("No 'CanSuspend' property");
-    }
-
-  /*Get the CanHibernate bit*/
-  value = g_hash_table_lookup (props, "CanHibernate");
-
-  if (G_LIKELY (value))
-    {
-      helper->can_hibernate = g_value_get_boolean (value);
-    }
-  else
-    {
-      g_warning ("No 'CanHibernate' property");
-    }
-
-  g_hash_table_destroy (props);
-
-  return TRUE;
-}
-#endif /*ENABLE_UPOWER*/
-
-
-/**
- * xfsm_shutdown_helper_check_console_kit:
- *
- * Check Consolekit for methods:
- * Stop (Shutdown), Restart.
- **/
-#ifdef ENABLE_CONSOLE_KIT
-static gboolean
-xfsm_shutdown_helper_check_console_kit (XfsmShutdownHelper *helper)
-{
-  DBusGProxy *proxy;
-  GError *error = NULL;
-  gboolean ret;
-
-  proxy = dbus_g_proxy_new_for_name (helper->system_bus,
-                                     "org.freedesktop.ConsoleKit",
-                                     "/org/freedesktop/ConsoleKit/Manager",
-                                     "org.freedesktop.ConsoleKit.Manager");
-
-  if (!proxy)
-    {
-      g_warning ("Failed to create proxy for 'org.freedesktop.ConsoleKit'");
-      return FALSE;
-    }
-
-  ret = dbus_g_proxy_call (proxy, "CanStop", &error,
-                           G_TYPE_INVALID,
-                           G_TYPE_BOOLEAN, &helper->can_shutdown,
-                           G_TYPE_INVALID);
-
-  if (error)
-    {
-      g_warning ("'CanStop' method failed : %s", error->message);
-      g_error_free (error);
-      goto out;
-    }
-
-  dbus_g_proxy_call (proxy, "CanRestart", &error,
-                     G_TYPE_INVALID,
-                     G_TYPE_BOOLEAN, &helper->can_restart,
-                     G_TYPE_INVALID);
-
-  if (error)
-    {
-      g_warning ("'CanRestart' method failed : %s", error->message);
-      g_error_free (error);
-      goto out;
-    }
-
-  ret = TRUE;
-
- out:
-
-  g_object_unref (proxy);
-
-  return ret;
-}
-#endif /*ENABLE_CONSOLE_KIT*/
-
-
-/**
- * xfsm_shutdown_helper_check_hal:
- *
- * Check if HAL is running and for its PowerManagement bits
- *
- **/
-#ifdef ENABLE_HAL
-static gboolean
-xfsm_shutdown_helper_check_hal (XfsmShutdownHelper *helper)
-{
-  DBusGProxy *proxy_power;
-  DBusGProxy *proxy_device;
-  GError *error = NULL;
-  gboolean ret = FALSE;
-
-  proxy_power =
-      dbus_g_proxy_new_for_name (helper->system_bus,
-                                 "org.freedesktop.Hal",
-                                 "/org/freedesktop/Hal/devices/computer",
-                                 "org.freedesktop.Hal.Device.SystemPowerManagement");
-
-  if (!proxy_power)
-    {
-      g_warning ("Failed to create proxy for 'org.freedesktop.Hal' ");
-      return FALSE;
-    }
-
-  dbus_g_proxy_call (proxy_power, "JustToCheckUserPermission", &error,
-                     G_TYPE_INVALID,
-                     G_TYPE_INVALID);
-
-  g_object_unref (proxy_power);
-
-  if (G_LIKELY (error))
-    {
-      /* The message passed dbus permission check? */
-      if ( !g_error_matches (error, DBUS_GERROR, DBUS_GERROR_UNKNOWN_METHOD) )
-        {
-          g_error_free (error);
-          return FALSE;
-        }
-
-      g_error_free (error);
-      error = NULL;
-    }
-  else
-    {
-      /*Something went wrong with HAL*/
-      return FALSE;
-    }
-
-  /*
-   * Message raised DBUS_GERROR_UNKNOWN_METHOD, so it reached HAL,
-   * we can consider thatn  HAL allows us to use its power management interface
-   */
-  helper->auth_shutdown  = TRUE;
-  helper->auth_restart   = TRUE;
-  helper->auth_suspend   = TRUE;
-  helper->auth_hibernate = TRUE;
-  /* HAL doesn't have can_shutdown and can_reboot bits since it can always
-   shutdown and reboot the system */
-  helper->can_shutdown   = TRUE;
-  helper->can_restart    = TRUE;
-
-  /*Check to see is the system can_hibernate and can_suspend*/
-  proxy_device = dbus_g_proxy_new_for_name (helper->system_bus,
-                                            "org.freedesktop.Hal",
-                                            "/org/freedesktop/Hal/devices/computer",
-                                            "org.freedesktop.Hal.Device");
-
-  if (!proxy_device)
-    return FALSE;
-
-  dbus_g_proxy_call (proxy_device, "GetPropertyBoolean", &error,
-                     G_TYPE_STRING, "power_management.can_hibernate",
-                     G_TYPE_INVALID,
-                     G_TYPE_BOOLEAN, &helper->can_hibernate,
-                     G_TYPE_INVALID);
-
-  if (error)
-    {
-      g_warning ("Method 'GetPropertyBoolean' failed : %s", error->message);
-      g_error_free (error);
-      goto out;
-    }
-
-  dbus_g_proxy_call (proxy_device, "GetPropertyBoolean", &error,
-                     G_TYPE_STRING, "power_management.can_suspend",
-                     G_TYPE_INVALID,
-                     G_TYPE_BOOLEAN, &helper->can_suspend,
-                     G_TYPE_INVALID);
-
-  if (error)
-    {
-      g_warning ("Method 'GetPropertyBoolean' failed : %s", error->message);
-      g_error_free (error);
-      goto out;
-    }
-
-  ret = TRUE;
-
- out:
-
-  g_object_unref (proxy_device);
-
-  return ret;
-}
-#endif /*ENABLE_HAL*/
-
-/**
- * xfsm_shutdown_helper_check_polkit_authorization:
- *
- **/
-#ifdef ENABLE_POLKIT
-static gboolean
-xfsm_shutdown_helper_check_authorization (XfsmShutdownHelper *helper,
-                                          const gchar *action_id)
-{
-  GValueArray *result;
-  GValue result_val = { 0 };
-  GError *error = NULL;
-  gboolean is_authorized = FALSE;
-  gboolean ret;
-
-  /**
-   * <method name="CheckAuthorization">
-   *   <arg type="(sa{sv})" name="subject" direction="in"/>
-   *   <arg type="s" name="action_id" direction="in"/>
-   *   <arg type="a{ss}" name="details" direction="in"/>
-   *   <arg type="u" name="flags" direction="in"/>
-   *   <arg type="s" name="cancellation_id" direction="in"/>
-   *   <arg type="(bba{ss})" name="result" direction="out"/>
-   * </method>
-   *
-   **/
-
-  g_return_val_if_fail (helper->polkit_proxy != NULL, FALSE);
-  g_return_val_if_fail (helper->polkit_subject, FALSE);
-  g_return_val_if_fail (helper->polkit_details, FALSE);
-
-  /* Initialized DBus GTypes */
-  init_dbus_gtypes ();
-
-  result = g_value_array_new (0);
-
-  ret = dbus_g_proxy_call (helper->polkit_proxy, "CheckAuthorization", &error,
-                           polkit_subject_gtype, helper->polkit_subject,
-                           G_TYPE_STRING, action_id,
-                           polkit_details_gtype, helper->polkit_details,
-                           G_TYPE_UINT, 0,
-                           G_TYPE_STRING, NULL,
-                           G_TYPE_INVALID,
-                           polkit_result_gtype, &result,
-                           G_TYPE_INVALID);
-
-  if (G_LIKELY (ret))
-    {
-      g_value_init (&result_val, polkit_result_gtype);
-      g_value_set_static_boxed (&result_val, result);
-
-      dbus_g_type_struct_get (&result_val,
-                              0, &is_authorized,
-                              G_MAXUINT);
-      g_value_unset (&result_val);
-    }
-  else if (error)
-    {
-      g_warning ("'CheckAuthorization' failed : %s", error->message);
-      g_error_free (error);
-    }
-
-  g_value_array_free (result);
-  return is_authorized;
-}
-#endif /*ENABLE_POLKIT*/
-
-/**
- *xfsm_shutdown_helper_check_backends:
- *
- * Try to check what is the best available backend to use
- * Supported: ConsoleKit, HAL, upower and sudo.
- *
- **/
-static void
-xfsm_shutdown_helper_check_backends (XfsmShutdownHelper *helper)
-{
-#ifdef ENABLE_POLKIT
-  /*if polkit data was successfully initialized*/
-  gboolean polkit_ok = FALSE;
-#endif
-
-#ifdef ENABLE_UPOWER
-  /*Check upower (formely devicekit-power)*/
-  if ( xfsm_shutdown_helper_check_devkit_upower (helper) )
-    helper->sleep_backend = XFSM_SLEEP_BACKEND_UPOWER;
-#endif /* ENABLE_UPOWER */
-
-#ifdef ENABLE_CONSOLE_KIT
-  if ( xfsm_shutdown_helper_check_console_kit (helper) )
-    {
-      helper->shutdown_backend = XFSM_SHUTDOWN_BACKEND_CONSOLE_KIT;
-      /*ConsoleKit doesn't use Polkit*/
-      helper->auth_shutdown = helper->can_shutdown;
-      helper->auth_restart  = helper->can_restart;
-    }
-#endif
-
-  if ( helper->sleep_backend  == XFSM_SLEEP_BACKEND_UPOWER )
-    {
-#ifdef ENABLE_POLKIT
-
-      polkit_ok = xfsm_shutdown_helper_init_polkit_data (helper);
-
-      if (polkit_ok)
-        {
-          const gchar *action_hibernate, *action_suspend;
-
-          if (helper->devkit_is_upower)
-            {
-              action_hibernate = "org.freedesktop.upower.hibernate";
-              action_suspend   = "org.freedesktop.upower.suspend";
-            }
-          else
-            {
-              action_hibernate = "org.freedesktop.devicekit.power.hibernate";
-              action_suspend   = "org.freedesktop.devicekit.power.suspend";
-            }
-
-          helper->auth_hibernate =
-            xfsm_shutdown_helper_check_authorization (helper, action_hibernate);
-
-          helper->auth_suspend =
-            xfsm_shutdown_helper_check_authorization (helper, action_suspend);
-        }
-      else
-        {
-          helper->auth_hibernate = TRUE;
-          helper->auth_suspend   = TRUE;
-        }
-#else
-      helper->auth_hibernate = TRUE;
-      helper->auth_suspend   = TRUE;
-#endif /* ENABLE_POLKIT */
-    }
-
-  /*
-   * Use HAL just as a fallback.
-   */
-#ifdef ENABLE_HAL
-  if (helper->sleep_backend == XFSM_SLEEP_BACKEND_NOT_SUPPORTED ||
-      helper->shutdown_backend == XFSM_SHUTDOWN_BACKEND_NOT_SUPPORTED)
-    {
-      if (xfsm_shutdown_helper_check_hal (helper))
-        {
-          if (helper->shutdown_backend == XFSM_SHUTDOWN_BACKEND_NOT_SUPPORTED)
-            helper->shutdown_backend = XFSM_SHUTDOWN_BACKEND_HAL;
-
-          if (helper->sleep_backend == XFSM_SLEEP_BACKEND_NOT_SUPPORTED)
-            helper->sleep_backend = XFSM_SLEEP_BACKEND_HAL;
-        }
-    }
-#endif
-
-  /* Fallback for sudo */
-  if (helper->shutdown_backend == XFSM_SHUTDOWN_BACKEND_NOT_SUPPORTED)
-    {
-      if (xfsm_shutdown_helper_check_sudo (helper) )
-        {
-          helper->shutdown_backend = XFSM_SHUTDOWN_BACKEND_SUDO;
-          helper->can_shutdown  = TRUE;
-          helper->can_restart   =  TRUE;
-          helper->auth_shutdown = TRUE;
-          helper->auth_restart  = TRUE;
-        }
-    }
-
-#ifdef DEBUG
-  {
-    const gchar *shutdown_str[] =  {"Shutdown not supported",
-        "Using ConsoleKit for shutdown",
-        "Using HAL for shutdown",
-        "Using Sudo for shutdown",
-        NULL};
-
-    const gchar *sleep_str[] = {"Sleep not supported",
-        "Using UPower for sleep",
-        "Using HAL for sleep",
-        "Using Sudo for sleep",
-        NULL};
-
-    g_debug ("%s", shutdown_str[helper->shutdown_backend]);
-    g_debug ("%s", sleep_str[helper->sleep_backend]);
-
-    g_debug ("can_shutdown=%d can_restart=%d can_hibernate=%d can_suspend=%d",
-             helper->can_shutdown, helper->can_restart,
-             helper->can_hibernate, helper->can_suspend);
-
-    g_debug ("auth_shutdown=%d auth_restart=%d auth_hibernate=%d auth_suspend=%d",
-             helper->auth_shutdown, helper->auth_restart,
-             helper->auth_hibernate, helper->auth_suspend);
-  }
-#endif
-
-#ifdef ENABLE_POLKIT
-
-  if (polkit_ok)
-    {
-      g_hash_table_destroy (helper->polkit_details);
-      g_hash_table_destroy (helper->polkit_subject_hash);
-      g_value_array_free (helper->polkit_subject);
-    }
-
-#endif
-
-}
-
-static void
-xfsm_shutdown_helper_class_init (XfsmShutdownHelperClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-  object_class->finalize = xfsm_shutdown_helper_finalize;
-
-  object_class->get_property = xfsm_shutdown_helper_get_property;
-  object_class->set_property = xfsm_shutdown_helper_set_property;
-
-  /**
-   * XfsmShutdownHelper::authorized-to-shutdown
-   *
-   * Whether the user is allowed to preform shutdown.
-   **/
-  g_object_class_install_property (object_class,
-                                   PROP_AUTHORIZED_TO_SHUTDOWN,
-                                   g_param_spec_boolean ("authorized-to-shutdown",
-                                                         NULL, NULL,
-                                                         FALSE,
-                                                         G_PARAM_READABLE));
-
-  /**
-   * XfsmShutdownHelper::authorized-to-reboot
-   *
-   * Whether the user is allowed to preform reboot.
-   **/
-  g_object_class_install_property (object_class,
-                                   PROP_AUTHORIZED_TO_RESTART,
-                                   g_param_spec_boolean ("authorized-to-restart",
-                                                         NULL, NULL,
-                                                         FALSE,
-                                                         G_PARAM_READABLE));
-
-  /**
-   * XfsmShutdownHelper::authorized-to-suspend
-   *
-   * Whether the user is allowed to preform suspend.
-   **/
-  g_object_class_install_property (object_class,
-                                   PROP_AUTHORIZED_TO_SUSPEND,
-                                   g_param_spec_boolean ("authorized-to-suspend",
-                                                         NULL, NULL,
-                                                         FALSE,
-                                                         G_PARAM_READABLE));
-
-  /**
-   * XfsmShutdownHelper::authorized-to-hibernate
-   *
-   * Whether the user is allowed to preform hibernate.
-   **/
-  g_object_class_install_property (object_class,
-                                   PROP_AUTHORIZED_TO_HIBERNATE,
-                                   g_param_spec_boolean ("authorized-to-hibernate",
-                                                         NULL, NULL, FALSE,
-                                                         G_PARAM_READABLE));
-
-  /**
-   * XfsmShutdownHelper::can-shutdown
-   *
-   * Whether the system can do shutdown.
-   **/
-  g_object_class_install_property (object_class,
-                                   PROP_CAN_SHUTDOWN,
-                                   g_param_spec_boolean ("can-shutdown",
-                                                         NULL, NULL,
-                                                         FALSE,
-                                                         G_PARAM_READABLE));
-
-  /**
-   * XfsmShutdownHelper::can-restart
-   *
-   * Whether the system can do restart.
-   **/
-  g_object_class_install_property (object_class,
-                                   PROP_CAN_RESTART,
-                                   g_param_spec_boolean ("can-restart",
-                                                         NULL, NULL,
-                                                         FALSE,
-                                                         G_PARAM_READABLE));
-
-  /**
-   * XfsmShutdownHelper::can-suspend
-   *
-   * Whether the system can do suspend.
-   **/
-  g_object_class_install_property (object_class,
-                                   PROP_CAN_SUSPEND,
-                                   g_param_spec_boolean ("can-suspend",
-                                                         NULL, NULL,
-                                                         FALSE,
-                                                         G_PARAM_READABLE));
-  /**
-   * XfsmShutdownHelper::can-hibernate
-   *
-   * Whether the system can do hibernate.
-   **/
-  g_object_class_install_property (object_class,
-                                   PROP_CAN_HIBERNATE,
-                                   g_param_spec_boolean ("can-hibernate",
-                                                         NULL, NULL,
-                                                         FALSE,
-                                                         G_PARAM_READABLE));
-
-  /**
-   * XfsmShutdownHelper::user-can-shutdown
-   *
-   * Whether the user is allowed and the system can shutdown.
-   **/
-  g_object_class_install_property (object_class,
-                                   PROP_USER_CAN_SHUTDOWN,
-                                   g_param_spec_boolean ("user-can-shutdown",
-                                                         NULL, NULL,
-                                                         FALSE,
-                                                         G_PARAM_READABLE));
-
-  /**
-   * XfsmShutdownHelper::user-can-restart
-   *
-   * Whether the user is allowed and the system can restart.
-   **/
-  g_object_class_install_property (object_class,
-                                   PROP_USER_CAN_RESTART,
-                                   g_param_spec_boolean ("user-can-restart",
-                                                         NULL, NULL,
-                                                         FALSE,
-                                                         G_PARAM_READABLE));
-
-  /**
-   * XfsmShutdownHelper::user-can-suspend
-   *
-   * Whether the user is allowed and the system can suspend.
-   **/
-  g_object_class_install_property (object_class,
-                                   PROP_USER_CAN_SUSPEND,
-                                   g_param_spec_boolean ("user-can-suspend",
-                                                         NULL, NULL,
-                                                         FALSE,
-                                                         G_PARAM_READABLE));
-  /**
-   * XfsmShutdownHelper::user-can-hibernate
-   *
-   * Whether the user is allowed and the system can hibernate.
-   **/
-  g_object_class_install_property (object_class,
-                                   PROP_USER_CAN_HIBERNATE,
-                                   g_param_spec_boolean ("user-can-hibernate",
-                                                         NULL, NULL,
-                                                         FALSE,
-                                                         G_PARAM_READABLE));
-
-  /**
-   * XfsmShutdownHelper::require-password
-   *
-   * Whether the shutdown operation requires a password to
-   * pass to sudo.
-   **/
-  g_object_class_install_property (object_class,
-                                   PROP_REQUIRE_PASSWORD,
-                                   g_param_spec_boolean ("require-password",
-                                                         NULL, NULL,
-                                                         FALSE,
-                                                         G_PARAM_READABLE));
-
-}
-
-static void
-xfsm_shutdown_helper_init (XfsmShutdownHelper *helper)
-{
-  GError *error = NULL;
-
-#ifdef ENABLE_POLKIT
-  helper->polkit_proxy     = NULL;
-  helper->polkit_subject   = NULL;
-  helper->polkit_details   = NULL;
-  helper->polkit_subject_hash = NULL;
-#endif
-
-  helper->sudo             = NULL;
-  helper->infile           = NULL;
-  helper->outfile          = NULL;
-  helper->pid              = 0;
-  helper->require_password = FALSE;
-
-  helper->sleep_backend    = XFSM_SLEEP_BACKEND_NOT_SUPPORTED;
-  helper->shutdown_backend = XFSM_SHUTDOWN_BACKEND_NOT_SUPPORTED;
-
-  helper->auth_shutdown    = FALSE;
-  helper->auth_restart     = FALSE;
-  helper->auth_suspend     = FALSE;
-  helper->auth_hibernate   = FALSE;
-  helper->can_shutdown     = FALSE;
-  helper->can_restart      = FALSE;
-  helper->can_suspend      = FALSE;
-  helper->can_hibernate    = FALSE;
-
-  helper->system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
-
-  if (G_LIKELY (helper->system_bus))
-    {
-      xfsm_shutdown_helper_check_backends (helper);
-    }
-  else
-    {
-      g_warning ("Failed to connect to the system bus : %s", error->message);
-      g_error_free (error);
-
-      /* Unable to connect to the system bus, just try sudo */
-      if (xfsm_shutdown_helper_check_sudo (helper))
-        {
-          helper->shutdown_backend = XFSM_SHUTDOWN_BACKEND_SUDO;
-
-          helper->can_shutdown = TRUE;
-          helper->can_restart = TRUE;
-          helper->auth_shutdown = TRUE;
-          helper->auth_restart  = TRUE;
-        }
-    }
-}
-
-static void xfsm_shutdown_helper_set_property (GObject *object,
-                                               guint prop_id,
-                                               const GValue *value,
-                                               GParamSpec *pspec)
-{
-  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-}
-
-static void xfsm_shutdown_helper_get_property (GObject *object,
-                             guint prop_id,
-                             GValue *value,
-                             GParamSpec *pspec)
-{
-  XfsmShutdownHelper *helper;
-
-  helper = XFSM_SHUTDOWN_HELPER (object);
-
-  switch (prop_id)
-    {
-    case PROP_AUTHORIZED_TO_SHUTDOWN:
-      g_value_set_boolean (value, helper->auth_shutdown);
-      break;
-    case PROP_AUTHORIZED_TO_RESTART:
-      g_value_set_boolean (value, helper->auth_restart);
-      break;
-    case PROP_AUTHORIZED_TO_SUSPEND:
-      g_value_set_boolean (value, helper->auth_suspend);
-      break;
-    case PROP_AUTHORIZED_TO_HIBERNATE:
-      g_value_set_boolean (value, helper->auth_hibernate);
-      break;
-    case PROP_CAN_SUSPEND:
-      g_value_set_boolean (value, helper->can_suspend);
-      break;
-    case PROP_CAN_HIBERNATE:
-      g_value_set_boolean (value, helper->can_hibernate);
-      break;
-    case PROP_CAN_RESTART:
-      g_value_set_boolean (value, helper->can_restart);
-      break;
-    case PROP_CAN_SHUTDOWN:
-      g_value_set_boolean (value, helper->can_shutdown);
-      break;
-    case PROP_USER_CAN_SUSPEND:
-      g_value_set_boolean (value, helper->can_suspend && helper->auth_suspend);
-      break;
-    case PROP_USER_CAN_HIBERNATE:
-      g_value_set_boolean (value, helper->can_hibernate && helper->auth_hibernate);
-      break;
-    case PROP_USER_CAN_RESTART:
-      g_value_set_boolean (value, helper->can_restart && helper->auth_restart);
-      break;
-    case PROP_USER_CAN_SHUTDOWN:
-      g_value_set_boolean (value, helper->can_shutdown && helper->auth_shutdown);
-      break;
-    case PROP_REQUIRE_PASSWORD:
-      g_value_set_boolean (value, helper->require_password);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static void
-xfsm_shutdown_helper_finalize (GObject *object)
-{
-  XfsmShutdownHelper *helper;
-  gint status;
-
-  helper = XFSM_SHUTDOWN_HELPER (object);
-
-#ifdef ENABLE_POLKIT
-  if (helper->polkit_proxy)
-    g_object_unref (helper->polkit_proxy);
-#endif
-
-  if (helper->system_bus)
-    dbus_g_connection_unref (helper->system_bus);
-
-  if (helper->infile != NULL)
-    fclose (helper->infile);
-
-  if (helper->outfile != NULL)
-    fclose (helper->outfile);
-
-  if (helper->pid > 0)
-    waitpid (helper->pid, &status, 0);
-
-  g_free (helper->sudo);
-
-  G_OBJECT_CLASS (xfsm_shutdown_helper_parent_class)->finalize (object);
-}
-
-/**
- * xfsm_shutdown_helper_upower_sleep:
- * @helper: a #XfsmShutdownHelper,
- * @action: 'Hibernate' or 'Suspend'
- * @error: a #GError
- *
- **/
-#ifdef ENABLE_UPOWER
-static gboolean
-xfsm_shutdown_helper_upower_sleep (XfsmShutdownHelper *helper,
-                                   const gchar *action,
-                                   GError **error)
-{
-  DBusGProxy *proxy;
-  GError *error_local = NULL;
-  const gchar *name, *path, *iface;
-  gboolean ret;
-
-  if (helper->devkit_is_upower)
-    {
-      name = "org.freedesktop.UPower";
-      path = "/org/freedesktop/UPower";
-      iface = "org.freedesktop.UPower";
-    }
-  else
-    {
-      name = "org.freedesktop.DeviceKit.Power";
-      path = "/org/freedesktop/DeviceKit/Power";
-      iface = "org.freedesktop.DeviceKit.Power";
-    }
-
-  g_message (G_STRLOC ": Using %s to %s", name, action);
-
-  proxy = dbus_g_proxy_new_for_name_owner (helper->system_bus,
-                                           name,
-                                           path,
-                                           iface,
-                                           &error_local);
-
-  if (!proxy)
-    {
-      g_warning ("Failed to create proxy for %s : %s", name, error_local->message);
-      g_set_error (error, 1, 0, "%s", error_local->message);
-      g_error_free (error_local);
-      return FALSE;
-    }
-
-  ret = dbus_g_proxy_call (proxy, action, &error_local,
-                           G_TYPE_INVALID,
-                           G_TYPE_INVALID);
-
-  g_object_unref (proxy);
-
-  if (!ret)
-    {
-      /* DBus timeout?*/
-      if (g_error_matches (error_local, DBUS_GERROR, DBUS_GERROR_NO_REPLY))
-        {
-          g_error_free (error_local);
-          return TRUE;
-        }
-      else
-        {
-          g_set_error (error, 1, 0, "%s", error_local->message);
-          g_error_free (error_local);
-          return FALSE;
-        }
-    }
-
-  return TRUE;
-}
-#endif /*ENABLE_UPOWER*/
-
-/**
- * xfsm_shutdown_helper_console_kit_shutdown:
- * @helper: a #XfsmShutdownHelper,
- * @action: 'Stop' for shutdown and 'Restart' for reboot.
- * @error: a #GError
- *
- **/
-#ifdef ENABLE_CONSOLE_KIT
-static gboolean
-xfsm_shutdown_helper_console_kit_shutdown (XfsmShutdownHelper *helper,
-                                           const gchar *action,
-                                           GError **error)
-{
-  DBusGProxy *proxy;
-  GError *error_local = NULL;
-  gboolean ret;
-
-  g_message (G_STRLOC ": Using ConsoleKit to %s", action);
-
-  proxy = dbus_g_proxy_new_for_name_owner (helper->system_bus,
-                                           "org.freedesktop.ConsoleKit",
-                                           "/org/freedesktop/ConsoleKit/Manager",
-                                           "org.freedesktop.ConsoleKit.Manager",
-                                           &error_local);
-
-  if (!proxy)
-    {
-      g_warning ("Failed to create proxy for 'org.freedesktop.ConsoleKit' : %s", error_local->message);
-      g_set_error (error, 1, 0, "%s", error_local->message);
-      g_error_free (error_local);
-      return FALSE;
-    }
-
-  ret = dbus_g_proxy_call (proxy, action, &error_local,
-                           G_TYPE_INVALID,
-                           G_TYPE_INVALID);
-
-  g_object_unref (proxy);
-
-  if (!ret)
-    {
-      g_set_error (error, 1, 0, "%s", error_local->message);
-      g_error_free (error_local);
-      return FALSE;
-    }
-
-  return TRUE;
-}
-#endif /*ENABLE_CONSOLE_KIT*/
-
-/**
- * xfsm_shutdown_helper_hal_send:
- * @helper: a #XfsmShutdownHelper,
- * @action: 'Reboot' 'Shutdown' 'Hibernate' 'Suspend'
- * @error: a #GError
- *
- **/
-#ifdef ENABLE_HAL
-static gboolean
-xfsm_shutdown_helper_hal_send (XfsmShutdownHelper *helper,
-                               const gchar *action,
-                               GError **error)
-{
-  DBusGProxy *proxy;
-  GError *error_local = NULL;
-  gboolean ret;
-  gint return_code;
-
-  g_message (G_STRLOC ": Using ConsoleKit to %s", action);
-
-  proxy = dbus_g_proxy_new_for_name_owner (helper->system_bus,
-                                           "org.freedesktop.Hal",
-                                           "/org/freedesktop/Hal/devices/computer",
-                                           "org.freedesktop.Hal.Device.SystemPowerManagement",
-                                           &error_local);
-  if (!proxy)
-    {
-      g_warning ("Failed to create proxy for 'org.freedesktop.Hal' : %s", error_local->message);
-      g_set_error (error, 1, 0, "%s", error_local->message);
-      g_error_free (error_local);
-      return FALSE;
-    }
-
-  if (!g_strcmp0 (action, "Suspend"))
-    {
-      gint seconds = 0;
-      ret = dbus_g_proxy_call (proxy, action, &error_local,
-                               G_TYPE_INT, seconds,
-                               G_TYPE_INVALID,
-                               G_TYPE_INT, &return_code,
-                               G_TYPE_INVALID);
-    }
-  else
-    {
-      ret = dbus_g_proxy_call (proxy, action, &error_local,
-                               G_TYPE_INVALID,
-                               G_TYPE_INT, &return_code,
-                               G_TYPE_INVALID);
-    }
-
-  g_object_unref (proxy);
-
-  if (!ret)
-    {
-      /* A D-Bus timeout? */
-      if (g_error_matches (error_local, DBUS_GERROR, DBUS_GERROR_NO_REPLY))
-        {
-          g_error_free (error_local);
-          return TRUE;
-        }
-      else
-        {
-          g_set_error (error, 1, 0, "%s", error_local->message);
-          g_error_free (error_local);
-          return FALSE;
-        }
-    }
-
-  return TRUE;
-}
-#endif /*ENABLE_HAL*/
-
-/**
- * xfsm_shutdown_helper_sudo_send:
- *
- *
- **/
-static gboolean
-xfsm_shutdown_helper_sudo_send (XfsmShutdownHelper *helper,
-                                const gchar *action,
-                                GError **error)
-{
-  gchar  response[256];
-
-  fprintf (helper->outfile, "%s\n", action);
-  fflush (helper->outfile);
-
-  g_message (G_STRLOC ": Using sudo to %s", action);
-
-  if (ferror (helper->outfile))
-    {
-      if (errno == EINTR)
-        {
-          /* probably succeeded but the helper got killed */
-          return TRUE;
-        }
-
-      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
-                   _("Error sending command to shutdown helper: %s"),
-                   strerror (errno));
-      return FALSE;
-    }
-
-  if (fgets (response, 256, helper->infile) == NULL)
-    {
-      if (errno == EINTR)
-        {
-          /* probably succeeded but the helper got killed */
-          return TRUE;
-        }
-
-      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
-                   _("Error receiving response from shutdown helper: %s"),
-                   strerror (errno));
-
-      return FALSE;
-    }
-
-  if (strncmp (response, "SUCCEED", 7) != 0)
-    {
-      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
-                   _("Shutdown command failed"));
-
-      return FALSE;
-    }
-  return TRUE;
-}
-
-/**
- * xfsm_shutdown_helper_new:
- *
- **/
-XfsmShutdownHelper *
-xfsm_shutdown_helper_new (void)
-{
-  XfsmShutdownHelper *xfsm_shutdown_helper = NULL;
-
-  xfsm_shutdown_helper = g_object_new (XFSM_TYPE_SHUTDOWN_HELPER, NULL);
-
-  return xfsm_shutdown_helper;
-}
-
-/**
- * xfsm_shutdown_helper_send_password:
- *
- * Send password to sudo
- *
- **/
-gboolean xfsm_shutdown_helper_send_password (XfsmShutdownHelper *helper, const gchar *password)
-{
-  gssize result;
-  gchar  buffer[1024];
-  gsize  failed;
-  gsize  length;
-  gsize  bytes;
-  gint   fd;
-
-  g_return_val_if_fail (password != NULL, FALSE);
-  g_return_val_if_fail (helper->shutdown_backend == XFSM_SHUTDOWN_BACKEND_SUDO, FALSE);
-  g_return_val_if_fail (helper->require_password, FALSE);
-
-  g_snprintf (buffer, 1024, "%s\n", password);
-  length = strlen (buffer);
-  bytes = fwrite (buffer, 1, length, helper->outfile);
-  fflush (helper->outfile);
-  bzero (buffer, length);
-
-  if (bytes != length)
-    {
-      fprintf (stderr, "Failed to write password (bytes=%lu, length=%lu)\n", (long)bytes, (long)length);
-      return FALSE;
-    }
-
-  if (ferror (helper->outfile))
-    {
-      fprintf (stderr, "Pipe error\n");
-      return FALSE;
-    }
-
-  fd = fileno (helper->infile);
-
-  for (failed = length = 0;;)
-    {
-      result = read (fd, buffer + length, 256 - length);
-
-      if (result < 0)
-        {
-          perror ("read");
-          return FALSE;
-        }
-      else if (result == 0)
-        {
-          if (++failed > 20)
-            return FALSE;
-          continue;
-        }
-      else if (result + length >= 1024)
-        {
-          fprintf (stderr, "Too much output from sudo!\n");
-          return FALSE;
-        }
-
-      length += result;
-      buffer[length] = 0;
-
-      if (length >= 15)
-        {
-          if (strncmp (buffer + (length - 15), "XFSM_SUDO_PASS ", 15) == 0)
-            {
-              return FALSE;
-            }
-          else if (strncmp (buffer + (length - 15), "XFSM_SUDO_DONE ", 15) == 0)
-            {
-              helper->require_password = FALSE;
-              break;
-            }
-        }
-    }
-
-  return TRUE;
-}
-
-/**
- * xfsm_shutdown_helper_shutdown:
- *
- *
- **/
-gboolean xfsm_shutdown_helper_shutdown (XfsmShutdownHelper *helper, GError **error)
-{
-  g_return_val_if_fail (!error || !*error, FALSE);
-
-#ifdef ENABLE_CONSOLE_KIT
-  if ( helper->shutdown_backend == XFSM_SHUTDOWN_BACKEND_CONSOLE_KIT )
-    {
-      return xfsm_shutdown_helper_console_kit_shutdown (helper, "Stop", error);
-    }
-#endif
-
-#ifdef ENABLE_HAL
-  if ( helper->shutdown_backend == XFSM_SHUTDOWN_BACKEND_HAL )
-    {
-      return xfsm_shutdown_helper_hal_send (helper, "Shutdown", error);
-    }
-#endif
-
-  /*Use Sudo mode*/
-  return xfsm_shutdown_helper_sudo_send (helper, "POWEROFF", error);
-
-}
-
-/**
- * xfsm_shutdown_helper_restart:
- *
- *
- **/
-gboolean xfsm_shutdown_helper_restart (XfsmShutdownHelper *helper, GError **error)
-{
-  g_return_val_if_fail (!error || !*error, FALSE);
-
-#ifdef ENABLE_CONSOLE_KIT
-  if ( helper->shutdown_backend == XFSM_SHUTDOWN_BACKEND_CONSOLE_KIT )
-    {
-      return xfsm_shutdown_helper_console_kit_shutdown (helper, "Restart", error);
-    }
-#endif
-
-#ifdef ENABLE_HAL
-  if ( helper->shutdown_backend == XFSM_SHUTDOWN_BACKEND_HAL )
-    {
-      return xfsm_shutdown_helper_hal_send (helper, "Reboot", error);
-    }
-#endif
-
-  return xfsm_shutdown_helper_sudo_send (helper, "REBOOT", error);
-
-}
-
-/**
- * xfsm_shutdown_helper_suspend:
- *
- **/
-gboolean xfsm_shutdown_helper_suspend (XfsmShutdownHelper *helper, GError **error)
-{
-  g_return_val_if_fail (!error || !*error, FALSE);
-
-#ifdef ENABLE_UPOWER
-  if ( helper->sleep_backend == XFSM_SLEEP_BACKEND_UPOWER )
-    {
-      return xfsm_shutdown_helper_upower_sleep (helper, "Suspend", error);
-    }
-#endif
-
-#ifdef ENABLE_HAL
-  if ( helper->sleep_backend == XFSM_SLEEP_BACKEND_HAL )
-    {
-      return xfsm_shutdown_helper_hal_send (helper, "Suspend", error);
-    }
-#endif
-
-  g_set_error (error, 1, 0, "%s", _("Suspend failed, no backend supported"));
-
-  return FALSE;
-}
-
-/**
- * xfsm_shutdown_helper_hibernate:
- *
- **/
-gboolean xfsm_shutdown_helper_hibernate (XfsmShutdownHelper *helper, GError **error)
-{
-  g_return_val_if_fail (!error || !*error, FALSE);
-
-#ifdef ENABLE_UPOWER
-  if ( helper->sleep_backend == XFSM_SLEEP_BACKEND_UPOWER )
-    {
-      return xfsm_shutdown_helper_upower_sleep (helper, "Hibernate", error);
-    }
-#endif
-
-#ifdef ENABLE_HAL
-  if ( helper->sleep_backend == XFSM_SLEEP_BACKEND_HAL )
-    {
-      return xfsm_shutdown_helper_hal_send (helper, "Hibernate", error);
-    }
-#endif
-
-  g_set_error (error, 1, 0, "%s", _("Hibernate failed, no backend supported"));
-
-  return FALSE;
-}
-
-/**
- * xfsm_shutdown_helper_send_command:
- *
- **/
-gboolean xfsm_shutdown_helper_send_command (XfsmShutdownHelper *helper,
-                                            XfsmShutdownType shutdown_type,
-                                            GError **error)
-{
-  g_return_val_if_fail (!error || !*error, FALSE);
-
-  switch (shutdown_type)
-    {
-    case XFSM_SHUTDOWN_HALT:
-      return xfsm_shutdown_helper_shutdown (helper, error);
-    case XFSM_SHUTDOWN_REBOOT:
-      return xfsm_shutdown_helper_restart (helper, error);
-    case XFSM_SHUTDOWN_HIBERNATE:
-      return xfsm_shutdown_helper_hibernate (helper, error);
-    case XFSM_SHUTDOWN_SUSPEND:
-      return xfsm_shutdown_helper_suspend (helper, error);
-    default:
-      g_warn_if_reached ();
-      break;
-    }
-
-  g_set_error (error, 1, 0, "%s", _("Shutdown Command not found"));
-
-  return FALSE;
-}
diff --git a/xfce4-session/xfsm-shutdown-helper.h b/xfce4-session/xfsm-shutdown-helper.h
deleted file mode 100644
index 4bacbe8..0000000
--- a/xfce4-session/xfsm-shutdown-helper.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* $Id$ */
-/*-
- * Copyright (c) 2003-2006 Benedikt Meurer <benny at xfce.org>
- * Copyright (c) 2010      Ali Abdallah    <aliov at xfce.org>
- * All rights reserved.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA.
- */
-
-#ifndef __XFSM_SHUTDOWN_HELPER_H
-#define __XFSM_SHUTDOWN_HELPER_H
-
-#include <glib-object.h>
-#include <xfce4-session/xfsm-global.h>
-
-G_BEGIN_DECLS
-
-#define XFSM_TYPE_SHUTDOWN_HELPER        (xfsm_shutdown_helper_get_type () )
-#define XFSM_SHUTDOWN_HELPER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), XFSM_TYPE_SHUTDOWN_HELPER, XfsmShutdownHelper))
-#define XFSM_IS_SHUTDOWN_HELPER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), XFSM_TYPE_SHUTDOWN_HELPER))
-
-typedef struct _XfsmShutdownHelperClass XfsmShutdownHelperClass;
-typedef struct _XfsmShutdownHelper      XfsmShutdownHelper;
-
-GType                     xfsm_shutdown_helper_get_type        (void) G_GNUC_CONST;
-
-XfsmShutdownHelper       *xfsm_shutdown_helper_new             (void);
-
-gboolean                  xfsm_shutdown_helper_send_password   (XfsmShutdownHelper *helper,
-								const gchar *password);
-
-gboolean                  xfsm_shutdown_helper_shutdown        (XfsmShutdownHelper *helper,
-								GError **error);
-
-gboolean                  xfsm_shutdown_helper_restart         (XfsmShutdownHelper *helper,
-								GError **error);
-
-gboolean                  xfsm_shutdown_helper_suspend         (XfsmShutdownHelper *helper,
-								GError **error);
-
-gboolean                  xfsm_shutdown_helper_hibernate       (XfsmShutdownHelper *helper,
-								GError **error);
-
-gboolean                  xfsm_shutdown_helper_send_command    (XfsmShutdownHelper *helper,
-								XfsmShutdownType shutdown_type,
-								GError **error);
-
-
-G_END_DECLS
-
-#endif /* __XFSM_SHUTDOWN_HELPER_H */
diff --git a/xfce4-session/xfsm-shutdown.c b/xfce4-session/xfsm-shutdown.c
index 9246c01..2436dcd 100644
--- a/xfce4-session/xfsm-shutdown.c
+++ b/xfce4-session/xfsm-shutdown.c
@@ -1,6 +1,6 @@
-/* $Id$ */
 /*-
  * Copyright (c) 2003-2004 Benedikt Meurer <benny at xfce.org>
+ * Copyright (c) 2011      Nick Schermer <nick at xfce.org>
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -36,7 +36,19 @@
 #ifdef HAVE_STRING_H
 #include <string.h>
 #endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
 
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
 #include <libxfce4util/libxfce4util.h>
 #include <gtk/gtk.h>
 
@@ -48,60 +60,682 @@
 #include <xfce4-session/xfsm-fadeout.h>
 #include <xfce4-session/xfsm-global.h>
 #include <xfce4-session/xfsm-legacy.h>
-#include <xfce4-session/xfsm-shutdown-helper.h>
+#include <xfce4-session/xfsm-consolekit.h>
+
+
+
+static void xfsm_shutdown_finalize  (GObject      *object);
+static void xfsm_shutdown_sudo_free (XfsmShutdown *shutdown);
+
+
+
+struct _XfsmShutdownClass
+{
+  GObjectClass __parent__;
+};
+
+typedef enum
+{
+  SUDO_NOT_INITIAZED,
+  SUDO_AVAILABLE,
+  SUDO_FAILED
+}
+HelperState;
+
+struct _XfsmShutdown
+{
+  GObject __parent__;
+
+  XfsmConsolekit *consolekit;
+
+  /* sudo helper */
+  HelperState     helper_state;
+  pid_t           helper_pid;
+  FILE           *helper_infile;
+  FILE           *helper_outfile;
+  guint           helper_watchid;
+  gboolean        helper_require_password;
+};
+
+
+
+G_DEFINE_TYPE (XfsmShutdown, xfsm_shutdown, G_TYPE_OBJECT)
+
+
+
+static void
+xfsm_shutdown_class_init (XfsmShutdownClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = xfsm_shutdown_finalize;
+}
+
+
+
+static void
+xfsm_shutdown_init (XfsmShutdown *shutdown)
+{
+  shutdown->consolekit = xfsm_consolekit_get ();
+  shutdown->helper_state = SUDO_NOT_INITIAZED;
+  shutdown->helper_require_password = FALSE;
+}
+
+
+
+static void
+xfsm_shutdown_finalize (GObject *object)
+{
+  XfsmShutdown *shutdown = XFSM_SHUTDOWN (object);
+
+  g_object_unref (G_OBJECT (shutdown->consolekit));
+
+  /* close down helper */
+  xfsm_shutdown_sudo_free (shutdown);
+
+  (*G_OBJECT_CLASS (xfsm_shutdown_parent_class)->finalize) (object);
+}
+
+
+
+static void
+xfsm_shutdown_sudo_free (XfsmShutdown *shutdown)
+{
+  gint status;
+
+  /* close down helper */
+  if (shutdown->helper_infile != NULL)
+    {
+      fclose (shutdown->helper_infile);
+      shutdown->helper_infile = NULL;
+    }
+
+  if (shutdown->helper_outfile != NULL)
+    {
+      fclose (shutdown->helper_outfile);
+      shutdown->helper_outfile = NULL;
+    }
+
+  if (shutdown->helper_watchid > 0)
+    {
+      g_source_remove (shutdown->helper_watchid);
+      shutdown->helper_watchid = 0;
+    }
+
+  if (shutdown->helper_pid > 0)
+    {
+      waitpid (shutdown->helper_pid, &status, 0);
+      shutdown->helper_pid = 0;
+    }
+
+  /* reset state */
+  shutdown->helper_state = SUDO_NOT_INITIAZED;
+}
+
+
+
+static void
+xfsm_shutdown_sudo_childwatch (GPid     pid,
+                               gint     status,
+                               gpointer data)
+{
+  /* close down sudo stuff */
+  xfsm_shutdown_sudo_free (XFSM_SHUTDOWN (data));
+}
+
+
+
+static gboolean
+xfsm_shutdown_sudo_init (XfsmShutdown  *shutdown,
+                         GError       **error)
+{
+  gchar  *cmd;
+  struct  rlimit rlp;
+  gchar   buf[15];
+  gint    parent_pipe[2];
+  gint    child_pipe[2];
+  gint    n;
+
+  /* return state if we succeeded */
+  if (shutdown->helper_state != SUDO_NOT_INITIAZED)
+    return shutdown->helper_state == SUDO_AVAILABLE;
+
+  g_return_val_if_fail (shutdown->helper_infile == NULL, FALSE);
+  g_return_val_if_fail (shutdown->helper_outfile == NULL, FALSE);
+  g_return_val_if_fail (shutdown->helper_watchid == 0, FALSE);
+  g_return_val_if_fail (shutdown->helper_pid == 0, FALSE);
+
+  /* assume it won't work for now */
+  shutdown->helper_state = SUDO_FAILED;
+
+  cmd = g_find_program_in_path ("sudo");
+  if (G_UNLIKELY (cmd == NULL))
+    {
+      g_set_error_literal (error, 1, 0,
+                           "The program \"sudo\" was not found");
+      return FALSE;
+    }
+
+  if (pipe (parent_pipe) == -1)
+    {
+      g_set_error (error, 1, 0,
+                   "Unable to create parent pipe: %s",
+                   strerror (errno));
+      goto err0;
+    }
+
+  if (pipe (child_pipe) == -1)
+    {
+      g_set_error (error, 1, 0,
+                   "Unable to create child pipe: %s",
+                   strerror (errno));
+      goto err1;
+    }
+
+  shutdown->helper_pid = fork ();
+  if (shutdown->helper_pid < 0)
+    {
+      g_set_error (error, 1, 0,
+                   "Unable to fork sudo helper: %s",
+                   strerror (errno));
+      goto err2;
+    }
+  else if (shutdown->helper_pid == 0)
+    {
+      /* setup signals */
+      signal (SIGPIPE, SIG_IGN);
+
+      /* setup environment */
+      xfce_setenv ("LC_ALL", "C", TRUE);
+      xfce_setenv ("LANG", "C", TRUE);
+      xfce_setenv ("LANGUAGE", "C", TRUE);
+
+      /* setup the 3 standard file handles */
+      dup2 (child_pipe[0], STDIN_FILENO);
+      dup2 (parent_pipe[1], STDOUT_FILENO);
+      dup2 (parent_pipe[1], STDERR_FILENO);
+
+      /* close all other file handles */
+      getrlimit (RLIMIT_NOFILE, &rlp);
+      for (n = 0; n < (gint) rlp.rlim_cur; ++n)
+        {
+          if (n != STDIN_FILENO && n != STDOUT_FILENO && n != STDERR_FILENO)
+            close (n);
+        }
+
+      /* execute sudo with the helper */
+      execl (cmd, "sudo", "-H", "-S", "-p",
+             "XFSM_SUDO_PASS ", "--",
+             XFSM_SHUTDOWN_HELPER_CMD, NULL);
+
+      g_free (cmd);
+      cmd = NULL;
+
+      _exit (127);
+    }
+  else
+    {
+      /* watch the sudo helper */
+      shutdown->helper_watchid = g_child_watch_add (shutdown->helper_pid,
+                                                    xfsm_shutdown_sudo_childwatch,
+                                                    shutdown);
+    }
+
+  /* read sudo/helper answer */
+  n = read (parent_pipe[0], buf, sizeof (buf));
+  if (n < 15)
+    {
+      g_set_error (error, 1, 0,
+                   "Unable to read response from sudo helper: %s",
+                   n < 0 ? strerror (errno) : "Unknown error");
+      goto err2;
+    }
+
+  /* open pipe to receive replies from sudo */
+  shutdown->helper_infile = fdopen (parent_pipe[0], "r");
+  if (shutdown->helper_infile == NULL)
+    {
+      g_set_error (error, 1, 0,
+                   "Unable to open parent pipe: %s",
+                   strerror (errno));
+      goto err2;
+    }
+  close (parent_pipe[1]);
+
+  /* open pipe to send passwords to sudo */
+  shutdown->helper_outfile = fdopen (child_pipe[1], "w");
+  if (shutdown->helper_outfile == NULL)
+    {
+      g_set_error (error, 1, 0,
+                   "Unable to open parent pipe: %s",
+                   strerror (errno));
+      goto err2;
+    }
+  close (child_pipe[0]);
+
+  /* check if NOPASSWD is set in /etc/sudoers */
+  if (memcmp (buf, "XFSM_SUDO_PASS ", 15) == 0)
+    {
+      shutdown->helper_require_password = TRUE;
+    }
+  else if (memcmp (buf, "XFSM_SUDO_DONE ", 15) == 0)
+    {
+      shutdown->helper_require_password = FALSE;
+    }
+  else
+    {
+      g_set_error (error, 1, 0,
+                   "Got unexpected reply from sudo shutdown helper");
+      goto err2;
+    }
+
+  /* if we try again */
+  shutdown->helper_state = SUDO_AVAILABLE;
+
+  return TRUE;
+
+err2:
+  xfsm_shutdown_sudo_free (shutdown);
+
+  close (child_pipe[0]);
+  close (child_pipe[1]);
+
+err1:
+  close (parent_pipe[0]);
+  close (parent_pipe[1]);
+
+err0:
+  g_free (cmd);
+
+  shutdown->helper_pid = 0;
+
+  return FALSE;
+}
+
+
+
+static gboolean
+xfsm_shutdown_sudo_try_action (XfsmShutdown      *shutdown,
+                               XfsmShutdownType   type,
+                               GError           **error)
+{
+  const gchar *action;
+  gchar        reply[256];
+
+  g_return_val_if_fail (shutdown->helper_state == SUDO_AVAILABLE, FALSE);
+  g_return_val_if_fail (shutdown->helper_outfile != NULL, FALSE);
+  g_return_val_if_fail (shutdown->helper_infile != NULL, FALSE);
+  g_return_val_if_fail (type == XFSM_SHUTDOWN_SHUTDOWN
+                        || type == XFSM_SHUTDOWN_RESTART, FALSE);
 
-gint
-xfsm_shutdown(XfsmShutdownType type)
+  /* the command we send to sudo */
+  if (type == XFSM_SHUTDOWN_SHUTDOWN)
+    action = "POWEROFF";
+  else if (type == XFSM_SHUTDOWN_RESTART)
+    action = "REBOOT";
+  else
+    return FALSE;
+
+  /* write action to sudo helper */
+  if (fprintf (shutdown->helper_outfile, "%s\n", action) > 0)
+    fflush (shutdown->helper_outfile);
+
+  /* check if the write succeeded */
+  if (ferror (shutdown->helper_outfile) != 0)
+    {
+      /* probably succeeded but the helper got killed */
+      if (errno == EINTR)
+        return TRUE;
+
+      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
+                   _("Error sending command to shutdown helper: %s"),
+                   strerror (errno));
+      return FALSE;
+    }
+
+  /* get responce from sudo helper */
+  if (fgets (reply, sizeof (reply), shutdown->helper_infile) == NULL)
+    {
+      /* probably succeeded but the helper got killed */
+      if (errno == EINTR)
+        return TRUE;
+
+      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
+                   _("Error receiving response from shutdown helper: %s"),
+                   strerror (errno));
+      return FALSE;
+    }
+
+  if (strncmp (reply, "SUCCEED", 7) != 0)
+    {
+      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                   _("Shutdown command failed"));
+
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+
+
+static XfsmPassState
+xfsm_shutdown_sudo_send_password (XfsmShutdown  *shutdown,
+                                  const gchar   *password)
 {
-  gboolean            result;
-  GError             *error = NULL;
-  XfsmShutdownHelper *shutdown_helper;
+  gchar        buf[1024];
+  gsize        len_buf, len_send;
+  gint         fd;
+  gsize        len;
+  gssize       result;
+  gint         attempts;
+  const gchar *errmsg = NULL;
+
+  g_return_val_if_fail (shutdown->helper_state == SUDO_AVAILABLE, PASSWORD_FAILED);
+  g_return_val_if_fail (shutdown->helper_outfile != NULL, PASSWORD_FAILED);
+  g_return_val_if_fail (shutdown->helper_infile != NULL, PASSWORD_FAILED);
+  g_return_val_if_fail (shutdown->helper_require_password, PASSWORD_FAILED);
+  g_return_val_if_fail (password != NULL, PASSWORD_FAILED);
+
+  /* write password to sudo helper */
+  g_snprintf (buf, sizeof (buf), "%s\n", password);
+  len_buf = strlen (buf);
+  len_send = fwrite (buf, 1, len_buf, shutdown->helper_outfile);
+  fflush (shutdown->helper_outfile);
+  bzero (buf, len_buf);
 
-  /* kludge */
-  if (type == XFSM_SHUTDOWN_ASK)
+  if (len_send != len_buf
+      || ferror (shutdown->helper_outfile) != 0)
     {
-      g_warning ("xfsm_shutdown () passed XFSM_SHUTDOWN_ASK.  This is a bug.");
-      type = XFSM_SHUTDOWN_LOGOUT;
+      errmsg = "Failed to send password to sudo";
+      goto err1;
     }
 
-  /* these two remember if they were started or not */
-  xfsm_compat_gnome_shutdown ();
-  xfsm_compat_kde_shutdown ();
+  fd = fileno (shutdown->helper_infile);
+
+  for (len = 0, attempts = 0;;)
+    {
+      result = read (fd, buf + len, 256 - len);
+
+      if (result < 0)
+        {
+          errmsg = "Failed to read data from sudo";
+          goto err1;
+        }
+      else if (result == 0)
+        {
+          /* don't try too often */
+          if (++attempts > 20)
+            {
+              errmsg = "Too many password attempts";
+              goto err1;
+            }
+
+          continue;
+        }
+      else if (result + len >= sizeof (buf))
+        {
+          errmsg = "Received too much data from sudo";
+          goto err1;
+        }
 
-  /* kill legacy clients */
-  xfsm_legacy_shutdown ();
+      len += result;
+      buf[len] = '\0';
+
+      if (len >= 15)
+        {
+          if (g_str_has_suffix (buf, "XFSM_SUDO_PASS "))
+            {
+              return PASSWORD_RETRY;
+            }
+          else if (g_str_has_suffix (buf, "XFSM_SUDO_DONE "))
+            {
+              /* sudo is unlocked, no further passwords required */
+              shutdown->helper_require_password = FALSE;
+
+              return PASSWORD_SUCCEED;
+            }
+        }
+    }
+
+  return PASSWORD_FAILED;
+
+  err1:
+
+  g_printerr (PACKAGE_NAME ": %s.\n\n", errmsg);
+  return PASSWORD_FAILED;
+}
 
-#if !defined(__NR_ioprio_set) && defined(HAVE_SYNC)
-  /* sync disk block in-core status with that on disk.  if
-   * we have ioprio_set (), then we've already synced. */
-  if (fork () == 0)
+
+
+static gboolean
+xfsm_shutdown_query_xfpm (XfsmShutdown  *shutdown,
+                          const gchar   *method,
+                          gboolean      *can_method,
+                          GError       **error)
+{
+  DBusGConnection *conn;
+  DBusGProxy      *proxy;
+  gboolean         result = FALSE;
+
+  g_return_val_if_fail (can_method != NULL, FALSE);
+
+  /* never return true if something fails */
+  *can_method = FALSE;
+
+  conn = dbus_g_bus_get (DBUS_BUS_SESSION, error);
+  if (conn == NULL)
+    return FALSE;
+
+  proxy = dbus_g_proxy_new_for_name_owner (conn, "org.xfce.Power.Manager",
+                                           "/org/xfce/PowerManager",
+                                           "org.xfce.Power.Manager", error);
+  if (proxy != NULL)
+    {
+      result = dbus_g_proxy_call (proxy, method, error,
+                                  G_TYPE_INVALID,
+                                  G_TYPE_BOOLEAN, can_method,
+                                  G_TYPE_INVALID);
+      g_object_unref (proxy);
+    }
+
+  dbus_g_connection_unref (conn);
+
+  return result;
+}
+
+
+
+XfsmShutdown *
+xfsm_shutdown_get (void)
+{
+  static XfsmShutdown *object = NULL;
+
+  if (G_LIKELY (object != NULL))
+    {
+      g_object_ref (G_OBJECT (object));
+    }
+  else
     {
-# ifdef HAVE_SETSID
-      setsid ();
-# endif
-      sync ();
-      _exit (EXIT_SUCCESS);
+      object = g_object_new (XFSM_TYPE_SHUTDOWN, NULL);
+      g_object_add_weak_pointer (G_OBJECT (object), (gpointer) &object);
     }
-#endif  /* HAVE_SYNC */
 
-  if (type == XFSM_SHUTDOWN_LOGOUT)
-    return EXIT_SUCCESS;
+  return object;
+}
+
+
+
+gboolean
+xfsm_shutdown_password_require (XfsmShutdown     *shutdown,
+                                XfsmShutdownType  type)
+{
+  g_return_val_if_fail (XFSM_IS_SHUTDOWN (shutdown), FALSE);
+
+  /* the helper only handled shutdown and restart */
+  if (type == XFSM_SHUTDOWN_SHUTDOWN || type == XFSM_SHUTDOWN_RESTART)
+    return shutdown->helper_require_password;
+
+  return FALSE;
+}
+
+
+
+XfsmPassState
+xfsm_shutdown_password_send (XfsmShutdown      *shutdown,
+                             XfsmShutdownType   type,
+                             const gchar       *password)
+{
+  g_return_val_if_fail (XFSM_IS_SHUTDOWN (shutdown), PASSWORD_FAILED);
+  g_return_val_if_fail (password != NULL, PASSWORD_FAILED);
+
+  if ((type == XFSM_SHUTDOWN_SHUTDOWN || type == XFSM_SHUTDOWN_RESTART)
+      && shutdown->helper_state == SUDO_AVAILABLE)
+    return xfsm_shutdown_sudo_send_password (shutdown, password);
+
+  return PASSWORD_FAILED;
+}
 
-  shutdown_helper = xfsm_shutdown_helper_new ();
-  result = xfsm_shutdown_helper_send_command (shutdown_helper, type, &error);
-  g_object_unref (shutdown_helper);
 
-  if (!result)
+
+gboolean
+xfsm_shutdown_try_type (XfsmShutdown      *shutdown,
+                        XfsmShutdownType   type,
+                        GError           **error)
+{
+  g_return_val_if_fail (XFSM_IS_SHUTDOWN (shutdown), FALSE);
+
+  switch (type)
     {
-      xfce_message_dialog (NULL, _("Shutdown Failed"),
-                           GTK_STOCK_DIALOG_ERROR,
-                           _("Unable to perform shutdown"),
-                           error->message,
-                           GTK_STOCK_QUIT, GTK_RESPONSE_ACCEPT,
-                           NULL);
-      g_error_free (error);
-      return EXIT_FAILURE;
+    case XFSM_SHUTDOWN_SHUTDOWN:
+      return xfsm_shutdown_try_shutdown (shutdown, error);
+
+    case XFSM_SHUTDOWN_RESTART:
+      return xfsm_shutdown_try_restart (shutdown, error);
+
+    case XFSM_SHUTDOWN_SUSPEND:
+      return xfsm_shutdown_try_suspend (shutdown, error);
+
+    case XFSM_SHUTDOWN_HIBERNATE:
+      return xfsm_shutdown_try_hibernate (shutdown, error);
+
+    default:
+      g_set_error (error, 1, 0, _("Unknown shutdown method %d"), type);
+      break;
     }
 
-  return EXIT_SUCCESS;
+  return FALSE;
+}
+
+
+
+gboolean
+xfsm_shutdown_try_restart (XfsmShutdown  *shutdown,
+                           GError       **error)
+{
+  g_return_val_if_fail (XFSM_IS_SHUTDOWN (shutdown), FALSE);
+
+  if (shutdown->helper_state == SUDO_AVAILABLE)
+    return xfsm_shutdown_sudo_try_action (shutdown, XFSM_SHUTDOWN_RESTART, error);
+  else
+    return xfsm_consolekit_try_restart (shutdown->consolekit, error);
+}
+
+
+
+gboolean
+xfsm_shutdown_try_shutdown (XfsmShutdown  *shutdown,
+                            GError       **error)
+{
+  g_return_val_if_fail (XFSM_IS_SHUTDOWN (shutdown), FALSE);
+
+  if (shutdown->helper_state == SUDO_AVAILABLE)
+    return xfsm_shutdown_sudo_try_action (shutdown, XFSM_SHUTDOWN_SHUTDOWN, error);
+  else
+    return xfsm_consolekit_try_shutdown (shutdown->consolekit, error);
+}
+
+
+
+gboolean
+xfsm_shutdown_try_suspend (XfsmShutdown  *shutdown,
+                           GError       **error)
+{
+  g_return_val_if_fail (XFSM_IS_SHUTDOWN (shutdown), FALSE);
+
+  return TRUE;
+}
+
+
+
+gboolean
+xfsm_shutdown_try_hibernate (XfsmShutdown  *shutdown,
+                             GError       **error)
+{
+  g_return_val_if_fail (XFSM_IS_SHUTDOWN (shutdown), FALSE);
+
+  return TRUE;
+}
+
+
+
+gboolean
+xfsm_shutdown_can_restart (XfsmShutdown  *shutdown,
+                           gboolean      *can_restart,
+                            GError       **error)
+{
+  g_return_val_if_fail (XFSM_IS_SHUTDOWN (shutdown), FALSE);
+
+  if (xfsm_consolekit_can_restart (shutdown->consolekit, can_restart, error))
+    return TRUE;
+
+  return xfsm_shutdown_sudo_init (shutdown, error);
+}
+
+
+
+gboolean
+xfsm_shutdown_can_shutdown (XfsmShutdown  *shutdown,
+                            gboolean      *can_shutdown,
+                            GError       **error)
+{
+  g_return_val_if_fail (XFSM_IS_SHUTDOWN (shutdown), FALSE);
+
+  if (xfsm_consolekit_can_shutdown (shutdown->consolekit, can_shutdown, error))
+    return TRUE;
+
+  return xfsm_shutdown_sudo_init (shutdown, error);
+}
+
+
+
+/* This function only queries the CanSuspend state of
+ * xfce4-power-manager. If this package is not installed,
+ * suspend is not supported. */
+gboolean
+xfsm_shutdown_can_suspend (XfsmShutdown  *shutdown,
+                           gboolean      *can_suspend,
+                           GError       **error)
+{
+  g_return_val_if_fail (XFSM_IS_SHUTDOWN (shutdown), FALSE);
+
+  return xfsm_shutdown_query_xfpm (shutdown, "CanSuspend",
+                                   can_suspend, error);
+}
+
+
+
+/* This function only queries the CanHibernate state of
+ * xfce4-power-manager. If this package is not installed,
+ * hibernation is not supported. */
+gboolean
+xfsm_shutdown_can_hibernate (XfsmShutdown  *shutdown,
+                             gboolean      *can_hibernate,
+                             GError       **error)
+{
+  g_return_val_if_fail (XFSM_IS_SHUTDOWN (shutdown), FALSE);
+
+  return xfsm_shutdown_query_xfpm (shutdown, "CanHibernate",
+                                   can_hibernate, error);
 }
diff --git a/xfce4-session/xfsm-shutdown.h b/xfce4-session/xfsm-shutdown.h
index 76d7145..2ec61f0 100644
--- a/xfce4-session/xfsm-shutdown.h
+++ b/xfce4-session/xfsm-shutdown.h
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2003-2004 Benedikt Meurer <benny at xfce.org>
+ * Copyright (c) 2011      Nick Schermer <nick at xfce.org>
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -21,8 +22,76 @@
 #ifndef __XFSM_SHUTDOWN_H__
 #define __XFSM_SHUTDOWN_H__
 
-#include <xfce4-session/xfsm-global.h>
+typedef struct _XfsmShutdownClass XfsmShutdownClass;
+typedef struct _XfsmShutdown      XfsmShutdown;
 
-gint	     xfsm_shutdown    (XfsmShutdownType type);
+#define XFSM_TYPE_SHUTDOWN            (xfsm_shutdown_get_type ())
+#define XFSM_SHUTDOWN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFSM_TYPE_SHUTDOWN, XfsmShutdown))
+#define XFSM_SHUTDOWN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFSM_TYPE_SHUTDOWN, XfsmShutdownClass))
+#define XFSM_IS_SHUTDOWN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFSM_TYPE_SHUTDOWN))
+#define XFSM_IS_SHUTDOWN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFSM_TYPE_SHUTDOWN))
+#define XFSM_SHUTDOWN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFSM_TYPE_SHUTDOWN, XfsmShutdownClass))
+
+typedef enum
+{
+  XFSM_SHUTDOWN_ASK = 0,
+  XFSM_SHUTDOWN_LOGOUT,
+  XFSM_SHUTDOWN_SHUTDOWN,
+  XFSM_SHUTDOWN_RESTART,
+  XFSM_SHUTDOWN_SUSPEND,
+  XFSM_SHUTDOWN_HIBERNATE,
+}
+XfsmShutdownType;
+
+typedef enum
+{
+  PASSWORD_RETRY,
+  PASSWORD_SUCCEED,
+  PASSWORD_FAILED
+}
+XfsmPassState;
+
+GType         xfsm_shutdown_get_type         (void) G_GNUC_CONST;
+
+XfsmShutdown *xfsm_shutdown_get              (void);
+
+gboolean      xfsm_shutdown_password_require (XfsmShutdown      *shutdown,
+                                              XfsmShutdownType   type);
+
+XfsmPassState xfsm_shutdown_password_send    (XfsmShutdown      *shutdown,
+                                              XfsmShutdownType   type,
+                                              const gchar       *password);
+
+gboolean      xfsm_shutdown_try_type         (XfsmShutdown      *shutdown,
+                                              XfsmShutdownType   type,
+                                              GError           **error);
+
+gboolean      xfsm_shutdown_try_restart      (XfsmShutdown      *shutdown,
+                                              GError           **error);
+
+gboolean      xfsm_shutdown_try_shutdown     (XfsmShutdown      *shutdown,
+                                              GError           **error);
+
+gboolean      xfsm_shutdown_try_suspend      (XfsmShutdown      *shutdown,
+                                              GError           **error);
+
+gboolean      xfsm_shutdown_try_hibernate    (XfsmShutdown      *shutdown,
+                                              GError           **error);
+
+gboolean      xfsm_shutdown_can_restart      (XfsmShutdown      *shutdown,
+                                              gboolean          *can_restart,
+                                              GError           **error);
+
+gboolean      xfsm_shutdown_can_shutdown     (XfsmShutdown      *shutdown,
+                                              gboolean          *can_shutdown,
+                                              GError           **error);
+
+gboolean      xfsm_shutdown_can_suspend      (XfsmShutdown      *shutdown,
+                                              gboolean          *can_suspend,
+                                              GError           **error);
+
+gboolean      xfsm_shutdown_can_hibernate    (XfsmShutdown      *shutdown,
+                                              gboolean          *can_hibernate,
+                                              GError           **error);
 
 #endif	/* !__XFSM_SHUTDOWN_H__ */


More information about the Xfce4-commits mailing list