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

2c033f
From 0a205c86df3422c4918d225c29adc0a06bc4e2d5 Mon Sep 17 00:00:00 2001
2c033f
From: Rui Matos <tiagomatos@gmail.com>
2c033f
Date: Sun, 25 Oct 2015 16:14:58 +0100
2c033f
Subject: [PATCH 4/4] monitor-manager-xrandr: Force an update when resuming
2c033f
 from suspend
2c033f
2c033f
The stack below us isn't as reliable as we'd like and in some cases
2c033f
doesn't generate RRScreenChangeNotify events when e.g. resuming a
2c033f
laptop on a dock, meaning that we'd miss newly attached outputs.
2c033f
---
2c033f
 src/backends/x11/meta-monitor-manager-xrandr.c | 215 +++++++++++++++++--------
2c033f
 1 file changed, 151 insertions(+), 64 deletions(-)
2c033f
2c033f
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
2c033f
index 9a64bb2..d2a5df2 100644
2c033f
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
2c033f
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
2c033f
@@ -59,6 +59,11 @@ struct _MetaMonitorManagerXrandr
2c033f
   XRRScreenResources *resources;
2c033f
   int rr_event_base;
2c033f
   int rr_error_base;
2c033f
+
2c033f
+  guint logind_watch_id;
2c033f
+  guint logind_signal_sub_id;
2c033f
+
2c033f
+  gboolean need_hardware_poll;
2c033f
 };
2c033f
 
2c033f
 struct _MetaMonitorManagerXrandrClass
2c033f
@@ -506,8 +511,15 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
2c033f
   manager->screen_width = WidthOfScreen (screen);
2c033f
   manager->screen_height = HeightOfScreen (screen);
2c033f
 
2c033f
-  resources = XRRGetScreenResourcesCurrent (manager_xrandr->xdisplay,
2c033f
-					    DefaultRootWindow (manager_xrandr->xdisplay));
2c033f
+  if (manager_xrandr->need_hardware_poll)
2c033f
+    {
2c033f
+      resources = XRRGetScreenResources (manager_xrandr->xdisplay,
2c033f
+                                         DefaultRootWindow (manager_xrandr->xdisplay));
2c033f
+      manager_xrandr->need_hardware_poll = FALSE;
2c033f
+    }
2c033f
+  else
2c033f
+    resources = XRRGetScreenResourcesCurrent (manager_xrandr->xdisplay,
2c033f
+                                              DefaultRootWindow (manager_xrandr->xdisplay));
2c033f
   if (!resources)
2c033f
     return;
2c033f
 
2c033f
@@ -1083,60 +1095,6 @@ meta_monitor_manager_xrandr_rebuild_derived (MetaMonitorManager *manager)
2c033f
   meta_monitor_manager_rebuild_derived (manager);
2c033f
 }
2c033f
 
2c033f
-static void
2c033f
-meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
2c033f
-{
2c033f
-  MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
2c033f
-
2c033f
-  manager_xrandr->xdisplay = meta_backend_x11_get_xdisplay (backend);
2c033f
-
2c033f
-  if (!XRRQueryExtension (manager_xrandr->xdisplay,
2c033f
-			  &manager_xrandr->rr_event_base,
2c033f
-			  &manager_xrandr->rr_error_base))
2c033f
-    {
2c033f
-      return;
2c033f
-    }
2c033f
-  else
2c033f
-    {
2c033f
-      /* We only use ScreenChangeNotify, but GDK uses the others,
2c033f
-	 and we don't want to step on its toes */
2c033f
-      XRRSelectInput (manager_xrandr->xdisplay,
2c033f
-		      DefaultRootWindow (manager_xrandr->xdisplay),
2c033f
-		      RRScreenChangeNotifyMask
2c033f
-		      | RRCrtcChangeNotifyMask
2c033f
-		      | RROutputPropertyNotifyMask);
2c033f
-    }
2c033f
-}
2c033f
-
2c033f
-static void
2c033f
-meta_monitor_manager_xrandr_finalize (GObject *object)
2c033f
-{
2c033f
-  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object);
2c033f
-
2c033f
-  if (manager_xrandr->resources)
2c033f
-    XRRFreeScreenResources (manager_xrandr->resources);
2c033f
-  manager_xrandr->resources = NULL;
2c033f
-
2c033f
-  G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
2c033f
-}
2c033f
-
2c033f
-static void
2c033f
-meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
2c033f
-{
2c033f
-  MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
2c033f
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
2c033f
-
2c033f
-  object_class->finalize = meta_monitor_manager_xrandr_finalize;
2c033f
-
2c033f
-  manager_class->read_current = meta_monitor_manager_xrandr_read_current;
2c033f
-  manager_class->read_edid = meta_monitor_manager_xrandr_read_edid;
2c033f
-  manager_class->apply_configuration = meta_monitor_manager_xrandr_apply_configuration;
2c033f
-  manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode;
2c033f
-  manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
2c033f
-  manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
2c033f
-  manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
2c033f
-}
2c033f
-
2c033f
 static gboolean
2c033f
 is_xvnc (MetaMonitorManager *manager)
2c033f
 {
2c033f
@@ -1149,9 +1107,8 @@ is_xvnc (MetaMonitorManager *manager)
2c033f
   return FALSE;
2c033f
 }
2c033f
 
2c033f
-gboolean
2c033f
-meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr,
2c033f
-					   XEvent                   *event)
2c033f
+static void
2c033f
+meta_monitor_manager_xrandr_update (MetaMonitorManagerXrandr *manager_xrandr)
2c033f
 {
2c033f
   MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
2c033f
   MetaOutput *old_outputs;
2c033f
@@ -1162,11 +1119,6 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
2c033f
   gboolean applied_config = FALSE;
2c033f
   unsigned int timestamp;
2c033f
 
2c033f
-  if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
2c033f
-    return FALSE;
2c033f
-
2c033f
-  XRRUpdateConfiguration (event);
2c033f
-
2c033f
   /* Save the old structures, so they stay valid during the update */
2c033f
   old_outputs = manager->outputs;
2c033f
   n_old_outputs = manager->n_outputs;
2c033f
@@ -1210,6 +1162,141 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
2c033f
   meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
2c033f
   meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
2c033f
   g_free (old_crtcs);
2c033f
+}
2c033f
+
2c033f
+static void
2c033f
+logind_signal_handler (GDBusConnection *connection,
2c033f
+                       const gchar     *sender_name,
2c033f
+                       const gchar     *object_path,
2c033f
+                       const gchar     *interface_name,
2c033f
+                       const gchar     *signal_name,
2c033f
+                       GVariant        *parameters,
2c033f
+                       gpointer         user_data)
2c033f
+{
2c033f
+  MetaMonitorManagerXrandr *manager_xrandr = user_data;
2c033f
+  gboolean suspending;
2c033f
+
2c033f
+  if (!g_str_equal (signal_name, "PrepareForSleep"))
2c033f
+    return;
2c033f
+
2c033f
+  g_variant_get (parameters, "(b)", &suspending);
2c033f
+  if (!suspending)
2c033f
+    {
2c033f
+      manager_xrandr->need_hardware_poll = TRUE;
2c033f
+      meta_monitor_manager_xrandr_update (manager_xrandr);
2c033f
+    }
2c033f
+}
2c033f
+
2c033f
+static void
2c033f
+logind_appeared (GDBusConnection *connection,
2c033f
+                 const gchar     *name,
2c033f
+                 const gchar     *name_owner,
2c033f
+                 gpointer         user_data)
2c033f
+{
2c033f
+  MetaMonitorManagerXrandr *manager_xrandr = user_data;
2c033f
+
2c033f
+  manager_xrandr->logind_signal_sub_id = g_dbus_connection_signal_subscribe (connection,
2c033f
+                                                                             "org.freedesktop.login1",
2c033f
+                                                                             "org.freedesktop.login1.Manager",
2c033f
+                                                                             "PrepareForSleep",
2c033f
+                                                                             "/org/freedesktop/login1",
2c033f
+                                                                             NULL,
2c033f
+                                                                             G_DBUS_SIGNAL_FLAGS_NONE,
2c033f
+                                                                             logind_signal_handler,
2c033f
+                                                                             manager_xrandr,
2c033f
+                                                                             NULL);
2c033f
+}
2c033f
+
2c033f
+static void
2c033f
+logind_vanished (GDBusConnection *connection,
2c033f
+                 const gchar     *name,
2c033f
+                 gpointer         user_data)
2c033f
+{
2c033f
+  MetaMonitorManagerXrandr *manager_xrandr = user_data;
2c033f
+
2c033f
+  if (connection && manager_xrandr->logind_signal_sub_id > 0)
2c033f
+    g_dbus_connection_signal_unsubscribe (connection, manager_xrandr->logind_signal_sub_id);
2c033f
+
2c033f
+  manager_xrandr->logind_signal_sub_id = 0;
2c033f
+}
2c033f
+
2c033f
+static void
2c033f
+meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
2c033f
+{
2c033f
+  MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
2c033f
+
2c033f
+  manager_xrandr->xdisplay = meta_backend_x11_get_xdisplay (backend);
2c033f
+
2c033f
+  if (!XRRQueryExtension (manager_xrandr->xdisplay,
2c033f
+			  &manager_xrandr->rr_event_base,
2c033f
+			  &manager_xrandr->rr_error_base))
2c033f
+    {
2c033f
+      return;
2c033f
+    }
2c033f
+  else
2c033f
+    {
2c033f
+      /* We only use ScreenChangeNotify, but GDK uses the others,
2c033f
+	 and we don't want to step on its toes */
2c033f
+      XRRSelectInput (manager_xrandr->xdisplay,
2c033f
+		      DefaultRootWindow (manager_xrandr->xdisplay),
2c033f
+		      RRScreenChangeNotifyMask
2c033f
+		      | RRCrtcChangeNotifyMask
2c033f
+		      | RROutputPropertyNotifyMask);
2c033f
+    }
2c033f
+
2c033f
+  manager_xrandr->logind_watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
2c033f
+                                                      "org.freedesktop.login1",
2c033f
+                                                      G_BUS_NAME_WATCHER_FLAGS_NONE,
2c033f
+                                                      logind_appeared,
2c033f
+                                                      logind_vanished,
2c033f
+                                                      manager_xrandr,
2c033f
+                                                      NULL);
2c033f
+  manager_xrandr->need_hardware_poll = TRUE;
2c033f
+}
2c033f
+
2c033f
+static void
2c033f
+meta_monitor_manager_xrandr_finalize (GObject *object)
2c033f
+{
2c033f
+  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object);
2c033f
+
2c033f
+  if (manager_xrandr->resources)
2c033f
+    XRRFreeScreenResources (manager_xrandr->resources);
2c033f
+  manager_xrandr->resources = NULL;
2c033f
+
2c033f
+  if (manager_xrandr->logind_watch_id > 0)
2c033f
+    g_bus_unwatch_name (manager_xrandr->logind_watch_id);
2c033f
+  manager_xrandr->logind_watch_id = 0;
2c033f
+
2c033f
+  G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
2c033f
+}
2c033f
+
2c033f
+static void
2c033f
+meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
2c033f
+{
2c033f
+  MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
2c033f
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
2c033f
+
2c033f
+  object_class->finalize = meta_monitor_manager_xrandr_finalize;
2c033f
+
2c033f
+  manager_class->read_current = meta_monitor_manager_xrandr_read_current;
2c033f
+  manager_class->read_edid = meta_monitor_manager_xrandr_read_edid;
2c033f
+  manager_class->apply_configuration = meta_monitor_manager_xrandr_apply_configuration;
2c033f
+  manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode;
2c033f
+  manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
2c033f
+  manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
2c033f
+  manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
2c033f
+}
2c033f
+
2c033f
+gboolean
2c033f
+meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr,
2c033f
+					   XEvent                   *event)
2c033f
+{
2c033f
+  if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
2c033f
+    return FALSE;
2c033f
+
2c033f
+  XRRUpdateConfiguration (event);
2c033f
+
2c033f
+  meta_monitor_manager_xrandr_update (manager_xrandr);
2c033f
 
2c033f
   return TRUE;
2c033f
 }
2c033f
-- 
2c033f
2.5.0
2c033f