1706f2543Smrg/* 2706f2543Smrg * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. 3706f2543Smrg * 4706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5706f2543Smrg * copy of this software and associated documentation files (the "Software"), 6706f2543Smrg * to deal in the Software without restriction, including without limitation 7706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 9706f2543Smrg * Software is furnished to do so, subject to the following conditions: 10706f2543Smrg * 11706f2543Smrg * The above copyright notice and this permission notice (including the next 12706f2543Smrg * paragraph) shall be included in all copies or substantial portions of the 13706f2543Smrg * Software. 14706f2543Smrg * 15706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18706f2543Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19706f2543Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20706f2543Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21706f2543Smrg * DEALINGS IN THE SOFTWARE. 22706f2543Smrg * 23706f2543Smrg * Copyright © 2003 Keith Packard 24706f2543Smrg * 25706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 26706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 27706f2543Smrg * the above copyright notice appear in all copies and that both that 28706f2543Smrg * copyright notice and this permission notice appear in supporting 29706f2543Smrg * documentation, and that the name of Keith Packard not be used in 30706f2543Smrg * advertising or publicity pertaining to distribution of the software without 31706f2543Smrg * specific, written prior permission. Keith Packard makes no 32706f2543Smrg * representations about the suitability of this software for any purpose. It 33706f2543Smrg * is provided "as is" without express or implied warranty. 34706f2543Smrg * 35706f2543Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 36706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 37706f2543Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 38706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 39706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 40706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 41706f2543Smrg * PERFORMANCE OF THIS SOFTWARE. 42706f2543Smrg */ 43706f2543Smrg 44706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 45706f2543Smrg#include <dix-config.h> 46706f2543Smrg#endif 47706f2543Smrg 48706f2543Smrg#include "compint.h" 49706f2543Smrg 50706f2543Smrg#ifdef PANORAMIX 51706f2543Smrg#include "panoramiXsrv.h" 52706f2543Smrg#endif 53706f2543Smrg 54706f2543Smrg#ifdef COMPOSITE_DEBUG 55706f2543Smrgstatic int 56706f2543SmrgcompCheckWindow (WindowPtr pWin, pointer data) 57706f2543Smrg{ 58706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 59706f2543Smrg PixmapPtr pWinPixmap = (*pScreen->GetWindowPixmap) (pWin); 60706f2543Smrg PixmapPtr pParentPixmap = pWin->parent ? (*pScreen->GetWindowPixmap) (pWin->parent) : 0; 61706f2543Smrg PixmapPtr pScreenPixmap = (*pScreen->GetScreenPixmap) (pScreen); 62706f2543Smrg 63706f2543Smrg if (!pWin->parent) 64706f2543Smrg { 65706f2543Smrg assert (pWin->redirectDraw == RedirectDrawNone); 66706f2543Smrg assert (pWinPixmap == pScreenPixmap); 67706f2543Smrg } 68706f2543Smrg else if (pWin->redirectDraw != RedirectDrawNone) 69706f2543Smrg { 70706f2543Smrg assert (pWinPixmap != pParentPixmap); 71706f2543Smrg assert (pWinPixmap != pScreenPixmap); 72706f2543Smrg } 73706f2543Smrg else 74706f2543Smrg { 75706f2543Smrg assert (pWinPixmap == pParentPixmap); 76706f2543Smrg } 77706f2543Smrg assert (0 < pWinPixmap->refcnt && pWinPixmap->refcnt < 3); 78706f2543Smrg assert (0 < pScreenPixmap->refcnt && pScreenPixmap->refcnt < 3); 79706f2543Smrg if (pParentPixmap) 80706f2543Smrg assert (0 <= pParentPixmap->refcnt && pParentPixmap->refcnt < 3); 81706f2543Smrg return WT_WALKCHILDREN; 82706f2543Smrg} 83706f2543Smrg 84706f2543Smrgvoid 85706f2543SmrgcompCheckTree (ScreenPtr pScreen) 86706f2543Smrg{ 87706f2543Smrg WalkTree (pScreen, compCheckWindow, 0); 88706f2543Smrg} 89706f2543Smrg#endif 90706f2543Smrg 91706f2543Smrgtypedef struct _compPixmapVisit { 92706f2543Smrg WindowPtr pWindow; 93706f2543Smrg PixmapPtr pPixmap; 94706f2543Smrg} CompPixmapVisitRec, *CompPixmapVisitPtr; 95706f2543Smrg 96706f2543Smrgstatic Bool 97706f2543SmrgcompRepaintBorder (ClientPtr pClient, pointer closure) 98706f2543Smrg{ 99706f2543Smrg WindowPtr pWindow; 100706f2543Smrg int rc = dixLookupWindow(&pWindow, (XID)(intptr_t)closure, pClient, DixWriteAccess); 101706f2543Smrg 102706f2543Smrg if (rc == Success) { 103706f2543Smrg RegionRec exposed; 104706f2543Smrg 105706f2543Smrg RegionNull(&exposed); 106706f2543Smrg RegionSubtract(&exposed, &pWindow->borderClip, &pWindow->winSize); 107706f2543Smrg miPaintWindow(pWindow, &exposed, PW_BORDER); 108706f2543Smrg RegionUninit(&exposed); 109706f2543Smrg } 110706f2543Smrg return TRUE; 111706f2543Smrg} 112706f2543Smrg 113706f2543Smrgstatic int 114706f2543SmrgcompSetPixmapVisitWindow (WindowPtr pWindow, pointer data) 115706f2543Smrg{ 116706f2543Smrg CompPixmapVisitPtr pVisit = (CompPixmapVisitPtr) data; 117706f2543Smrg ScreenPtr pScreen = pWindow->drawable.pScreen; 118706f2543Smrg 119706f2543Smrg if (pWindow != pVisit->pWindow && pWindow->redirectDraw != RedirectDrawNone) 120706f2543Smrg return WT_DONTWALKCHILDREN; 121706f2543Smrg (*pScreen->SetWindowPixmap) (pWindow, pVisit->pPixmap); 122706f2543Smrg /* 123706f2543Smrg * Recompute winSize and borderSize. This is duplicate effort 124706f2543Smrg * when resizing pixmaps, but necessary when changing redirection. 125706f2543Smrg * Might be nice to fix this. 126706f2543Smrg */ 127706f2543Smrg SetWinSize (pWindow); 128706f2543Smrg SetBorderSize (pWindow); 129706f2543Smrg if (HasBorder (pWindow)) 130706f2543Smrg QueueWorkProc (compRepaintBorder, serverClient, 131706f2543Smrg (pointer)(intptr_t) pWindow->drawable.id); 132706f2543Smrg return WT_WALKCHILDREN; 133706f2543Smrg} 134706f2543Smrg 135706f2543Smrgvoid 136706f2543SmrgcompSetPixmap (WindowPtr pWindow, PixmapPtr pPixmap) 137706f2543Smrg{ 138706f2543Smrg CompPixmapVisitRec visitRec; 139706f2543Smrg 140706f2543Smrg visitRec.pWindow = pWindow; 141706f2543Smrg visitRec.pPixmap = pPixmap; 142706f2543Smrg TraverseTree (pWindow, compSetPixmapVisitWindow, (pointer) &visitRec); 143706f2543Smrg compCheckTree (pWindow->drawable.pScreen); 144706f2543Smrg} 145706f2543Smrg 146706f2543SmrgBool 147706f2543SmrgcompCheckRedirect (WindowPtr pWin) 148706f2543Smrg{ 149706f2543Smrg CompWindowPtr cw = GetCompWindow (pWin); 150706f2543Smrg CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); 151706f2543Smrg Bool should; 152706f2543Smrg 153706f2543Smrg should = pWin->realized && (pWin->drawable.class != InputOnly) && 154706f2543Smrg (cw != NULL) && (pWin->parent != NULL); 155706f2543Smrg 156706f2543Smrg /* Never redirect the overlay window */ 157706f2543Smrg if (cs->pOverlayWin != NULL) { 158706f2543Smrg if (pWin == cs->pOverlayWin) { 159706f2543Smrg should = FALSE; 160706f2543Smrg } 161706f2543Smrg } 162706f2543Smrg 163706f2543Smrg if (should != (pWin->redirectDraw != RedirectDrawNone)) 164706f2543Smrg { 165706f2543Smrg if (should) 166706f2543Smrg return compAllocPixmap (pWin); 167706f2543Smrg else 168706f2543Smrg compFreePixmap (pWin); 169706f2543Smrg } 170706f2543Smrg return TRUE; 171706f2543Smrg} 172706f2543Smrg 173706f2543Smrgstatic int 174706f2543SmrgupdateOverlayWindow(ScreenPtr pScreen) 175706f2543Smrg{ 176706f2543Smrg CompScreenPtr cs; 177706f2543Smrg WindowPtr pWin; /* overlay window */ 178706f2543Smrg XID vlist[2]; 179706f2543Smrg int w = pScreen->width; 180706f2543Smrg int h = pScreen->height; 181706f2543Smrg 182706f2543Smrg#ifdef PANORAMIX 183706f2543Smrg if (!noPanoramiXExtension) 184706f2543Smrg { 185706f2543Smrg w = PanoramiXPixWidth; 186706f2543Smrg h = PanoramiXPixHeight; 187706f2543Smrg } 188706f2543Smrg#endif 189706f2543Smrg 190706f2543Smrg cs = GetCompScreen(pScreen); 191706f2543Smrg if ((pWin = cs->pOverlayWin) != NULL) { 192706f2543Smrg if ((pWin->drawable.width == w) && 193706f2543Smrg (pWin->drawable.height == h)) 194706f2543Smrg return Success; 195706f2543Smrg 196706f2543Smrg /* Let's resize the overlay window. */ 197706f2543Smrg vlist[0] = w; 198706f2543Smrg vlist[1] = h; 199706f2543Smrg return ConfigureWindow(pWin, CWWidth | CWHeight, vlist, wClient(pWin)); 200706f2543Smrg } 201706f2543Smrg 202706f2543Smrg /* Let's be on the safe side and not assume an overlay window is always allocated. */ 203706f2543Smrg return Success; 204706f2543Smrg} 205706f2543Smrg 206706f2543SmrgBool 207706f2543SmrgcompPositionWindow (WindowPtr pWin, int x, int y) 208706f2543Smrg{ 209706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 210706f2543Smrg CompScreenPtr cs = GetCompScreen (pScreen); 211706f2543Smrg Bool ret = TRUE; 212706f2543Smrg 213706f2543Smrg pScreen->PositionWindow = cs->PositionWindow; 214706f2543Smrg /* 215706f2543Smrg * "Shouldn't need this as all possible places should be wrapped 216706f2543Smrg * 217706f2543Smrg compCheckRedirect (pWin); 218706f2543Smrg */ 219706f2543Smrg#ifdef COMPOSITE_DEBUG 220706f2543Smrg if ((pWin->redirectDraw != RedirectDrawNone) != 221706f2543Smrg (pWin->viewable && (GetCompWindow(pWin) != NULL))) 222706f2543Smrg OsAbort (); 223706f2543Smrg#endif 224706f2543Smrg if (pWin->redirectDraw != RedirectDrawNone) 225706f2543Smrg { 226706f2543Smrg PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); 227706f2543Smrg int bw = wBorderWidth (pWin); 228706f2543Smrg int nx = pWin->drawable.x - bw; 229706f2543Smrg int ny = pWin->drawable.y - bw; 230706f2543Smrg 231706f2543Smrg if (pPixmap->screen_x != nx || pPixmap->screen_y != ny) 232706f2543Smrg { 233706f2543Smrg pPixmap->screen_x = nx; 234706f2543Smrg pPixmap->screen_y = ny; 235706f2543Smrg pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 236706f2543Smrg } 237706f2543Smrg } 238706f2543Smrg 239706f2543Smrg if (!(*pScreen->PositionWindow) (pWin, x, y)) 240706f2543Smrg ret = FALSE; 241706f2543Smrg cs->PositionWindow = pScreen->PositionWindow; 242706f2543Smrg pScreen->PositionWindow = compPositionWindow; 243706f2543Smrg compCheckTree (pWin->drawable.pScreen); 244706f2543Smrg if (updateOverlayWindow(pScreen) != Success) 245706f2543Smrg ret = FALSE; 246706f2543Smrg return ret; 247706f2543Smrg} 248706f2543Smrg 249706f2543SmrgBool 250706f2543SmrgcompRealizeWindow (WindowPtr pWin) 251706f2543Smrg{ 252706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 253706f2543Smrg CompScreenPtr cs = GetCompScreen (pScreen); 254706f2543Smrg Bool ret = TRUE; 255706f2543Smrg 256706f2543Smrg pScreen->RealizeWindow = cs->RealizeWindow; 257706f2543Smrg compCheckRedirect (pWin); 258706f2543Smrg if (!(*pScreen->RealizeWindow) (pWin)) 259706f2543Smrg ret = FALSE; 260706f2543Smrg cs->RealizeWindow = pScreen->RealizeWindow; 261706f2543Smrg pScreen->RealizeWindow = compRealizeWindow; 262706f2543Smrg compCheckTree (pWin->drawable.pScreen); 263706f2543Smrg return ret; 264706f2543Smrg} 265706f2543Smrg 266706f2543SmrgBool 267706f2543SmrgcompUnrealizeWindow (WindowPtr pWin) 268706f2543Smrg{ 269706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 270706f2543Smrg CompScreenPtr cs = GetCompScreen (pScreen); 271706f2543Smrg Bool ret = TRUE; 272706f2543Smrg 273706f2543Smrg pScreen->UnrealizeWindow = cs->UnrealizeWindow; 274706f2543Smrg compCheckRedirect (pWin); 275706f2543Smrg if (!(*pScreen->UnrealizeWindow) (pWin)) 276706f2543Smrg ret = FALSE; 277706f2543Smrg cs->UnrealizeWindow = pScreen->UnrealizeWindow; 278706f2543Smrg pScreen->UnrealizeWindow = compUnrealizeWindow; 279706f2543Smrg compCheckTree (pWin->drawable.pScreen); 280706f2543Smrg return ret; 281706f2543Smrg} 282706f2543Smrg 283706f2543Smrg/* 284706f2543Smrg * Called after the borderClip for the window has settled down 285706f2543Smrg * We use this to make sure our extra borderClip has the right origin 286706f2543Smrg */ 287706f2543Smrg 288706f2543Smrgvoid 289706f2543SmrgcompClipNotify (WindowPtr pWin, int dx, int dy) 290706f2543Smrg{ 291706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 292706f2543Smrg CompScreenPtr cs = GetCompScreen (pScreen); 293706f2543Smrg CompWindowPtr cw = GetCompWindow (pWin); 294706f2543Smrg 295706f2543Smrg if (cw) 296706f2543Smrg { 297706f2543Smrg if (cw->borderClipX != pWin->drawable.x || 298706f2543Smrg cw->borderClipY != pWin->drawable.y) 299706f2543Smrg { 300706f2543Smrg RegionTranslate(&cw->borderClip, 301706f2543Smrg pWin->drawable.x - cw->borderClipX, 302706f2543Smrg pWin->drawable.y - cw->borderClipY); 303706f2543Smrg cw->borderClipX = pWin->drawable.x; 304706f2543Smrg cw->borderClipY = pWin->drawable.y; 305706f2543Smrg } 306706f2543Smrg } 307706f2543Smrg if (cs->ClipNotify) 308706f2543Smrg { 309706f2543Smrg pScreen->ClipNotify = cs->ClipNotify; 310706f2543Smrg (*pScreen->ClipNotify) (pWin, dx, dy); 311706f2543Smrg cs->ClipNotify = pScreen->ClipNotify; 312706f2543Smrg pScreen->ClipNotify = compClipNotify; 313706f2543Smrg } 314706f2543Smrg} 315706f2543Smrg 316706f2543Smrg/* 317706f2543Smrg * Returns TRUE if the window needs server-provided automatic redirect, 318706f2543Smrg * which is true if the child and parent aren't both regular or ARGB visuals 319706f2543Smrg */ 320706f2543Smrg 321706f2543Smrgstatic Bool 322706f2543SmrgcompIsAlternateVisual (ScreenPtr pScreen, 323706f2543Smrg XID visual) 324706f2543Smrg{ 325706f2543Smrg CompScreenPtr cs = GetCompScreen (pScreen); 326706f2543Smrg int i; 327706f2543Smrg 328706f2543Smrg for (i = 0; i < cs->numAlternateVisuals; i++) 329706f2543Smrg if (cs->alternateVisuals[i] == visual) 330706f2543Smrg return TRUE; 331706f2543Smrg return FALSE; 332706f2543Smrg} 333706f2543Smrg 334706f2543Smrgstatic Bool 335706f2543SmrgcompImplicitRedirect (WindowPtr pWin, WindowPtr pParent) 336706f2543Smrg{ 337706f2543Smrg if (pParent) 338706f2543Smrg { 339706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 340706f2543Smrg XID winVisual = wVisual (pWin); 341706f2543Smrg XID parentVisual = wVisual (pParent); 342706f2543Smrg 343706f2543Smrg if (winVisual != parentVisual && 344706f2543Smrg (compIsAlternateVisual (pScreen, winVisual) || 345706f2543Smrg compIsAlternateVisual (pScreen, parentVisual))) 346706f2543Smrg return TRUE; 347706f2543Smrg } 348706f2543Smrg return FALSE; 349706f2543Smrg} 350706f2543Smrg 351706f2543Smrgstatic void compFreeOldPixmap(WindowPtr pWin) 352706f2543Smrg{ 353706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 354706f2543Smrg if (pWin->redirectDraw != RedirectDrawNone) 355706f2543Smrg { 356706f2543Smrg CompWindowPtr cw = GetCompWindow (pWin); 357706f2543Smrg if (cw->pOldPixmap) 358706f2543Smrg { 359706f2543Smrg (*pScreen->DestroyPixmap) (cw->pOldPixmap); 360706f2543Smrg cw->pOldPixmap = NullPixmap; 361706f2543Smrg } 362706f2543Smrg } 363706f2543Smrg} 364706f2543Smrgvoid 365706f2543SmrgcompMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) 366706f2543Smrg{ 367706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 368706f2543Smrg CompScreenPtr cs = GetCompScreen (pScreen); 369706f2543Smrg 370706f2543Smrg pScreen->MoveWindow = cs->MoveWindow; 371706f2543Smrg (*pScreen->MoveWindow) (pWin, x, y, pSib, kind); 372706f2543Smrg cs->MoveWindow = pScreen->MoveWindow; 373706f2543Smrg pScreen->MoveWindow = compMoveWindow; 374706f2543Smrg 375706f2543Smrg compFreeOldPixmap(pWin); 376706f2543Smrg compCheckTree (pScreen); 377706f2543Smrg} 378706f2543Smrg 379706f2543Smrgvoid 380706f2543SmrgcompResizeWindow (WindowPtr pWin, int x, int y, 381706f2543Smrg unsigned int w, unsigned int h, WindowPtr pSib) 382706f2543Smrg{ 383706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 384706f2543Smrg CompScreenPtr cs = GetCompScreen (pScreen); 385706f2543Smrg 386706f2543Smrg pScreen->ResizeWindow = cs->ResizeWindow; 387706f2543Smrg (*pScreen->ResizeWindow) (pWin, x, y, w, h, pSib); 388706f2543Smrg cs->ResizeWindow = pScreen->ResizeWindow; 389706f2543Smrg pScreen->ResizeWindow = compResizeWindow; 390706f2543Smrg 391706f2543Smrg compFreeOldPixmap(pWin); 392706f2543Smrg compCheckTree (pWin->drawable.pScreen); 393706f2543Smrg} 394706f2543Smrg 395706f2543Smrgvoid 396706f2543SmrgcompChangeBorderWidth (WindowPtr pWin, unsigned int bw) 397706f2543Smrg{ 398706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 399706f2543Smrg CompScreenPtr cs = GetCompScreen (pScreen); 400706f2543Smrg 401706f2543Smrg pScreen->ChangeBorderWidth = cs->ChangeBorderWidth; 402706f2543Smrg (*pScreen->ChangeBorderWidth) (pWin, bw); 403706f2543Smrg cs->ChangeBorderWidth = pScreen->ChangeBorderWidth; 404706f2543Smrg pScreen->ChangeBorderWidth = compChangeBorderWidth; 405706f2543Smrg 406706f2543Smrg compFreeOldPixmap(pWin); 407706f2543Smrg compCheckTree (pWin->drawable.pScreen); 408706f2543Smrg} 409706f2543Smrg 410706f2543Smrgvoid 411706f2543SmrgcompReparentWindow (WindowPtr pWin, WindowPtr pPriorParent) 412706f2543Smrg{ 413706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 414706f2543Smrg CompScreenPtr cs = GetCompScreen (pScreen); 415706f2543Smrg 416706f2543Smrg pScreen->ReparentWindow = cs->ReparentWindow; 417706f2543Smrg /* 418706f2543Smrg * Remove any implicit redirect due to synthesized visual 419706f2543Smrg */ 420706f2543Smrg if (compImplicitRedirect (pWin, pPriorParent)) 421706f2543Smrg compUnredirectWindow (serverClient, pWin, CompositeRedirectAutomatic); 422706f2543Smrg /* 423706f2543Smrg * Handle subwindows redirection 424706f2543Smrg */ 425706f2543Smrg compUnredirectOneSubwindow (pPriorParent, pWin); 426706f2543Smrg compRedirectOneSubwindow (pWin->parent, pWin); 427706f2543Smrg /* 428706f2543Smrg * Add any implict redirect due to synthesized visual 429706f2543Smrg */ 430706f2543Smrg if (compImplicitRedirect (pWin, pWin->parent)) 431706f2543Smrg compRedirectWindow (serverClient, pWin, CompositeRedirectAutomatic); 432706f2543Smrg 433706f2543Smrg /* 434706f2543Smrg * Allocate any necessary redirect pixmap 435706f2543Smrg * (this actually should never be true; pWin is always unmapped) 436706f2543Smrg */ 437706f2543Smrg compCheckRedirect (pWin); 438706f2543Smrg 439706f2543Smrg /* 440706f2543Smrg * Reset pixmap pointers as appropriate 441706f2543Smrg */ 442706f2543Smrg if (pWin->parent && pWin->redirectDraw == RedirectDrawNone) 443706f2543Smrg compSetPixmap (pWin, (*pScreen->GetWindowPixmap) (pWin->parent)); 444706f2543Smrg /* 445706f2543Smrg * Call down to next function 446706f2543Smrg */ 447706f2543Smrg if (pScreen->ReparentWindow) 448706f2543Smrg (*pScreen->ReparentWindow) (pWin, pPriorParent); 449706f2543Smrg cs->ReparentWindow = pScreen->ReparentWindow; 450706f2543Smrg pScreen->ReparentWindow = compReparentWindow; 451706f2543Smrg compCheckTree (pWin->drawable.pScreen); 452706f2543Smrg} 453706f2543Smrg 454706f2543Smrgvoid 455706f2543SmrgcompCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 456706f2543Smrg{ 457706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 458706f2543Smrg CompScreenPtr cs = GetCompScreen (pScreen); 459706f2543Smrg int dx = 0, dy = 0; 460706f2543Smrg 461706f2543Smrg if (pWin->redirectDraw != RedirectDrawNone) 462706f2543Smrg { 463706f2543Smrg PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); 464706f2543Smrg CompWindowPtr cw = GetCompWindow (pWin); 465706f2543Smrg 466706f2543Smrg assert (cw->oldx != COMP_ORIGIN_INVALID); 467706f2543Smrg assert (cw->oldy != COMP_ORIGIN_INVALID); 468706f2543Smrg if (cw->pOldPixmap) 469706f2543Smrg { 470706f2543Smrg /* 471706f2543Smrg * Ok, the old bits are available in pOldPixmap and 472706f2543Smrg * need to be copied to pNewPixmap. 473706f2543Smrg */ 474706f2543Smrg RegionRec rgnDst; 475706f2543Smrg PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); 476706f2543Smrg GCPtr pGC; 477706f2543Smrg 478706f2543Smrg dx = ptOldOrg.x - pWin->drawable.x; 479706f2543Smrg dy = ptOldOrg.y - pWin->drawable.y; 480706f2543Smrg RegionTranslate(prgnSrc, -dx, -dy); 481706f2543Smrg 482706f2543Smrg RegionNull(&rgnDst); 483706f2543Smrg 484706f2543Smrg RegionIntersect(&rgnDst, 485706f2543Smrg &pWin->borderClip, prgnSrc); 486706f2543Smrg 487706f2543Smrg RegionTranslate(&rgnDst, 488706f2543Smrg -pPixmap->screen_x, -pPixmap->screen_y); 489706f2543Smrg 490706f2543Smrg dx = dx + pPixmap->screen_x - cw->oldx; 491706f2543Smrg dy = dy + pPixmap->screen_y - cw->oldy; 492706f2543Smrg pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); 493706f2543Smrg if (pGC) 494706f2543Smrg { 495706f2543Smrg BoxPtr pBox = RegionRects (&rgnDst); 496706f2543Smrg int nBox = RegionNumRects (&rgnDst); 497706f2543Smrg 498706f2543Smrg ValidateGC(&pPixmap->drawable, pGC); 499706f2543Smrg while (nBox--) 500706f2543Smrg { 501706f2543Smrg (void) (*pGC->ops->CopyArea) (&cw->pOldPixmap->drawable, 502706f2543Smrg &pPixmap->drawable, 503706f2543Smrg pGC, 504706f2543Smrg pBox->x1 + dx, pBox->y1 + dy, 505706f2543Smrg pBox->x2 - pBox->x1, 506706f2543Smrg pBox->y2 - pBox->y1, 507706f2543Smrg pBox->x1, pBox->y1); 508706f2543Smrg pBox++; 509706f2543Smrg } 510706f2543Smrg FreeScratchGC (pGC); 511706f2543Smrg } 512706f2543Smrg return; 513706f2543Smrg } 514706f2543Smrg dx = pPixmap->screen_x - cw->oldx; 515706f2543Smrg dy = pPixmap->screen_y - cw->oldy; 516706f2543Smrg ptOldOrg.x += dx; 517706f2543Smrg ptOldOrg.y += dy; 518706f2543Smrg } 519706f2543Smrg 520706f2543Smrg pScreen->CopyWindow = cs->CopyWindow; 521706f2543Smrg if (ptOldOrg.x != pWin->drawable.x || ptOldOrg.y != pWin->drawable.y) 522706f2543Smrg { 523706f2543Smrg if (dx || dy) 524706f2543Smrg RegionTranslate(prgnSrc, dx, dy); 525706f2543Smrg (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); 526706f2543Smrg if (dx || dy) 527706f2543Smrg RegionTranslate(prgnSrc, -dx, -dy); 528706f2543Smrg } 529706f2543Smrg else 530706f2543Smrg { 531706f2543Smrg ptOldOrg.x -= dx; 532706f2543Smrg ptOldOrg.y -= dy; 533706f2543Smrg RegionTranslate(prgnSrc, 534706f2543Smrg pWin->drawable.x - ptOldOrg.x, 535706f2543Smrg pWin->drawable.y - ptOldOrg.y); 536706f2543Smrg DamageDamageRegion(&pWin->drawable, prgnSrc); 537706f2543Smrg } 538706f2543Smrg cs->CopyWindow = pScreen->CopyWindow; 539706f2543Smrg pScreen->CopyWindow = compCopyWindow; 540706f2543Smrg compCheckTree (pWin->drawable.pScreen); 541706f2543Smrg} 542706f2543Smrg 543706f2543SmrgBool 544706f2543SmrgcompCreateWindow (WindowPtr pWin) 545706f2543Smrg{ 546706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 547706f2543Smrg CompScreenPtr cs = GetCompScreen (pScreen); 548706f2543Smrg Bool ret; 549706f2543Smrg 550706f2543Smrg pScreen->CreateWindow = cs->CreateWindow; 551706f2543Smrg ret = (*pScreen->CreateWindow) (pWin); 552706f2543Smrg if (pWin->parent && ret) 553706f2543Smrg { 554706f2543Smrg CompSubwindowsPtr csw = GetCompSubwindows (pWin->parent); 555706f2543Smrg CompClientWindowPtr ccw; 556706f2543Smrg 557706f2543Smrg (*pScreen->SetWindowPixmap) (pWin, (*pScreen->GetWindowPixmap) (pWin->parent)); 558706f2543Smrg if (csw) 559706f2543Smrg for (ccw = csw->clients; ccw; ccw = ccw->next) 560706f2543Smrg compRedirectWindow (clients[CLIENT_ID(ccw->id)], 561706f2543Smrg pWin, ccw->update); 562706f2543Smrg if (compImplicitRedirect (pWin, pWin->parent)) 563706f2543Smrg compRedirectWindow (serverClient, pWin, CompositeRedirectAutomatic); 564706f2543Smrg } 565706f2543Smrg cs->CreateWindow = pScreen->CreateWindow; 566706f2543Smrg pScreen->CreateWindow = compCreateWindow; 567706f2543Smrg compCheckTree (pWin->drawable.pScreen); 568706f2543Smrg return ret; 569706f2543Smrg} 570706f2543Smrg 571706f2543SmrgBool 572706f2543SmrgcompDestroyWindow (WindowPtr pWin) 573706f2543Smrg{ 574706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 575706f2543Smrg CompScreenPtr cs = GetCompScreen (pScreen); 576706f2543Smrg CompWindowPtr cw; 577706f2543Smrg CompSubwindowsPtr csw; 578706f2543Smrg Bool ret; 579706f2543Smrg 580706f2543Smrg pScreen->DestroyWindow = cs->DestroyWindow; 581706f2543Smrg while ((cw = GetCompWindow (pWin))) 582706f2543Smrg FreeResource (cw->clients->id, RT_NONE); 583706f2543Smrg while ((csw = GetCompSubwindows (pWin))) 584706f2543Smrg FreeResource (csw->clients->id, RT_NONE); 585706f2543Smrg 586706f2543Smrg if (pWin->redirectDraw != RedirectDrawNone) 587706f2543Smrg compFreePixmap (pWin); 588706f2543Smrg ret = (*pScreen->DestroyWindow) (pWin); 589706f2543Smrg cs->DestroyWindow = pScreen->DestroyWindow; 590706f2543Smrg pScreen->DestroyWindow = compDestroyWindow; 59184795101Smrg 59284795101Smrg /* Did we just destroy the overlay window? */ 59384795101Smrg if (pWin == cs->pOverlayWin) 59484795101Smrg cs->pOverlayWin = NULL; 59584795101Smrg 596706f2543Smrg/* compCheckTree (pWin->drawable.pScreen); can't check -- tree isn't good*/ 597706f2543Smrg return ret; 598706f2543Smrg} 599706f2543Smrg 600706f2543Smrgvoid 601706f2543SmrgcompSetRedirectBorderClip (WindowPtr pWin, RegionPtr pRegion) 602706f2543Smrg{ 603706f2543Smrg CompWindowPtr cw = GetCompWindow (pWin); 604706f2543Smrg RegionRec damage; 605706f2543Smrg 606706f2543Smrg RegionNull(&damage); 607706f2543Smrg /* 608706f2543Smrg * Align old border clip with new border clip 609706f2543Smrg */ 610706f2543Smrg RegionTranslate(&cw->borderClip, 611706f2543Smrg pWin->drawable.x - cw->borderClipX, 612706f2543Smrg pWin->drawable.y - cw->borderClipY); 613706f2543Smrg /* 614706f2543Smrg * Compute newly visible portion of window for repaint 615706f2543Smrg */ 616706f2543Smrg RegionSubtract(&damage, pRegion, &cw->borderClip); 617706f2543Smrg /* 618706f2543Smrg * Report that as damaged so it will be redrawn 619706f2543Smrg */ 620706f2543Smrg DamageDamageRegion(&pWin->drawable, &damage); 621706f2543Smrg RegionUninit(&damage); 622706f2543Smrg /* 623706f2543Smrg * Save the new border clip region 624706f2543Smrg */ 625706f2543Smrg RegionCopy(&cw->borderClip, pRegion); 626706f2543Smrg cw->borderClipX = pWin->drawable.x; 627706f2543Smrg cw->borderClipY = pWin->drawable.y; 628706f2543Smrg} 629706f2543Smrg 630706f2543SmrgRegionPtr 631706f2543SmrgcompGetRedirectBorderClip (WindowPtr pWin) 632706f2543Smrg{ 633706f2543Smrg CompWindowPtr cw = GetCompWindow (pWin); 634706f2543Smrg 635706f2543Smrg return &cw->borderClip; 636706f2543Smrg} 637706f2543Smrg 638706f2543Smrgstatic VisualPtr 639706f2543SmrgcompGetWindowVisual (WindowPtr pWin) 640706f2543Smrg{ 641706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 642706f2543Smrg VisualID vid = wVisual (pWin); 643706f2543Smrg int i; 644706f2543Smrg 645706f2543Smrg for (i = 0; i < pScreen->numVisuals; i++) 646706f2543Smrg if (pScreen->visuals[i].vid == vid) 647706f2543Smrg return &pScreen->visuals[i]; 648706f2543Smrg return 0; 649706f2543Smrg} 650706f2543Smrg 651706f2543SmrgPictFormatPtr 652706f2543SmrgcompWindowFormat (WindowPtr pWin) 653706f2543Smrg{ 654706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 655706f2543Smrg 656706f2543Smrg return PictureMatchVisual (pScreen, pWin->drawable.depth, 657706f2543Smrg compGetWindowVisual (pWin)); 658706f2543Smrg} 659706f2543Smrg 660706f2543Smrgstatic void 661706f2543SmrgcompWindowUpdateAutomatic (WindowPtr pWin) 662706f2543Smrg{ 663706f2543Smrg CompWindowPtr cw = GetCompWindow (pWin); 664706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 665706f2543Smrg WindowPtr pParent = pWin->parent; 666706f2543Smrg PixmapPtr pSrcPixmap = (*pScreen->GetWindowPixmap) (pWin); 667706f2543Smrg PictFormatPtr pSrcFormat = compWindowFormat (pWin); 668706f2543Smrg PictFormatPtr pDstFormat = compWindowFormat (pWin->parent); 669706f2543Smrg int error; 670706f2543Smrg RegionPtr pRegion = DamageRegion (cw->damage); 671706f2543Smrg PicturePtr pSrcPicture = CreatePicture (0, &pSrcPixmap->drawable, 672706f2543Smrg pSrcFormat, 673706f2543Smrg 0, 0, 674706f2543Smrg serverClient, 675706f2543Smrg &error); 676706f2543Smrg XID subwindowMode = IncludeInferiors; 677706f2543Smrg PicturePtr pDstPicture = CreatePicture (0, &pParent->drawable, 678706f2543Smrg pDstFormat, 679706f2543Smrg CPSubwindowMode, 680706f2543Smrg &subwindowMode, 681706f2543Smrg serverClient, 682706f2543Smrg &error); 683706f2543Smrg 684706f2543Smrg /* 685706f2543Smrg * First move the region from window to screen coordinates 686706f2543Smrg */ 687706f2543Smrg RegionTranslate(pRegion, 688706f2543Smrg pWin->drawable.x, pWin->drawable.y); 689706f2543Smrg 690706f2543Smrg /* 691706f2543Smrg * Clip against the "real" border clip 692706f2543Smrg */ 693706f2543Smrg RegionIntersect(pRegion, pRegion, &cw->borderClip); 694706f2543Smrg 695706f2543Smrg /* 696706f2543Smrg * Now translate from screen to dest coordinates 697706f2543Smrg */ 698706f2543Smrg RegionTranslate(pRegion, 699706f2543Smrg -pParent->drawable.x, -pParent->drawable.y); 700706f2543Smrg 701706f2543Smrg /* 702706f2543Smrg * Clip the picture 703706f2543Smrg */ 704706f2543Smrg SetPictureClipRegion (pDstPicture, 0, 0, pRegion); 705706f2543Smrg 706706f2543Smrg /* 707706f2543Smrg * And paint 708706f2543Smrg */ 709706f2543Smrg CompositePicture (PictOpSrc, 710706f2543Smrg pSrcPicture, 711706f2543Smrg 0, 712706f2543Smrg pDstPicture, 713706f2543Smrg 0, 0, /* src_x, src_y */ 714706f2543Smrg 0, 0, /* msk_x, msk_y */ 715706f2543Smrg pSrcPixmap->screen_x - pParent->drawable.x, 716706f2543Smrg pSrcPixmap->screen_y - pParent->drawable.y, 717706f2543Smrg pSrcPixmap->drawable.width, 718706f2543Smrg pSrcPixmap->drawable.height); 719706f2543Smrg FreePicture (pSrcPicture, 0); 720706f2543Smrg FreePicture (pDstPicture, 0); 721706f2543Smrg /* 722706f2543Smrg * Empty the damage region. This has the nice effect of 723706f2543Smrg * rendering the translations above harmless 724706f2543Smrg */ 725706f2543Smrg DamageEmpty (cw->damage); 726706f2543Smrg} 727706f2543Smrg 728706f2543Smrgstatic void 729706f2543SmrgcompPaintWindowToParent (WindowPtr pWin) 730706f2543Smrg{ 731706f2543Smrg compPaintChildrenToWindow (pWin); 732706f2543Smrg 733706f2543Smrg if (pWin->redirectDraw != RedirectDrawNone) 734706f2543Smrg { 735706f2543Smrg CompWindowPtr cw = GetCompWindow(pWin); 736706f2543Smrg 737706f2543Smrg if (cw->damaged) 738706f2543Smrg { 739706f2543Smrg compWindowUpdateAutomatic (pWin); 740706f2543Smrg cw->damaged = FALSE; 741706f2543Smrg } 742706f2543Smrg } 743706f2543Smrg} 744706f2543Smrg 745706f2543Smrgvoid 746706f2543SmrgcompPaintChildrenToWindow (WindowPtr pWin) 747706f2543Smrg{ 748706f2543Smrg WindowPtr pChild; 749706f2543Smrg 750706f2543Smrg if (!pWin->damagedDescendants) 751706f2543Smrg return; 752706f2543Smrg 753706f2543Smrg for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) 754706f2543Smrg compPaintWindowToParent (pChild); 755706f2543Smrg 756706f2543Smrg pWin->damagedDescendants = FALSE; 757706f2543Smrg} 758706f2543Smrg 759706f2543SmrgWindowPtr 760706f2543SmrgCompositeRealChildHead (WindowPtr pWin) 761706f2543Smrg{ 762706f2543Smrg WindowPtr pChild, pChildBefore; 763706f2543Smrg CompScreenPtr cs; 764706f2543Smrg 765706f2543Smrg if (!pWin->parent && 766706f2543Smrg (screenIsSaved == SCREEN_SAVER_ON) && 767706f2543Smrg (HasSaverWindow (pWin->drawable.pScreen))) { 768706f2543Smrg 769706f2543Smrg /* First child is the screen saver; see if next child is the overlay */ 770706f2543Smrg pChildBefore = pWin->firstChild; 771706f2543Smrg pChild = pChildBefore->nextSib; 772706f2543Smrg 773706f2543Smrg } else { 774706f2543Smrg pChildBefore = NullWindow; 775706f2543Smrg pChild = pWin->firstChild; 776706f2543Smrg } 777706f2543Smrg 778706f2543Smrg if (!pChild) { 779706f2543Smrg return NullWindow; 780706f2543Smrg } 781706f2543Smrg 782706f2543Smrg cs = GetCompScreen(pWin->drawable.pScreen); 783706f2543Smrg if (pChild == cs->pOverlayWin) { 784706f2543Smrg return pChild; 785706f2543Smrg } else { 786706f2543Smrg return pChildBefore; 787706f2543Smrg } 788706f2543Smrg} 789706f2543Smrg 790706f2543Smrgint 791706f2543SmrgcompConfigNotify(WindowPtr pWin, int x, int y, int w, int h, 792706f2543Smrg int bw, WindowPtr pSib) 793706f2543Smrg{ 794706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 795706f2543Smrg CompScreenPtr cs = GetCompScreen (pScreen); 796706f2543Smrg Bool ret = 0; 797706f2543Smrg WindowPtr pParent = pWin->parent; 798706f2543Smrg int draw_x, draw_y; 799706f2543Smrg Bool alloc_ret; 800706f2543Smrg 801706f2543Smrg if (cs->ConfigNotify) 802706f2543Smrg { 803706f2543Smrg pScreen->ConfigNotify = cs->ConfigNotify; 804706f2543Smrg ret = (*pScreen->ConfigNotify)(pWin, x, y, w, h, bw, pSib); 805706f2543Smrg cs->ConfigNotify = pScreen->ConfigNotify; 806706f2543Smrg pScreen->ConfigNotify = compConfigNotify; 807706f2543Smrg 808706f2543Smrg if (ret) 809706f2543Smrg return ret; 810706f2543Smrg } 811706f2543Smrg 812706f2543Smrg if (pWin->redirectDraw == RedirectDrawNone) 813706f2543Smrg return Success; 814706f2543Smrg 815706f2543Smrg compCheckTree (pScreen); 816706f2543Smrg 817706f2543Smrg draw_x = pParent->drawable.x + x + bw; 818706f2543Smrg draw_y = pParent->drawable.y + y + bw; 819706f2543Smrg alloc_ret = compReallocPixmap (pWin, draw_x, draw_y, w, h, bw); 820706f2543Smrg 821706f2543Smrg if (alloc_ret == FALSE) 822706f2543Smrg return BadAlloc; 823706f2543Smrg return Success; 824706f2543Smrg} 825