From 677c216fbf52e5cbc1d5f0890ebc1ee9216cfd27 Mon Sep 17 00:00:00 2001
From: Rui Matos <tiagomatos@gmail.com>
Date: Sun, 25 Oct 2015 16:14:58 +0100
Subject: [PATCH] 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 | 157 +++++++++++++++++++------
1 file changed, 122 insertions(+), 35 deletions(-)
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
index 4a27b3a14..aa3ff76f5 100644
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
@@ -58,6 +58,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;
};
@@ -763,8 +768,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;
@@ -1414,6 +1426,100 @@ meta_monitor_manager_xrandr_init_monitors(MetaMonitorManagerXrandr *manager_xran
}
#endif
+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 hotplug;
+ unsigned int timestamp;
+
+ meta_monitor_manager_read_current_config (manager);
+
+ timestamp = manager_xrandr->resources->timestamp;
+ if (is_xvnc (manager))
+ timestamp += 100;
+
+ hotplug = timestamp < manager_xrandr->resources->configTimestamp;
+ if (hotplug)
+ {
+ /* This is a hotplug event, so go ahead and build a new configuration. */
+ meta_monitor_manager_on_hotplug (manager);
+ }
+ else
+ {
+ /* Something else changed -- tell the world about it. */
+ meta_monitor_manager_rebuild_derived (manager);
+ }
+}
+
+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)
{
@@ -1449,6 +1555,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
@@ -1460,6 +1575,10 @@ meta_monitor_manager_xrandr_finalize (GObject *object)
XRRFreeScreenResources (manager_xrandr->resources);
manager_xrandr->resources = NULL;
+ 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);
}
@@ -1484,48 +1603,16 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
#endif
}
-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 hotplug;
- unsigned int timestamp;
-
if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
return FALSE;
XRRUpdateConfiguration (event);
- meta_monitor_manager_read_current_config (manager);
-
- timestamp = manager_xrandr->resources->timestamp;
- if (is_xvnc (manager))
- timestamp += 100;
-
- hotplug = timestamp < manager_xrandr->resources->configTimestamp;
- if (hotplug)
- {
- /* This is a hotplug event, so go ahead and build a new configuration. */
- meta_monitor_manager_on_hotplug (manager);
- }
- else
- {
- /* Something else changed -- tell the world about it. */
- meta_monitor_manager_rebuild_derived (manager);
- }
+ meta_monitor_manager_xrandr_update (manager_xrandr);
return TRUE;
}
--
2.12.0