From 3f91e89223e61cda636a9a2428d1d221b9cd6d37 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <fourdan.olivier@wanadoo.fr>
Date: Wed, 7 Jun 2006 21:22:08 +0000
Subject: [PATCH] =?UTF-8?q?Avoid=20needlessly=20re-compositing=20opaque=20?=
 =?UTF-8?q?windows=20in=20front=20of=20other=20damaged=20windows.=20This?=
 =?UTF-8?q?=20also=20helps=20with=20stuff=20that=20isn't=20properly=20redi?=
 =?UTF-8?q?rected=20yet,=20such=20as=20Xv=20and=20DRI=20with=20free=20driv?=
 =?UTF-8?q?ers=20(patch=20originally=20contributed=20by=20Michel=20D=C3=A4?=
 =?UTF-8?q?nzer=20<michel@tungstengraphics.com>).=20Fix=20compilation=20wi?=
 =?UTF-8?q?th=20--enable-debug=3Dfull.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

(Old svn revision: 22034)
---
 src/compositor.c | 193 +++++++++++++++++++++++++++++++----------------
 src/main.c       |   1 -
 2 files changed, 128 insertions(+), 66 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index 4e3c5d49b..031c60c55 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -63,6 +63,12 @@
 #define SHADOW_OFFSET_Y (SHADOW_RADIUS * -5 / 4)
 #endif /* SHADOW_OFFSET_Y */
 
+#define WIN_IS_OPAQUE(cw)               (!(cw->argb) && \
+                                        (cw->opacity == NET_WM_OPAQUE) && \
+                                        ((cw->c == NULL) || \
+                                            !FLAG_TEST (cw->c->xfwm_flags, XFWM_FLAG_HAS_BORDER) || \
+                                            (cw->screen_info->params->frame_opacity == 100.0f)))
+
 #define IDLE_REPAINT
 
 typedef struct _CWindow CWindow;
@@ -923,6 +929,112 @@ get_window_picture (CWindow *cw)
     return None;
 }
 
+static void
+free_win_data (CWindow *cw, gboolean delete)
+{
+#if HAVE_NAME_WINDOW_PIXMAP
+    if (cw->name_window_pixmap)
+    {
+        XFreePixmap (myScreenGetXDisplay (cw->screen_info), cw->name_window_pixmap);
+        cw->name_window_pixmap = None;
+    }
+#endif
+
+    if (cw->picture)
+    {
+        XRenderFreePicture (myScreenGetXDisplay (cw->screen_info), cw->picture);
+        cw->picture = None;
+    }
+
+    if (cw->alphaPict)
+    {
+        XRenderFreePicture (myScreenGetXDisplay (cw->screen_info), cw->alphaPict);
+        cw->alphaPict = None;
+    }
+
+    if (cw->shadowPict)
+    {
+        XRenderFreePicture (myScreenGetXDisplay (cw->screen_info), cw->shadowPict);
+        cw->shadowPict = None;
+    }
+
+    if (cw->alphaBorderPict)
+    {
+        XRenderFreePicture (myScreenGetXDisplay (cw->screen_info), cw->alphaBorderPict);
+        cw->alphaBorderPict = None;
+    }
+
+    if ((delete) && (cw->damage != None))
+    {
+        XDamageDestroy (myScreenGetXDisplay (cw->screen_info), cw->damage);
+        cw->damage = None;
+    }
+
+    if (cw->borderSize)
+    {
+        XFixesDestroyRegion (myScreenGetXDisplay (cw->screen_info), cw->borderSize);
+        cw->borderSize = None;
+    }
+
+    if (cw->shadow)
+    {
+        XRenderFreePicture (myScreenGetXDisplay (cw->screen_info), cw->shadow);
+        cw->shadow = None;
+    }
+
+    if (cw->borderClip)
+    {
+        XFixesDestroyRegion (myScreenGetXDisplay (cw->screen_info), cw->borderClip);
+        cw->borderClip = None;
+    }
+
+    if (delete)
+    {
+        g_free (cw);
+    }
+}
+
+#if 0
+static void
+redirect_win (CWindow *cw)
+{
+    ScreenInfo *screen_info;
+    DisplayInfo *display_info;
+
+    g_return_if_fail (cw != NULL);
+    TRACE ("entering redirect_win");
+
+    if (!cw->redirected)
+    {
+        screen_info = cw->screen_info;
+        display_info = screen_info->display_info;    
+
+        XCompositeRedirectSubwindows (display_info->dpy, cw->id, display_info->composite_mode);
+        cw->redirected = TRUE;
+    }
+}
+
+static void
+unredirect_win (CWindow *cw)
+{
+    ScreenInfo *screen_info;
+    DisplayInfo *display_info;
+
+    g_return_if_fail (cw != NULL);
+    TRACE ("entering unredirect_win");
+
+    if (cw->redirected)
+    {
+        screen_info = cw->screen_info;
+        display_info = screen_info->display_info;    
+
+        XCompositeUnredirectSubwindows (display_info->dpy, cw->id, display_info->composite_mode);
+        free_win_data (cw, FALSE);
+        cw->redirected = FALSE;
+    }
+}
+#endif
+
 static void
 paint_win (CWindow *cw, XserverRegion region, gboolean solid_part)
 {
@@ -1312,71 +1424,6 @@ add_repair (DisplayInfo *display_info)
 #endif
 }
 
-static void
-free_win_data (CWindow *cw, gboolean delete)
-{
-#if HAVE_NAME_WINDOW_PIXMAP
-    if (cw->name_window_pixmap)
-    {
-        XFreePixmap (myScreenGetXDisplay (cw->screen_info), cw->name_window_pixmap);
-        cw->name_window_pixmap = None;
-    }
-#endif
-
-    if (cw->picture)
-    {
-        XRenderFreePicture (myScreenGetXDisplay (cw->screen_info), cw->picture);
-        cw->picture = None;
-    }
-
-    if (cw->alphaPict)
-    {
-        XRenderFreePicture (myScreenGetXDisplay (cw->screen_info), cw->alphaPict);
-        cw->alphaPict = None;
-    }
-
-    if (cw->shadowPict)
-    {
-        XRenderFreePicture (myScreenGetXDisplay (cw->screen_info), cw->shadowPict);
-        cw->shadowPict = None;
-    }
-
-    if (cw->alphaBorderPict)
-    {
-        XRenderFreePicture (myScreenGetXDisplay (cw->screen_info), cw->alphaBorderPict);
-        cw->alphaBorderPict = None;
-    }
-
-    if ((delete) && (cw->damage != None))
-    {
-        XDamageDestroy (myScreenGetXDisplay (cw->screen_info), cw->damage);
-        cw->damage = None;
-    }
-
-    if (cw->borderSize)
-    {
-        XFixesDestroyRegion (myScreenGetXDisplay (cw->screen_info), cw->borderSize);
-        cw->borderSize = None;
-    }
-
-    if (cw->shadow)
-    {
-        XRenderFreePicture (myScreenGetXDisplay (cw->screen_info), cw->shadow);
-        cw->shadow = None;
-    }
-
-    if (cw->borderClip)
-    {
-        XFixesDestroyRegion (myScreenGetXDisplay (cw->screen_info), cw->borderClip);
-        cw->borderClip = None;
-    }
-
-    if (delete)
-    {
-        g_free (cw);
-    }
-}
-
 static void
 add_damage (ScreenInfo *screen_info, XserverRegion damage)
 {
@@ -1441,6 +1488,22 @@ repair_win (CWindow *cw)
 
     if (parts)
     {
+        GList *index;
+        GList *sibling;
+
+        /* Exclude opaque windows in front of this window from damage */
+        sibling = g_list_find (screen_info->cwindows, (gconstpointer) cw);
+        for (index = g_list_previous(sibling); index; index = g_list_previous(index))
+        {
+            CWindow *cw2 = (CWindow *) index->data;
+
+            if (WIN_IS_OPAQUE (cw2) && (cw2->borderSize))
+            {
+                XFixesSubtractRegion (myScreenGetXDisplay (screen_info), parts,
+                                     parts, cw2->borderSize);
+            }
+        }
+
         cw->damaged = TRUE;
         add_damage (cw->screen_info, parts);
     }
diff --git a/src/main.c b/src/main.c
index e498a17ac..e4d7266db 100644
--- a/src/main.c
+++ b/src/main.c
@@ -383,7 +383,6 @@ initialize (int argc, char **argv, gint compositor_mode)
 {
     struct sigaction act;
     long ws;
-    SessionClient *client_session;
     gint i, nscreens;
     
     TRACE ("entering initialize");
-- 
GitLab