[gnome-session] Add system inhibitors



commit 3cc2619f53fb13a8ea2a32405ab3ad9476725572
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Jul 7 20:58:56 2012 -0400

    Add system inhibitors
    
    When we get a suspend inhibitor, we pass it on to the GsmSystem
    implementation, which may try to inhibit suspending system-wide.
    This is only implemented for systemd.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=677265

 configure.ac                   |    2 +-
 gnome-session/gsm-consolekit.c |   15 +++++++
 gnome-session/gsm-manager.c    |   10 ++++
 gnome-session/gsm-system.c     |   15 +++++++
 gnome-session/gsm-system.h     |   14 ++++++
 gnome-session/gsm-systemd.c    |   92 +++++++++++++++++++++++++++++++++++++++-
 6 files changed, 145 insertions(+), 3 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index c39d772..4adf0e2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -81,7 +81,7 @@ AC_ARG_ENABLE([systemd],
               [enable_systemd=auto])
 
 PKG_CHECK_MODULES(SYSTEMD,
-                  [libsystemd-login >= 183 libsystemd-daemon],
+                  [gio-unix-2.0 libsystemd-login >= 183 libsystemd-daemon],
                   [have_systemd=yes], [have_systemd=no])
 
 AC_MSG_CHECKING([whether to use systemd])
diff --git a/gnome-session/gsm-consolekit.c b/gnome-session/gsm-consolekit.c
index d1cb945..4c0eca5 100644
--- a/gnome-session/gsm-consolekit.c
+++ b/gnome-session/gsm-consolekit.c
@@ -856,6 +856,19 @@ gsm_consolekit_hibernate (GsmSystem *system)
 }
 
 static void
+gsm_consolekit_add_inhibitor (GsmSystem        *system,
+                              const gchar      *id,
+                              GsmInhibitorFlag  flag)
+{
+}
+
+static void
+gsm_consolekit_remove_inhibitor (GsmSystem   *system,
+                                 const gchar *id)
+{
+}
+
+static void
 gsm_consolekit_system_init (GsmSystemInterface *iface)
 {
         iface->can_switch_user = gsm_consolekit_can_switch_user;
@@ -869,6 +882,8 @@ gsm_consolekit_system_init (GsmSystemInterface *iface)
         iface->hibernate = gsm_consolekit_hibernate;
         iface->set_session_idle = gsm_consolekit_set_session_idle;
         iface->is_login_session = gsm_consolekit_is_login_session;
+        iface->add_inhibitor = gsm_consolekit_add_inhibitor;
+        iface->remove_inhibitor = gsm_consolekit_remove_inhibitor;
 }
 
 GsmConsolekit *
diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c
index 14957f0..a222210 100644
--- a/gnome-session/gsm-manager.c
+++ b/gnome-session/gsm-manager.c
@@ -2472,7 +2472,14 @@ on_store_inhibitor_added (GsmStore   *store,
                           const char *id,
                           GsmManager *manager)
 {
+        GsmInhibitor *i;
+
         g_debug ("GsmManager: Inhibitor added: %s", id);
+
+        i = GSM_INHIBITOR (gsm_store_lookup (store, id));
+        gsm_system_add_inhibitor (manager->priv->system, id,
+                                  gsm_inhibitor_peek_flags (i));
+
         g_signal_emit (manager, signals [INHIBITOR_ADDED], 0, id);
         update_idle (manager);
 }
@@ -2483,6 +2490,9 @@ on_store_inhibitor_removed (GsmStore   *store,
                             GsmManager *manager)
 {
         g_debug ("GsmManager: Inhibitor removed: %s", id);
+
+        gsm_system_remove_inhibitor (manager->priv->system, id);
+
         g_signal_emit (manager, signals [INHIBITOR_REMOVED], 0, id);
         update_idle (manager);
 }
diff --git a/gnome-session/gsm-system.c b/gnome-session/gsm-system.c
index 9a522f0..259cc19 100644
--- a/gnome-session/gsm-system.c
+++ b/gnome-session/gsm-system.c
@@ -124,6 +124,21 @@ gsm_system_set_session_idle (GsmSystem *system,
         GSM_SYSTEM_GET_IFACE (system)->set_session_idle (system, is_idle);
 }
 
+void
+gsm_system_add_inhibitor (GsmSystem        *system,
+                          const gchar      *id,
+                          GsmInhibitorFlag  flag)
+{
+        GSM_SYSTEM_GET_IFACE (system)->add_inhibitor (system, id, flag);
+}
+
+void
+gsm_system_remove_inhibitor (GsmSystem   *system,
+                             const gchar *id)
+{
+        GSM_SYSTEM_GET_IFACE (system)->remove_inhibitor (system, id);
+}
+
 gboolean
 gsm_system_is_login_session (GsmSystem *system)
 {
diff --git a/gnome-session/gsm-system.h b/gnome-session/gsm-system.h
index e93505f..b284e16 100644
--- a/gnome-session/gsm-system.h
+++ b/gnome-session/gsm-system.h
@@ -27,6 +27,8 @@
 #include <glib.h>
 #include <glib-object.h>
 
+#include "gsm-inhibitor.h"
+
 G_BEGIN_DECLS
 
 #define GSM_TYPE_SYSTEM             (gsm_system_get_type ())
@@ -59,6 +61,11 @@ struct _GsmSystemInterface
         void     (* set_session_idle) (GsmSystem *system,
                                        gboolean   is_idle);
         gboolean (* is_login_session) (GsmSystem *system);
+        void     (* add_inhibitor)    (GsmSystem        *system,
+                                       const gchar      *id,
+                                       GsmInhibitorFlag  flags);
+        void     (* remove_inhibitor) (GsmSystem        *system,
+                                       const gchar      *id);
 };
 
 enum _GsmSystemError {
@@ -95,6 +102,13 @@ void       gsm_system_set_session_idle (GsmSystem *system,
 
 gboolean   gsm_system_is_login_session (GsmSystem *system);
 
+void       gsm_system_add_inhibitor    (GsmSystem        *system,
+                                        const gchar      *id,
+                                        GsmInhibitorFlag  flags);
+
+void       gsm_system_remove_inhibitor (GsmSystem        *system,
+                                        const gchar      *id);
+
 G_END_DECLS
 
 #endif /* __GSM_SYSTEM_H__ */
diff --git a/gnome-session/gsm-systemd.c b/gnome-session/gsm-systemd.c
index 3c83329..ed45f83 100644
--- a/gnome-session/gsm-systemd.c
+++ b/gnome-session/gsm-systemd.c
@@ -39,6 +39,7 @@
 #include <glib-object.h>
 #include <glib/gi18n.h>
 #include <gio/gio.h>
+#include <gio/gunixfdlist.h>
 
 #include "gsm-marshal.h"
 #include "gsm-system.h"
@@ -54,6 +55,9 @@ struct _GsmSystemdPrivate
         GDBusProxy      *sd_proxy;
         gchar           *session_id;
         gchar           *session_path;
+
+        GSList          *inhibitors;
+        gint             inhibit_fd;
 };
 
 static void gsm_systemd_system_init (GsmSystemInterface *iface);
@@ -72,6 +76,11 @@ gsm_systemd_finalize (GObject *object)
         g_free (systemd->priv->session_id);
         g_free (systemd->priv->session_path);
 
+        if (systemd->priv->inhibitors != NULL) {
+                g_slist_free_full (systemd->priv->inhibitors, g_free);
+                close (systemd->priv->inhibit_fd);
+        }
+
         G_OBJECT_CLASS (gsm_systemd_parent_class)->finalize (object);
 }
 
@@ -422,7 +431,6 @@ suspend_done (GObject      *source,
               gpointer      user_data)
 {
         GDBusProxy *proxy = G_DBUS_PROXY (source);
-        GsmSystemd *manager = user_data;
         GError *error = NULL;
         GVariant *res;
 
@@ -442,7 +450,6 @@ hibernate_done (GObject      *source,
               gpointer      user_data)
 {
         GDBusProxy *proxy = G_DBUS_PROXY (source);
-        GsmSystemd *manager = user_data;
         GError *error = NULL;
         GVariant *res;
 
@@ -487,6 +494,85 @@ gsm_systemd_hibernate (GsmSystem *system)
 }
 
 static void
+inhibit_done (GObject      *source,
+              GAsyncResult *result,
+              gpointer      user_data)
+{
+        GDBusProxy *proxy = G_DBUS_PROXY (source);
+        GsmSystemd *manager = GSM_SYSTEMD (user_data);
+        GError *error = NULL;
+        GVariant *res;
+        GUnixFDList *fd_list = NULL;
+        gint idx;
+
+        res = g_dbus_proxy_call_with_unix_fd_list_finish (proxy, &fd_list, result, &error);
+
+        if (!res) {
+                g_warning ("Unable to inhibit system: %s", error->message);
+                g_error_free (error);
+        } else {
+                g_variant_get (res, "(h)", &idx);
+                manager->priv->inhibit_fd = g_unix_fd_list_get (fd_list, idx, &error);
+                if (manager->priv->inhibit_fd == -1) {
+                        g_warning ("Failed to receive system inhibitor fd: %s", error->message);
+                        g_error_free (error);
+                }
+                g_debug ("System inhibitor fd is %d", manager->priv->inhibit_fd);
+                g_object_unref (fd_list);
+                g_variant_unref (res);
+        }
+}
+
+static void
+gsm_systemd_add_inhibitor (GsmSystem        *system,
+                           const gchar      *id,
+                           GsmInhibitorFlag  flag)
+{
+        GsmSystemd *manager = GSM_SYSTEMD (system);
+
+        if ((flag & GSM_INHIBITOR_FLAG_SUSPEND) == 0)
+                return;
+
+        if (manager->priv->inhibitors == NULL) {
+                g_debug ("Adding system inhibitor");
+                g_dbus_proxy_call_with_unix_fd_list (manager->priv->sd_proxy,
+                                                     "Inhibit",
+                                                     g_variant_new ("(ssss)",
+                                                                    "sleep:shutdown",
+                                                                    g_get_user_name (),
+                                                                    "user session inhibited",
+                                                                    "block"),
+                                                     0,
+                                                     G_MAXINT,
+                                                     NULL,
+                                                     NULL,
+                                                     inhibit_done,
+                                                     manager);
+        }
+        manager->priv->inhibitors = g_slist_prepend (manager->priv->inhibitors, g_strdup (id));
+}
+
+static void
+gsm_systemd_remove_inhibitor (GsmSystem   *system,
+                              const gchar *id)
+{
+        GsmSystemd *manager = GSM_SYSTEMD (system);
+        GSList *l;
+
+        l = g_slist_find_custom (manager->priv->inhibitors, id, (GCompareFunc)g_strcmp0);
+        if (l == NULL)
+                return;
+
+        g_free (l->data);
+        manager->priv->inhibitors = g_slist_delete_link (manager->priv->inhibitors, l);
+        if (manager->priv->inhibitors == NULL) {
+                        g_debug ("Dropping system inhibitor");
+                        close (manager->priv->inhibit_fd);
+                        manager->priv->inhibit_fd = -1;
+        }
+}
+
+static void
 gsm_systemd_system_init (GsmSystemInterface *iface)
 {
         iface->can_switch_user = gsm_systemd_can_switch_user;
@@ -500,6 +586,8 @@ gsm_systemd_system_init (GsmSystemInterface *iface)
         iface->hibernate = gsm_systemd_hibernate;
         iface->set_session_idle = gsm_systemd_set_session_idle;
         iface->is_login_session = gsm_systemd_is_login_session;
+        iface->add_inhibitor = gsm_systemd_add_inhibitor;
+        iface->remove_inhibitor = gsm_systemd_remove_inhibitor;
 }
 
 GsmSystemd *



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