compositor: Ignore offscreen windows when unredirecting
authorJonas Ådahl <jadahl@gmail.com>
Fri, 13 Oct 2017 08:29:20 +0000 (16:29 +0800)
committerJeremy Bicha <jbicha@debian.org>
Sat, 21 Oct 2017 23:47:22 +0000 (00:47 +0100)
When determining whether we should unredirect a window or not, ignore
offscreen windows, and just check the top most visible window.

Previously this was not an issue, but since 'stack-tracker: Keep
override redirect windows on top' we started sorting the UI frames
window, which is an offscreen override redirect window, on top, causing
the unredirect checking code to always check whether to unredirect the
UI frames window. This effectively disabled the compositor bypass
functionality.

https://bugzilla.gnome.org/show_bug.cgi?id=788493

Gbp-Pq: Name 0013-compositor-Ignore-offscreen-windows.patch

src/compositor/compositor-private.h
src/compositor/compositor.c

index ba58bf1753a64d846671e49f9385378e98699038..40c0344ccee4345546e2ee4cf36be88711e78b71 100644 (file)
@@ -31,6 +31,8 @@ struct _MetaCompositor
 
   CoglContext           *context;
 
+  MetaWindowActor       *top_window_actor;
+
   /* Used for unredirecting fullscreen windows */
   guint                  disable_unredirect_count;
   MetaWindow            *unredirected_window;
index 17e8a55dd662b97254dff74af0f3f87ec0caa5be..a75ac12c5612d9e0afda1676c815108d8b88ba15 100644 (file)
@@ -923,6 +923,32 @@ sync_actor_stacking (MetaCompositor *compositor)
   g_list_free (backgrounds);
 }
 
+/*
+ * Find the top most window that is visible on the screen. The intention of
+ * this is to avoid offscreen windows that isn't actually part of the visible
+ * desktop (such as the UI frames override redirect window).
+ */
+static MetaWindowActor *
+get_top_visible_window_actor (MetaCompositor *compositor)
+{
+  GList *l;
+
+  for (l = g_list_last (compositor->windows); l; l = l->prev)
+    {
+      MetaWindowActor *window_actor = l->data;
+      MetaWindow *window = meta_window_actor_get_meta_window (window_actor);
+      MetaRectangle buffer_rect;
+
+      meta_window_get_buffer_rect (window, &buffer_rect);
+
+      if (meta_rectangle_overlap (&compositor->display->screen->rect,
+                                  &buffer_rect))
+        return window_actor;
+    }
+
+  return NULL;
+}
+
 void
 meta_compositor_sync_stack (MetaCompositor  *compositor,
                            GList           *stack)
@@ -1009,6 +1035,8 @@ meta_compositor_sync_stack (MetaCompositor  *compositor,
     }
 
   sync_actor_stacking (compositor);
+
+  compositor->top_window_actor = get_top_visible_window_actor (compositor);
 }
 
 void
@@ -1065,19 +1093,26 @@ static gboolean
 meta_pre_paint_func (gpointer data)
 {
   GList *l;
-  MetaWindowActor *top_window;
+  MetaWindowActor *top_window_actor;
   MetaCompositor *compositor = data;
 
   if (compositor->windows == NULL)
     return TRUE;
 
-  top_window = g_list_last (compositor->windows)->data;
-
-  if (meta_window_actor_should_unredirect (top_window) &&
+  top_window_actor = compositor->top_window_actor;
+  if (top_window_actor &&
+      meta_window_actor_should_unredirect (top_window_actor) &&
       compositor->disable_unredirect_count == 0)
-    set_unredirected_window (compositor, meta_window_actor_get_meta_window (top_window));
+    {
+      MetaWindow *top_window;
+
+      top_window = meta_window_actor_get_meta_window (top_window_actor);
+      set_unredirected_window (compositor, top_window);
+    }
   else
-    set_unredirected_window (compositor, NULL);
+    {
+      set_unredirected_window (compositor, NULL);
+    }
 
   for (l = compositor->windows; l; l = l->next)
     meta_window_actor_pre_paint (l->data);