105b261ecSmrg/***********************************************************
205b261ecSmrg
305b261ecSmrgCopyright 1987, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included in
1205b261ecSmrgall copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2005b261ecSmrg
2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be
2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings
2305b261ecSmrgin this Software without prior written authorization from The Open Group.
2405b261ecSmrg
2505b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
2605b261ecSmrg
2705b261ecSmrg                        All Rights Reserved
2805b261ecSmrg
2935c4bbdfSmrgPermission to use, copy, modify, and distribute this software and its
3035c4bbdfSmrgdocumentation for any purpose and without fee is hereby granted,
3105b261ecSmrgprovided that the above copyright notice appear in all copies and that
3235c4bbdfSmrgboth that copyright notice and this permission notice appear in
3305b261ecSmrgsupporting documentation, and that the name of Digital not be
3405b261ecSmrgused in advertising or publicity pertaining to distribution of the
3535c4bbdfSmrgsoftware without specific, written prior permission.
3605b261ecSmrg
3705b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
3905b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4305b261ecSmrgSOFTWARE.
4405b261ecSmrg
4505b261ecSmrg******************************************************************/
4605b261ecSmrg/*****************************************************************
4705b261ecSmrg
4805b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
4905b261ecSmrg
5005b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy
5105b261ecSmrgof this software and associated documentation files (the "Software"), to deal
5205b261ecSmrgin the Software without restriction, including without limitation the rights
5305b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5405b261ecSmrgcopies of the Software.
5505b261ecSmrg
5605b261ecSmrgThe above copyright notice and this permission notice shall be included in
5705b261ecSmrgall copies or substantial portions of the Software.
5805b261ecSmrg
5905b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6005b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6105b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
6205b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
6305b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
6405b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
6505b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6605b261ecSmrg
6705b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation
6805b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other
6905b261ecSmrgdealings in this Software without prior written authorization from Digital
7005b261ecSmrgEquipment Corporation.
7105b261ecSmrg
7205b261ecSmrg******************************************************************/
7305b261ecSmrg
7405b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
7505b261ecSmrg#include <dix-config.h>
7605b261ecSmrg#endif
7705b261ecSmrg
7805b261ecSmrg#include <X11/X.h>
7905b261ecSmrg#include <X11/Xproto.h>
8005b261ecSmrg#include <X11/Xprotostr.h>
8105b261ecSmrg
8205b261ecSmrg#include "misc.h"
8305b261ecSmrg#include "regionstr.h"
8405b261ecSmrg#include "scrnintstr.h"
8505b261ecSmrg#include "gcstruct.h"
8605b261ecSmrg#include "windowstr.h"
8705b261ecSmrg#include "pixmap.h"
8805b261ecSmrg#include "input.h"
8905b261ecSmrg
9005b261ecSmrg#include "dixstruct.h"
9105b261ecSmrg#include "mi.h"
9205b261ecSmrg#include <X11/Xmd.h>
9305b261ecSmrg
9405b261ecSmrg#include "globals.h"
9505b261ecSmrg
9605b261ecSmrg#ifdef PANORAMIX
9705b261ecSmrg#include "panoramiX.h"
9805b261ecSmrg#include "panoramiXsrv.h"
9905b261ecSmrg#endif
10005b261ecSmrg
10105b261ecSmrg/*
10205b261ecSmrg    machine-independent graphics exposure code.  any device that uses
10305b261ecSmrgthe region package can call this.
10405b261ecSmrg*/
10505b261ecSmrg
10605b261ecSmrg#ifndef RECTLIMIT
10735c4bbdfSmrg#define RECTLIMIT 25            /* pick a number, any number > 8 */
10805b261ecSmrg#endif
10905b261ecSmrg
11035c4bbdfSmrg/* miHandleExposures
11105b261ecSmrg    generate a region for exposures for areas that were copied from obscured or
11205b261ecSmrgnon-existent areas to non-obscured areas of the destination.  Paint the
11305b261ecSmrgbackground for the region, if the destination is a window.
11405b261ecSmrg
11505b261ecSmrg*/
11605b261ecSmrg
1176747b715SmrgRegionPtr
1184642e01fSmrgmiHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
11935c4bbdfSmrg                  GCPtr pGC, int srcx, int srcy, int width, int height,
12035c4bbdfSmrg                  int dstx, int dsty)
12105b261ecSmrg{
12235c4bbdfSmrg    RegionPtr prgnSrcClip;      /* drawable-relative source clip */
12305b261ecSmrg    RegionRec rgnSrcRec;
12435c4bbdfSmrg    RegionPtr prgnDstClip;      /* drawable-relative dest clip */
12505b261ecSmrg    RegionRec rgnDstRec;
12635c4bbdfSmrg    BoxRec srcBox;              /* unclipped source */
12735c4bbdfSmrg    RegionRec rgnExposed;       /* exposed region, calculated source-
12835c4bbdfSmrg                                   relative, made dst relative to
12935c4bbdfSmrg                                   intersect with visible parts of
13035c4bbdfSmrg                                   dest and send events to client,
13135c4bbdfSmrg                                   and then screen relative to paint
13235c4bbdfSmrg                                   the window background
13335c4bbdfSmrg                                 */
13405b261ecSmrg    WindowPtr pSrcWin;
1351b5d61b8Smrg    BoxRec expBox = { 0, };
13605b261ecSmrg    Bool extents;
13705b261ecSmrg
13805b261ecSmrg    /* avoid work if we can */
139ed6184dfSmrg    if (!pGC->graphicsExposures && pDstDrawable->type == DRAWABLE_PIXMAP)
14035c4bbdfSmrg        return NULL;
14135c4bbdfSmrg
14205b261ecSmrg    srcBox.x1 = srcx;
14305b261ecSmrg    srcBox.y1 = srcy;
14435c4bbdfSmrg    srcBox.x2 = srcx + width;
14535c4bbdfSmrg    srcBox.y2 = srcy + height;
14635c4bbdfSmrg
14735c4bbdfSmrg    if (pSrcDrawable->type != DRAWABLE_PIXMAP) {
14835c4bbdfSmrg        BoxRec TsrcBox;
14935c4bbdfSmrg
15035c4bbdfSmrg        TsrcBox.x1 = srcx + pSrcDrawable->x;
15135c4bbdfSmrg        TsrcBox.y1 = srcy + pSrcDrawable->y;
15235c4bbdfSmrg        TsrcBox.x2 = TsrcBox.x1 + width;
15335c4bbdfSmrg        TsrcBox.y2 = TsrcBox.y1 + height;
15435c4bbdfSmrg        pSrcWin = (WindowPtr) pSrcDrawable;
15535c4bbdfSmrg        if (pGC->subWindowMode == IncludeInferiors) {
15635c4bbdfSmrg            prgnSrcClip = NotClippedByChildren(pSrcWin);
15735c4bbdfSmrg            if ((RegionContainsRect(prgnSrcClip, &TsrcBox)) == rgnIN) {
15835c4bbdfSmrg                RegionDestroy(prgnSrcClip);
15935c4bbdfSmrg                return NULL;
16035c4bbdfSmrg            }
16135c4bbdfSmrg        }
16235c4bbdfSmrg        else {
16335c4bbdfSmrg            if ((RegionContainsRect(&pSrcWin->clipList, &TsrcBox)) == rgnIN)
16435c4bbdfSmrg                return NULL;
16535c4bbdfSmrg            prgnSrcClip = &rgnSrcRec;
16635c4bbdfSmrg            RegionNull(prgnSrcClip);
16735c4bbdfSmrg            RegionCopy(prgnSrcClip, &pSrcWin->clipList);
16835c4bbdfSmrg        }
16935c4bbdfSmrg        RegionTranslate(prgnSrcClip, -pSrcDrawable->x, -pSrcDrawable->y);
17005b261ecSmrg    }
17135c4bbdfSmrg    else {
17235c4bbdfSmrg        BoxRec box;
17335c4bbdfSmrg
17435c4bbdfSmrg        if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
17535c4bbdfSmrg            (srcBox.x2 <= pSrcDrawable->width) &&
17635c4bbdfSmrg            (srcBox.y2 <= pSrcDrawable->height))
17735c4bbdfSmrg            return NULL;
17835c4bbdfSmrg
17935c4bbdfSmrg        box.x1 = 0;
18035c4bbdfSmrg        box.y1 = 0;
18135c4bbdfSmrg        box.x2 = pSrcDrawable->width;
18235c4bbdfSmrg        box.y2 = pSrcDrawable->height;
18335c4bbdfSmrg        prgnSrcClip = &rgnSrcRec;
18435c4bbdfSmrg        RegionInit(prgnSrcClip, &box, 1);
18535c4bbdfSmrg        pSrcWin = NULL;
18605b261ecSmrg    }
18705b261ecSmrg
18835c4bbdfSmrg    if (pDstDrawable == pSrcDrawable) {
18935c4bbdfSmrg        prgnDstClip = prgnSrcClip;
19005b261ecSmrg    }
19135c4bbdfSmrg    else if (pDstDrawable->type != DRAWABLE_PIXMAP) {
19235c4bbdfSmrg        if (pGC->subWindowMode == IncludeInferiors) {
19335c4bbdfSmrg            prgnDstClip = NotClippedByChildren((WindowPtr) pDstDrawable);
19435c4bbdfSmrg        }
19535c4bbdfSmrg        else {
19635c4bbdfSmrg            prgnDstClip = &rgnDstRec;
19735c4bbdfSmrg            RegionNull(prgnDstClip);
19835c4bbdfSmrg            RegionCopy(prgnDstClip, &((WindowPtr) pDstDrawable)->clipList);
19935c4bbdfSmrg        }
20035c4bbdfSmrg        RegionTranslate(prgnDstClip, -pDstDrawable->x, -pDstDrawable->y);
20105b261ecSmrg    }
20235c4bbdfSmrg    else {
20335c4bbdfSmrg        BoxRec box;
20435c4bbdfSmrg
20535c4bbdfSmrg        box.x1 = 0;
20635c4bbdfSmrg        box.y1 = 0;
20735c4bbdfSmrg        box.x2 = pDstDrawable->width;
20835c4bbdfSmrg        box.y2 = pDstDrawable->height;
20935c4bbdfSmrg        prgnDstClip = &rgnDstRec;
21035c4bbdfSmrg        RegionInit(prgnDstClip, &box, 1);
21105b261ecSmrg    }
21205b261ecSmrg
21305b261ecSmrg    /* drawable-relative source region */
2146747b715Smrg    RegionInit(&rgnExposed, &srcBox, 1);
21505b261ecSmrg
21635c4bbdfSmrg    /* now get the hidden parts of the source box */
2176747b715Smrg    RegionSubtract(&rgnExposed, &rgnExposed, prgnSrcClip);
21805b261ecSmrg
21905b261ecSmrg    /* move them over the destination */
22035c4bbdfSmrg    RegionTranslate(&rgnExposed, dstx - srcx, dsty - srcy);
22105b261ecSmrg
22205b261ecSmrg    /* intersect with visible areas of dest */
2236747b715Smrg    RegionIntersect(&rgnExposed, &rgnExposed, prgnDstClip);
2246747b715Smrg
2256747b715Smrg    /* intersect with client clip region. */
22635c4bbdfSmrg    if (pGC->clientClip)
22735c4bbdfSmrg        RegionIntersect(&rgnExposed, &rgnExposed, pGC->clientClip);
22805b261ecSmrg
22905b261ecSmrg    /*
23005b261ecSmrg     * If we have LOTS of rectangles, we decide to take the extents
23105b261ecSmrg     * and force an exposure on that.  This should require much less
23205b261ecSmrg     * work overall, on both client and server.  This is cheating, but
23305b261ecSmrg     * isn't prohibited by the protocol ("spontaneous combustion" :-)
23405b261ecSmrg     * for windows.
23505b261ecSmrg     */
23605b261ecSmrg    extents = pGC->graphicsExposures &&
23735c4bbdfSmrg        (RegionNumRects(&rgnExposed) > RECTLIMIT) &&
23835c4bbdfSmrg        (pDstDrawable->type != DRAWABLE_PIXMAP);
23935c4bbdfSmrg    if (pSrcWin) {
24035c4bbdfSmrg        RegionPtr region;
24135c4bbdfSmrg
24235c4bbdfSmrg        if (!(region = wClipShape(pSrcWin)))
24335c4bbdfSmrg            region = wBoundingShape(pSrcWin);
24435c4bbdfSmrg        /*
24535c4bbdfSmrg         * If you try to CopyArea the extents of a shaped window, compacting the
24635c4bbdfSmrg         * exposed region will undo all our work!
24735c4bbdfSmrg         */
24835c4bbdfSmrg        if (extents && pSrcWin && region &&
24935c4bbdfSmrg            (RegionContainsRect(region, &srcBox) != rgnIN))
25035c4bbdfSmrg            extents = FALSE;
25105b261ecSmrg    }
25235c4bbdfSmrg    if (extents) {
25335c4bbdfSmrg        expBox = *RegionExtents(&rgnExposed);
25435c4bbdfSmrg        RegionReset(&rgnExposed, &expBox);
25505b261ecSmrg    }
25605b261ecSmrg    if ((pDstDrawable->type != DRAWABLE_PIXMAP) &&
25735c4bbdfSmrg        (((WindowPtr) pDstDrawable)->backgroundState != None)) {
25835c4bbdfSmrg        WindowPtr pWin = (WindowPtr) pDstDrawable;
25905b261ecSmrg
26035c4bbdfSmrg        /* make the exposed area screen-relative */
26135c4bbdfSmrg        RegionTranslate(&rgnExposed, pDstDrawable->x, pDstDrawable->y);
26235c4bbdfSmrg
26335c4bbdfSmrg        if (extents) {
26435c4bbdfSmrg            /* PaintWindow doesn't clip, so we have to */
26535c4bbdfSmrg            RegionIntersect(&rgnExposed, &rgnExposed, &pWin->clipList);
26635c4bbdfSmrg        }
26735c4bbdfSmrg        pDstDrawable->pScreen->PaintWindow((WindowPtr) pDstDrawable,
26835c4bbdfSmrg                                           &rgnExposed, PW_BACKGROUND);
26935c4bbdfSmrg
27035c4bbdfSmrg        if (extents) {
27135c4bbdfSmrg            RegionReset(&rgnExposed, &expBox);
27235c4bbdfSmrg        }
27335c4bbdfSmrg        else
27435c4bbdfSmrg            RegionTranslate(&rgnExposed, -pDstDrawable->x, -pDstDrawable->y);
27535c4bbdfSmrg    }
27635c4bbdfSmrg    if (prgnDstClip == &rgnDstRec) {
27735c4bbdfSmrg        RegionUninit(prgnDstClip);
27805b261ecSmrg    }
27935c4bbdfSmrg    else if (prgnDstClip != prgnSrcClip) {
28035c4bbdfSmrg        RegionDestroy(prgnDstClip);
28105b261ecSmrg    }
28205b261ecSmrg
28335c4bbdfSmrg    if (prgnSrcClip == &rgnSrcRec) {
28435c4bbdfSmrg        RegionUninit(prgnSrcClip);
28505b261ecSmrg    }
28635c4bbdfSmrg    else {
28735c4bbdfSmrg        RegionDestroy(prgnSrcClip);
28805b261ecSmrg    }
28905b261ecSmrg
29035c4bbdfSmrg    if (pGC->graphicsExposures) {
29135c4bbdfSmrg        /* don't look */
29235c4bbdfSmrg        RegionPtr exposed = RegionCreate(NullBox, 0);
29305b261ecSmrg
29435c4bbdfSmrg        *exposed = rgnExposed;
29535c4bbdfSmrg        return exposed;
29605b261ecSmrg    }
29735c4bbdfSmrg    else {
29835c4bbdfSmrg        RegionUninit(&rgnExposed);
29935c4bbdfSmrg        return NULL;
30005b261ecSmrg    }
30105b261ecSmrg}
30205b261ecSmrg
30305b261ecSmrgvoid
30435c4bbdfSmrgmiSendExposures(WindowPtr pWin, RegionPtr pRgn, int dx, int dy)
30505b261ecSmrg{
30605b261ecSmrg    BoxPtr pBox;
30705b261ecSmrg    int numRects;
30805b261ecSmrg    xEvent *pEvent, *pe;
30905b261ecSmrg    int i;
31005b261ecSmrg
3116747b715Smrg    pBox = RegionRects(pRgn);
3126747b715Smrg    numRects = RegionNumRects(pRgn);
31335c4bbdfSmrg    if (!(pEvent = calloc(1, numRects * sizeof(xEvent))))
31435c4bbdfSmrg        return;
31535c4bbdfSmrg
31635c4bbdfSmrg    for (i = numRects, pe = pEvent; --i >= 0; pe++, pBox++) {
31735c4bbdfSmrg        pe->u.u.type = Expose;
31835c4bbdfSmrg        pe->u.expose.window = pWin->drawable.id;
31935c4bbdfSmrg        pe->u.expose.x = pBox->x1 - dx;
32035c4bbdfSmrg        pe->u.expose.y = pBox->y1 - dy;
32135c4bbdfSmrg        pe->u.expose.width = pBox->x2 - pBox->x1;
32235c4bbdfSmrg        pe->u.expose.height = pBox->y2 - pBox->y1;
32335c4bbdfSmrg        pe->u.expose.count = i;
32405b261ecSmrg    }
32505b261ecSmrg
32605b261ecSmrg#ifdef PANORAMIX
32735c4bbdfSmrg    if (!noPanoramiXExtension) {
32835c4bbdfSmrg        int scrnum = pWin->drawable.pScreen->myNum;
32935c4bbdfSmrg        int x = 0, y = 0;
33035c4bbdfSmrg        XID realWin = 0;
33135c4bbdfSmrg
33235c4bbdfSmrg        if (!pWin->parent) {
33335c4bbdfSmrg            x = screenInfo.screens[scrnum]->x;
33435c4bbdfSmrg            y = screenInfo.screens[scrnum]->y;
33535c4bbdfSmrg            pWin = screenInfo.screens[0]->root;
33635c4bbdfSmrg            realWin = pWin->drawable.id;
33735c4bbdfSmrg        }
33835c4bbdfSmrg        else if (scrnum) {
33935c4bbdfSmrg            PanoramiXRes *win;
34035c4bbdfSmrg
34135c4bbdfSmrg            win = PanoramiXFindIDByScrnum(XRT_WINDOW,
34235c4bbdfSmrg                                          pWin->drawable.id, scrnum);
34335c4bbdfSmrg            if (!win) {
34435c4bbdfSmrg                free(pEvent);
34535c4bbdfSmrg                return;
34635c4bbdfSmrg            }
34735c4bbdfSmrg            realWin = win->info[0].id;
34835c4bbdfSmrg            dixLookupWindow(&pWin, realWin, serverClient, DixSendAccess);
34935c4bbdfSmrg        }
35035c4bbdfSmrg        if (x || y || scrnum)
35135c4bbdfSmrg            for (i = 0; i < numRects; i++) {
35235c4bbdfSmrg                pEvent[i].u.expose.window = realWin;
35335c4bbdfSmrg                pEvent[i].u.expose.x += x;
35435c4bbdfSmrg                pEvent[i].u.expose.y += y;
35535c4bbdfSmrg            }
35605b261ecSmrg    }
35705b261ecSmrg#endif
35805b261ecSmrg
35905b261ecSmrg    DeliverEvents(pWin, pEvent, numRects, NullWindow);
36005b261ecSmrg
3616747b715Smrg    free(pEvent);
36205b261ecSmrg}
36305b261ecSmrg
3646747b715Smrgvoid
36535c4bbdfSmrgmiWindowExposures(WindowPtr pWin, RegionPtr prgn)
36605b261ecSmrg{
36735c4bbdfSmrg    RegionPtr exposures = prgn;
36835c4bbdfSmrg
36935c4bbdfSmrg    if (prgn && !RegionNil(prgn)) {
37035c4bbdfSmrg        RegionRec expRec;
37135c4bbdfSmrg        int clientInterested =
37235c4bbdfSmrg            (pWin->eventMask | wOtherEventMasks(pWin)) & ExposureMask;
37335c4bbdfSmrg        if (clientInterested && (RegionNumRects(prgn) > RECTLIMIT)) {
37435c4bbdfSmrg            /*
37535c4bbdfSmrg             * If we have LOTS of rectangles, we decide to take the extents
37635c4bbdfSmrg             * and force an exposure on that.  This should require much less
37735c4bbdfSmrg             * work overall, on both client and server.  This is cheating, but
37835c4bbdfSmrg             * isn't prohibited by the protocol ("spontaneous combustion" :-).
37935c4bbdfSmrg             */
38035c4bbdfSmrg            BoxRec box = *RegionExtents(prgn);
38135c4bbdfSmrg            exposures = &expRec;
38235c4bbdfSmrg            RegionInit(exposures, &box, 1);
38335c4bbdfSmrg            RegionReset(prgn, &box);
38435c4bbdfSmrg            /* miPaintWindow doesn't clip, so we have to */
38535c4bbdfSmrg            RegionIntersect(prgn, prgn, &pWin->clipList);
38635c4bbdfSmrg        }
38735c4bbdfSmrg        pWin->drawable.pScreen->PaintWindow(pWin, prgn, PW_BACKGROUND);
38835c4bbdfSmrg        if (clientInterested)
38935c4bbdfSmrg            miSendExposures(pWin, exposures,
39035c4bbdfSmrg                            pWin->drawable.x, pWin->drawable.y);
39135c4bbdfSmrg        if (exposures == &expRec)
39235c4bbdfSmrg            RegionUninit(exposures);
39335c4bbdfSmrg        RegionEmpty(prgn);
39405b261ecSmrg    }
39505b261ecSmrg}
39605b261ecSmrg
3974642e01fSmrgvoid
3984642e01fSmrgmiPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
39905b261ecSmrg{
40035c4bbdfSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
4016747b715Smrg    ChangeGCVal gcval[6];
40235c4bbdfSmrg    BITS32 gcmask;
40335c4bbdfSmrg    GCPtr pGC;
40435c4bbdfSmrg    int i;
40535c4bbdfSmrg    BoxPtr pbox;
40635c4bbdfSmrg    xRectangle *prect;
407ed6184dfSmrg    int numRects, regionnumrects;
40835c4bbdfSmrg
4094642e01fSmrg    /*
4104642e01fSmrg     * Distance from screen to destination drawable, use this
4114642e01fSmrg     * to adjust rendering coordinates which come in in screen space
4124642e01fSmrg     */
41335c4bbdfSmrg    int draw_x_off, draw_y_off;
41435c4bbdfSmrg
4154642e01fSmrg    /*
4164642e01fSmrg     * Tile offset for drawing; these need to align the tile
4174642e01fSmrg     * to the appropriate window origin
4184642e01fSmrg     */
41935c4bbdfSmrg    int tile_x_off, tile_y_off;
42035c4bbdfSmrg    PixUnion fill;
42135c4bbdfSmrg    Bool solid = TRUE;
42235c4bbdfSmrg    DrawablePtr drawable = &pWin->drawable;
42335c4bbdfSmrg
42435c4bbdfSmrg    if (what == PW_BACKGROUND) {
42535c4bbdfSmrg        while (pWin->backgroundState == ParentRelative)
42635c4bbdfSmrg            pWin = pWin->parent;
42735c4bbdfSmrg
42835c4bbdfSmrg        draw_x_off = drawable->x;
42935c4bbdfSmrg        draw_y_off = drawable->y;
43035c4bbdfSmrg
43135c4bbdfSmrg        tile_x_off = pWin->drawable.x - draw_x_off;
43235c4bbdfSmrg        tile_y_off = pWin->drawable.y - draw_y_off;
43335c4bbdfSmrg        fill = pWin->background;
43435c4bbdfSmrg#ifdef COMPOSITE
43535c4bbdfSmrg        if (pWin->inhibitBGPaint)
43635c4bbdfSmrg            return;
4376747b715Smrg#endif
43835c4bbdfSmrg        switch (pWin->backgroundState) {
43935c4bbdfSmrg        case None:
44035c4bbdfSmrg            return;
44135c4bbdfSmrg        case BackgroundPixmap:
44235c4bbdfSmrg            solid = FALSE;
44335c4bbdfSmrg            break;
44435c4bbdfSmrg        }
44505b261ecSmrg    }
44635c4bbdfSmrg    else {
44735c4bbdfSmrg        PixmapPtr pixmap;
44835c4bbdfSmrg
44935c4bbdfSmrg        fill = pWin->border;
45035c4bbdfSmrg        solid = pWin->borderIsPixel;
45135c4bbdfSmrg
45235c4bbdfSmrg        /* servers without pixmaps draw their own borders */
45335c4bbdfSmrg        if (!pScreen->GetWindowPixmap)
45435c4bbdfSmrg            return;
45535c4bbdfSmrg        pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable);
45635c4bbdfSmrg        drawable = &pixmap->drawable;
45735c4bbdfSmrg
45835c4bbdfSmrg        while (pWin->backgroundState == ParentRelative)
45935c4bbdfSmrg            pWin = pWin->parent;
46035c4bbdfSmrg
46135c4bbdfSmrg        tile_x_off = pWin->drawable.x;
46235c4bbdfSmrg        tile_y_off = pWin->drawable.y;
46335c4bbdfSmrg
4644642e01fSmrg#ifdef COMPOSITE
46535c4bbdfSmrg        draw_x_off = pixmap->screen_x;
46635c4bbdfSmrg        draw_y_off = pixmap->screen_y;
46735c4bbdfSmrg        tile_x_off -= draw_x_off;
46835c4bbdfSmrg        tile_y_off -= draw_y_off;
4694642e01fSmrg#else
47035c4bbdfSmrg        draw_x_off = 0;
47135c4bbdfSmrg        draw_y_off = 0;
4724642e01fSmrg#endif
47305b261ecSmrg    }
47435c4bbdfSmrg
4754642e01fSmrg    gcval[0].val = GXcopy;
4764642e01fSmrg    gcmask = GCFunction;
47705b261ecSmrg
4786747b715Smrg#ifdef ROOTLESS_SAFEALPHA
4796747b715Smrg/* Bit mask for alpha channel with a particular number of bits per
4806747b715Smrg * pixel. Note that we only care for 32bpp data. Mac OS X uses planar
4816747b715Smrg * alpha for 16bpp.
4826747b715Smrg */
4836747b715Smrg#define RootlessAlphaMask(bpp) ((bpp) == 32 ? 0xFF000000 : 0)
4846747b715Smrg#endif
48535c4bbdfSmrg
48635c4bbdfSmrg    if (solid) {
4876747b715Smrg#ifdef ROOTLESS_SAFEALPHA
48835c4bbdfSmrg        gcval[1].val =
48935c4bbdfSmrg            fill.pixel | RootlessAlphaMask(pWin->drawable.bitsPerPixel);
4906747b715Smrg#else
49135c4bbdfSmrg        gcval[1].val = fill.pixel;
4926747b715Smrg#endif
49335c4bbdfSmrg        gcval[2].val = FillSolid;
49435c4bbdfSmrg        gcmask |= GCForeground | GCFillStyle;
4954642e01fSmrg    }
49635c4bbdfSmrg    else {
49735c4bbdfSmrg        int c = 1;
49835c4bbdfSmrg
4996747b715Smrg#ifdef ROOTLESS_SAFEALPHA
50035c4bbdfSmrg        gcval[c++].val =
50135c4bbdfSmrg            ((CARD32) -1) & ~RootlessAlphaMask(pWin->drawable.bitsPerPixel);
50235c4bbdfSmrg        gcmask |= GCPlaneMask;
5036747b715Smrg#endif
50435c4bbdfSmrg        gcval[c++].val = FillTiled;
50535c4bbdfSmrg        gcval[c++].ptr = (void *) fill.pixmap;
50635c4bbdfSmrg        gcval[c++].val = tile_x_off;
50735c4bbdfSmrg        gcval[c++].val = tile_y_off;
50835c4bbdfSmrg        gcmask |= GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin;
5094642e01fSmrg    }
5104642e01fSmrg
511ed6184dfSmrg    regionnumrects = RegionNumRects(prgn);
512ed6184dfSmrg    if (regionnumrects == 0)
513ed6184dfSmrg        return;
514ed6184dfSmrg    prect = xallocarray(regionnumrects, sizeof(xRectangle));
51505b261ecSmrg    if (!prect)
51635c4bbdfSmrg        return;
51705b261ecSmrg
5184642e01fSmrg    pGC = GetScratchGC(drawable->depth, drawable->pScreen);
51935c4bbdfSmrg    if (!pGC) {
52035c4bbdfSmrg        free(prect);
52135c4bbdfSmrg        return;
52205b261ecSmrg    }
52335c4bbdfSmrg
52435c4bbdfSmrg    ChangeGC(NullClient, pGC, gcmask, gcval);
52535c4bbdfSmrg    ValidateGC(drawable, pGC);
52605b261ecSmrg
5276747b715Smrg    numRects = RegionNumRects(prgn);
5286747b715Smrg    pbox = RegionRects(prgn);
52935c4bbdfSmrg    for (i = numRects; --i >= 0; pbox++, prect++) {
53035c4bbdfSmrg        prect->x = pbox->x1 - draw_x_off;
53135c4bbdfSmrg        prect->y = pbox->y1 - draw_y_off;
53235c4bbdfSmrg        prect->width = pbox->x2 - pbox->x1;
53335c4bbdfSmrg        prect->height = pbox->y2 - pbox->y1;
53405b261ecSmrg    }
53505b261ecSmrg    prect -= numRects;
53635c4bbdfSmrg    (*pGC->ops->PolyFillRect) (drawable, pGC, numRects, prect);
5376747b715Smrg    free(prect);
53805b261ecSmrg
5394642e01fSmrg    FreeScratchGC(pGC);
54005b261ecSmrg}
54105b261ecSmrg
54205b261ecSmrg/* MICLEARDRAWABLE -- sets the entire drawable to the background color of
54335c4bbdfSmrg * the GC.  Useful when we have a scratch drawable and need to initialize
54405b261ecSmrg * it. */
5456747b715Smrgvoid
5464642e01fSmrgmiClearDrawable(DrawablePtr pDraw, GCPtr pGC)
54705b261ecSmrg{
5486747b715Smrg    ChangeGCVal fg, bg;
54905b261ecSmrg    xRectangle rect;
55005b261ecSmrg
5516747b715Smrg    fg.val = pGC->fgPixel;
5526747b715Smrg    bg.val = pGC->bgPixel;
55305b261ecSmrg    rect.x = 0;
55405b261ecSmrg    rect.y = 0;
55505b261ecSmrg    rect.width = pDraw->width;
55605b261ecSmrg    rect.height = pDraw->height;
5576747b715Smrg    ChangeGC(NullClient, pGC, GCForeground, &bg);
55805b261ecSmrg    ValidateGC(pDraw, pGC);
55935c4bbdfSmrg    (*pGC->ops->PolyFillRect) (pDraw, pGC, 1, &rect);
5606747b715Smrg    ChangeGC(NullClient, pGC, GCForeground, &fg);
56105b261ecSmrg    ValidateGC(pDraw, pGC);
56205b261ecSmrg}
563