[mutter/wip/rstrode/rhel-8.0.0: 99/117] monitor-manager-xrandr: Force an update when resuming from suspend



commit a6f95bc8cd82e88234512694e61bbb6cc58ed894
Author: Rui Matos <tiagomatos gmail com>
Date:   Mon Jun 4 16:35:04 2018 -0400

    monitor-manager-xrandr: Force an update when resuming from suspend
    
    The stack below us isn't as reliable as we'd like and in some cases
    doesn't generate RRScreenChangeNotify events when e.g. resuming a
    laptop on a dock, meaning that we'd miss newly attached outputs.

 src/backends/meta-gpu.c                        |  7 ++
 src/backends/meta-gpu.h                        |  2 +
 src/backends/x11/meta-gpu-xrandr.c             | 26 ++++++-
 src/backends/x11/meta-monitor-manager-xrandr.c | 96 +++++++++++++++++++++++---
 4 files changed, 121 insertions(+), 10 deletions(-)
---
diff --git a/src/backends/meta-gpu.c b/src/backends/meta-gpu.c
index 3577391e5..946f72387 100644
--- a/src/backends/meta-gpu.c
+++ b/src/backends/meta-gpu.c
@@ -64,6 +64,13 @@ meta_gpu_has_hotplug_mode_update (MetaGpu *gpu)
   return FALSE;
 }
 
+void
+meta_gpu_poll_hardware (MetaGpu *gpu)
+{
+  if (META_GPU_GET_CLASS (gpu)->poll_hardware)
+    META_GPU_GET_CLASS (gpu)->poll_hardware (gpu);
+}
+
 gboolean
 meta_gpu_read_current (MetaGpu  *gpu,
                        GError  **error)
diff --git a/src/backends/meta-gpu.h b/src/backends/meta-gpu.h
index 4badcbd26..3cec8e5b0 100644
--- a/src/backends/meta-gpu.h
+++ b/src/backends/meta-gpu.h
@@ -35,12 +35,14 @@ struct _MetaGpuClass
 
   gboolean (* read_current) (MetaGpu  *gpu,
                              GError  **error);
+  void     (* poll_hardware) (MetaGpu *gpu);
 };
 
 int meta_gpu_get_kms_fd (MetaGpu *gpu);
 
 const char * meta_gpu_get_kms_file_path (MetaGpu *gpu);
 
+void meta_gpu_poll_hardware (MetaGpu *gpu);
 gboolean meta_gpu_read_current (MetaGpu  *gpu,
                                 GError  **error);
 
diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c
index 14b46d530..add80c0d2 100644
--- a/src/backends/x11/meta-gpu-xrandr.c
+++ b/src/backends/x11/meta-gpu-xrandr.c
@@ -44,6 +44,8 @@ struct _MetaGpuXrandr
 
   int max_screen_width;
   int max_screen_height;
+
+  gboolean need_hardware_poll;
 };
 
 G_DEFINE_TYPE (MetaGpuXrandr, meta_gpu_xrandr, META_TYPE_GPU)
@@ -81,6 +83,14 @@ get_xmode_name (XRRModeInfo *xmode)
   return g_strdup_printf ("%dx%d", width, height);
 }
 
+static void
+meta_gpu_xrandr_poll_hardware (MetaGpu *gpu)
+{
+  MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (gpu);
+
+  gpu_xrandr->need_hardware_poll = TRUE;
+}
+
 static gboolean
 meta_gpu_xrandr_read_current (MetaGpu  *gpu,
                               GError  **error)
@@ -148,8 +158,18 @@ meta_gpu_xrandr_read_current (MetaGpu  *gpu,
   monitor_manager->screen_width = WidthOfScreen (screen);
   monitor_manager->screen_height = HeightOfScreen (screen);
 
-  resources = XRRGetScreenResourcesCurrent (xdisplay,
-                                            DefaultRootWindow (xdisplay));
+  if (gpu_xrandr->need_hardware_poll)
+    {
+      resources = XRRGetScreenResources (xdisplay,
+                                         DefaultRootWindow (xdisplay));
+      gpu_xrandr->need_hardware_poll = FALSE;
+    }
+  else
+    {
+      resources = XRRGetScreenResourcesCurrent (xdisplay,
+                                                DefaultRootWindow (xdisplay));
+    }
+
   if (!resources)
     {
       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
@@ -282,6 +302,7 @@ meta_gpu_xrandr_finalize (GObject *object)
 static void
 meta_gpu_xrandr_init (MetaGpuXrandr *gpu_xrandr)
 {
+  gpu_xrandr->need_hardware_poll = TRUE;
 }
 
 static void
@@ -293,4 +314,5 @@ meta_gpu_xrandr_class_init (MetaGpuXrandrClass *klass)
   object_class->finalize = meta_gpu_xrandr_finalize;
 
   gpu_class->read_current = meta_gpu_xrandr_read_current;
+  gpu_class->poll_hardware = meta_gpu_xrandr_poll_hardware;
 }
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
index c6eb4b6aa..26dccb247 100644
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
@@ -60,6 +60,10 @@ struct _MetaMonitorManagerXrandr
   Display *xdisplay;
   int rr_event_base;
   int rr_error_base;
+
+  guint logind_watch_id;
+  guint logind_signal_sub_id;
+
   gboolean has_randr15;
 
   /*
@@ -95,6 +99,8 @@ typedef struct _MetaMonitorXrandrData
 GQuark quark_meta_monitor_xrandr_data;
 #endif /* HAVE_RANDR15 */
 
+static void meta_monitor_manager_xrandr_update (MetaMonitorManagerXrandr *manager_xrandr);
+
 Display *
 meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xrandr)
 {
@@ -966,6 +972,62 @@ meta_monitor_manager_xrandr_get_default_layout_mode (MetaMonitorManager *manager
   return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
 }
 
+static void
+logind_signal_handler (GDBusConnection *connection,
+                       const gchar     *sender_name,
+                       const gchar     *object_path,
+                       const gchar     *interface_name,
+                       const gchar     *signal_name,
+                       GVariant        *parameters,
+                       gpointer         user_data)
+{
+  MetaMonitorManagerXrandr *manager_xrandr = user_data;
+  gboolean suspending;
+
+  if (!g_str_equal (signal_name, "PrepareForSleep"))
+    return;
+
+  g_variant_get (parameters, "(b)", &suspending);
+  if (!suspending)
+    {
+      meta_gpu_poll_hardware (manager_xrandr->gpu);
+      meta_monitor_manager_xrandr_update (manager_xrandr);
+    }
+}
+
+static void
+logind_appeared (GDBusConnection *connection,
+                 const gchar     *name,
+                 const gchar     *name_owner,
+                 gpointer         user_data)
+{
+  MetaMonitorManagerXrandr *manager_xrandr = user_data;
+
+  manager_xrandr->logind_signal_sub_id = g_dbus_connection_signal_subscribe (connection,
+                                                                             "org.freedesktop.login1",
+                                                                             
"org.freedesktop.login1.Manager",
+                                                                             "PrepareForSleep",
+                                                                             "/org/freedesktop/login1",
+                                                                             NULL,
+                                                                             G_DBUS_SIGNAL_FLAGS_NONE,
+                                                                             logind_signal_handler,
+                                                                             manager_xrandr,
+                                                                             NULL);
+}
+
+static void
+logind_vanished (GDBusConnection *connection,
+                 const gchar     *name,
+                 gpointer         user_data)
+{
+  MetaMonitorManagerXrandr *manager_xrandr = user_data;
+
+  if (connection && manager_xrandr->logind_signal_sub_id > 0)
+    g_dbus_connection_signal_unsubscribe (connection, manager_xrandr->logind_signal_sub_id);
+
+  manager_xrandr->logind_signal_sub_id = 0;
+}
+
 static void
 meta_monitor_manager_xrandr_constructed (GObject *object)
 {
@@ -1024,12 +1086,23 @@ meta_monitor_manager_xrandr_finalize (GObject *object)
   g_hash_table_destroy (manager_xrandr->tiled_monitor_atoms);
   g_free (manager_xrandr->supported_scales);
 
+  if (manager_xrandr->logind_watch_id > 0)
+    g_bus_unwatch_name (manager_xrandr->logind_watch_id);
+  manager_xrandr->logind_watch_id = 0;
+
   G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
 }
 
 static void
 meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
 {
+  manager_xrandr->logind_watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
+                                                      "org.freedesktop.login1",
+                                                      G_BUS_NAME_WATCHER_FLAGS_NONE,
+                                                      logind_appeared,
+                                                      logind_vanished,
+                                                      manager_xrandr,
+                                                      NULL);
 }
 
 static void
@@ -1076,9 +1149,8 @@ is_xvnc (MetaMonitorManager *manager)
   return FALSE;
 }
 
-gboolean
-meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr,
-                                          XEvent                   *event)
+static void
+meta_monitor_manager_xrandr_update (MetaMonitorManagerXrandr *manager_xrandr)
 {
   MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
   MetaGpuXrandr *gpu_xrandr;
@@ -1087,11 +1159,6 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
   gboolean is_our_configuration;
   unsigned int timestamp;
 
-  if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
-    return FALSE;
-
-  XRRUpdateConfiguration (event);
-
   meta_monitor_manager_read_current_state (manager);
 
   gpu_xrandr = META_GPU_XRANDR (manager_xrandr->gpu);
@@ -1126,6 +1193,19 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
 
       meta_monitor_manager_xrandr_rebuild_derived (manager, config);
     }
+}
+
+gboolean
+meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr,
+                                          XEvent                   *event)
+{
+
+  if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
+    return FALSE;
+
+  XRRUpdateConfiguration (event);
+
+  meta_monitor_manager_xrandr_update (manager_xrandr);
 
   return TRUE;
 }


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