From: Ville Syrjälä <[email protected]> If a window has automatically redirected children, the contents of said children is copied to the parent window by compBlockHandler(). Block handlers may not get executed between every request. That may cause following GetImage, graphics ops with IncludeInferiors subwindow mode, etc. requests on the parent to use stale data for the areas covered by automatically redirected children.
The composite protocol seems to allow this: "Automatic shadow update. When a hierarchy is rendered off-screen, the X server provides an automatic mechanism for presenting those contents within the parent window. The implementation is free to make this update lag behind actual rendering operations by an unspecified amount of time. This automatic update mechanism may be disabled so that the parent window contents can be completely determined by an external application." Presumably that means that the client should unredirect the window before the parent window contents need to be determined. That doesn't really work if multiple clients have requested the window to be redirected. But the current behaviour still seems to be OK according to the spec. Implicit redirection also suffers from the same problem since it can't be disabled at all. However the parent window contents under children of different depth is undefined in most cases, so one could say that the current implementation is still OK. Backing store however seems to be the real problem case. AFAICS nothing allows such stale data to appear in the parent window contents under a child which has backing store enabled. So every time that the parent window's contents are expected to be up to date, the contents of the children should be copied immediately to the parent. Instead of trying to identify all parts of the code that have that requirement, add a simple hook into NotClippedByChildren(), which can perform the update process. Hopefully that should cover most of the cases, if not all of them. Signed-off-by: Ville Syrjälä <[email protected]> --- composite/compinit.c | 17 +++-------------- composite/compint.h | 3 +++ composite/compwindow.c | 26 ++++++++++++++++++++++++++ dix/window.c | 15 +++++++++++++++ include/window.h | 4 ++++ 5 files changed, 51 insertions(+), 14 deletions(-) diff --git a/composite/compinit.c b/composite/compinit.c index 5db9f02..29293c5 100644 --- a/composite/compinit.c +++ b/composite/compinit.c @@ -131,19 +131,6 @@ compChangeWindowAttributes(WindowPtr pWin, unsigned long mask) } static void -compScreenUpdate (ScreenPtr pScreen) -{ - CompScreenPtr cs = GetCompScreen (pScreen); - - compCheckTree (pScreen); - if (cs->damaged) - { - compWindowUpdate (pScreen->root); - cs->damaged = FALSE; - } -} - -static void compBlockHandler (int i, pointer blockData, pointer pTimeout, @@ -153,7 +140,7 @@ compBlockHandler (int i, CompScreenPtr cs = GetCompScreen (pScreen); pScreen->BlockHandler = cs->BlockHandler; - compScreenUpdate (pScreen); + CompositeUpdateWindow (pScreen->root); (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); cs->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = compBlockHandler; @@ -397,5 +384,7 @@ compScreenInit (ScreenPtr pScreen) RegisterRealChildHeadProc(CompositeRealChildHead); + RegisterUpdateWindowProc(CompositeUpdateWindow); + return TRUE; } diff --git a/composite/compint.h b/composite/compint.h index b2fc541..a975922 100644 --- a/composite/compint.h +++ b/composite/compint.h @@ -319,6 +319,9 @@ compCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc); void compWindowUpdate (WindowPtr pWin); +void +CompositeUpdateWindow (WindowPtr pWin); + WindowPtr CompositeRealChildHead (WindowPtr pWin); diff --git a/composite/compwindow.c b/composite/compwindow.c index b84c437..7383a29 100644 --- a/composite/compwindow.c +++ b/composite/compwindow.c @@ -733,6 +733,32 @@ compWindowUpdate (WindowPtr pWin) } } +void +CompositeUpdateWindow (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + static Bool updating; + + /* Prevent recursion */ + if (updating) + return; + updating = TRUE; + + compCheckTree (pScreen); + if (cs->damaged) { + WindowPtr pChild; + + for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) + compWindowUpdate (pChild); + + if (pWin == pScreen->root) + cs->damaged = FALSE; + } + + updating = FALSE; +} + WindowPtr CompositeRealChildHead (WindowPtr pWin) { diff --git a/dix/window.c b/dix/window.c index 0362dce..7962bc0 100644 --- a/dix/window.c +++ b/dix/window.c @@ -3005,6 +3005,20 @@ PointInWindowIsVisible(WindowPtr pWin, int x, int y) return FALSE; } +static UpdateWindowProc updateWindowProc = NULL; + +void +RegisterUpdateWindowProc (UpdateWindowProc proc) +{ + updateWindowProc = proc; +} + +static void +UpdateWindow (WindowPtr pWin) +{ + if (updateWindowProc) + updateWindowProc (pWin); +} RegionPtr NotClippedByChildren(WindowPtr pWin) @@ -3015,6 +3029,7 @@ NotClippedByChildren(WindowPtr pWin) !HasSaverWindow (pWin->drawable.pScreen)) { RegionIntersect(pReg, &pWin->borderClip, &pWin->winSize); + UpdateWindow(pWin); } return pReg; } diff --git a/include/window.h b/include/window.h index 6fb2f8c..072a782 100644 --- a/include/window.h +++ b/include/window.h @@ -100,6 +100,10 @@ extern _X_EXPORT void RegisterRealChildHeadProc (RealChildHeadProc proc); extern _X_EXPORT WindowPtr RealChildHead( WindowPtr /*pWin*/); +typedef void (* UpdateWindowProc) (WindowPtr pWin); + +extern _X_EXPORT void RegisterUpdateWindowProc (UpdateWindowProc proc); + extern _X_EXPORT WindowPtr CreateWindow( Window /*wid*/, WindowPtr /*pParent*/, -- 1.7.2.2 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
