Blob Blame History Raw
From 4ac28995769b7820d802683bf86f1dc6c821a52b 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 | 99 ++++++++++++++++++++++++++++++++-----
 1 file changed, 87 insertions(+), 12 deletions(-)

diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c
index 2f090e233..eb8790967 100644
--- a/src/backends/meta-backend.c
+++ b/src/backends/meta-backend.c
@@ -1,93 +1,96 @@
 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 
 /*
  * Copyright (C) 2014 Red Hat
  *
  * 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., 59 Temple Place - Suite 330, Boston, MA
  * 02111-1307, USA.
  *
  * Written by:
  *     Jasper St. Pierre <jstpierre@mecheye.net>
  */
 
 #include "config.h"
 
 #include <stdlib.h>
 
+#include <gio/gunixfdlist.h>
+
 #include <clutter/clutter-mutter.h>
 #include <meta/meta-backend.h>
 #include <meta/main.h>
 #include <meta/util.h>
 #include "meta-backend-private.h"
 #include "meta-input-settings-private.h"
 #include "backends/x11/meta-backend-x11.h"
 #include "meta-cursor-tracker-private.h"
 #include "meta-stage-private.h"
 #include "meta-dbus-login1.h"
 
 #ifdef HAVE_REMOTE_DESKTOP
 #include "backends/meta-dbus-session-watcher.h"
 #include "backends/meta-screen-cast.h"
 #include "backends/meta-remote-access-controller-private.h"
 #include "backends/meta-remote-desktop.h"
 #endif
 
 #ifdef HAVE_NATIVE_BACKEND
 #include "backends/native/meta-backend-native.h"
 #endif
 
 #include "backends/meta-idle-monitor-private.h"
 #include "backends/meta-logical-monitor.h"
 #include "backends/meta-monitor-manager-dummy.h"
 #include "backends/meta-settings-private.h"
 
 #define META_IDLE_MONITOR_CORE_DEVICE 0
 
 enum
 {
   KEYMAP_CHANGED,
   KEYMAP_LAYOUT_GROUP_CHANGED,
   LAST_DEVICE_CHANGED,
-
+  SUSPENDING,
+  RESUMING,
   N_SIGNALS
 };
 
 static guint signals[N_SIGNALS];
 
 static MetaBackend *_backend;
 
 static gboolean stage_views_disabled = FALSE;
 
 /**
  * meta_get_backend:
  *
  * Accessor for the singleton MetaBackend.
  *
  * Returns: (transfer none): The only #MetaBackend there is.
  */
 MetaBackend *
 meta_get_backend (void)
 {
   return _backend;
 }
 
 struct _MetaBackendPrivate
 {
   MetaMonitorManager *monitor_manager;
   MetaOrientationManager *orientation_manager;
   MetaCursorTracker *cursor_tracker;
   MetaCursorRenderer *cursor_renderer;
   MetaInputSettings *input_settings;
   MetaRenderer *renderer;
@@ -523,149 +526,221 @@ meta_backend_class_init (MetaBackendClass *klass)
   object_class->finalize = meta_backend_finalize;
 
   klass->post_init = meta_backend_real_post_init;
   klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer;
   klass->grab_device = meta_backend_real_grab_device;
   klass->ungrab_device = meta_backend_real_ungrab_device;
   klass->select_stage_events = meta_backend_real_select_stage_events;
   klass->get_relative_motion_deltas = meta_backend_real_get_relative_motion_deltas;
 
   signals[KEYMAP_CHANGED] =
     g_signal_new ("keymap-changed",
                   G_TYPE_FROM_CLASS (object_class),
                   G_SIGNAL_RUN_LAST,
                   0,
                   NULL, NULL, NULL,
                   G_TYPE_NONE, 0);
   signals[KEYMAP_LAYOUT_GROUP_CHANGED] =
     g_signal_new ("keymap-layout-group-changed",
                   G_TYPE_FROM_CLASS (object_class),
                   G_SIGNAL_RUN_LAST,
                   0,
                   NULL, NULL, NULL,
                   G_TYPE_NONE, 1, G_TYPE_UINT);
   signals[LAST_DEVICE_CHANGED] =
     g_signal_new ("last-device-changed",
                   G_TYPE_FROM_CLASS (object_class),
                   G_SIGNAL_RUN_LAST,
                   0,
                   NULL, NULL, NULL,
                   G_TYPE_NONE, 1, G_TYPE_INT);
+  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;
 }
 
 static MetaMonitorManager *
 meta_backend_create_monitor_manager (MetaBackend *backend,
                                      GError     **error)
 {
   if (g_getenv ("META_DUMMY_MONITORS"))
     return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
 
   return META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend,
                                                                    error);
 }
 
 static MetaRenderer *
 meta_backend_create_renderer (MetaBackend *backend,
                               GError     **error)
 {
   return META_BACKEND_GET_CLASS (backend)->create_renderer (backend, error);
 }
 
 static void
 lid_is_closed_changed_cb (UpClient   *client,
                           GParamSpec *pspec,
                           gpointer    user_data)
 {
   if (up_client_get_lid_is_closed (client))
     return;
 
   meta_idle_monitor_reset_idletime (meta_idle_monitor_get_core ());
 }
 
+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 ());
 }
 
 static Login1Manager *
 get_logind_proxy (GCancellable *cancellable,
                   GError      **error)
 {
   Login1Manager *proxy;
 
   proxy =
     login1_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
                                            G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
                                            "org.freedesktop.login1",
                                            "/org/freedesktop/login1",
                                            cancellable, error);
   if (!proxy)
     g_prefix_error (error, "Could not get logind proxy: ");
 
   return proxy;
 }
 
 static void
 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;
 
   bus = g_bus_get_finish (res, NULL);
   if (!bus)
     return;
 
   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
 meta_backend_initable_init (GInitable     *initable,
                             GCancellable  *cancellable,
                             GError       **error)
 {
   MetaBackend *backend = META_BACKEND (initable);
   MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
 
   priv->settings = meta_settings_new (backend);
 
   priv->egl = g_object_new (META_TYPE_EGL, NULL);
 
   priv->orientation_manager = g_object_new (META_TYPE_ORIENTATION_MANAGER, NULL);
 
   priv->monitor_manager = meta_backend_create_monitor_manager (backend, error);
   if (!priv->monitor_manager)
     return FALSE;
 
   priv->renderer = meta_backend_create_renderer (backend, error);
   if (!priv->renderer)
     return FALSE;
 
   priv->cursor_tracker = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
 
   priv->dnd = g_object_new (META_TYPE_DND, NULL);
 
   priv->up_client = up_client_new ();
   g_signal_connect (priv->up_client, "notify::lid-is-closed",
-- 
2.18.1