Blame SOURCES/0001-composite-Implement-backing-store-Always.patch

72f588
From e3891866bcb133289d923b645228d70d55c67706 Mon Sep 17 00:00:00 2001
72f588
From: rpm-build <rpm-build>
72f588
Date: Tue, 24 Jul 2018 09:36:38 -0400
72f588
Subject: [PATCH] 0001-composite-Implement-backing-store-Always.patch
72f588
72f588
---
72f588
 composite/compalloc.c  |   2 +-
72f588
 composite/compinit.c   |  37 +++++++++---
72f588
 composite/compint.h    |   8 +++
72f588
 composite/compwindow.c |  70 +++++++++++++++++++++-
72f588
 dix/window.c           |  78 ++++++++++++------------
72f588
 include/windowstr.h    |   1 +
72f588
 mi/mibitblt.c          |   5 +-
72f588
 mi/micopy.c            |   7 +--
72f588
 mi/mivaltree.c         | 132 ++++++++++++++++++++++-------------------
72f588
 mi/miwindow.c          |  30 +++++-----
72f588
 10 files changed, 236 insertions(+), 134 deletions(-)
72f588
72f588
diff --git a/composite/compalloc.c b/composite/compalloc.c
72f588
index 05ffc7e..199c130 100644
72f588
--- a/composite/compalloc.c
72f588
+++ b/composite/compalloc.c
72f588
@@ -106,7 +106,7 @@ compMarkWindows(WindowPtr pWin, WindowPtr *ppLayerWin)
72f588
     ScreenPtr pScreen = pWin->drawable.pScreen;
72f588
     WindowPtr pLayerWin = pWin;
72f588
 
72f588
-    if (!pWin->viewable)
72f588
+    if (!pWin->viewable && pWin->backingStore != Always)
72f588
         return FALSE;
72f588
 
72f588
     (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin);
72f588
diff --git a/composite/compinit.c b/composite/compinit.c
72f588
index 791fec9..2851bb8 100644
72f588
--- a/composite/compinit.c
72f588
+++ b/composite/compinit.c
72f588
@@ -67,6 +67,7 @@ compCloseScreen(ScreenPtr pScreen)
72f588
     pScreen->ConfigNotify = cs->ConfigNotify;
72f588
     pScreen->MoveWindow = cs->MoveWindow;
72f588
     pScreen->ResizeWindow = cs->ResizeWindow;
72f588
+    pScreen->MarkUnrealizedWindow = cs->MarkUnrealizedWindow;
72f588
     pScreen->ChangeBorderWidth = cs->ChangeBorderWidth;
72f588
 
72f588
     pScreen->ClipNotify = cs->ClipNotify;
72f588
@@ -74,6 +75,7 @@ compCloseScreen(ScreenPtr pScreen)
72f588
     pScreen->RealizeWindow = cs->RealizeWindow;
72f588
     pScreen->DestroyWindow = cs->DestroyWindow;
72f588
     pScreen->CreateWindow = cs->CreateWindow;
72f588
+    pScreen->WindowExposures = cs->WindowExposures;
72f588
     pScreen->CopyWindow = cs->CopyWindow;
72f588
     pScreen->PositionWindow = cs->PositionWindow;
72f588
 
72f588
@@ -105,18 +107,33 @@ compInstallColormap(ColormapPtr pColormap)
72f588
     pScreen->InstallColormap = compInstallColormap;
72f588
 }
72f588
 
72f588
+static void
72f588
+compCheckPaintable(WindowPtr pWin)
72f588
+{
72f588
+    pWin->paintable = pWin->viewable || pWin->backingStore == Always;
72f588
+}
72f588
+
72f588
 static void
72f588
 compCheckBackingStore(WindowPtr pWin)
72f588
 {
72f588
-    if (pWin->backingStore != NotUseful && !pWin->backStorage) {
72f588
-        compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
72f588
-        pWin->backStorage = TRUE;
72f588
+    Bool should =
72f588
+        (pWin->backingStore == Always) ||
72f588
+        (pWin->backingStore == WhenMapped && pWin->viewable);
72f588
+
72f588
+    if (should && !pWin->backStorage) {
72f588
+        compCheckPaintable(pWin);
72f588
+        if (Success == compRedirectWindow(serverClient, pWin,
72f588
+                                          CompositeRedirectAutomatic))
72f588
+            pWin->backStorage = TRUE;
72f588
     }
72f588
-    else if (pWin->backingStore == NotUseful && pWin->backStorage) {
72f588
-        compUnredirectWindow(serverClient, pWin,
72f588
-                             CompositeRedirectAutomatic);
72f588
-        pWin->backStorage = FALSE;
72f588
+    else if (!should && pWin->backStorage) {
72f588
+        compCheckPaintable(pWin);
72f588
+        if (Success == compUnredirectWindow(serverClient, pWin,
72f588
+                                            CompositeRedirectAutomatic))
72f588
+            pWin->backStorage = FALSE;
72f588
     }
72f588
+    pWin->paintable = pWin->viewable ||
72f588
+        (pWin->backingStore == Always && pWin->backStorage);
72f588
 }
72f588
 
72f588
 /* Fake backing store via automatic redirection */
72f588
@@ -421,6 +438,9 @@ compScreenInit(ScreenPtr pScreen)
72f588
     cs->UnrealizeWindow = pScreen->UnrealizeWindow;
72f588
     pScreen->UnrealizeWindow = compUnrealizeWindow;
72f588
 
72f588
+    cs->WindowExposures = pScreen->WindowExposures;
72f588
+    pScreen->WindowExposures = compWindowExposures;
72f588
+
72f588
     cs->ClipNotify = pScreen->ClipNotify;
72f588
     pScreen->ClipNotify = compClipNotify;
72f588
 
72f588
@@ -433,6 +453,9 @@ compScreenInit(ScreenPtr pScreen)
72f588
     cs->ResizeWindow = pScreen->ResizeWindow;
72f588
     pScreen->ResizeWindow = compResizeWindow;
72f588
 
72f588
+    cs->MarkUnrealizedWindow = pScreen->MarkUnrealizedWindow;
72f588
+    pScreen->MarkUnrealizedWindow = compMarkUnrealizedWindow;
72f588
+
72f588
     cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
72f588
     pScreen->ChangeBorderWidth = compChangeBorderWidth;
72f588
 
72f588
diff --git a/composite/compint.h b/composite/compint.h
72f588
index f05c2d8..e0c02ea 100644
72f588
--- a/composite/compint.h
72f588
+++ b/composite/compint.h
72f588
@@ -131,6 +131,7 @@ typedef struct _CompScreen {
72f588
     DestroyWindowProcPtr DestroyWindow;
72f588
     RealizeWindowProcPtr RealizeWindow;
72f588
     UnrealizeWindowProcPtr UnrealizeWindow;
72f588
+    WindowExposuresProcPtr WindowExposures;
72f588
     ClipNotifyProcPtr ClipNotify;
72f588
     /*
72f588
      * Called from ConfigureWindow, these
72f588
@@ -140,6 +141,7 @@ typedef struct _CompScreen {
72f588
     ConfigNotifyProcPtr ConfigNotify;
72f588
     MoveWindowProcPtr MoveWindow;
72f588
     ResizeWindowProcPtr ResizeWindow;
72f588
+    MarkUnrealizedWindowProcPtr MarkUnrealizedWindow;
72f588
     ChangeBorderWidthProcPtr ChangeBorderWidth;
72f588
     /*
72f588
      * Reparenting has an effect on Subwindows redirect
72f588
@@ -288,6 +290,9 @@ Bool
72f588
 Bool
72f588
  compUnrealizeWindow(WindowPtr pWin);
72f588
 
72f588
+void
72f588
+compWindowExposures(WindowPtr pWin, RegionPtr reg);
72f588
+
72f588
 void
72f588
  compClipNotify(WindowPtr pWin, int dx, int dy);
72f588
 
72f588
@@ -299,6 +304,9 @@ void
72f588
 compResizeWindow(WindowPtr pWin, int x, int y,
72f588
                  unsigned int w, unsigned int h, WindowPtr pSib);
72f588
 
72f588
+void
72f588
+ compMarkUnrealizedWindow(WindowPtr pChild, WindowPtr pWin, Bool fromConfigure);
72f588
+
72f588
 void
72f588
  compChangeBorderWidth(WindowPtr pWin, unsigned int border_width);
72f588
 
72f588
diff --git a/composite/compwindow.c b/composite/compwindow.c
72f588
index bcd230c..19698b8 100644
72f588
--- a/composite/compwindow.c
72f588
+++ b/composite/compwindow.c
72f588
@@ -152,8 +152,10 @@ compCheckRedirect(WindowPtr pWin)
72f588
     CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen);
72f588
     Bool should;
72f588
 
72f588
-    should = pWin->realized && (pWin->drawable.class != InputOnly) &&
72f588
-        (cw != NULL) && (pWin->parent != NULL);
72f588
+    should = (pWin->realized || pWin->backingStore == Always) &&
72f588
+        (pWin->drawable.class != InputOnly) &&
72f588
+        (cw != NULL) &&
72f588
+        (pWin->parent != NULL);
72f588
 
72f588
     /* Never redirect the overlay window */
72f588
     if (cs->pOverlayWin != NULL) {
72f588
@@ -290,6 +292,32 @@ compUnrealizeWindow(WindowPtr pWin)
72f588
     return ret;
72f588
 }
72f588
 
72f588
+void
72f588
+compWindowExposures(WindowPtr pWin, RegionPtr reg)
72f588
+{
72f588
+    ScreenPtr pScreen = pWin->drawable.pScreen;
72f588
+    CompScreenPtr cs = GetCompScreen(pScreen);
72f588
+
72f588
+    pScreen->WindowExposures = cs->WindowExposures;
72f588
+
72f588
+    if (pWin->backStorage) {
72f588
+        DamageDamageRegion(&pWin->drawable, reg);
72f588
+
72f588
+        /* should be RegionEmpty but buggy apps expect an expose */
72f588
+        {
72f588
+            BoxRec box = *RegionExtents(reg);
72f588
+            box.x2 = box.x1 + 1;
72f588
+            box.y2 = box.x1 + 1;
72f588
+            RegionReset(reg, &box);
72f588
+        }
72f588
+    }
72f588
+
72f588
+    pScreen->WindowExposures(pWin, reg);
72f588
+
72f588
+    cs->WindowExposures = pScreen->WindowExposures;
72f588
+    pScreen->WindowExposures = compWindowExposures;
72f588
+}
72f588
+
72f588
 /*
72f588
  * Called after the borderClip for the window has settled down
72f588
  * We use this to make sure our extra borderClip has the right origin
72f588
@@ -432,6 +460,36 @@ compChangeBorderWidth(WindowPtr pWin, unsigned int bw)
72f588
     compCheckTree(pWin->drawable.pScreen);
72f588
 }
72f588
 
72f588
+/*
72f588
+ * pWin is the top-level window being unmapped, pChild is one of its
72f588
+ * (previously viewable) descendents.  MUW under us will try to empty
72f588
+ * the child clip.
72f588
+ */
72f588
+void
72f588
+compMarkUnrealizedWindow(WindowPtr pChild, WindowPtr pWin, Bool fromConfigure)
72f588
+{
72f588
+    Bool should = FALSE;
72f588
+
72f588
+    if (pWin == pChild && pWin->backingStore == Always && pWin->backStorage) {
72f588
+        /* this is the top-level being unmapped, restore paintable */
72f588
+        pWin->paintable = (pWin->drawable.class == InputOutput);
72f588
+    } else if (pChild->parent->paintable && pChild->mapped) {
72f588
+        pChild->paintable = (pWin->drawable.class == InputOutput);
72f588
+    } else {
72f588
+        should = TRUE;
72f588
+    }
72f588
+
72f588
+    if (should) {
72f588
+        ScreenPtr pScreen = pWin->drawable.pScreen;
72f588
+        CompScreenPtr cs = GetCompScreen(pScreen);
72f588
+
72f588
+        pScreen->MarkUnrealizedWindow = cs->MarkUnrealizedWindow;
72f588
+        (*pScreen->MarkUnrealizedWindow) (pChild, pWin, fromConfigure);
72f588
+        cs->MarkUnrealizedWindow = pScreen->MarkUnrealizedWindow;
72f588
+        pScreen->MarkUnrealizedWindow = compMarkUnrealizedWindow;
72f588
+    }
72f588
+}
72f588
+
72f588
 void
72f588
 compReparentWindow(WindowPtr pWin, WindowPtr pPriorParent)
72f588
 {
72f588
@@ -597,6 +655,14 @@ compDestroyWindow(WindowPtr pWin)
72f588
     CompSubwindowsPtr csw;
72f588
     Bool ret;
72f588
 
72f588
+    /*
72f588
+     * Take down bs explicitly, to get ->backStorage cleared
72f588
+     */
72f588
+    if (pWin->backingStore != NotUseful) {
72f588
+        pWin->backingStore = NotUseful;
72f588
+        pScreen->ChangeWindowAttributes(pWin, CWBackingStore);
72f588
+    }
72f588
+
72f588
     pScreen->DestroyWindow = cs->DestroyWindow;
72f588
     while ((cw = GetCompWindow(pWin)))
72f588
         FreeResource(cw->clients->id, RT_NONE);
72f588
diff --git a/dix/window.c b/dix/window.c
72f588
index ead4dc2..1247a56 100644
72f588
--- a/dix/window.c
72f588
+++ b/dix/window.c
72f588
@@ -492,6 +492,7 @@ SetWindowToDefaults(WindowPtr pWin)
72f588
     pWin->mapped = FALSE;       /* off */
72f588
     pWin->realized = FALSE;     /* off */
72f588
     pWin->viewable = FALSE;
72f588
+    pWin->paintable = FALSE;
72f588
     pWin->visibility = VisibilityNotViewable;
72f588
     pWin->overrideRedirect = FALSE;
72f588
     pWin->saveUnder = FALSE;
72f588
@@ -1056,6 +1057,7 @@ CrushTree(WindowPtr pWin)
72f588
             FreeResource(pChild->drawable.id, RT_WINDOW);
72f588
             pSib = pChild->nextSib;
72f588
             pChild->viewable = FALSE;
72f588
+            pChild->paintable = FALSE;
72f588
             if (pChild->realized) {
72f588
                 pChild->realized = FALSE;
72f588
                 (*UnrealizeWindow) (pChild);
72f588
@@ -1587,7 +1589,7 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client)
72f588
        for the tile to be rotated, and the correct function selected.
72f588
      */
72f588
     if (((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) || borderRelative)
72f588
-        && pWin->viewable && HasBorder(pWin)) {
72f588
+        && pWin->paintable && HasBorder(pWin)) {
72f588
         RegionRec exposed;
72f588
 
72f588
         RegionNull(&exposed);
72f588
@@ -2161,7 +2163,7 @@ ReflectStackChange(WindowPtr pWin, WindowPtr pSib, VTKind kind)
72f588
 {
72f588
 /* Note that pSib might be NULL */
72f588
 
72f588
-    Bool WasViewable = (Bool) pWin->viewable;
72f588
+    Bool WasPaintable = (Bool) pWin->paintable;
72f588
     Bool anyMarked;
72f588
     WindowPtr pFirstChange;
72f588
     WindowPtr pLayerWin;
72f588
@@ -2173,7 +2175,7 @@ ReflectStackChange(WindowPtr pWin, WindowPtr pSib, VTKind kind)
72f588
 
72f588
     pFirstChange = MoveWindowInStack(pWin, pSib);
72f588
 
72f588
-    if (WasViewable) {
72f588
+    if (WasPaintable) {
72f588
         anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pFirstChange,
72f588
                                                        &pLayerWin);
72f588
         if (pLayerWin != pWin)
72f588
@@ -2612,8 +2614,9 @@ RealizeTree(WindowPtr pWin)
72f588
     pChild = pWin;
72f588
     while (1) {
72f588
         if (pChild->mapped) {
72f588
-            pChild->realized = TRUE;
72f588
+            pChild->realized = pChild->parent->realized;
72f588
             pChild->viewable = (pChild->drawable.class == InputOutput);
72f588
+            pChild->paintable = (pChild->drawable.class == InputOutput);
72f588
             (*Realize) (pChild);
72f588
             if (pChild->firstChild) {
72f588
                 pChild = pChild->firstChild;
72f588
@@ -2689,7 +2692,7 @@ MapWindow(WindowPtr pWin, ClientPtr client)
72f588
         if (SubStrSend(pWin, pParent))
72f588
             DeliverMapNotify(pWin);
72f588
 
72f588
-        if (!pParent->realized)
72f588
+        if (!pParent->realized && !pParent->paintable)
72f588
             return Success;
72f588
         RealizeTree(pWin);
72f588
         if (pWin->viewable) {
72f588
@@ -2711,6 +2714,7 @@ MapWindow(WindowPtr pWin, ClientPtr client)
72f588
         pWin->mapped = TRUE;
72f588
         pWin->realized = TRUE;  /* for roots */
72f588
         pWin->viewable = pWin->drawable.class == InputOutput;
72f588
+        pWin->paintable = pWin->drawable.class == InputOutput;
72f588
         /* We SHOULD check for an error value here XXX */
72f588
         (*pScreen->RealizeWindow) (pWin);
72f588
         if (pScreen->ClipNotify)
72f588
@@ -2759,7 +2763,7 @@ MapSubwindows(WindowPtr pParent, ClientPtr client)
72f588
 
72f588
             if (!pFirstMapped)
72f588
                 pFirstMapped = pWin;
72f588
-            if (pParent->realized) {
72f588
+            if (pParent->realized || pParent->paintable) {
72f588
                 RealizeTree(pWin);
72f588
                 if (pWin->viewable) {
72f588
                     anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pWin,
72f588
@@ -2817,6 +2821,7 @@ UnrealizeTree(WindowPtr pWin, Bool fromConfigure)
72f588
             DeleteWindowFromAnyEvents(pChild, FALSE);
72f588
             if (pChild->viewable) {
72f588
                 pChild->viewable = FALSE;
72f588
+                pChild->paintable = FALSE;
72f588
                 (*MarkUnrealizedWindow) (pChild, pWin, fromConfigure);
72f588
                 pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
72f588
             }
72f588
@@ -2856,7 +2861,7 @@ UnmapWindow(WindowPtr pWin, Bool fromConfigure)
72f588
 {
72f588
     WindowPtr pParent;
72f588
     Bool wasRealized = (Bool) pWin->realized;
72f588
-    Bool wasViewable = (Bool) pWin->viewable;
72f588
+    Bool wasPaintable = pWin->paintable;
72f588
     ScreenPtr pScreen = pWin->drawable.pScreen;
72f588
     WindowPtr pLayerWin = pWin;
72f588
 
72f588
@@ -2864,21 +2869,19 @@ UnmapWindow(WindowPtr pWin, Bool fromConfigure)
72f588
         return Success;
72f588
     if (SubStrSend(pWin, pParent))
72f588
         DeliverUnmapNotify(pWin, fromConfigure);
72f588
-    if (wasViewable && !fromConfigure) {
72f588
-        pWin->valdata = UnmapValData;
72f588
+    if (wasPaintable && !fromConfigure) {
72f588
+        (*pScreen->MarkWindow) (pWin);
72f588
         (*pScreen->MarkOverlappedWindows) (pWin, pWin->nextSib, &pLayerWin);
72f588
         (*pScreen->MarkWindow) (pLayerWin->parent);
72f588
     }
72f588
     pWin->mapped = FALSE;
72f588
     if (wasRealized)
72f588
         UnrealizeTree(pWin, fromConfigure);
72f588
-    if (wasViewable) {
72f588
-        if (!fromConfigure) {
72f588
-            (*pScreen->ValidateTree) (pLayerWin->parent, pWin, VTUnmap);
72f588
-            (*pScreen->HandleExposures) (pLayerWin->parent);
72f588
-            if (pScreen->PostValidateTree)
72f588
-                (*pScreen->PostValidateTree) (pLayerWin->parent, pWin, VTUnmap);
72f588
-        }
72f588
+    if (wasPaintable && !fromConfigure) {
72f588
+        (*pScreen->ValidateTree) (pLayerWin->parent, pWin, VTUnmap);
72f588
+        (*pScreen->HandleExposures) (pLayerWin->parent);
72f588
+        if (pScreen->PostValidateTree)
72f588
+            (*pScreen->PostValidateTree) (pLayerWin->parent, pWin, VTUnmap);
72f588
     }
72f588
     if (wasRealized && !fromConfigure) {
72f588
         WindowsRestructured();
72f588
@@ -2898,7 +2901,7 @@ UnmapSubwindows(WindowPtr pWin)
72f588
 {
72f588
     WindowPtr pChild, pHead;
72f588
     Bool wasRealized = (Bool) pWin->realized;
72f588
-    Bool wasViewable = (Bool) pWin->viewable;
72f588
+    Bool wasPaintable = pWin->paintable;
72f588
     Bool anyMarked = FALSE;
72f588
     Mask parentNotify;
72f588
     WindowPtr pLayerWin = NULL;
72f588
@@ -2909,7 +2912,7 @@ UnmapSubwindows(WindowPtr pWin)
72f588
     parentNotify = SubSend(pWin);
72f588
     pHead = RealChildHead(pWin);
72f588
 
72f588
-    if (wasViewable)
72f588
+    if (wasPaintable)
72f588
         pLayerWin = (*pScreen->GetLayerWindow) (pWin);
72f588
 
72f588
     for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) {
72f588
@@ -2917,7 +2920,7 @@ UnmapSubwindows(WindowPtr pWin)
72f588
             if (parentNotify || StrSend(pChild))
72f588
                 DeliverUnmapNotify(pChild, xFalse);
72f588
             if (pChild->viewable) {
72f588
-                pChild->valdata = UnmapValData;
72f588
+                (*pScreen->MarkWindow) (pChild);
72f588
                 anyMarked = TRUE;
72f588
             }
72f588
             pChild->mapped = FALSE;
72f588
@@ -2925,31 +2928,28 @@ UnmapSubwindows(WindowPtr pWin)
72f588
                 UnrealizeTree(pChild, FALSE);
72f588
         }
72f588
     }
72f588
-    if (wasViewable) {
72f588
-        if (anyMarked) {
72f588
-            if (pLayerWin->parent == pWin)
72f588
-                (*pScreen->MarkWindow) (pWin);
72f588
-            else {
72f588
-                WindowPtr ptmp;
72f588
+    if (wasPaintable && anyMarked) {
72f588
+        if (pLayerWin->parent == pWin)
72f588
+            (*pScreen->MarkWindow) (pWin);
72f588
+        else {
72f588
+            WindowPtr ptmp;
72f588
 
72f588
-                (*pScreen->MarkOverlappedWindows) (pWin, pLayerWin, NULL);
72f588
-                (*pScreen->MarkWindow) (pLayerWin->parent);
72f588
+            (*pScreen->MarkOverlappedWindows) (pWin, pLayerWin, NULL);
72f588
+            (*pScreen->MarkWindow) (pLayerWin->parent);
72f588
 
72f588
-                /* Windows between pWin and pLayerWin may not have been marked */
72f588
-                ptmp = pWin;
72f588
+            /* Windows between pWin and pLayerWin may not have been marked */
72f588
+            ptmp = pWin;
72f588
 
72f588
-                while (ptmp != pLayerWin->parent) {
72f588
-                    (*pScreen->MarkWindow) (ptmp);
72f588
-                    ptmp = ptmp->parent;
72f588
-                }
72f588
-                pHead = pWin->firstChild;
72f588
+            while (ptmp != pLayerWin->parent) {
72f588
+                (*pScreen->MarkWindow) (ptmp);
72f588
+                ptmp = ptmp->parent;
72f588
             }
72f588
-            (*pScreen->ValidateTree) (pLayerWin->parent, pHead, VTUnmap);
72f588
-            (*pScreen->HandleExposures) (pLayerWin->parent);
72f588
-            if (pScreen->PostValidateTree)
72f588
-                (*pScreen->PostValidateTree) (pLayerWin->parent, pHead,
72f588
-                                              VTUnmap);
72f588
+            pHead = pWin->firstChild;
72f588
         }
72f588
+        (*pScreen->ValidateTree) (pLayerWin->parent, pHead, VTUnmap);
72f588
+        (*pScreen->HandleExposures) (pLayerWin->parent);
72f588
+        if (pScreen->PostValidateTree)
72f588
+            (*pScreen->PostValidateTree) (pLayerWin->parent, pHead, VTUnmap);
72f588
     }
72f588
     if (wasRealized) {
72f588
         WindowsRestructured();
72f588
diff --git a/include/windowstr.h b/include/windowstr.h
72f588
index 4383dab..8a6ef24 100644
72f588
--- a/include/windowstr.h
72f588
+++ b/include/windowstr.h
72f588
@@ -167,6 +167,7 @@ typedef struct _Window {
72f588
     unsigned damagedDescendants:1;      /* some descendants are damaged */
72f588
     unsigned inhibitBGPaint:1;  /* paint the background? */
72f588
 #endif
72f588
+    unsigned paintable:1;
72f588
 } WindowRec;
72f588
 
72f588
 /*
72f588
diff --git a/mi/mibitblt.c b/mi/mibitblt.c
72f588
index 28296a4..69735b0 100644
72f588
--- a/mi/mibitblt.c
72f588
+++ b/mi/mibitblt.c
72f588
@@ -96,9 +96,8 @@ miCopyArea(DrawablePtr pSrcDrawable,
72f588
     srcx = xIn + pSrcDrawable->x;
72f588
     srcy = yIn + pSrcDrawable->y;
72f588
 
72f588
-    /* If the destination isn't realized, this is easy */
72f588
-    if (pDstDrawable->type == DRAWABLE_WINDOW &&
72f588
-        !((WindowPtr) pDstDrawable)->realized)
72f588
+    /* Bail early if we'd do no work */
72f588
+    if (RegionNil(pGC->pCompositeClip))
72f588
         return NULL;
72f588
 
72f588
     /* clip the source */
72f588
diff --git a/mi/micopy.c b/mi/micopy.c
72f588
index 12cdad4..65a8cf5 100644
72f588
--- a/mi/micopy.c
72f588
+++ b/mi/micopy.c
72f588
@@ -152,12 +152,9 @@ miDoCopy(DrawablePtr pSrcDrawable,
72f588
     Bool fastDst = FALSE;       /* for fast clipping with one rect dest */
72f588
     Bool fastExpose = FALSE;    /* for fast exposures with pixmap source */
72f588
 
72f588
-    /* Short cut for unmapped windows */
72f588
-
72f588
-    if (pDstDrawable->type == DRAWABLE_WINDOW &&
72f588
-        !((WindowPtr) pDstDrawable)->realized) {
72f588
+    /* Bail early if we'd do no work */
72f588
+    if (RegionNil(pGC->pCompositeClip))
72f588
         return NULL;
72f588
-    }
72f588
 
72f588
     if (pSrcDrawable->pScreen->SourceValidate) {
72f588
         (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, xIn, yIn,
72f588
diff --git a/mi/mivaltree.c b/mi/mivaltree.c
72f588
index ea6889f..3f44b0f 100644
72f588
--- a/mi/mivaltree.c
72f588
+++ b/mi/mivaltree.c
72f588
@@ -162,16 +162,28 @@ miShapedWindowIn(RegionPtr universe, RegionPtr bounding,
72f588
     return rgnOUT;
72f588
 }
72f588
 
72f588
+static void
72f588
+setVisibility(WindowPtr pWin, int newVis)
72f588
+{
72f588
+    if (pWin->visibility != newVis) {
72f588
+        pWin->visibility = newVis;
72f588
+        if ((pWin->eventMask | wOtherEventMasks(pWin)) & VisibilityChangeMask)
72f588
+            SendVisibilityNotify(pWin);
72f588
+    }
72f588
+}
72f588
+
72f588
 /*
72f588
  * Manual redirected windows are treated as transparent; they do not obscure
72f588
- * siblings or parent windows
72f588
+ * siblings or parent windows.  Likewise windows that are paintable but not
72f588
+ * mapped.
72f588
  */
72f588
 
72f588
-#ifdef COMPOSITE
72f588
-#define TreatAsTransparent(w)	((w)->redirectDraw == RedirectDrawManual)
72f588
-#else
72f588
-#define TreatAsTransparent(w)	FALSE
72f588
-#endif
72f588
+static Bool
72f588
+TreatAsTransparent(WindowPtr w)
72f588
+{
72f588
+    return (w->redirectDraw == RedirectDrawManual) ||
72f588
+        (w->paintable && !w->mapped);
72f588
+}
72f588
 
72f588
 #define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
72f588
 				    HasBorder(w) && \
72f588
@@ -181,7 +193,7 @@ miShapedWindowIn(RegionPtr universe, RegionPtr bounding,
72f588
  *-----------------------------------------------------------------------
72f588
  * miComputeClips --
72f588
  *	Recompute the clipList, borderClip, exposed and borderExposed
72f588
- *	regions for pParent and its children. Only viewable windows are
72f588
+ *	regions for pParent and its children. Only paintable windows are
72f588
  *	taken into account.
72f588
  *
72f588
  * Results:
72f588
@@ -240,40 +252,41 @@ miComputeClips(WindowPtr pParent,
72f588
     }
72f588
 #endif
72f588
 
72f588
-    oldVis = pParent->visibility;
72f588
-    switch (RegionContainsRect(universe, &borderSize)) {
72f588
-    case rgnIN:
72f588
-        newVis = VisibilityUnobscured;
72f588
-        break;
72f588
-    case rgnPART:
72f588
-        newVis = VisibilityPartiallyObscured;
72f588
-        {
72f588
-            RegionPtr pBounding;
72f588
+    oldVis = newVis = pParent->visibility;
72f588
+    if (pParent->realized) {
72f588
+        switch (RegionContainsRect(universe, &borderSize)) {
72f588
+        case rgnIN:
72f588
+            newVis = VisibilityUnobscured;
72f588
+            break;
72f588
+        case rgnPART:
72f588
+            newVis = VisibilityPartiallyObscured;
72f588
+            {
72f588
+                RegionPtr pBounding;
72f588
 
72f588
-            if ((pBounding = wBoundingShape(pParent))) {
72f588
-                switch (miShapedWindowIn(universe, pBounding,
72f588
-                                         &borderSize,
72f588
-                                         pParent->drawable.x,
72f588
-                                         pParent->drawable.y)) {
72f588
-                case rgnIN:
72f588
-                    newVis = VisibilityUnobscured;
72f588
-                    break;
72f588
-                case rgnOUT:
72f588
-                    newVis = VisibilityFullyObscured;
72f588
-                    break;
72f588
+                if ((pBounding = wBoundingShape(pParent))) {
72f588
+                    switch (miShapedWindowIn(universe, pBounding,
72f588
+                                             &borderSize,
72f588
+                                             pParent->drawable.x,
72f588
+                                             pParent->drawable.y)) {
72f588
+                    case rgnIN:
72f588
+                        newVis = VisibilityUnobscured;
72f588
+                        break;
72f588
+                    case rgnOUT:
72f588
+                        newVis = VisibilityFullyObscured;
72f588
+                        break;
72f588
+                    }
72f588
                 }
72f588
             }
72f588
+            break;
72f588
+        default:
72f588
+            newVis = VisibilityFullyObscured;
72f588
+            break;
72f588
         }
72f588
-        break;
72f588
-    default:
72f588
-        newVis = VisibilityFullyObscured;
72f588
-        break;
72f588
     }
72f588
-    pParent->visibility = newVis;
72f588
-    if (oldVis != newVis &&
72f588
-        ((pParent->
72f588
-          eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
72f588
-        SendVisibilityNotify(pParent);
72f588
+    else {
72f588
+        newVis = VisibilityNotViewable;
72f588
+    }
72f588
+    setVisibility(pParent, newVis);
72f588
 
72f588
     dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
72f588
     dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
72f588
@@ -293,14 +306,13 @@ miComputeClips(WindowPtr pParent,
72f588
              (oldVis == VisibilityUnobscured))) {
72f588
             pChild = pParent;
72f588
             while (1) {
72f588
-                if (pChild->viewable) {
72f588
+                if (pChild->paintable) {
72f588
                     if (pChild->visibility != VisibilityFullyObscured) {
72f588
                         RegionTranslate(&pChild->borderClip, dx, dy);
72f588
                         RegionTranslate(&pChild->clipList, dx, dy);
72f588
                         pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
72f588
                         if (pScreen->ClipNotify)
72f588
                             (*pScreen->ClipNotify) (pChild, dx, dy);
72f588
-
72f588
                     }
72f588
                     if (pChild->valdata) {
72f588
                         RegionNull(&pChild->valdata->after.borderExposed);
72f588
@@ -399,22 +411,22 @@ miComputeClips(WindowPtr pParent,
72f588
             ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
72f588
              (pChild->drawable.x < pParent->lastChild->drawable.x))) {
72f588
             for (; pChild; pChild = pChild->nextSib) {
72f588
-                if (pChild->viewable && !TreatAsTransparent(pChild))
72f588
+                if (pChild->paintable && !TreatAsTransparent(pChild))
72f588
                     RegionAppend(&childUnion, &pChild->borderSize);
72f588
             }
72f588
         }
72f588
         else {
72f588
             for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib) {
72f588
-                if (pChild->viewable && !TreatAsTransparent(pChild))
72f588
+                if (pChild->paintable && !TreatAsTransparent(pChild))
72f588
                     RegionAppend(&childUnion, &pChild->borderSize);
72f588
             }
72f588
         }
72f588
         RegionValidate(&childUnion, &overlap);
72f588
 
72f588
         for (pChild = pParent->firstChild; pChild; pChild = pChild->nextSib) {
72f588
-            if (pChild->viewable) {
72f588
+            if (pChild->paintable) {
72f588
                 /*
72f588
-                 * If the child is viewable, we want to remove its extents
72f588
+                 * If the child is paintable, we want to remove its extents
72f588
                  * from the current universe, but we only re-clip it if
72f588
                  * it's been marked.
72f588
                  */
72f588
@@ -482,16 +494,11 @@ static void
72f588
 miTreeObscured(WindowPtr pParent)
72f588
 {
72f588
     WindowPtr pChild;
72f588
-    int oldVis;
72f588
 
72f588
     pChild = pParent;
72f588
     while (1) {
72f588
         if (pChild->viewable) {
72f588
-            oldVis = pChild->visibility;
72f588
-            if (oldVis != (pChild->visibility = VisibilityFullyObscured) &&
72f588
-                ((pChild->
72f588
-                  eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask))
72f588
-                SendVisibilityNotify(pChild);
72f588
+            setVisibility(pChild, VisibilityFullyObscured);
72f588
             if (pChild->firstChild) {
72f588
                 pChild = pChild->firstChild;
72f588
                 continue;
72f588
@@ -564,7 +571,7 @@ miValidateTree(WindowPtr pParent,       /* Parent to validate */
72f588
     ScreenPtr pScreen;
72f588
     WindowPtr pWin;
72f588
     Bool overlap;
72f588
-    int viewvals;
72f588
+    int paintables = 0;
72f588
     Bool forward;
72f588
 
72f588
     pScreen = pParent->drawable.pScreen;
72f588
@@ -581,7 +588,6 @@ miValidateTree(WindowPtr pParent,       /* Parent to validate */
72f588
      * children in their new configuration.
72f588
      */
72f588
     RegionNull(&totalClip);
72f588
-    viewvals = 0;
72f588
     if (RegionBroken(&pParent->clipList) && !RegionBroken(&pParent->borderClip)) {
72f588
         kind = VTBroken;
72f588
         /*
72f588
@@ -593,12 +599,12 @@ miValidateTree(WindowPtr pParent,       /* Parent to validate */
72f588
         RegionIntersect(&totalClip, &totalClip, &pParent->winSize);
72f588
 
72f588
         for (pWin = pParent->firstChild; pWin != pChild; pWin = pWin->nextSib) {
72f588
-            if (pWin->viewable && !TreatAsTransparent(pWin))
72f588
+            if (pWin->paintable && !TreatAsTransparent(pWin))
72f588
                 RegionSubtract(&totalClip, &totalClip, &pWin->borderSize);
72f588
         }
72f588
         for (pWin = pChild; pWin; pWin = pWin->nextSib)
72f588
-            if (pWin->valdata && pWin->viewable)
72f588
-                viewvals++;
72f588
+            if (pWin->valdata && pWin->paintable)
72f588
+                paintables++;
72f588
 
72f588
         RegionEmpty(&pParent->clipList);
72f588
     }
72f588
@@ -610,8 +616,8 @@ miValidateTree(WindowPtr pParent,       /* Parent to validate */
72f588
             for (pWin = pChild; pWin; pWin = pWin->nextSib) {
72f588
                 if (pWin->valdata) {
72f588
                     RegionAppend(&totalClip, getBorderClip(pWin));
72f588
-                    if (pWin->viewable)
72f588
-                        viewvals++;
72f588
+                    if (pWin->paintable)
72f588
+                        paintables++;
72f588
                 }
72f588
             }
72f588
         }
72f588
@@ -621,8 +627,8 @@ miValidateTree(WindowPtr pParent,       /* Parent to validate */
72f588
             while (1) {
72f588
                 if (pWin->valdata) {
72f588
                     RegionAppend(&totalClip, getBorderClip(pWin));
72f588
-                    if (pWin->viewable)
72f588
-                        viewvals++;
72f588
+                    if (pWin->paintable)
72f588
+                        paintables++;
72f588
                 }
72f588
                 if (pWin == pChild)
72f588
                     break;
72f588
@@ -642,7 +648,7 @@ miValidateTree(WindowPtr pParent,       /* Parent to validate */
72f588
     overlap = TRUE;
72f588
     if (kind != VTStack) {
72f588
         RegionUnion(&totalClip, &totalClip, &pParent->clipList);
72f588
-        if (viewvals > 1) {
72f588
+        if (paintables > 1) {
72f588
             /*
72f588
              * precompute childUnion to discover whether any of them
72f588
              * overlap.  This seems redundant, but performance studies
72f588
@@ -653,14 +659,14 @@ miValidateTree(WindowPtr pParent,       /* Parent to validate */
72f588
             RegionNull(&childUnion);
72f588
             if (forward) {
72f588
                 for (pWin = pChild; pWin; pWin = pWin->nextSib)
72f588
-                    if (pWin->valdata && pWin->viewable &&
72f588
+                    if (pWin->valdata && pWin->paintable &&
72f588
                         !TreatAsTransparent(pWin))
72f588
                         RegionAppend(&childUnion, &pWin->borderSize);
72f588
             }
72f588
             else {
72f588
                 pWin = pParent->lastChild;
72f588
                 while (1) {
72f588
-                    if (pWin->valdata && pWin->viewable &&
72f588
+                    if (pWin->valdata && pWin->paintable &&
72f588
                         !TreatAsTransparent(pWin))
72f588
                         RegionAppend(&childUnion, &pWin->borderSize);
72f588
                     if (pWin == pChild)
72f588
@@ -675,7 +681,7 @@ miValidateTree(WindowPtr pParent,       /* Parent to validate */
72f588
     }
72f588
 
72f588
     for (pWin = pChild; pWin != NullWindow; pWin = pWin->nextSib) {
72f588
-        if (pWin->viewable) {
72f588
+        if (pWin->paintable) {
72f588
             if (pWin->valdata) {
72f588
                 RegionIntersect(&childClip, &totalClip, &pWin->borderSize);
72f588
                 miComputeClips(pWin, pScreen, &childClip, kind, &exposed);
72f588
@@ -683,7 +689,8 @@ miValidateTree(WindowPtr pParent,       /* Parent to validate */
72f588
                     RegionSubtract(&totalClip, &totalClip, &pWin->borderSize);
72f588
                 }
72f588
             }
72f588
-            else if (pWin->visibility == VisibilityNotViewable) {
72f588
+            else if (pWin->viewable &&
72f588
+                     pWin->visibility == VisibilityNotViewable) {
72f588
                 miTreeObscured(pWin);
72f588
             }
72f588
         }
72f588
@@ -693,6 +700,7 @@ miValidateTree(WindowPtr pParent,       /* Parent to validate */
72f588
                 if (pScreen->ClipNotify)
72f588
                     (*pScreen->ClipNotify) (pWin, 0, 0);
72f588
                 RegionEmpty(&pWin->borderClip);
72f588
+                free(pWin->valdata);
72f588
                 pWin->valdata = NULL;
72f588
             }
72f588
         }
72f588
diff --git a/mi/miwindow.c b/mi/miwindow.c
72f588
index 39c279e..1b910d9 100644
72f588
--- a/mi/miwindow.c
72f588
+++ b/mi/miwindow.c
72f588
@@ -151,7 +151,7 @@ miMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, WindowPtr *ppLayerWin)
72f588
          */
72f588
         pChild = pWin;
72f588
         while (1) {
72f588
-            if (pChild->viewable) {
72f588
+            if (pChild->paintable) {
72f588
                 if (RegionBroken(&pChild->winSize))
72f588
                     SetWinSize(pChild);
72f588
                 if (RegionBroken(&pChild->borderSize))
72f588
@@ -175,7 +175,7 @@ miMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, WindowPtr *ppLayerWin)
72f588
         box = RegionExtents(&pWin->borderSize);
72f588
         pLast = pChild->parent->lastChild;
72f588
         while (1) {
72f588
-            if (pChild->viewable) {
72f588
+            if (pChild->paintable) {
72f588
                 if (RegionBroken(&pChild->winSize))
72f588
                     SetWinSize(pChild);
72f588
                 if (RegionBroken(&pChild->borderSize))
72f588
@@ -244,7 +244,7 @@ void
72f588
 miMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pNextSib, VTKind kind)
72f588
 {
72f588
     WindowPtr pParent;
72f588
-    Bool WasViewable = (Bool) (pWin->viewable);
72f588
+    Bool WasPaintable = pWin->paintable;
72f588
     short bw;
72f588
     RegionPtr oldRegion = NULL;
72f588
     DDXPointRec oldpt;
72f588
@@ -261,7 +261,7 @@ miMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pNextSib, VTKind kind)
72f588
 
72f588
     oldpt.x = pWin->drawable.x;
72f588
     oldpt.y = pWin->drawable.y;
72f588
-    if (WasViewable) {
72f588
+    if (WasPaintable) {
72f588
         oldRegion = RegionCreate(NullBox, 1);
72f588
         RegionCopy(oldRegion, &pWin->borderClip);
72f588
         anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin);
72f588
@@ -280,7 +280,7 @@ miMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pNextSib, VTKind kind)
72f588
 
72f588
     ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0);
72f588
 
72f588
-    if (WasViewable) {
72f588
+    if (WasPaintable) {
72f588
         if (pLayerWin == pWin)
72f588
             anyMarked |= (*pScreen->MarkOverlappedWindows)
72f588
                 (pWin, windowToValidate, NULL);
72f588
@@ -343,7 +343,7 @@ miResizeWindow(WindowPtr pWin, int x, int y, unsigned int w, unsigned int h,
72f588
                WindowPtr pSib)
72f588
 {
72f588
     WindowPtr pParent;
72f588
-    Bool WasViewable = (Bool) (pWin->viewable);
72f588
+    Bool WasPaintable = pWin->paintable;
72f588
     unsigned short width = pWin->drawable.width, height = pWin->drawable.height;
72f588
     short oldx = pWin->drawable.x, oldy = pWin->drawable.y;
72f588
     int bw = wBorderWidth(pWin);
72f588
@@ -373,7 +373,7 @@ miResizeWindow(WindowPtr pWin, int x, int y, unsigned int w, unsigned int h,
72f588
     pScreen = pWin->drawable.pScreen;
72f588
     newx = pParent->drawable.x + x + bw;
72f588
     newy = pParent->drawable.y + y + bw;
72f588
-    if (WasViewable) {
72f588
+    if (WasPaintable) {
72f588
         anyMarked = FALSE;
72f588
         /*
72f588
          * save the visible region of the window
72f588
@@ -448,7 +448,7 @@ miResizeWindow(WindowPtr pWin, int x, int y, unsigned int w, unsigned int h,
72f588
 
72f588
     pFirstChange = MoveWindowInStack(pWin, pSib);
72f588
 
72f588
-    if (WasViewable) {
72f588
+    if (WasPaintable) {
72f588
         pRegion = RegionCreate(NullBox, 1);
72f588
 
72f588
         if (pLayerWin == pWin)
72f588
@@ -474,7 +474,7 @@ miResizeWindow(WindowPtr pWin, int x, int y, unsigned int w, unsigned int h,
72f588
 
72f588
     GravityTranslate(x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny;;
72f588
 
72f588
-    if (WasViewable) {
72f588
+    if (WasPaintable) {
72f588
         /* avoid the border */
72f588
         if (HasBorder(pWin)) {
72f588
             int offx, offy, dx, dy;
72f588
@@ -636,13 +636,13 @@ miGetLayerWindow(WindowPtr pWin)
72f588
 void
72f588
 miSetShape(WindowPtr pWin, int kind)
72f588
 {
72f588
-    Bool WasViewable = (Bool) (pWin->viewable);
72f588
+    Bool WasPaintable = pWin->paintable;
72f588
     ScreenPtr pScreen = pWin->drawable.pScreen;
72f588
     Bool anyMarked = FALSE;
72f588
     WindowPtr pLayerWin;
72f588
 
72f588
     if (kind != ShapeInput) {
72f588
-        if (WasViewable) {
72f588
+        if (WasPaintable) {
72f588
             anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin,
72f588
                                                            &pLayerWin);
72f588
             if (pWin->valdata) {
72f588
@@ -663,7 +663,7 @@ miSetShape(WindowPtr pWin, int kind)
72f588
 
72f588
         ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
72f588
 
72f588
-        if (WasViewable) {
72f588
+        if (WasPaintable) {
72f588
             anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL);
72f588
 
72f588
             if (anyMarked) {
72f588
@@ -689,7 +689,7 @@ miChangeBorderWidth(WindowPtr pWin, unsigned int width)
72f588
     int oldwidth;
72f588
     Bool anyMarked = FALSE;
72f588
     ScreenPtr pScreen;
72f588
-    Bool WasViewable = (Bool) (pWin->viewable);
72f588
+    Bool WasPaintable = pWin->paintable;
72f588
     Bool HadBorder;
72f588
     WindowPtr pLayerWin;
72f588
 
72f588
@@ -698,13 +698,13 @@ miChangeBorderWidth(WindowPtr pWin, unsigned int width)
72f588
         return;
72f588
     HadBorder = HasBorder(pWin);
72f588
     pScreen = pWin->drawable.pScreen;
72f588
-    if (WasViewable && width < oldwidth)
72f588
+    if (WasPaintable && width < oldwidth)
72f588
         anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin);
72f588
 
72f588
     pWin->borderWidth = width;
72f588
     SetBorderSize(pWin);
72f588
 
72f588
-    if (WasViewable) {
72f588
+    if (WasPaintable) {
72f588
         if (width > oldwidth) {
72f588
             anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin,
72f588
                                                            &pLayerWin);
72f588
-- 
72f588
2.17.0
72f588