Blob Blame History Raw
From ed7cad0561b79e68ddd91f0e12042087199676ea Mon Sep 17 00:00:00 2001
From: Rui Matos <tiagomatos@gmail.com>
Date: Sun, 25 Oct 2015 16:14:58 +0100
Subject: [PATCH 3/8] 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/x11/meta-monitor-manager-xrandr.c | 188 ++++++++++++++++++-------
 1 file changed, 137 insertions(+), 51 deletions(-)

diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
index 8d1bdfb69..d451fcccc 100644
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
@@ -61,6 +61,11 @@ struct _MetaMonitorManagerXrandr
   XRRScreenResources *resources;
   int rr_event_base;
   int rr_error_base;
+
+  guint logind_watch_id;
+  guint logind_signal_sub_id;
+
+  gboolean need_hardware_poll;
   gboolean has_randr15;
 
   xcb_timestamp_t last_xrandr_set_timestamp;
@@ -787,8 +792,15 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
   manager->screen_width = WidthOfScreen (screen);
   manager->screen_height = HeightOfScreen (screen);
 
-  resources = XRRGetScreenResourcesCurrent (manager_xrandr->xdisplay,
-					    DefaultRootWindow (manager_xrandr->xdisplay));
+  if (manager_xrandr->need_hardware_poll)
+    {
+      resources = XRRGetScreenResources (manager_xrandr->xdisplay,
+                                         DefaultRootWindow (manager_xrandr->xdisplay));
+      manager_xrandr->need_hardware_poll = FALSE;
+    }
+  else
+    resources = XRRGetScreenResourcesCurrent (manager_xrandr->xdisplay,
+                                              DefaultRootWindow (manager_xrandr->xdisplay));
   if (!resources)
     return;
 
@@ -1910,6 +1922,115 @@ meta_monitor_manager_xrandr_get_default_layout_mode (MetaMonitorManager *manager
   return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
 }
 
+static gboolean
+is_xvnc (MetaMonitorManager *manager)
+{
+  unsigned int i;
+
+  for (i = 0; i < manager->n_outputs; ++i)
+    if (g_str_has_prefix (manager->outputs[i].name, "VNC-"))
+      return TRUE;
+
+  return FALSE;
+}
+
+static void
+meta_monitor_manager_xrandr_update (MetaMonitorManagerXrandr *manager_xrandr)
+{
+  MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
+  gboolean is_hotplug;
+  gboolean is_our_configuration;
+  unsigned int timestamp;
+
+  meta_monitor_manager_read_current_state (manager);
+
+  timestamp = manager_xrandr->resources->timestamp;
+  if (is_xvnc (manager))
+    timestamp += 100;
+
+  is_hotplug = (timestamp < manager_xrandr->resources->configTimestamp);
+  is_our_configuration = (manager_xrandr->resources->timestamp ==
+                          manager_xrandr->last_xrandr_set_timestamp);
+  if (is_hotplug)
+    {
+      meta_monitor_manager_on_hotplug (manager);
+    }
+  else
+    {
+      MetaMonitorsConfig *config;
+
+      if (is_our_configuration)
+        {
+          MetaMonitorConfigManager *config_manager =
+            meta_monitor_manager_get_config_manager (manager);
+
+          config = meta_monitor_config_manager_get_current (config_manager);
+        }
+      else
+        {
+          config = NULL;
+        }
+
+      meta_monitor_manager_rebuild_derived (manager, config);
+    }
+}
+
+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)
+    {
+      manager_xrandr->need_hardware_poll = TRUE;
+      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_init (MetaMonitorManagerXrandr *manager_xrandr)
 {
@@ -1948,6 +2069,15 @@ meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
       meta_monitor_manager_xrandr_init_monitors (manager_xrandr);
 #endif
     }
+
+  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);
+  manager_xrandr->need_hardware_poll = TRUE;
 }
 
 static void
@@ -1962,6 +2092,10 @@ 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);
 }
 
@@ -1996,64 +2130,16 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
     g_quark_from_static_string ("-meta-monitor-xrandr-data");
 }
 
-static gboolean
-is_xvnc (MetaMonitorManager *manager)
-{
-  unsigned int i;
-
-  for (i = 0; i < manager->n_outputs; ++i)
-    if (g_str_has_prefix (manager->outputs[i].name, "VNC-"))
-      return TRUE;
-
-  return FALSE;
-}
-
 gboolean
 meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr,
 					   XEvent                   *event)
 {
-  MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
-  gboolean is_hotplug;
-  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);
-
-
-  timestamp = manager_xrandr->resources->timestamp;
-  if (is_xvnc (manager))
-    timestamp += 100;
-
-  is_hotplug = (timestamp < manager_xrandr->resources->configTimestamp);
-  is_our_configuration = (manager_xrandr->resources->timestamp ==
-                          manager_xrandr->last_xrandr_set_timestamp);
-  if (is_hotplug)
-    {
-      meta_monitor_manager_on_hotplug (manager);
-    }
-  else
-    {
-      MetaMonitorsConfig *config;
-
-      if (is_our_configuration)
-        {
-          MetaMonitorConfigManager *config_manager =
-            meta_monitor_manager_get_config_manager (manager);
-
-          config = meta_monitor_config_manager_get_current (config_manager);
-        }
-      else
-        {
-          config = NULL;
-        }
-
-      meta_monitor_manager_xrandr_rebuild_derived (manager, config);
-    }
+  meta_monitor_manager_xrandr_update (manager_xrandr);
 
   return TRUE;
 }
-- 
2.14.2