kathenas / rpms / mutter

Forked from rpms/mutter 5 years ago
Clone
Blob Blame History Raw
From a4a703c75e208badf78c81558994a249797dbb0a Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Sat, 12 Jan 2019 12:38:01 -0500
Subject: [PATCH 4/9] wayland: force X clients to redraw on resume

On nvidia, the textures backing Xwayland client window contents get
corrupted on suspend.  Xwayland currently doesn't handle this situation
itself.

For now, in order to work around this issue, send an empty output
change event to Xwayland.  This will cause it to force Expose events
to get sent to all clients and get them to redraw.
---
 .../native/meta-monitor-manager-kms.c         |  7 +++
 src/wayland/meta-wayland-outputs.c            | 47 +++++++++++++++++++
 src/wayland/meta-wayland-outputs.h            |  1 +
 3 files changed, 55 insertions(+)

diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index 9a0364441..7bcceee97 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -60,6 +60,7 @@
 #include "clutter/clutter.h"
 #include "meta/main.h"
 #include "meta/meta-x11-errors.h"
+#include "wayland/meta-wayland-outputs.h"
 
 #define DRM_CARD_UDEV_DEVICE_TYPE "drm_minor"
 
@@ -505,9 +506,15 @@ void
 meta_monitor_manager_kms_resume (MetaMonitorManagerKms *manager_kms)
 {
   MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
+  ClutterBackend *clutter_backend = clutter_get_default_backend ();
+  CoglContext *cogl_context =
+    clutter_backend_get_cogl_context (clutter_backend);
 
   meta_monitor_manager_kms_connect_uevent_handler (manager_kms);
   handle_hotplug_event (manager);
+
+  if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_UNSTABLE_TEXTURES))
+    meta_wayland_outputs_redraw (meta_wayland_compositor_get_default ());
 }
 
 static gboolean
diff --git a/src/wayland/meta-wayland-outputs.c b/src/wayland/meta-wayland-outputs.c
index 099e87ab9..bc69d699d 100644
--- a/src/wayland/meta-wayland-outputs.c
+++ b/src/wayland/meta-wayland-outputs.c
@@ -496,6 +496,53 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
   return new_table;
 }
 
+void
+meta_wayland_outputs_redraw (MetaWaylandCompositor *compositor)
+{
+  MetaMonitorManager *monitor_manager;
+  GList *logical_monitors, *l;
+
+  monitor_manager = meta_monitor_manager_get ();
+
+  logical_monitors =
+    meta_monitor_manager_get_logical_monitors (monitor_manager);
+
+  for (l = logical_monitors; l; l = l->next)
+    {
+      MetaLogicalMonitor *logical_monitor = l->data;
+      MetaWaylandOutput *wayland_output;
+      GList *iter;
+
+      if (logical_monitor->winsys_id == 0)
+        continue;
+
+      wayland_output =
+        g_hash_table_lookup (compositor->outputs,
+                             GSIZE_TO_POINTER (logical_monitor->winsys_id));
+
+      if (wayland_output == NULL)
+        continue;
+
+      /* Just output a "changes done" event for one of the outputs, with no actual changes.
+       * xwayland takes this as a cue to send expose events to all X clients.
+       */
+      for (iter = wayland_output->resources; iter; iter = iter->next)
+        {
+          struct wl_resource *resource = iter->data;
+          if (wl_resource_get_version (resource) >= WL_OUTPUT_DONE_SINCE_VERSION)
+            wl_output_send_done (resource);
+        }
+
+      for (iter = wayland_output->xdg_output_resources; iter; iter = iter->next)
+        {
+          struct wl_resource *xdg_output = iter->data;
+          zxdg_output_v1_send_done (xdg_output);
+        }
+
+      break;
+    }
+}
+
 static void
 on_monitors_changed (MetaMonitorManager    *monitors,
                      MetaWaylandCompositor *compositor)
diff --git a/src/wayland/meta-wayland-outputs.h b/src/wayland/meta-wayland-outputs.h
index ff15a81bd..d649e0fa1 100644
--- a/src/wayland/meta-wayland-outputs.h
+++ b/src/wayland/meta-wayland-outputs.h
@@ -49,5 +49,6 @@ struct _MetaWaylandOutput
 };
 
 void meta_wayland_outputs_init (MetaWaylandCompositor *compositor);
+void meta_wayland_outputs_redraw (MetaWaylandCompositor *compositor);
 
 #endif /* META_WAYLAND_OUTPUTS_H */
-- 
2.21.0