summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefano Karapetsas <[email protected]>2013-03-05 20:39:33 +0100
committerStefano Karapetsas <[email protected]>2013-03-05 20:39:33 +0100
commit31fdf9eb550e0f2e69fa1ba96a1d7d78b8d2e060 (patch)
tree832bb7dcfcbdbba34eaf2b66cbbb659a7c692c93
parent29e5cd2f28f6ddc253d393064c0b24130af0ee35 (diff)
downloadmate-session-manager-31fdf9eb550e0f2e69fa1ba96a1d7d78b8d2e060.tar.bz2
mate-session-manager-31fdf9eb550e0f2e69fa1ba96a1d7d78b8d2e060.tar.xz
Add initial systemd support
-rw-r--r--configure.ac26
-rw-r--r--mate-session/Makefile.am6
-rw-r--r--mate-session/gsm-logout-dialog.c60
-rw-r--r--mate-session/gsm-manager.c264
-rw-r--r--mate-session/gsm-systemd.c776
-rw-r--r--mate-session/gsm-systemd.h104
-rw-r--r--mate-session/main.c41
7 files changed, 1238 insertions, 39 deletions
diff --git a/configure.ac b/configure.ac
index d450884..26025e3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -104,6 +104,29 @@ dnl GSettings
dnl ====================================================================
GLIB_GSETTINGS
+
+dnl ====================================================================
+dnl Systemd
+dnl ====================================================================
+
+AC_ARG_WITH(systemd,
+ AS_HELP_STRING([--with-systemd],
+ [Add systemd support]),,
+ with_systemd=auto)
+
+use_systemd=no
+if test "x$with_systemd" != "xno" ; then
+ PKG_CHECK_MODULES(SYSTEMD, libsystemd-login libsystemd-daemon, use_systemd=yes, use_systemd=no)
+
+ if test "x$use_systemd" = "xyes"; then
+ AC_DEFINE(HAVE_SYSTEMD, 1, [systemd support])
+ AC_SUBST(SYSTEMD_CFLAGS)
+ AC_SUBST(SYSTEMD_LIBS)
+ fi
+fi
+AM_CONDITIONAL(HAVE_SYSTEMD, test "x$use_systemd" = "xyes")
+AC_SUBST(HAVE_SYSTEMD)
+
dnl ====================================================================
dnl X development libraries check
dnl ====================================================================
@@ -137,7 +160,7 @@ fi
AC_CHECK_LIB(Xau, XauFileName, [X_LIBS="$X_LIBS -lXau"],
[AC_MSG_ERROR([
-*** Can't find the Xauth library. It is needed to compile mate-session.])],
+*** Cant find the Xauth library. It is needed to compile mate-session.])],
$X_LIBS)
AC_SUBST(X_LIBS)
@@ -361,6 +384,7 @@ echo "
GTK+ version: ${with_gtk}
Default WM: ${with_default_wm}
+ Systemd support: ${use_systemd}
IPv6 support: ${have_full_ipv6}
Backtrace support: ${have_backtrace}
XRender support: ${have_xrender}
diff --git a/mate-session/Makefile.am b/mate-session/Makefile.am
index b2ddcbd..f37a0e2 100644
--- a/mate-session/Makefile.am
+++ b/mate-session/Makefile.am
@@ -5,7 +5,8 @@ noinst_PROGRAMS = \
test-inhibit
AM_CPPFLAGS = \
- $(MATE_SESSION_CFLAGS) \
+ $(MATE_SESSION_CFLAGS) \
+ $(SYSTEMD_CFLAGS) \
$(DISABLE_DEPRECATED_CFLAGS)
AM_CFLAGS = $(WARN_CFLAGS)
@@ -25,6 +26,8 @@ mate_session_SOURCES = \
gsm-marshal.c \
gsm-consolekit.c \
gsm-consolekit.h \
+ gsm-systemd.c \
+ gsm-systemd.h \
gsm-logout-dialog.h \
gsm-logout-dialog.c \
gsm-inhibit-dialog.h \
@@ -72,6 +75,7 @@ mate_session_LDADD = \
$(XTEST_LIBS) \
$(XEXT_LIBS) \
$(MATE_SESSION_LIBS) \
+ $(SYSTEMD_LIBS) \
$(EXECINFO_LIBS)
libgsmutil_la_SOURCES = \
diff --git a/mate-session/gsm-logout-dialog.c b/mate-session/gsm-logout-dialog.c
index ad40367..ba28105 100644
--- a/mate-session/gsm-logout-dialog.c
+++ b/mate-session/gsm-logout-dialog.c
@@ -30,6 +30,10 @@
#include <upower.h>
#include "gsm-logout-dialog.h"
+#ifdef HAVE_SYSTEMD
+#include "gsm-systemd.h"
+#include <systemd/sd-daemon.h>
+#endif
#include "gsm-consolekit.h"
#include "mdm.h"
@@ -51,6 +55,9 @@ struct _GsmLogoutDialogPrivate
GsmDialogLogoutType type;
UpClient *up_client;
+#ifdef HAVE_SYSTEMD
+ GsmSystemd *systemd;
+#endif
GsmConsolekit *consolekit;
int timeout;
@@ -144,6 +151,11 @@ gsm_logout_dialog_init (GsmLogoutDialog *logout_dialog)
logout_dialog->priv->up_client = up_client_new ();
+#ifdef HAVE_SYSTEMD
+ if (sd_booted() > 0)
+ logout_dialog->priv->systemd = gsm_get_systemd ();
+ else
+#endif
logout_dialog->priv->consolekit = gsm_get_consolekit ();
g_signal_connect (logout_dialog,
@@ -171,6 +183,13 @@ gsm_logout_dialog_destroy (GsmLogoutDialog *logout_dialog,
logout_dialog->priv->up_client = NULL;
}
+#ifdef HAVE_SYSTEMD
+ if (logout_dialog->priv->systemd) {
+ g_object_unref (logout_dialog->priv->systemd);
+ logout_dialog->priv->systemd = NULL;
+ }
+#endif
+
if (logout_dialog->priv->consolekit) {
g_object_unref (logout_dialog->priv->consolekit);
logout_dialog->priv->consolekit = NULL;
@@ -196,6 +215,11 @@ gsm_logout_supports_switch_user (GsmLogoutDialog *logout_dialog)
{
gboolean ret;
+#ifdef HAVE_SYSTEMD
+ if (sd_booted () > 0)
+ ret = gsm_systemd_can_switch_user (logout_dialog->priv->systemd);
+ else
+#endif
ret = gsm_consolekit_can_switch_user (logout_dialog->priv->consolekit);
return ret;
@@ -206,6 +230,11 @@ gsm_logout_supports_reboot (GsmLogoutDialog *logout_dialog)
{
gboolean ret;
+#ifdef HAVE_SYSTEMD
+ if (sd_booted () > 0)
+ ret = gsm_systemd_can_restart (logout_dialog->priv->systemd);
+ else
+#endif
ret = gsm_consolekit_can_restart (logout_dialog->priv->consolekit);
if (!ret) {
ret = mdm_supports_logout_action (MDM_LOGOUT_ACTION_REBOOT);
@@ -219,6 +248,11 @@ gsm_logout_supports_shutdown (GsmLogoutDialog *logout_dialog)
{
gboolean ret;
+#ifdef HAVE_SYSTEMD
+ if (sd_booted () > 0)
+ ret = gsm_systemd_can_stop (logout_dialog->priv->systemd);
+ else
+#endif
ret = gsm_consolekit_can_stop (logout_dialog->priv->consolekit);
if (!ret) {
@@ -242,6 +276,7 @@ gsm_logout_dialog_timeout (gpointer data)
char *secondary_text;
int seconds_to_show;
static char *session_type = NULL;
+ static gboolean is_not_login;
logout_dialog = (GsmLogoutDialog *) data;
@@ -283,14 +318,27 @@ gsm_logout_dialog_timeout (gpointer data)
}
if (session_type == NULL) {
- GsmConsolekit *consolekit;
-
+#ifdef HAVE_SYSTEMD
+ if (sd_booted () > 0) {
+ GsmSystemd *systemd;
+ systemd = gsm_get_systemd ();
+ session_type = gsm_systemd_get_current_session_type (systemd);
+ g_object_unref (systemd);
+ is_not_login = (g_strcmp0 (session_type, GSM_SYSTEMD_SESSION_TYPE_LOGIN_WINDOW) != 0);
+ }
+ else {
+#endif
+ GsmConsolekit *consolekit;
consolekit = gsm_get_consolekit ();
session_type = gsm_consolekit_get_current_session_type (consolekit);
g_object_unref (consolekit);
+ is_not_login = (g_strcmp0 (session_type, GSM_CONSOLEKIT_SESSION_TYPE_LOGIN_WINDOW) != 0);
+#ifdef HAVE_SYSTEMD
+ }
+#endif
}
- if (g_strcmp0 (session_type, GSM_CONSOLEKIT_SESSION_TYPE_LOGIN_WINDOW) != 0) {
+ if (is_not_login) {
char *name, *tmp;
name = g_locale_to_utf8 (g_get_real_name (), -1, NULL, NULL, NULL);
@@ -308,9 +356,9 @@ gsm_logout_dialog_timeout (gpointer data)
g_free (tmp);
g_free (name);
- } else {
- secondary_text = g_strdup (seconds_warning);
- }
+ } else {
+ secondary_text = g_strdup (seconds_warning);
+ }
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (logout_dialog),
secondary_text,
diff --git a/mate-session/gsm-manager.c b/mate-session/gsm-manager.c
index ad4ed89..b817fb2 100644
--- a/mate-session/gsm-manager.c
+++ b/mate-session/gsm-manager.c
@@ -60,6 +60,10 @@
#include "gsm-logout-dialog.h"
#include "gsm-inhibit-dialog.h"
#include "gsm-consolekit.h"
+#ifdef HAVE_SYSTEMD
+#include "gsm-systemd.h"
+#include <systemd/sd-daemon.h>
+#endif
#include "gsm-session-save.h"
#define GSM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_MANAGER, GsmManagerPrivate))
@@ -391,9 +395,9 @@ phase_num_to_name (guint phase)
static void start_phase (GsmManager *manager);
static void
-quit_request_completed (GsmConsolekit *consolekit,
- GError *error,
- gpointer user_data)
+quit_request_completed_consolekit (GsmConsolekit *consolekit,
+ GError *error,
+ gpointer user_data)
{
MdmLogoutAction fallback_action = GPOINTER_TO_INT (user_data);
@@ -406,10 +410,31 @@ quit_request_completed (GsmConsolekit *consolekit,
gtk_main_quit ();
}
+#ifdef HAVE_SYSTEMD
+static void
+quit_request_completed_systemd (GsmSystemd *systemd,
+ GError *error,
+ gpointer user_data)
+{
+ MdmLogoutAction fallback_action = GPOINTER_TO_INT (user_data);
+
+ if (error != NULL) {
+ mdm_set_logout_action (fallback_action);
+ }
+
+ g_object_unref (systemd);
+
+ gtk_main_quit ();
+}
+#endif
+
static void
gsm_manager_quit (GsmManager *manager)
{
GsmConsolekit *consolekit;
+#ifdef HAVE_SYSTEMD
+ GsmSystemd *systemd;
+#endif
/* See the comment in request_reboot() for some more details about how
* this works. */
@@ -422,12 +447,26 @@ gsm_manager_quit (GsmManager *manager)
case GSM_MANAGER_LOGOUT_REBOOT_INTERACT:
mdm_set_logout_action (MDM_LOGOUT_ACTION_NONE);
+ #ifdef HAVE_SYSTEMD
+ if (sd_booted () > 0) {
+ systemd = gsm_get_systemd ();
+ g_signal_connect (systemd,
+ "request-completed",
+ G_CALLBACK (quit_request_completed_systemd),
+ GINT_TO_POINTER (MDM_LOGOUT_ACTION_REBOOT));
+ gsm_systemd_attempt_restart (systemd);
+ }
+ else {
+ #endif
consolekit = gsm_get_consolekit ();
g_signal_connect (consolekit,
"request-completed",
- G_CALLBACK (quit_request_completed),
+ G_CALLBACK (quit_request_completed_consolekit),
GINT_TO_POINTER (MDM_LOGOUT_ACTION_REBOOT));
gsm_consolekit_attempt_restart (consolekit);
+ #ifdef HAVE_SYSTEMD
+ }
+ #endif
break;
case GSM_MANAGER_LOGOUT_REBOOT_MDM:
mdm_set_logout_action (MDM_LOGOUT_ACTION_REBOOT);
@@ -437,12 +476,26 @@ gsm_manager_quit (GsmManager *manager)
case GSM_MANAGER_LOGOUT_SHUTDOWN_INTERACT:
mdm_set_logout_action (MDM_LOGOUT_ACTION_NONE);
+ #ifdef HAVE_SYSTEMD
+ if (sd_booted () > 0) {
+ systemd = gsm_get_systemd ();
+ g_signal_connect (systemd,
+ "request-completed",
+ G_CALLBACK (quit_request_completed_systemd),
+ GINT_TO_POINTER (MDM_LOGOUT_ACTION_SHUTDOWN));
+ gsm_systemd_attempt_stop (systemd);
+ }
+ else {
+ #endif
consolekit = gsm_get_consolekit ();
g_signal_connect (consolekit,
"request-completed",
- G_CALLBACK (quit_request_completed),
+ G_CALLBACK (quit_request_completed_consolekit),
GINT_TO_POINTER (MDM_LOGOUT_ACTION_SHUTDOWN));
gsm_consolekit_attempt_stop (consolekit);
+ #ifdef HAVE_SYSTEMD
+ }
+ #endif
break;
case GSM_MANAGER_LOGOUT_SHUTDOWN_MDM:
mdm_set_logout_action (MDM_LOGOUT_ACTION_SHUTDOWN);
@@ -1822,16 +1875,33 @@ auto_save_is_enabled (GsmManager *manager)
static void
maybe_save_session (GsmManager *manager)
{
- GsmConsolekit *consolekit;
+ GsmConsolekit *consolekit = NULL;
+#ifdef HAVE_SYSTEMD
+ GsmSystemd *systemd = NULL;
+#endif
char *session_type;
GError *error;
+#ifdef HAVE_SYSTEMD
+ if (sd_booted () > 0) {
+ systemd = gsm_get_systemd ();
+ session_type = gsm_systemd_get_current_session_type (systemd);
+
+ if (g_strcmp0 (session_type, GSM_SYSTEMD_SESSION_TYPE_LOGIN_WINDOW) == 0) {
+ goto out;
+ }
+ }
+ else {
+#endif
consolekit = gsm_get_consolekit ();
session_type = gsm_consolekit_get_current_session_type (consolekit);
if (g_strcmp0 (session_type, GSM_CONSOLEKIT_SESSION_TYPE_LOGIN_WINDOW) == 0) {
goto out;
}
+#ifdef HAVE_SYSTEMD
+ }
+#endif
/* We only allow session saving when session is running or when
* logging out */
@@ -1849,7 +1919,12 @@ maybe_save_session (GsmManager *manager)
}
out:
- g_object_unref (consolekit);
+ if (consolekit != NULL)
+ g_object_unref (consolekit);
+#ifdef HAVE_SYSTEMD
+ if (systemd != NULL)
+ g_object_unref (systemd);
+#endif
g_free (session_type);
}
@@ -2335,11 +2410,24 @@ on_presence_status_changed (GsmPresence *presence,
guint status,
GsmManager *manager)
{
+#ifdef HAVE_SYSTEMD
+ if (sd_booted () > 0) {
+ GsmSystemd *systemd;
+
+ systemd = gsm_get_systemd ();
+ gsm_systemd_set_session_idle (systemd,
+ (status == GSM_PRESENCE_STATUS_IDLE));
+ }
+ else {
+#endif
GsmConsolekit *consolekit;
consolekit = gsm_get_consolekit ();
gsm_consolekit_set_session_idle (consolekit,
(status == GSM_PRESENCE_STATUS_IDLE));
+#ifdef HAVE_SYSTEMD
+ }
+#endif
}
static void
@@ -2520,17 +2608,17 @@ gsm_manager_is_suspend_inhibited (GsmManager *manager)
}
static void
-request_reboot_privileges_completed (GsmConsolekit *consolekit,
- gboolean success,
- gboolean ask_later,
- GError *error,
- GsmManager *manager)
+request_reboot_privileges_completed_consolekit (GsmConsolekit *consolekit,
+ gboolean success,
+ gboolean ask_later,
+ GError *error,
+ GsmManager *manager)
{
/* make sure we disconnect the signal handler so that it's not called
* again next time the event is fired -- this can happen if the reboot
* is cancelled. */
g_signal_handlers_disconnect_by_func (consolekit,
- request_reboot_privileges_completed,
+ request_reboot_privileges_completed_consolekit,
manager);
g_object_unref (consolekit);
@@ -2546,10 +2634,42 @@ request_reboot_privileges_completed (GsmConsolekit *consolekit,
}
}
+#ifdef HAVE_SYSTEMD
+static void
+request_reboot_privileges_completed_systemd (GsmSystemd *systemd,
+ gboolean success,
+ gboolean ask_later,
+ GError *error,
+ GsmManager *manager)
+{
+ /* make sure we disconnect the signal handler so that it's not called
+ * again next time the event is fired -- this can happen if the reboot
+ * is cancelled. */
+ g_signal_handlers_disconnect_by_func (systemd,
+ request_reboot_privileges_completed_systemd,
+ manager);
+
+ g_object_unref (systemd);
+
+ if (success) {
+ if (ask_later) {
+ manager->priv->logout_type = GSM_MANAGER_LOGOUT_REBOOT_INTERACT;
+ } else {
+ manager->priv->logout_type = GSM_MANAGER_LOGOUT_REBOOT;
+ }
+
+ end_phase (manager);
+ }
+}
+#endif
+
static void
request_reboot (GsmManager *manager)
{
GsmConsolekit *consolekit;
+#ifdef HAVE_SYSTEMD
+ GsmSystemd *systemd;
+#endif
gboolean success;
g_debug ("GsmManager: requesting reboot");
@@ -2557,6 +2677,7 @@ request_reboot (GsmManager *manager)
/* We request the privileges before doing anything. There are a few
* different cases here:
*
+ * - no systemd: we fallback on ConsoleKit
* - no ConsoleKit: we fallback on MDM
* - no password required: everything is fine
* - password asked once: we ask for it now. If the user enters it
@@ -2575,36 +2696,60 @@ request_reboot (GsmManager *manager)
* just work fine.
*/
+#ifdef HAVE_SYSTEMD
+ if (sd_booted () > 0) {
+ systemd = gsm_get_systemd ();
+ g_signal_connect (systemd,
+ "privileges-completed",
+ G_CALLBACK (request_reboot_privileges_completed_systemd),
+ manager);
+ success = gsm_systemd_get_restart_privileges (systemd);
+
+ if (!success) {
+ g_signal_handlers_disconnect_by_func (systemd,
+ request_reboot_privileges_completed_systemd,
+ manager);
+ g_object_unref (systemd);
+
+ manager->priv->logout_type = GSM_MANAGER_LOGOUT_REBOOT_MDM;
+ end_phase (manager);
+ }
+ }
+ else {
+#endif
consolekit = gsm_get_consolekit ();
g_signal_connect (consolekit,
"privileges-completed",
- G_CALLBACK (request_reboot_privileges_completed),
+ G_CALLBACK (request_reboot_privileges_completed_consolekit),
manager);
success = gsm_consolekit_get_restart_privileges (consolekit);
if (!success) {
g_signal_handlers_disconnect_by_func (consolekit,
- request_reboot_privileges_completed,
+ request_reboot_privileges_completed_consolekit,
manager);
g_object_unref (consolekit);
manager->priv->logout_type = GSM_MANAGER_LOGOUT_REBOOT_MDM;
end_phase (manager);
}
+#ifdef HAVE_SYSTEMD
+ }
+#endif
}
static void
-request_shutdown_privileges_completed (GsmConsolekit *consolekit,
- gboolean success,
- gboolean ask_later,
- GError *error,
- GsmManager *manager)
+request_shutdown_privileges_completed_consolekit (GsmConsolekit *consolekit,
+ gboolean success,
+ gboolean ask_later,
+ GError *error,
+ GsmManager *manager)
{
/* make sure we disconnect the signal handler so that it's not called
* again next time the event is fired -- this can happen if the reboot
* is cancelled. */
g_signal_handlers_disconnect_by_func (consolekit,
- request_shutdown_privileges_completed,
+ request_shutdown_privileges_completed_consolekit,
manager);
g_object_unref (consolekit);
@@ -2620,10 +2765,42 @@ request_shutdown_privileges_completed (GsmConsolekit *consolekit,
}
}
+#ifdef HAVE_SYSTEMD
+static void
+request_shutdown_privileges_completed_systemd (GsmSystemd *systemd,
+ gboolean success,
+ gboolean ask_later,
+ GError *error,
+ GsmManager *manager)
+{
+ /* make sure we disconnect the signal handler so that it's not called
+ * again next time the event is fired -- this can happen if the reboot
+ * is cancelled. */
+ g_signal_handlers_disconnect_by_func (systemd,
+ request_shutdown_privileges_completed_systemd,
+ manager);
+
+ g_object_unref (systemd);
+
+ if (success) {
+ if (ask_later) {
+ manager->priv->logout_type = GSM_MANAGER_LOGOUT_SHUTDOWN_INTERACT;
+ } else {
+ manager->priv->logout_type = GSM_MANAGER_LOGOUT_SHUTDOWN;
+ }
+
+ end_phase (manager);
+ }
+}
+#endif
+
static void
request_shutdown (GsmManager *manager)
{
GsmConsolekit *consolekit;
+#ifdef HAVE_SYSTEMD
+ GsmSystemd *systemd;
+#endif
gboolean success;
g_debug ("GsmManager: requesting shutdown");
@@ -2631,22 +2808,46 @@ request_shutdown (GsmManager *manager)
/* See the comment in request_reboot() for some more details about how
* this works. */
+#ifdef HAVE_SYSTEMD
+ if (sd_booted () > 0) {
+ systemd = gsm_get_systemd ();
+ g_signal_connect (systemd,
+ "privileges-completed",
+ G_CALLBACK (request_shutdown_privileges_completed_systemd),
+ manager);
+ success = gsm_systemd_get_stop_privileges (systemd);
+
+ if (!success) {
+ g_signal_handlers_disconnect_by_func (systemd,
+ request_shutdown_privileges_completed_systemd,
+ manager);
+ g_object_unref (systemd);
+
+ manager->priv->logout_type = GSM_MANAGER_LOGOUT_SHUTDOWN_MDM;
+ end_phase (manager);
+ }
+ }
+ else {
+#endif
consolekit = gsm_get_consolekit ();
g_signal_connect (consolekit,
"privileges-completed",
- G_CALLBACK (request_shutdown_privileges_completed),
+ G_CALLBACK (request_shutdown_privileges_completed_consolekit),
manager);
success = gsm_consolekit_get_stop_privileges (consolekit);
if (!success) {
g_signal_handlers_disconnect_by_func (consolekit,
- request_shutdown_privileges_completed,
+ request_shutdown_privileges_completed_consolekit,
manager);
g_object_unref (consolekit);
manager->priv->logout_type = GSM_MANAGER_LOGOUT_SHUTDOWN_MDM;
end_phase (manager);
}
+#ifdef HAVE_SYSTEMD
+ }
+#endif
}
static void
@@ -2938,6 +3139,9 @@ gsm_manager_can_shutdown (GsmManager *manager,
GError **error)
{
GsmConsolekit *consolekit;
+#ifdef HAVE_SYSTEMD
+ GsmSystemd *systemd;
+#endif
gboolean can_suspend;
gboolean can_hibernate;
@@ -2950,12 +3154,26 @@ gsm_manager_can_shutdown (GsmManager *manager,
g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE);
+#ifdef HAVE_SYSTEMD
+ if (sd_booted () > 0) {
+ systemd = gsm_get_systemd ();
+ *shutdown_available = gsm_systemd_can_stop (systemd)
+ || gsm_systemd_can_restart (systemd)
+ || can_suspend
+ || can_hibernate;
+ g_object_unref (systemd);
+ }
+ else {
+#endif
consolekit = gsm_get_consolekit ();
*shutdown_available = gsm_consolekit_can_stop (consolekit)
|| gsm_consolekit_can_restart (consolekit)
|| can_suspend
|| can_hibernate;
g_object_unref (consolekit);
+#ifdef HAVE_SYSTEMD
+ }
+#endif
return TRUE;
}
diff --git a/mate-session/gsm-systemd.c b/mate-session/gsm-systemd.c
new file mode 100644
index 0000000..050d931
--- /dev/null
+++ b/mate-session/gsm-systemd.c
@@ -0,0 +1,776 @@
+/*
+ * Copyright (C) 2013 Stefano Karapetsas <[email protected]>
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#ifdef HAVE_SYSTEMD
+#include <systemd/sd-login.h>
+#endif
+
+#include "gsm-marshal.h"
+#include "gsm-systemd.h"
+
+#define SD_NAME "org.freedesktop.login1"
+#define SD_PATH "/org/freedesktop/login1"
+#define SD_INTERFACE "org.freedesktop.login1.Manager"
+#define SD_SEAT_INTERFACE "org.freedesktop.login1.Seat"
+#define SD_SESSION_INTERFACE "org.freedesktop.login1.Session"
+
+#define GSM_SYSTEMD_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_SYSTEMD, GsmSystemdPrivate))
+
+struct _GsmSystemdPrivate
+{
+ DBusGConnection *dbus_connection;
+ DBusGProxy *bus_proxy;
+ DBusGProxy *sd_proxy;
+ guint32 is_connected : 1;
+};
+
+enum {
+ PROP_0,
+ PROP_IS_CONNECTED
+};
+
+enum {
+ REQUEST_COMPLETED = 0,
+ PRIVILEGES_COMPLETED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void gsm_systemd_class_init (GsmSystemdClass *klass);
+static void gsm_systemd_init (GsmSystemd *sd);
+static void gsm_systemd_finalize (GObject *object);
+
+static void gsm_systemd_free_dbus (GsmSystemd *manager);
+
+static DBusHandlerResult gsm_systemd_dbus_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data);
+
+static void gsm_systemd_on_name_owner_changed (DBusGProxy *bus_proxy,
+ const char *name,
+ const char *prev_owner,
+ const char *new_owner,
+ GsmSystemd *manager);
+
+G_DEFINE_TYPE (GsmSystemd, gsm_systemd, G_TYPE_OBJECT);
+
+static void
+gsm_systemd_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsmSystemd *manager = GSM_SYSTEMD (object);
+
+ switch (prop_id) {
+ case PROP_IS_CONNECTED:
+ g_value_set_boolean (value,
+ manager->priv->is_connected);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+ prop_id,
+ pspec);
+ }
+}
+
+static void
+gsm_systemd_class_init (GsmSystemdClass *manager_class)
+{
+ GObjectClass *object_class;
+ GParamSpec *param_spec;
+
+ object_class = G_OBJECT_CLASS (manager_class);
+
+ object_class->finalize = gsm_systemd_finalize;
+ object_class->get_property = gsm_systemd_get_property;
+
+ param_spec = g_param_spec_boolean ("is-connected",
+ "Is connected",
+ "Whether the session is connected to Systemd",
+ FALSE,
+ G_PARAM_READABLE);
+
+ g_object_class_install_property (object_class, PROP_IS_CONNECTED,
+ param_spec);
+
+ signals [REQUEST_COMPLETED] =
+ g_signal_new ("request-completed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsmSystemdClass, request_completed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1, G_TYPE_POINTER);
+
+ signals [PRIVILEGES_COMPLETED] =
+ g_signal_new ("privileges-completed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsmSystemdClass, privileges_completed),
+ NULL,
+ NULL,
+ gsm_marshal_VOID__BOOLEAN_BOOLEAN_POINTER,
+ G_TYPE_NONE,
+ 3, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_POINTER);
+
+ g_type_class_add_private (manager_class, sizeof (GsmSystemdPrivate));
+}
+
+static DBusHandlerResult
+gsm_systemd_dbus_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GsmSystemd *manager;
+
+ manager = GSM_SYSTEMD (user_data);
+
+ if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_LOCAL, "Disconnected") &&
+ strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) {
+ gsm_systemd_free_dbus (manager);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static gboolean
+gsm_systemd_ensure_sd_connection (GsmSystemd *manager,
+ GError **error)
+{
+ GError *connection_error;
+ gboolean is_connected;
+
+ connection_error = NULL;
+
+ if (manager->priv->dbus_connection == NULL) {
+ DBusConnection *connection;
+
+ manager->priv->dbus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM,
+ &connection_error);
+
+ if (manager->priv->dbus_connection == NULL) {
+ g_propagate_error (error, connection_error);
+ is_connected = FALSE;
+ goto out;
+ }
+
+ connection = dbus_g_connection_get_connection (manager->priv->dbus_connection);
+ dbus_connection_set_exit_on_disconnect (connection, FALSE);
+ dbus_connection_add_filter (connection,
+ gsm_systemd_dbus_filter,
+ manager, NULL);
+ }
+
+ if (manager->priv->bus_proxy == NULL) {
+ manager->priv->bus_proxy =
+ dbus_g_proxy_new_for_name_owner (manager->priv->dbus_connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ &connection_error);
+
+ if (manager->priv->bus_proxy == NULL) {
+ g_propagate_error (error, connection_error);
+ is_connected = FALSE;
+ goto out;
+ }
+
+ dbus_g_proxy_add_signal (manager->priv->bus_proxy,
+ "NameOwnerChanged",
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_INVALID);
+
+ dbus_g_proxy_connect_signal (manager->priv->bus_proxy,
+ "NameOwnerChanged",
+ G_CALLBACK (gsm_systemd_on_name_owner_changed),
+ manager, NULL);
+ }
+
+ if (manager->priv->sd_proxy == NULL) {
+ manager->priv->sd_proxy =
+ dbus_g_proxy_new_for_name_owner (manager->priv->dbus_connection,
+ SD_NAME,
+ SD_PATH,
+ SD_INTERFACE,
+ &connection_error);
+
+ if (manager->priv->sd_proxy == NULL) {
+ g_propagate_error (error, connection_error);
+ is_connected = FALSE;
+ goto out;
+ }
+ }
+
+ is_connected = TRUE;
+
+out:
+ if (manager->priv->is_connected != is_connected) {
+ manager->priv->is_connected = is_connected;
+ g_object_notify (G_OBJECT (manager), "is-connected");
+ }
+
+ if (!is_connected) {
+ if (manager->priv->dbus_connection == NULL) {
+ if (manager->priv->bus_proxy != NULL) {
+ g_object_unref (manager->priv->bus_proxy);
+ manager->priv->bus_proxy = NULL;
+ }
+
+ if (manager->priv->sd_proxy != NULL) {
+ g_object_unref (manager->priv->sd_proxy);
+ manager->priv->sd_proxy = NULL;
+ }
+ } else if (manager->priv->bus_proxy == NULL) {
+ if (manager->priv->sd_proxy != NULL) {
+ g_object_unref (manager->priv->sd_proxy);
+ manager->priv->sd_proxy = NULL;
+ }
+ }
+ }
+
+ return is_connected;
+}
+
+static void
+gsm_systemd_on_name_owner_changed (DBusGProxy *bus_proxy,
+ const char *name,
+ const char *prev_owner,
+ const char *new_owner,
+ GsmSystemd *manager)
+{
+ if (name != NULL && g_strcmp0 (name, SD_NAME) != 0) {
+ return;
+ }
+
+ if (manager->priv->sd_proxy != NULL) {
+ g_object_unref (manager->priv->sd_proxy);
+ manager->priv->sd_proxy = NULL;
+ }
+
+ gsm_systemd_ensure_sd_connection (manager, NULL);
+}
+
+static void
+gsm_systemd_init (GsmSystemd *manager)
+{
+ GError *error;
+
+ manager->priv = GSM_SYSTEMD_GET_PRIVATE (manager);
+
+ error = NULL;
+
+ if (!gsm_systemd_ensure_sd_connection (manager, &error)) {
+ g_warning ("Could not connect to Systemd: %s",
+ error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+gsm_systemd_free_dbus (GsmSystemd *manager)
+{
+ if (manager->priv->bus_proxy != NULL) {
+ g_object_unref (manager->priv->bus_proxy);
+ manager->priv->bus_proxy = NULL;
+ }
+
+ if (manager->priv->sd_proxy != NULL) {
+ g_object_unref (manager->priv->sd_proxy);
+ manager->priv->sd_proxy = NULL;
+ }
+
+ if (manager->priv->dbus_connection != NULL) {
+ DBusConnection *connection;
+ connection = dbus_g_connection_get_connection (manager->priv->dbus_connection);
+ dbus_connection_remove_filter (connection,
+ gsm_systemd_dbus_filter,
+ manager);
+
+ dbus_g_connection_unref (manager->priv->dbus_connection);
+ manager->priv->dbus_connection = NULL;
+ }
+}
+
+static void
+gsm_systemd_finalize (GObject *object)
+{
+ GsmSystemd *manager;
+ GObjectClass *parent_class;
+
+ manager = GSM_SYSTEMD (object);
+
+ parent_class = G_OBJECT_CLASS (gsm_systemd_parent_class);
+
+ gsm_systemd_free_dbus (manager);
+
+ if (parent_class->finalize != NULL) {
+ parent_class->finalize (object);
+ }
+}
+
+GQuark
+gsm_systemd_error_quark (void)
+{
+ static GQuark error_quark = 0;
+
+ if (error_quark == 0) {
+ error_quark = g_quark_from_static_string ("gsm-systemd-error");
+ }
+
+ return error_quark;
+}
+
+GsmSystemd *
+gsm_systemd_new (void)
+{
+ GsmSystemd *manager;
+
+ manager = g_object_new (GSM_TYPE_SYSTEMD, NULL);
+
+ return manager;
+}
+
+static void
+emit_restart_complete (GsmSystemd *manager,
+ GError *error)
+{
+ GError *call_error;
+
+ call_error = NULL;
+
+ if (error != NULL) {
+ call_error = g_error_new_literal (GSM_SYSTEMD_ERROR,
+ GSM_SYSTEMD_ERROR_RESTARTING,
+ error->message);
+ }
+
+ g_signal_emit (G_OBJECT (manager),
+ signals [REQUEST_COMPLETED],
+ 0, call_error);
+
+ if (call_error != NULL) {
+ g_error_free (call_error);
+ }
+}
+
+static void
+emit_stop_complete (GsmSystemd *manager,
+ GError *error)
+{
+ GError *call_error;
+
+ call_error = NULL;
+
+ if (error != NULL) {
+ call_error = g_error_new_literal (GSM_SYSTEMD_ERROR,
+ GSM_SYSTEMD_ERROR_STOPPING,
+ error->message);
+ }
+
+ g_signal_emit (G_OBJECT (manager),
+ signals [REQUEST_COMPLETED],
+ 0, call_error);
+
+ if (call_error != NULL) {
+ g_error_free (call_error);
+ }
+}
+
+void
+gsm_systemd_attempt_restart (GsmSystemd *manager)
+{
+ gboolean res;
+ GError *error;
+
+ error = NULL;
+
+ if (!gsm_systemd_ensure_sd_connection (manager, &error)) {
+ g_warning ("Could not connect to Systemd: %s",
+ error->message);
+ emit_restart_complete (manager, error);
+ g_error_free (error);
+ return;
+ }
+
+ res = dbus_g_proxy_call_with_timeout (manager->priv->sd_proxy,
+ "Reboot",
+ INT_MAX,
+ &error,
+ G_TYPE_BOOLEAN, TRUE, /* interactive */
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+
+ if (!res) {
+ g_warning ("Unable to restart system: %s", error->message);
+ emit_restart_complete (manager, error);
+ g_error_free (error);
+ } else {
+ emit_restart_complete (manager, NULL);
+ }
+}
+
+void
+gsm_systemd_attempt_stop (GsmSystemd *manager)
+{
+ gboolean res;
+ GError *error;
+
+ error = NULL;
+
+ if (!gsm_systemd_ensure_sd_connection (manager, &error)) {
+ g_warning ("Could not connect to Systemd: %s",
+ error->message);
+ emit_stop_complete (manager, error);
+ g_error_free (error);
+ return;
+ }
+
+ res = dbus_g_proxy_call_with_timeout (manager->priv->sd_proxy,
+ "PowerOff",
+ INT_MAX,
+ &error,
+ G_TYPE_BOOLEAN, TRUE, /* interactive */
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+
+ if (!res) {
+ g_warning ("Unable to stop system: %s", error->message);
+ emit_stop_complete (manager, error);
+ g_error_free (error);
+ } else {
+ emit_stop_complete (manager, NULL);
+ }
+}
+
+static void
+gsm_systemd_get_session_path (DBusConnection *connection,
+ char **session_path)
+{
+ DBusError local_error;
+ DBusMessage *message;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ gchar *session_id = NULL;
+
+#ifdef HAVE_SYSTEMD
+ sd_pid_get_session (getpid (), &session_id);
+#endif
+
+ if (session_id == NULL)
+ return;
+
+ reply = NULL;
+
+ dbus_error_init (&local_error);
+ message = dbus_message_new_method_call (SD_NAME,
+ SD_PATH,
+ SD_INTERFACE,
+ "GetSession");
+ if (message == NULL) {
+ goto out;
+ }
+
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &session_id);
+
+ dbus_error_init (&local_error);
+ reply = dbus_connection_send_with_reply_and_block (connection,
+ message,
+ -1,
+ &local_error);
+ if (reply == NULL) {
+ if (dbus_error_is_set (&local_error)) {
+ g_warning ("Unable to get session path: %s", local_error.message);
+ dbus_error_free (&local_error);
+ goto out;
+ }
+ }
+
+ dbus_message_iter_init (reply, &iter);
+ dbus_message_iter_get_basic (&iter, session_path);
+
+out:
+ if (message != NULL) {
+ dbus_message_unref (message);
+ }
+ if (reply != NULL) {
+ dbus_message_unref (reply);
+ }
+ if (session_id != NULL) {
+ g_free (session_id);
+ }
+}
+
+
+void
+gsm_systemd_set_session_idle (GsmSystemd *manager,
+ gboolean is_idle)
+{
+ GError *error;
+ char *session_path;
+ DBusMessage *message;
+ DBusMessage *reply;
+ DBusError dbus_error;
+ DBusMessageIter iter;
+
+ error = NULL;
+
+ if (!gsm_systemd_ensure_sd_connection (manager, &error)) {
+ g_warning ("Could not connect to Systemd: %s",
+ error->message);
+ g_error_free (error);
+ return;
+ }
+
+ gsm_systemd_get_session_path (dbus_g_connection_get_connection (manager->priv->dbus_connection), &session_path);
+
+ g_debug ("Updating Systemd idle status: %d", is_idle);
+ message = dbus_message_new_method_call (SD_NAME,
+ session_path,
+ SD_SESSION_INTERFACE,
+ "SetIdleHint");
+ if (message == NULL) {
+ g_debug ("Couldn't allocate the D-Bus message");
+ return;
+ }
+
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &is_idle);
+
+ /* FIXME: use async? */
+ dbus_error_init (&dbus_error);
+ reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (manager->priv->dbus_connection),
+ message,
+ -1,
+ &dbus_error);
+ dbus_message_unref (message);
+
+ if (reply != NULL) {
+ dbus_message_unref (reply);
+ }
+
+ if (dbus_error_is_set (&dbus_error)) {
+ g_debug ("%s raised:\n %s\n\n", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ }
+
+ g_free (session_path);
+}
+
+gboolean
+gsm_systemd_can_switch_user (GsmSystemd *manager)
+{
+ GError *error;
+ char *session_id = NULL;
+ char *seat_id = NULL;
+ int ret = 0;
+
+ error = NULL;
+
+ if (!gsm_systemd_ensure_sd_connection (manager, &error)) {
+ g_warning ("Could not connect to Systemd: %s",
+ error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+#ifdef HAVE_SYSTEMD
+ sd_pid_get_session (getpid (), &session_id);
+#endif
+
+ if (session_id == NULL)
+ return FALSE;
+
+#ifdef HAVE_SYSTEMD
+ sd_session_get_seat (session_id, &seat_id);
+ ret = sd_seat_can_multi_session (seat_id);
+
+ g_free (session_id);
+ g_free (seat_id);
+#endif
+
+ return ret > 0;
+}
+
+gboolean
+gsm_systemd_get_restart_privileges (GsmSystemd *manager)
+{
+ g_signal_emit (G_OBJECT (manager),
+ signals [PRIVILEGES_COMPLETED],
+ 0, TRUE, TRUE, NULL);
+
+ return TRUE;
+}
+
+gboolean
+gsm_systemd_get_stop_privileges (GsmSystemd *manager)
+{
+ g_signal_emit (G_OBJECT (manager),
+ signals [PRIVILEGES_COMPLETED],
+ 0, TRUE, TRUE, NULL);
+
+ return TRUE;
+}
+
+gboolean
+gsm_systemd_can_restart (GsmSystemd *manager)
+{
+ gboolean res;
+ gchar *value;
+ gboolean can_restart;
+ GError *error;
+
+ error = NULL;
+
+ if (!gsm_systemd_ensure_sd_connection (manager, &error)) {
+ g_warning ("Could not connect to Systemd: %s",
+ error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ res = dbus_g_proxy_call_with_timeout (manager->priv->sd_proxy,
+ "CanReboot",
+ INT_MAX,
+ &error,
+ G_TYPE_INVALID,
+ G_TYPE_STRING, &value,
+ G_TYPE_INVALID);
+ if (res == FALSE) {
+ g_warning ("Could not make DBUS call: %s",
+ error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ can_restart = g_strcmp0 (value, "yes") == 0 ||
+ g_strcmp0 (value, "challenge") == 0;
+ g_free (value);
+ return can_restart;
+}
+
+gboolean
+gsm_systemd_can_stop (GsmSystemd *manager)
+{
+ gboolean res;
+ gchar *value;
+ gboolean can_stop;
+ GError *error;
+
+ error = NULL;
+
+ if (!gsm_systemd_ensure_sd_connection (manager, &error)) {
+ g_warning ("Could not connect to Systemd: %s",
+ error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ res = dbus_g_proxy_call_with_timeout (manager->priv->sd_proxy,
+ "CanPowerOff",
+ INT_MAX,
+ &error,
+ G_TYPE_INVALID,
+ G_TYPE_STRING, &value,
+ G_TYPE_INVALID);
+
+ if (res == FALSE) {
+ g_warning ("Could not make DBUS call: %s",
+ error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ can_stop = g_strcmp0 (value, "yes") == 0 ||
+ g_strcmp0 (value, "challenge") == 0;
+ g_free (value);
+ return can_stop;
+}
+
+gchar *
+gsm_systemd_get_current_session_type (GsmSystemd *manager)
+{
+ GError *gerror;
+ int session_id;
+ gchar *session_class = NULL;
+ int res;
+
+ gerror = NULL;
+
+ if (!gsm_systemd_ensure_sd_connection (manager, &gerror)) {
+ g_warning ("Could not connect to Systemd: %s",
+ gerror->message);
+ g_error_free (gerror);
+ return NULL;
+ }
+
+#ifdef HAVE_SYSTEMD
+ sd_pid_get_session (getpid (), &session_id);
+#endif
+
+ if (session_id == NULL)
+ return NULL;
+
+#ifdef HAVE_SYSTEMD
+ res = sd_session_get_class (session_id, &session_class);
+ if (res < 0) {
+ g_warning ("Could not get Systemd session class!");
+ return NULL;
+ }
+#endif
+
+ return session_class;
+}
+
+
+GsmSystemd *
+gsm_get_systemd (void)
+{
+ static GsmSystemd *manager = NULL;
+
+ if (manager == NULL) {
+ manager = gsm_systemd_new ();
+ }
+
+ return g_object_ref (manager);
+}
diff --git a/mate-session/gsm-systemd.h b/mate-session/gsm-systemd.h
new file mode 100644
index 0000000..ad38ac7
--- /dev/null
+++ b/mate-session/gsm-systemd.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2013 Stefano Karapetsas
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Authors:
+ * Stefano Karapetsas <[email protected]>
+ */
+
+#ifndef __GSM_SYSTEMD_H__
+#define __GSM_SYSTEMD_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSM_TYPE_SYSTEMD (gsm_systemd_get_type ())
+#define GSM_SYSTEMD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_SYSTEMD, GsmSystemd))
+#define GSM_SYSTEMD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_SYSTEMD, GsmSystemdClass))
+#define GSM_IS_SYSTEMD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_SYSTEMD))
+#define GSM_IS_SYSTEMD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_SYSTEMD))
+#define GSM_SYSTEMD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GSM_TYPE_SYSTEMD, GsmSystemdClass))
+#define GSM_SYSTEMD_ERROR (gsm_systemd_error_quark ())
+
+typedef struct _GsmSystemd GsmSystemd;
+typedef struct _GsmSystemdClass GsmSystemdClass;
+typedef struct _GsmSystemdPrivate GsmSystemdPrivate;
+typedef enum _GsmSystemdError GsmSystemdError;
+
+struct _GsmSystemd
+{
+ GObject parent;
+
+ GsmSystemdPrivate *priv;
+};
+
+struct _GsmSystemdClass
+{
+ GObjectClass parent_class;
+
+ void (* request_completed) (GsmSystemd *manager,
+ GError *error);
+
+ void (* privileges_completed) (GsmSystemd *manager,
+ gboolean success,
+ gboolean ask_later,
+ GError *error);
+};
+
+enum _GsmSystemdError {
+ GSM_SYSTEMD_ERROR_RESTARTING = 0,
+ GSM_SYSTEMD_ERROR_STOPPING
+};
+
+#define GSM_SYSTEMD_SESSION_TYPE_LOGIN_WINDOW "greeter"
+
+GType gsm_systemd_get_type (void);
+
+GQuark gsm_systemd_error_quark (void);
+
+GsmSystemd *gsm_systemd_new (void) G_GNUC_MALLOC;
+
+gboolean gsm_systemd_can_switch_user (GsmSystemd *manager);
+
+gboolean gsm_systemd_get_restart_privileges (GsmSystemd *manager);
+
+gboolean gsm_systemd_get_stop_privileges (GsmSystemd *manager);
+
+gboolean gsm_systemd_can_stop (GsmSystemd *manager);
+
+gboolean gsm_systemd_can_restart (GsmSystemd *manager);
+
+void gsm_systemd_attempt_stop (GsmSystemd *manager);
+
+void gsm_systemd_attempt_restart (GsmSystemd *manager);
+
+void gsm_systemd_set_session_idle (GsmSystemd *manager,
+ gboolean is_idle);
+
+gchar *gsm_systemd_get_current_session_type (GsmSystemd *manager);
+
+GsmSystemd *gsm_get_systemd (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSM_SYSTEMD_H__ */
diff --git a/mate-session/main.c b/mate-session/main.c
index 0a6259c..da2a687 100644
--- a/mate-session/main.c
+++ b/mate-session/main.c
@@ -42,6 +42,10 @@
#include "mdm-log.h"
#include "gsm-consolekit.h"
+#ifdef HAVE_SYSTEMD
+#include "gsm-systemd.h"
+#include <systemd/sd-daemon.h>
+#endif
#include "gsm-util.h"
#include "gsm-manager.h"
#include "gsm-xsmp-server.h"
@@ -259,26 +263,47 @@ static void append_required_apps(GsmManager* manager)
static void maybe_load_saved_session_apps(GsmManager* manager)
{
- GsmConsolekit* consolekit;
+ GsmConsolekit* consolekit = NULL;
+#ifdef HAVE_SYSTEMD
+ GsmSystemd* systemd = NULL;
+#endif
char* session_type;
+ gboolean is_login;
+#ifdef HAVE_SYSTEMD
+ if (sd_booted() > 0) {
+ systemd = gsm_get_systemd();
+ session_type = gsm_systemd_get_current_session_type(systemd);
+ is_login = g_strcmp0 (session_type, GSM_SYSTEMD_SESSION_TYPE_LOGIN_WINDOW) == 0;
+ }
+ else {
+#endif
consolekit = gsm_get_consolekit();
session_type = gsm_consolekit_get_current_session_type(consolekit);
+ is_login = g_strcmp0 (session_type, GSM_CONSOLEKIT_SESSION_TYPE_LOGIN_WINDOW) == 0;
+#ifdef HAVE_SYSTEMD
+ }
+#endif
- if (g_strcmp0 (session_type, GSM_CONSOLEKIT_SESSION_TYPE_LOGIN_WINDOW) != 0)
+ if (!is_login)
{
- GSettings* settings;
- gboolean autostart;
+ GSettings* settings;
+ gboolean autostart;
settings = g_settings_new (GSM_SCHEMA);
- autostart = g_settings_get_boolean (settings, KEY_AUTOSAVE);
- g_object_unref (settings);
+ autostart = g_settings_get_boolean (settings, KEY_AUTOSAVE);
+ g_object_unref (settings);
- if (autostart == TRUE)
+ if (autostart == TRUE)
gsm_manager_add_autostart_apps_from_dir(manager, gsm_util_get_saved_session_dir());
}
- g_object_unref(consolekit);
+ if (consolekit != NULL)
+ g_object_unref(consolekit);
+#ifdef HAVE_SYSTEMD
+ if (systemd != NULL)
+ g_object_unref(systemd);
+#endif
g_free(session_type);
}