Blob Blame History Raw
From c5020c3d303ab211a970d88638e7d723034688db Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 10 Jan 2019 10:47:19 -0500
Subject: [PATCH 3/9] backend: add signals for reporting suspend and resume

This commit adds "suspending" and "resuming" signals
to MetaBackend.

It's preliminary work needed for tracking when to purge
and recreate all textures (needed by nvidia).
---
 src/backends/meta-backend.c    | 98 ++++++++++++++++++++++++++++++----
 src/org.freedesktop.login1.xml |  1 +
 2 files changed, 88 insertions(+), 11 deletions(-)

diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c
index 5d71977c6..f59b899b7 100644
--- a/src/backends/meta-backend.c
+++ b/src/backends/meta-backend.c
@@ -53,6 +53,8 @@
 
 #include <stdlib.h>
 
+#include <gio/gunixfdlist.h>
+
 #include "backends/meta-cursor-tracker-private.h"
 #include "backends/meta-idle-monitor-private.h"
 #include "backends/meta-input-settings-private.h"
@@ -87,6 +89,8 @@ enum
   LAST_DEVICE_CHANGED,
   LID_IS_CLOSED_CHANGED,
 
+  SUSPENDING,
+  RESUMING,
   N_SIGNALS
 };
 
@@ -745,6 +749,20 @@ meta_backend_class_init (MetaBackendClass *klass)
                   0,
                   NULL, NULL, NULL,
                   G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+  signals[SUSPENDING] =
+    g_signal_new ("suspending",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+  signals[RESUMING] =
+    g_signal_new ("resuming",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
 
   mutter_stage_views = g_getenv ("MUTTER_STAGE_VIEWS");
   stage_views_disabled = g_strcmp0 (mutter_stage_views, "0") == 0;
@@ -768,15 +786,66 @@ meta_backend_create_renderer (MetaBackend *backend,
   return META_BACKEND_GET_CLASS (backend)->create_renderer (backend, error);
 }
 
+static void
+inhibit_sleep (MetaBackend *backend)
+{
+  MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
+  g_autoptr (GVariant) fd_variant = NULL;
+  g_autoptr (GUnixFDList) fd_list = NULL;
+  g_autoptr (GError) error = NULL;
+  int handle, fd;
+
+  if (priv->inhibit_sleep_fd >= 0)
+    return;
+
+  if (!login1_manager_call_inhibit_sync (priv->logind_proxy,
+                                         "sleep",
+                                         "Display Server",
+                                         "Prepare for suspend",
+                                         "delay",
+                                         NULL,
+                                         &fd_variant,
+                                         &fd_list,
+                                         priv->cancellable,
+                                         &error))
+    {
+      g_warning ("Failed to inhibit sleep: %s", error->message);
+      return;
+    }
+
+  handle = g_variant_get_handle (fd_variant);
+  fd = g_unix_fd_list_get (fd_list, handle, &error);
+
+  if (fd < 0)
+    {
+      g_warning ("Failed to fetch sleep inhibitor fd: %s", error->message);
+      return;
+    }
+
+  priv->inhibit_sleep_fd = fd;
+}
+
+static void
+uninhibit_sleep (MetaBackend *backend)
+{
+  MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
+
+  close (priv->inhibit_sleep_fd);
+  priv->inhibit_sleep_fd = -1;
+}
+
 static void
 prepare_for_sleep_cb (MetaBackend *backend,
                       gboolean     suspending)
 {
-  gboolean suspending;
-
-  g_variant_get (parameters, "(b)", &suspending);
-  if (suspending)
+  if (suspending) {
+    g_signal_emit (backend, signals[SUSPENDING], 0);
+    uninhibit_sleep (backend);
     return;
+  }
+
+  inhibit_sleep (backend);
+  g_signal_emit (backend, signals[RESUMING], 0);
   meta_idle_monitor_reset_idletime (meta_idle_monitor_get_core ());
 }
 
@@ -803,6 +872,7 @@ system_bus_gotten_cb (GObject      *object,
                       GAsyncResult *res,
                       gpointer      user_data)
 {
+  MetaBackend *backend = META_BACKEND (user_data);
   MetaBackendPrivate *priv;
   g_autoptr (GError) error = NULL;
   GDBusConnection *bus;
@@ -814,15 +884,21 @@ system_bus_gotten_cb (GObject      *object,
   priv = meta_backend_get_instance_private (user_data);
   priv->system_bus = bus;
   priv->logind_proxy = get_logind_proxy (priv->cancellable, &error);
+  priv->inhibit_sleep_fd = -1;
 
   if (!priv->logind_proxy)
-    g_warning ("Failed to get logind proxy: %s", error->message);
-
-  g_signal_connect_object (priv->logind_proxy,
-                           "prepare-for-sleep",
-                           G_CALLBACK (prepare_for_sleep_cb),
-                           user_data,
-                           G_CONNECT_SWAPPED);
+    {
+      g_warning ("Failed to get logind proxy: %s", error->message);
+    }
+  else
+    {
+      inhibit_sleep (backend);
+      g_signal_connect_object (priv->logind_proxy,
+                               "prepare-for-sleep",
+                               G_CALLBACK (prepare_for_sleep_cb),
+                               user_data,
+                               G_CONNECT_SWAPPED);
+    }
 }
 
 static gboolean
diff --git a/src/org.freedesktop.login1.xml b/src/org.freedesktop.login1.xml
index 1ecfd976f..7db8f373c 100644
--- a/src/org.freedesktop.login1.xml
+++ b/src/org.freedesktop.login1.xml
@@ -46,6 +46,7 @@
 
   <interface name="org.freedesktop.login1.Manager">
     <method name="Inhibit">
+      <annotation name="org.gtk.GDBus.C.UnixFD" value="true"/>
       <arg name="what" type="s" direction="in"/>
       <arg name="who" type="s" direction="in"/>
       <arg name="why" type="s" direction="in"/>
-- 
2.21.0