[gtk/portal-session-state] Application: Support sandboxed session state changes



commit eadf40975ed0e4d9a602d08233f392f230858e78
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Jan 20 11:29:04 2019 -0500

    Application: Support sandboxed session state changes
    
    React to the session-state in StateChanged signals from
    the inhibit portal and call QueryEndResponse as appropriate.

 gtk/gtkapplication-dbus.c   | 39 ++++++++++++++++++++++++++++++++++++---
 gtk/gtkapplicationprivate.h |  1 +
 2 files changed, 37 insertions(+), 3 deletions(-)
---
diff --git a/gtk/gtkapplication-dbus.c b/gtk/gtkapplication-dbus.c
index 05af8f2ecc..62e601a4c6 100644
--- a/gtk/gtkapplication-dbus.c
+++ b/gtk/gtkapplication-dbus.c
@@ -191,6 +191,13 @@ screensaver_signal_session (GDBusProxy     *proxy,
   gtk_application_set_screensaver_active (application, active);
 }
 
+enum {
+  UNKNOWN   = 0,
+  RUNNING   = 1,
+  QUERY_END = 2,
+  ENDING    = 3
+};
+
 static void
 screensaver_signal_portal (GDBusConnection *connection,
                            const char       *sender_name,
@@ -200,16 +207,42 @@ screensaver_signal_portal (GDBusConnection *connection,
                            GVariant         *parameters,
                            gpointer          data)
 {
-  GtkApplication   *application = data;
+  GtkApplicationImplDBus *dbus = (GtkApplicationImplDBus *)impl;
+  GtkApplication *application = data;
   gboolean active;
   GVariant *state;
+  guint32 session_state = UNKNOWN;
 
   if (!g_str_equal (signal_name, "StateChanged"))
     return;
 
   g_variant_get (parameters, "(o@a{sv})", NULL, &state);
   g_variant_lookup (state, "screensaver-active", "b", &active);
-  gtk_application_set_screensaver_active (application, active);
+  gtk_application_set_screensaver_active (dbus->impl.application, active);
+
+  g_variant_lookup (state, "session-state", "u", &session_state);
+  if (session_state != dbus->session_state)
+    {
+      dbus->session_state = session_state;
+
+      /* Note that we'll only ever get here if we get a session-state,
+       * in which case, the interface is new enough to have QueryEndResponse.
+       */
+      if (session_state == ENDING)
+        {
+          g_application_quit (G_APPLICATION (application));
+        }
+      else if (session_state == QUERY_END)
+        {
+          g_dbus_proxy_call (dbus->inhibit_proxy,
+                             "QueryEndResponse",
+                             g_variant_new ("(o)", dbus->session_id),
+                             G_DBUS_CALL_FLAGS_NONE,
+                             G_MAXINT,
+                             NULL,
+                             NULL, NULL);
+        }
+    }
 }
 
 static void
@@ -453,7 +486,7 @@ gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
                                                   NULL,
                                                   G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
                                                   screensaver_signal_portal,
-                                                  impl->application,
+                                                  dbus,
                                                   NULL);
           g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
           g_variant_builder_add (&opt_builder, "{sv}",
diff --git a/gtk/gtkapplicationprivate.h b/gtk/gtkapplicationprivate.h
index cbea1973c6..01b674a709 100644
--- a/gtk/gtkapplicationprivate.h
+++ b/gtk/gtkapplicationprivate.h
@@ -139,6 +139,7 @@ typedef struct
   GSList *inhibit_handles;
   guint            state_changed_handler;
   char *           session_id;
+  guint            session_state;
 } GtkApplicationImplDBus;
 
 typedef struct


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