Blame SOURCES/0001-monitor-manager-xrandr-Force-an-update-when-resuming.patch

f73620
From 100795c2729305f919ff9611c877ea3e74d528b7 Mon Sep 17 00:00:00 2001
f73620
From: Rui Matos <tiagomatos@gmail.com>
f73620
Date: Mon, 4 Jun 2018 16:35:04 -0400
f73620
Subject: [PATCH] monitor-manager-xrandr: Force an update when resuming from
f73620
 suspend
f73620
f73620
The stack below us isn't as reliable as we'd like and in some cases
f73620
doesn't generate RRScreenChangeNotify events when e.g. resuming a
f73620
laptop on a dock, meaning that we'd miss newly attached outputs.
f73620
---
f73620
 src/backends/meta-gpu.c                       |  7 ++
f73620
 src/backends/meta-gpu.h                       |  2 +
f73620
 src/backends/x11/meta-gpu-xrandr.c            | 26 ++++-
f73620
 .../x11/meta-monitor-manager-xrandr.c         | 96 +++++++++++++++++--
f73620
 4 files changed, 121 insertions(+), 10 deletions(-)
f73620
f73620
diff --git a/src/backends/meta-gpu.c b/src/backends/meta-gpu.c
f73620
index 3577391e5..946f72387 100644
f73620
--- a/src/backends/meta-gpu.c
f73620
+++ b/src/backends/meta-gpu.c
f73620
@@ -37,60 +37,67 @@ enum
f73620
 static GParamSpec *obj_props[PROP_LAST];
f73620
 
f73620
 typedef struct _MetaGpuPrivate
f73620
 {
f73620
   MetaMonitorManager *monitor_manager;
f73620
 
f73620
   GList *outputs;
f73620
   GList *crtcs;
f73620
   GList *modes;
f73620
 } MetaGpuPrivate;
f73620
 
f73620
 G_DEFINE_TYPE_WITH_PRIVATE (MetaGpu, meta_gpu, G_TYPE_OBJECT)
f73620
 
f73620
 gboolean
f73620
 meta_gpu_has_hotplug_mode_update (MetaGpu *gpu)
f73620
 {
f73620
   MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu);
f73620
   GList *l;
f73620
 
f73620
   for (l = priv->outputs; l; l = l->next)
f73620
     {
f73620
       MetaOutput *output = l->data;
f73620
 
f73620
       if (output->hotplug_mode_update)
f73620
         return TRUE;
f73620
     }
f73620
 
f73620
   return FALSE;
f73620
 }
f73620
 
f73620
+void
f73620
+meta_gpu_poll_hardware (MetaGpu *gpu)
f73620
+{
f73620
+  if (META_GPU_GET_CLASS (gpu)->poll_hardware)
f73620
+    META_GPU_GET_CLASS (gpu)->poll_hardware (gpu);
f73620
+}
f73620
+
f73620
 gboolean
f73620
 meta_gpu_read_current (MetaGpu  *gpu,
f73620
                        GError  **error)
f73620
 {
f73620
   MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu);
f73620
   gboolean ret;
f73620
   GList *old_outputs;
f73620
   GList *old_crtcs;
f73620
   GList *old_modes;
f73620
 
f73620
   /* TODO: Get rid of this when objects incref:s what they need instead */
f73620
   old_outputs = priv->outputs;
f73620
   old_crtcs = priv->crtcs;
f73620
   old_modes = priv->modes;
f73620
 
f73620
   ret = META_GPU_GET_CLASS (gpu)->read_current (gpu, error);
f73620
 
f73620
   g_list_free_full (old_outputs, g_object_unref);
f73620
   g_list_free_full (old_modes, g_object_unref);
f73620
   g_list_free_full (old_crtcs, g_object_unref);
f73620
 
f73620
   return ret;
f73620
 }
f73620
 
f73620
 MetaMonitorManager *
f73620
 meta_gpu_get_monitor_manager (MetaGpu *gpu)
f73620
 {
f73620
   MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu);
f73620
 
f73620
   return priv->monitor_manager;
f73620
diff --git a/src/backends/meta-gpu.h b/src/backends/meta-gpu.h
f73620
index 4badcbd26..3cec8e5b0 100644
f73620
--- a/src/backends/meta-gpu.h
f73620
+++ b/src/backends/meta-gpu.h
f73620
@@ -8,59 +8,61 @@
f73620
  * published by the Free Software Foundation; either version 2 of the
f73620
  * License, or (at your option) any later version.
f73620
  *
f73620
  * This program is distributed in the hope that it will be useful, but
f73620
  * WITHOUT ANY WARRANTY; without even the implied warranty of
f73620
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
f73620
  * General Public License for more details.
f73620
  *
f73620
  * You should have received a copy of the GNU General Public License
f73620
  * along with this program; if not, write to the Free Software
f73620
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
f73620
  * 02111-1307, USA.
f73620
  */
f73620
 
f73620
 #ifndef META_GPU_H
f73620
 #define META_GPU_H
f73620
 
f73620
 #include <glib-object.h>
f73620
 
f73620
 #include "backends/meta-monitor-manager-private.h"
f73620
 
f73620
 #define META_TYPE_GPU (meta_gpu_get_type ())
f73620
 G_DECLARE_DERIVABLE_TYPE (MetaGpu, meta_gpu, META, GPU, GObject)
f73620
 
f73620
 struct _MetaGpuClass
f73620
 {
f73620
   GObjectClass parent_class;
f73620
 
f73620
   gboolean (* read_current) (MetaGpu  *gpu,
f73620
                              GError  **error);
f73620
+  void     (* poll_hardware) (MetaGpu *gpu);
f73620
 };
f73620
 
f73620
 int meta_gpu_get_kms_fd (MetaGpu *gpu);
f73620
 
f73620
 const char * meta_gpu_get_kms_file_path (MetaGpu *gpu);
f73620
 
f73620
+void meta_gpu_poll_hardware (MetaGpu *gpu);
f73620
 gboolean meta_gpu_read_current (MetaGpu  *gpu,
f73620
                                 GError  **error);
f73620
 
f73620
 gboolean meta_gpu_has_hotplug_mode_update (MetaGpu *gpu);
f73620
 
f73620
 MetaMonitorManager * meta_gpu_get_monitor_manager (MetaGpu *gpu);
f73620
 
f73620
 GList * meta_gpu_get_outputs (MetaGpu *gpu);
f73620
 
f73620
 GList * meta_gpu_get_crtcs (MetaGpu *gpu);
f73620
 
f73620
 GList * meta_gpu_get_modes (MetaGpu *gpu);
f73620
 
f73620
 void meta_gpu_take_outputs (MetaGpu *gpu,
f73620
                             GList   *outputs);
f73620
 
f73620
 void meta_gpu_take_crtcs (MetaGpu *gpu,
f73620
                           GList   *crtcs);
f73620
 
f73620
 void meta_gpu_take_modes (MetaGpu *gpu,
f73620
                           GList   *modes);
f73620
 
f73620
 #endif /* META_GPU_H */
f73620
diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c
f73620
index 14b46d530..add80c0d2 100644
f73620
--- a/src/backends/x11/meta-gpu-xrandr.c
f73620
+++ b/src/backends/x11/meta-gpu-xrandr.c
f73620
@@ -17,97 +17,107 @@
f73620
  * This program is distributed in the hope that it will be useful, but
f73620
  * WITHOUT ANY WARRANTY; without even the implied warranty of
f73620
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
f73620
  * General Public License for more details.
f73620
  *
f73620
  * You should have received a copy of the GNU General Public License
f73620
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
f73620
  */
f73620
 
f73620
 #include "config.h"
f73620
 
f73620
 #include "backends/x11/meta-gpu-xrandr.h"
f73620
 
f73620
 #include <string.h>
f73620
 #include <X11/extensions/dpms.h>
f73620
 #include <X11/Xlibint.h>
f73620
 
f73620
 #include "backends/meta-output.h"
f73620
 #include "backends/x11/meta-crtc-xrandr.h"
f73620
 #include "backends/x11/meta-monitor-manager-xrandr.h"
f73620
 #include "backends/x11/meta-output-xrandr.h"
f73620
 
f73620
 struct _MetaGpuXrandr
f73620
 {
f73620
   MetaGpu parent;
f73620
 
f73620
   XRRScreenResources *resources;
f73620
 
f73620
   int max_screen_width;
f73620
   int max_screen_height;
f73620
+
f73620
+  gboolean need_hardware_poll;
f73620
 };
f73620
 
f73620
 G_DEFINE_TYPE (MetaGpuXrandr, meta_gpu_xrandr, META_TYPE_GPU)
f73620
 
f73620
 XRRScreenResources *
f73620
 meta_gpu_xrandr_get_resources (MetaGpuXrandr *gpu_xrandr)
f73620
 {
f73620
   return gpu_xrandr->resources;
f73620
 }
f73620
 
f73620
 void
f73620
 meta_gpu_xrandr_get_max_screen_size (MetaGpuXrandr *gpu_xrandr,
f73620
                                      int           *max_width,
f73620
                                      int           *max_height)
f73620
 {
f73620
   *max_width = gpu_xrandr->max_screen_width;
f73620
   *max_height = gpu_xrandr->max_screen_height;
f73620
 }
f73620
 
f73620
 static int
f73620
 compare_outputs (const void *one,
f73620
                  const void *two)
f73620
 {
f73620
   const MetaOutput *o_one = one, *o_two = two;
f73620
 
f73620
   return strcmp (o_one->name, o_two->name);
f73620
 }
f73620
 
f73620
 static char *
f73620
 get_xmode_name (XRRModeInfo *xmode)
f73620
 {
f73620
   int width = xmode->width;
f73620
   int height = xmode->height;
f73620
 
f73620
   return g_strdup_printf ("%dx%d", width, height);
f73620
 }
f73620
 
f73620
+static void
f73620
+meta_gpu_xrandr_poll_hardware (MetaGpu *gpu)
f73620
+{
f73620
+  MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (gpu);
f73620
+
f73620
+  gpu_xrandr->need_hardware_poll = TRUE;
f73620
+}
f73620
+
f73620
 static gboolean
f73620
 meta_gpu_xrandr_read_current (MetaGpu  *gpu,
f73620
                               GError  **error)
f73620
 {
f73620
   MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (gpu);
f73620
   MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu);
f73620
   MetaMonitorManagerXrandr *monitor_manager_xrandr =
f73620
     META_MONITOR_MANAGER_XRANDR (monitor_manager);
f73620
   Display *xdisplay =
f73620
     meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr);
f73620
   XRRScreenResources *resources;
f73620
   RROutput primary_output;
f73620
   unsigned int i, j;
f73620
   GList *l;
f73620
   int min_width, min_height;
f73620
   Screen *screen;
f73620
   BOOL dpms_capable, dpms_enabled;
f73620
   CARD16 dpms_state;
f73620
   GList *outputs = NULL;
f73620
   GList *modes = NULL;
f73620
   GList *crtcs = NULL;
f73620
 
f73620
   if (gpu_xrandr->resources)
f73620
     XRRFreeScreenResources (gpu_xrandr->resources);
f73620
   gpu_xrandr->resources = NULL;
f73620
 
f73620
   dpms_capable = DPMSCapable (xdisplay);
f73620
 
f73620
   if (dpms_capable &&
f73620
       DPMSInfo (xdisplay, &dpms_state, &dpms_enabled) &&
f73620
@@ -121,62 +131,72 @@ meta_gpu_xrandr_read_current (MetaGpu  *gpu,
f73620
         case DPMSModeStandby:
f73620
           monitor_manager->power_save_mode = META_POWER_SAVE_STANDBY;
f73620
           break;
f73620
         case DPMSModeSuspend:
f73620
           monitor_manager->power_save_mode = META_POWER_SAVE_SUSPEND;
f73620
           break;
f73620
         case DPMSModeOff:
f73620
           monitor_manager->power_save_mode = META_POWER_SAVE_OFF;
f73620
           break;
f73620
         default:
f73620
           monitor_manager->power_save_mode = META_POWER_SAVE_UNSUPPORTED;
f73620
           break;
f73620
         }
f73620
     }
f73620
   else
f73620
     {
f73620
       monitor_manager->power_save_mode = META_POWER_SAVE_UNSUPPORTED;
f73620
     }
f73620
 
f73620
   XRRGetScreenSizeRange (xdisplay, DefaultRootWindow (xdisplay),
f73620
                          &min_width,
f73620
                          &min_height,
f73620
                          &gpu_xrandr->max_screen_width,
f73620
                          &gpu_xrandr->max_screen_height);
f73620
 
f73620
   screen = ScreenOfDisplay (xdisplay, DefaultScreen (xdisplay));
f73620
   /* This is updated because we called XRRUpdateConfiguration. */
f73620
   monitor_manager->screen_width = WidthOfScreen (screen);
f73620
   monitor_manager->screen_height = HeightOfScreen (screen);
f73620
 
f73620
-  resources = XRRGetScreenResourcesCurrent (xdisplay,
f73620
-                                            DefaultRootWindow (xdisplay));
f73620
+  if (gpu_xrandr->need_hardware_poll)
f73620
+    {
f73620
+      resources = XRRGetScreenResources (xdisplay,
f73620
+                                         DefaultRootWindow (xdisplay));
f73620
+      gpu_xrandr->need_hardware_poll = FALSE;
f73620
+    }
f73620
+  else
f73620
+    {
f73620
+      resources = XRRGetScreenResourcesCurrent (xdisplay,
f73620
+                                                DefaultRootWindow (xdisplay));
f73620
+    }
f73620
+
f73620
   if (!resources)
f73620
     {
f73620
       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
f73620
                    "Failed to retrieve Xrandr screen resources");
f73620
       return FALSE;
f73620
     }
f73620
 
f73620
   gpu_xrandr->resources = resources;
f73620
 
f73620
   outputs = NULL;
f73620
   modes = NULL;
f73620
   crtcs = NULL;
f73620
 
f73620
   for (i = 0; i < (unsigned)resources->nmode; i++)
f73620
     {
f73620
       XRRModeInfo *xmode = &resources->modes[i];
f73620
       MetaCrtcMode *mode;
f73620
 
f73620
       mode = g_object_new (META_TYPE_CRTC_MODE, NULL);
f73620
 
f73620
       mode->mode_id = xmode->id;
f73620
       mode->width = xmode->width;
f73620
       mode->height = xmode->height;
f73620
       mode->refresh_rate = (xmode->dotClock /
f73620
                             ((float)xmode->hTotal * xmode->vTotal));
f73620
       mode->flags = xmode->modeFlags;
f73620
       mode->name = get_xmode_name (xmode);
f73620
 
f73620
       modes = g_list_append (modes, mode);
f73620
     }
f73620
@@ -255,42 +275,44 @@ meta_gpu_xrandr_read_current (MetaGpu  *gpu,
f73620
                 }
f73620
             }
f73620
         }
f73620
     }
f73620
 
f73620
   return TRUE;
f73620
 }
f73620
 
f73620
 MetaGpuXrandr *
f73620
 meta_gpu_xrandr_new (MetaMonitorManagerXrandr *monitor_manager_xrandr)
f73620
 {
f73620
   return g_object_new (META_TYPE_GPU_XRANDR,
f73620
                        "monitor-manager", monitor_manager_xrandr,
f73620
                        NULL);
f73620
 }
f73620
 
f73620
 static void
f73620
 meta_gpu_xrandr_finalize (GObject *object)
f73620
 {
f73620
   MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (object);
f73620
 
f73620
   g_clear_pointer (&gpu_xrandr->resources,
f73620
                    XRRFreeScreenResources);
f73620
 
f73620
   G_OBJECT_CLASS (meta_gpu_xrandr_parent_class)->finalize (object);
f73620
 }
f73620
 
f73620
 static void
f73620
 meta_gpu_xrandr_init (MetaGpuXrandr *gpu_xrandr)
f73620
 {
f73620
+  gpu_xrandr->need_hardware_poll = TRUE;
f73620
 }
f73620
 
f73620
 static void
f73620
 meta_gpu_xrandr_class_init (MetaGpuXrandrClass *klass)
f73620
 {
f73620
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
f73620
   MetaGpuClass *gpu_class = META_GPU_CLASS (klass);
f73620
 
f73620
   object_class->finalize = meta_gpu_xrandr_finalize;
f73620
 
f73620
   gpu_class->read_current = meta_gpu_xrandr_read_current;
f73620
+  gpu_class->poll_hardware = meta_gpu_xrandr_poll_hardware;
f73620
 }
f73620
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
f73620
index 90a3952db..2d9a32339 100644
f73620
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
f73620
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
f73620
@@ -33,95 +33,101 @@
f73620
 #include <clutter/clutter.h>
f73620
 
f73620
 #include <X11/Xlibint.h>
f73620
 #include <X11/extensions/dpms.h>
f73620
 #include <X11/Xlib-xcb.h>
f73620
 #include <xcb/randr.h>
f73620
 
f73620
 #include "meta-backend-x11.h"
f73620
 #include <meta/main.h>
f73620
 #include <meta/errors.h>
f73620
 #include "backends/meta-crtc.h"
f73620
 #include "backends/meta-monitor-config-manager.h"
f73620
 #include "backends/meta-logical-monitor.h"
f73620
 #include "backends/meta-output.h"
f73620
 #include "backends/x11/meta-crtc-xrandr.h"
f73620
 #include "backends/x11/meta-gpu-xrandr.h"
f73620
 #include "backends/x11/meta-output-xrandr.h"
f73620
 
f73620
 /* Look for DPI_FALLBACK in:
f73620
  * http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c
f73620
  * for the reasoning */
f73620
 #define DPI_FALLBACK 96.0
f73620
 
f73620
 struct _MetaMonitorManagerXrandr
f73620
 {
f73620
   MetaMonitorManager parent_instance;
f73620
 
f73620
   Display *xdisplay;
f73620
   int rr_event_base;
f73620
   int rr_error_base;
f73620
+
f73620
+  guint logind_watch_id;
f73620
+  guint logind_signal_sub_id;
f73620
+
f73620
   gboolean has_randr15;
f73620
 
f73620
   /*
f73620
    * The X server deals with multiple GPUs for us, soe just see what the X
f73620
    * server gives us as one single GPU, even though it may actually be backed
f73620
    * by multiple.
f73620
    */
f73620
   MetaGpu *gpu;
f73620
 
f73620
   xcb_timestamp_t last_xrandr_set_timestamp;
f73620
 
f73620
 #ifdef HAVE_XRANDR15
f73620
   GHashTable *tiled_monitor_atoms;
f73620
 #endif /* HAVE_XRANDR15 */
f73620
 
f73620
   float *supported_scales;
f73620
   int n_supported_scales;
f73620
 };
f73620
 
f73620
 struct _MetaMonitorManagerXrandrClass
f73620
 {
f73620
   MetaMonitorManagerClass parent_class;
f73620
 };
f73620
 
f73620
 G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER);
f73620
 
f73620
 #ifdef HAVE_XRANDR15
f73620
 typedef struct _MetaMonitorXrandrData
f73620
 {
f73620
   Atom xrandr_name;
f73620
 } MetaMonitorXrandrData;
f73620
 
f73620
 GQuark quark_meta_monitor_xrandr_data;
f73620
 #endif /* HAVE_RANDR15 */
f73620
 
f73620
+static void meta_monitor_manager_xrandr_update (MetaMonitorManagerXrandr *manager_xrandr);
f73620
+
f73620
 Display *
f73620
 meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xrandr)
f73620
 {
f73620
   return manager_xrandr->xdisplay;
f73620
 }
f73620
 
f73620
 gboolean
f73620
 meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr)
f73620
 {
f73620
   return manager_xrandr->has_randr15;
f73620
 }
f73620
 
f73620
 static GBytes *
f73620
 meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager,
f73620
                                        MetaOutput         *output)
f73620
 {
f73620
   return meta_output_xrandr_read_edid (output);
f73620
 }
f73620
 
f73620
 static void
f73620
 meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
f73620
 						 MetaPowerSave       mode)
f73620
 {
f73620
   MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
f73620
   CARD16 state;
f73620
 
f73620
   switch (mode) {
f73620
   case META_POWER_SAVE_ON:
f73620
     state = DPMSModeOn;
f73620
     break;
f73620
@@ -934,198 +940,272 @@ meta_monitor_manager_xrandr_calculate_supported_scales (MetaMonitorManager
f73620
                    manager_xrandr->n_supported_scales * sizeof (float));
f73620
 }
f73620
 
f73620
 static MetaMonitorManagerCapability
f73620
 meta_monitor_manager_xrandr_get_capabilities (MetaMonitorManager *manager)
f73620
 {
f73620
   return (META_MONITOR_MANAGER_CAPABILITY_MIRRORING |
f73620
           META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED);
f73620
 }
f73620
 
f73620
 static gboolean
f73620
 meta_monitor_manager_xrandr_get_max_screen_size (MetaMonitorManager *manager,
f73620
                                                  int                *max_width,
f73620
                                                  int                *max_height)
f73620
 {
f73620
   MetaMonitorManagerXrandr *manager_xrandr =
f73620
     META_MONITOR_MANAGER_XRANDR (manager);
f73620
 
f73620
   meta_gpu_xrandr_get_max_screen_size (META_GPU_XRANDR (manager_xrandr->gpu),
f73620
                                        max_width, max_height);
f73620
 
f73620
   return TRUE;
f73620
 }
f73620
 
f73620
 static MetaLogicalMonitorLayoutMode
f73620
 meta_monitor_manager_xrandr_get_default_layout_mode (MetaMonitorManager *manager)
f73620
 {
f73620
   return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
f73620
 }
f73620
 
f73620
+static void
f73620
+logind_signal_handler (GDBusConnection *connection,
f73620
+                       const gchar     *sender_name,
f73620
+                       const gchar     *object_path,
f73620
+                       const gchar     *interface_name,
f73620
+                       const gchar     *signal_name,
f73620
+                       GVariant        *parameters,
f73620
+                       gpointer         user_data)
f73620
+{
f73620
+  MetaMonitorManagerXrandr *manager_xrandr = user_data;
f73620
+  gboolean suspending;
f73620
+
f73620
+  if (!g_str_equal (signal_name, "PrepareForSleep"))
f73620
+    return;
f73620
+
f73620
+  g_variant_get (parameters, "(b)", &suspending);
f73620
+  if (!suspending)
f73620
+    {
f73620
+      meta_gpu_poll_hardware (manager_xrandr->gpu);
f73620
+      meta_monitor_manager_xrandr_update (manager_xrandr);
f73620
+    }
f73620
+}
f73620
+
f73620
+static void
f73620
+logind_appeared (GDBusConnection *connection,
f73620
+                 const gchar     *name,
f73620
+                 const gchar     *name_owner,
f73620
+                 gpointer         user_data)
f73620
+{
f73620
+  MetaMonitorManagerXrandr *manager_xrandr = user_data;
f73620
+
f73620
+  manager_xrandr->logind_signal_sub_id = g_dbus_connection_signal_subscribe (connection,
f73620
+                                                                             "org.freedesktop.login1",
f73620
+                                                                             "org.freedesktop.login1.Manager",
f73620
+                                                                             "PrepareForSleep",
f73620
+                                                                             "/org/freedesktop/login1",
f73620
+                                                                             NULL,
f73620
+                                                                             G_DBUS_SIGNAL_FLAGS_NONE,
f73620
+                                                                             logind_signal_handler,
f73620
+                                                                             manager_xrandr,
f73620
+                                                                             NULL);
f73620
+}
f73620
+
f73620
+static void
f73620
+logind_vanished (GDBusConnection *connection,
f73620
+                 const gchar     *name,
f73620
+                 gpointer         user_data)
f73620
+{
f73620
+  MetaMonitorManagerXrandr *manager_xrandr = user_data;
f73620
+
f73620
+  if (connection && manager_xrandr->logind_signal_sub_id > 0)
f73620
+    g_dbus_connection_signal_unsubscribe (connection, manager_xrandr->logind_signal_sub_id);
f73620
+
f73620
+  manager_xrandr->logind_signal_sub_id = 0;
f73620
+}
f73620
+
f73620
 static void
f73620
 meta_monitor_manager_xrandr_constructed (GObject *object)
f73620
 {
f73620
   MetaMonitorManagerXrandr *manager_xrandr =
f73620
     META_MONITOR_MANAGER_XRANDR (object);
f73620
   MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
f73620
   MetaBackendX11 *backend =
f73620
     META_BACKEND_X11 (meta_monitor_manager_get_backend (manager));
f73620
 
f73620
   manager_xrandr->xdisplay = meta_backend_x11_get_xdisplay (backend);
f73620
 
f73620
   manager_xrandr->gpu = META_GPU (meta_gpu_xrandr_new (manager_xrandr));
f73620
   meta_monitor_manager_add_gpu (manager, manager_xrandr->gpu);
f73620
 
f73620
   if (!XRRQueryExtension (manager_xrandr->xdisplay,
f73620
 			  &manager_xrandr->rr_event_base,
f73620
 			  &manager_xrandr->rr_error_base))
f73620
     {
f73620
       return;
f73620
     }
f73620
   else
f73620
     {
f73620
       int major_version, minor_version;
f73620
       /* We only use ScreenChangeNotify, but GDK uses the others,
f73620
 	 and we don't want to step on its toes */
f73620
       XRRSelectInput (manager_xrandr->xdisplay,
f73620
 		      DefaultRootWindow (manager_xrandr->xdisplay),
f73620
 		      RRScreenChangeNotifyMask
f73620
 		      | RRCrtcChangeNotifyMask
f73620
 		      | RROutputPropertyNotifyMask);
f73620
 
f73620
       manager_xrandr->has_randr15 = FALSE;
f73620
       XRRQueryVersion (manager_xrandr->xdisplay, &major_version,
f73620
                        &minor_version);
f73620
 #ifdef HAVE_XRANDR15
f73620
       if (major_version > 1 ||
f73620
           (major_version == 1 &&
f73620
            minor_version >= 5))
f73620
         {
f73620
           manager_xrandr->has_randr15 = TRUE;
f73620
           manager_xrandr->tiled_monitor_atoms = g_hash_table_new (NULL, NULL);
f73620
         }
f73620
       meta_monitor_manager_xrandr_init_monitors (manager_xrandr);
f73620
 #endif
f73620
     }
f73620
 
f73620
   G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->constructed (object);
f73620
 }
f73620
 
f73620
 static void
f73620
 meta_monitor_manager_xrandr_finalize (GObject *object)
f73620
 {
f73620
   MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object);
f73620
 
f73620
   g_clear_object (&manager_xrandr->gpu);
f73620
   g_hash_table_destroy (manager_xrandr->tiled_monitor_atoms);
f73620
   g_free (manager_xrandr->supported_scales);
f73620
 
f73620
+  if (manager_xrandr->logind_watch_id > 0)
f73620
+    g_bus_unwatch_name (manager_xrandr->logind_watch_id);
f73620
+  manager_xrandr->logind_watch_id = 0;
f73620
+
f73620
   G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
f73620
 }
f73620
 
f73620
 static void
f73620
 meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
f73620
 {
f73620
+  manager_xrandr->logind_watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
f73620
+                                                      "org.freedesktop.login1",
f73620
+                                                      G_BUS_NAME_WATCHER_FLAGS_NONE,
f73620
+                                                      logind_appeared,
f73620
+                                                      logind_vanished,
f73620
+                                                      manager_xrandr,
f73620
+                                                      NULL);
f73620
 }
f73620
 
f73620
 static void
f73620
 meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
f73620
 {
f73620
   MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
f73620
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
f73620
 
f73620
   object_class->finalize = meta_monitor_manager_xrandr_finalize;
f73620
   object_class->constructed = meta_monitor_manager_xrandr_constructed;
f73620
 
f73620
   manager_class->read_edid = meta_monitor_manager_xrandr_read_edid;
f73620
   manager_class->ensure_initial_config = meta_monitor_manager_xrandr_ensure_initial_config;
f73620
   manager_class->apply_monitors_config = meta_monitor_manager_xrandr_apply_monitors_config;
f73620
   manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode;
f73620
   manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
f73620
   manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
f73620
   manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
f73620
 #ifdef HAVE_XRANDR15
f73620
   manager_class->tiled_monitor_added = meta_monitor_manager_xrandr_tiled_monitor_added;
f73620
   manager_class->tiled_monitor_removed = meta_monitor_manager_xrandr_tiled_monitor_removed;
f73620
 #endif
f73620
   manager_class->is_transform_handled = meta_monitor_manager_xrandr_is_transform_handled;
f73620
   manager_class->calculate_monitor_mode_scale = meta_monitor_manager_xrandr_calculate_monitor_mode_scale;
f73620
   manager_class->calculate_supported_scales = meta_monitor_manager_xrandr_calculate_supported_scales;
f73620
   manager_class->get_capabilities = meta_monitor_manager_xrandr_get_capabilities;
f73620
   manager_class->get_max_screen_size = meta_monitor_manager_xrandr_get_max_screen_size;
f73620
   manager_class->get_default_layout_mode = meta_monitor_manager_xrandr_get_default_layout_mode;
f73620
 
f73620
   quark_meta_monitor_xrandr_data =
f73620
     g_quark_from_static_string ("-meta-monitor-xrandr-data");
f73620
 }
f73620
 
f73620
 static gboolean
f73620
 is_xvnc (MetaMonitorManager *manager)
f73620
 {
f73620
   MetaMonitorManagerXrandr *manager_xrandr =
f73620
     META_MONITOR_MANAGER_XRANDR (manager);
f73620
   GList *l;
f73620
 
f73620
   for (l = meta_gpu_get_outputs (manager_xrandr->gpu); l; l = l->next)
f73620
     {
f73620
       MetaOutput *output = l->data;
f73620
 
f73620
       if (g_str_has_prefix (output->name, "VNC-"))
f73620
         return TRUE;
f73620
     }
f73620
 
f73620
   return FALSE;
f73620
 }
f73620
 
f73620
-gboolean
f73620
-meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr,
f73620
-					   XEvent                   *event)
f73620
+static void
f73620
+meta_monitor_manager_xrandr_update (MetaMonitorManagerXrandr *manager_xrandr)
f73620
 {
f73620
   MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
f73620
   MetaGpuXrandr *gpu_xrandr;
f73620
   XRRScreenResources *resources;
f73620
   gboolean is_hotplug;
f73620
   gboolean is_our_configuration;
f73620
   unsigned int timestamp;
f73620
 
f73620
-  if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
f73620
-    return FALSE;
f73620
-
f73620
-  XRRUpdateConfiguration (event);
f73620
-
f73620
   meta_monitor_manager_read_current_state (manager);
f73620
 
f73620
   gpu_xrandr = META_GPU_XRANDR (manager_xrandr->gpu);
f73620
   resources = meta_gpu_xrandr_get_resources (gpu_xrandr);
f73620
 
f73620
   timestamp = resources->timestamp;
f73620
   if (is_xvnc (manager))
f73620
     timestamp += 100;
f73620
 
f73620
   is_hotplug = timestamp < resources->configTimestamp;
f73620
   is_our_configuration = (resources->timestamp ==
f73620
                           manager_xrandr->last_xrandr_set_timestamp);
f73620
   if (is_hotplug)
f73620
     {
f73620
       meta_monitor_manager_on_hotplug (manager);
f73620
     }
f73620
   else
f73620
     {
f73620
       MetaMonitorsConfig *config;
f73620
 
f73620
       if (is_our_configuration)
f73620
         {
f73620
           MetaMonitorConfigManager *config_manager =
f73620
             meta_monitor_manager_get_config_manager (manager);
f73620
 
f73620
           config = meta_monitor_config_manager_get_current (config_manager);
f73620
         }
f73620
       else
f73620
         {
f73620
           config = NULL;
f73620
         }
f73620
 
f73620
       meta_monitor_manager_xrandr_rebuild_derived (manager, config);
f73620
     }
f73620
+}
f73620
+
f73620
+gboolean
f73620
+meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr,
f73620
+					   XEvent                   *event)
f73620
+{
f73620
+
f73620
+  if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
f73620
+    return FALSE;
f73620
+
f73620
+  XRRUpdateConfiguration (event);
f73620
+
f73620
+  meta_monitor_manager_xrandr_update (manager_xrandr);
f73620
 
f73620
   return TRUE;
f73620
 }
f73620
-- 
f73620
2.17.1
f73620