[gtk+/portal: 13/17] Support the Inhibit portal



commit 89439232add5aaa7390402240d08bcab67c5d5ea
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Jul 1 21:19:12 2016 -0400

    Support the Inhibit portal
    
    xdg-desktop-portal now has a portal for inhibiting session status
    changes. We don't need to use it if we can talk to the session
    manager, but if can't, try org.freedesktop.portal.Inhibit.

 gtk/gtkapplication-dbus.c   |  177 ++++++++++++++++++++++++++++++++++---------
 gtk/gtkapplicationprivate.h |    4 +
 2 files changed, 144 insertions(+), 37 deletions(-)
---
diff --git a/gtk/gtkapplication-dbus.c b/gtk/gtkapplication-dbus.c
index 128c000..844dd03 100644
--- a/gtk/gtkapplication-dbus.c
+++ b/gtk/gtkapplication-dbus.c
@@ -190,7 +190,6 @@ gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
       g_warning ("Failed to get the GNOME session proxy: %s", error->message);
       g_clear_error (&error);
       g_clear_object (&dbus->sm_proxy);
-      goto out;
     }
 
   if (!dbus->sm_proxy)
@@ -228,7 +227,7 @@ gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
   if (error)
     {
       g_warning ("Failed to register client: %s", error->message);
-      g_error_free (error);
+      g_clear_error (&error);
       g_clear_object (&dbus->sm_proxy);
       goto out;
     }
@@ -238,7 +237,6 @@ gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
 
   g_debug ("Registered client at '%s'", dbus->client_path);
 
-  /* Try the GNOME client interface */
   if (g_str_equal (g_dbus_proxy_get_name (dbus->sm_proxy), GNOME_DBUS_NAME))
     {
       bus_name = GNOME_DBUS_NAME;
@@ -259,8 +257,11 @@ gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
                                               &error);
   if (error)
     {
-      g_warning ("Failed to connect to the GNOME client proxy: %s", error->message);
+      g_warning ("Failed to get client proxy: %s", error->message);
       g_clear_error (&error);
+      g_clear_object (&dbus->client_proxy);
+      g_free (dbus->client_path);
+      dbus->client_path = NULL;
       goto out;
     }
 
@@ -313,6 +314,23 @@ gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
                   "gtk-shell-shows-app-menu", FALSE,
                   "gtk-shell-shows-menubar", FALSE,
                   NULL);
+
+  if (dbus->sm_proxy == NULL)
+    {
+      dbus->inhibit_proxy = g_dbus_proxy_new_sync (dbus->session,
+                                                   G_DBUS_PROXY_FLAGS_NONE,
+                                                   NULL,
+                                                   "org.freedesktop.portal.Desktop",
+                                                   "/org/freedesktop/portal/desktop",
+                                                   "org.freedesktop.portal.Inhibit",
+                                                   NULL,
+                                                   &error);
+      if (error)
+        {
+          g_warning ("Failed to get an inhibit portal proxy: %s", error->message);
+          g_clear_error (&error);
+        }
+    }
 }
 
 static void
@@ -438,6 +456,22 @@ gtk_application_impl_dbus_get_window_system_id (GtkApplicationImplDBus *dbus,
   return GTK_APPLICATION_IMPL_DBUS_GET_CLASS (dbus)->get_window_system_id (dbus, window);
 }
 
+static int next_cookie;
+
+typedef struct {
+  char *handle;
+  int cookie;
+} InhibitHandle;
+
+static void
+inhibit_handle_free (gpointer data)
+{
+  InhibitHandle *handle = data;
+
+  g_free (handle->handle);
+  g_free (handle);
+}
+
 static guint
 gtk_application_impl_dbus_inhibit (GtkApplicationImpl         *impl,
                                    GtkWindow                  *window,
@@ -450,37 +484,80 @@ gtk_application_impl_dbus_inhibit (GtkApplicationImpl         *impl,
   guint cookie;
   static gboolean warned = FALSE;
 
-  if (dbus->sm_proxy == NULL)
-    return 0;
-
-  res = g_dbus_proxy_call_sync (dbus->sm_proxy,
-                                "Inhibit",
-                                g_variant_new ("(s@usu)",
-                                               dbus->application_id,
-                                               window ? gtk_application_impl_dbus_get_window_system_id 
(dbus, window) : g_variant_new_uint32 (0),
-                                               reason,
-                                               flags),
-                                G_DBUS_CALL_FLAGS_NONE,
-                                G_MAXINT,
-                                NULL,
-                                &error);
-
- if (error)
+  if (dbus->sm_proxy)
     {
-      if (!warned)
+      res = g_dbus_proxy_call_sync (dbus->sm_proxy,
+                                    "Inhibit",
+                                    g_variant_new ("(s@usu)",
+                                                   dbus->application_id,
+                                                   window ? gtk_application_impl_dbus_get_window_system_id 
(dbus, window) : g_variant_new_uint32 (0),
+                                                   reason,
+                                                   flags),
+                                    G_DBUS_CALL_FLAGS_NONE,
+                                    G_MAXINT,
+                                    NULL,
+                                    &error);
+
+      if (res)
         {
-          g_warning ("Calling Inhibit failed: %s", error->message);
-          warned = TRUE;
+          g_variant_get (res, "(u)", &cookie);
+          g_variant_unref (res);
+          return cookie;
+        }
+
+      if (error)
+        {
+          if (!warned)
+            {
+              g_warning ("Calling org.gnome.SessionManager.Inhibit failed: %s", error->message);
+              warned = TRUE;
+            }
+          g_clear_error (&error);
         }
-      g_error_free (error);
-      return 0;
     }
+  else if (dbus->inhibit_proxy)
+    {
+      GVariantBuilder options;
+
+      g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT);
+      g_variant_builder_add (&options, "{sv}", "reason", g_variant_new_string (reason));
+      res = g_dbus_proxy_call_sync (dbus->inhibit_proxy,
+                                    "Inhibit",
+                                    g_variant_new ("(su@a{sv})",
+                                                   "", /* window */
+                                                   flags,
+                                                   g_variant_builder_end (&options)),
+                                    G_DBUS_CALL_FLAGS_NONE,
+                                    G_MAXINT,
+                                    NULL,
+                                    &error);
+      if (res)
+        {
+          InhibitHandle *handle;
 
-  g_variant_get (res, "(u)", &cookie);
-  g_variant_unref (res);
+          handle = g_new (InhibitHandle, 1);
+          handle->cookie = ++next_cookie;
 
-  return cookie;
+          g_variant_get (res, "(o)", &handle->handle);
+          g_variant_unref (res);
+
+          dbus->inhibit_handles = g_slist_prepend (dbus->inhibit_handles, handle);
+
+          return handle->cookie;
+        }
+
+      if (error)
+        {
+          if (!warned)
+            {
+              g_warning ("Calling org.freedesktop.portal.Inhibit.Inhibit failed: %s", error->message);
+              warned = TRUE;
+            }
+          g_clear_error (&error);
+        }
+    }
 
+  return 0;
 }
 
 static void
@@ -489,16 +566,40 @@ gtk_application_impl_dbus_uninhibit (GtkApplicationImpl *impl,
 {
   GtkApplicationImplDBus *dbus = (GtkApplicationImplDBus *) impl;
 
-  /* Application could only obtain a cookie through a session
-   * manager proxy, so it's valid to assert its presence here. */
-  g_return_if_fail (dbus->sm_proxy != NULL);
+  if (dbus->sm_proxy)
+    {
+      g_dbus_proxy_call (dbus->sm_proxy,
+                         "Uninhibit",
+                         g_variant_new ("(u)", cookie),
+                         G_DBUS_CALL_FLAGS_NONE,
+                         G_MAXINT,
+                         NULL, NULL, NULL);
+    }
+  else if (dbus->inhibit_proxy)
+    {
+      GSList *l;
 
-  g_dbus_proxy_call (dbus->sm_proxy,
-                     "Uninhibit",
-                     g_variant_new ("(u)", cookie),
-                     G_DBUS_CALL_FLAGS_NONE,
-                     G_MAXINT,
-                     NULL, NULL, NULL);
+      for (l = dbus->inhibit_handles; l; l = l->next)
+        {
+          InhibitHandle *handle = l->data;
+          if (handle->cookie == cookie)
+            {
+              g_dbus_connection_call (dbus->session,
+                                      "org.freedesktop.portal.Desktop",
+                                      handle->handle,
+                                      "org.freedesktop.portal.Request",
+                                      "Close",
+                                      g_variant_new ("()"),
+                                      G_VARIANT_TYPE_UNIT,
+                                      G_DBUS_CALL_FLAGS_NONE,
+                                      G_MAXINT,
+                                      NULL, NULL, NULL);
+              dbus->inhibit_handles = g_slist_remove (dbus->inhibit_handles, handle);
+              inhibit_handle_free (handle);
+              break;
+            }
+        }
+    }
 }
 
 static gboolean
@@ -580,6 +681,8 @@ gtk_application_impl_dbus_finalize (GObject *object)
 {
   GtkApplicationImplDBus *dbus = (GtkApplicationImplDBus *) object;
 
+  g_object_unref (dbus->inhibit_proxy);
+  g_slist_free_full (dbus->inhibit_handles, inhibit_handle_free);
   g_free (dbus->app_menu_path);
   g_free (dbus->menubar_path);
 
diff --git a/gtk/gtkapplicationprivate.h b/gtk/gtkapplicationprivate.h
index f359d20..59eff02 100644
--- a/gtk/gtkapplicationprivate.h
+++ b/gtk/gtkapplicationprivate.h
@@ -129,6 +129,10 @@ typedef struct
   GDBusProxy      *sm_proxy;
   GDBusProxy      *client_proxy;
   gchar           *client_path;
+
+  /* Portal support */
+  GDBusProxy      *inhibit_proxy;
+  GSList *inhibit_handles;
 } GtkApplicationImplDBus;
 
 typedef struct


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