From 214aced750835ed3e983d3ba9ed45bcaed145b70 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Sat, 12 Jan 2019 12:38:01 -0500 Subject: [PATCH] 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 438069110..f9a9e1c6d 100644 --- a/src/backends/native/meta-monitor-manager-kms.c +++ b/src/backends/native/meta-monitor-manager-kms.c @@ -34,6 +34,7 @@ #include "meta-crtc-kms.h" #include "meta-gpu-kms.h" #include "meta-output-kms.h" +#include "wayland/meta-wayland-outputs.h" #include #include @@ -415,9 +416,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 1f99a163d..450f5e484 100644 --- a/src/wayland/meta-wayland-outputs.c +++ b/src/wayland/meta-wayland-outputs.c @@ -452,6 +452,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 e6b60d5fa..d8c648174 100644 --- a/src/wayland/meta-wayland-outputs.h +++ b/src/wayland/meta-wayland-outputs.h @@ -47,5 +47,6 @@ struct _MetaWaylandOutput }; void meta_wayland_outputs_init (MetaWaylandCompositor *compositor); +void meta_wayland_outputs_redraw (MetaWaylandCompositor *compositor); #endif /* META_WAYLAND_OUTPUTS_H */