miexpose.c revision 35c4bbdf
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
11505b261ecSmrgNOTE:
11605b261ecSmrg     this should generally be called, even if graphicsExposures is false,
11705b261ecSmrgbecause this is where bits get recovered from backing store.
11805b261ecSmrg
11905b261ecSmrg*/
12005b261ecSmrg
1216747b715SmrgRegionPtr
1224642e01fSmrgmiHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
12335c4bbdfSmrg                  GCPtr pGC, int srcx, int srcy, int width, int height,
12435c4bbdfSmrg                  int dstx, int dsty)
12505b261ecSmrg{
12635c4bbdfSmrg    RegionPtr prgnSrcClip;      /* drawable-relative source clip */
12705b261ecSmrg    RegionRec rgnSrcRec;
12835c4bbdfSmrg    RegionPtr prgnDstClip;      /* drawable-relative dest clip */
12905b261ecSmrg    RegionRec rgnDstRec;
13035c4bbdfSmrg    BoxRec srcBox;              /* unclipped source */
13135c4bbdfSmrg    RegionRec rgnExposed;       /* exposed region, calculated source-
13235c4bbdfSmrg                                   relative, made dst relative to
13335c4bbdfSmrg                                   intersect with visible parts of
13435c4bbdfSmrg                                   dest and send events to client,
13535c4bbdfSmrg                                   and then screen relative to paint
13635c4bbdfSmrg                                   the window background
13735c4bbdfSmrg                                 */
13805b261ecSmrg    WindowPtr pSrcWin;
13905b261ecSmrg    BoxRec expBox;
14005b261ecSmrg    Bool extents;
14105b261ecSmrg
14205b261ecSmrg    /* avoid work if we can */
14305b261ecSmrg    if (!pGC->graphicsExposures &&
14435c4bbdfSmrg        (pDstDrawable->type == DRAWABLE_PIXMAP) &&
14535c4bbdfSmrg        ((pSrcDrawable->type == DRAWABLE_PIXMAP) ||
14635c4bbdfSmrg         (((WindowPtr) pSrcDrawable)->backStorage == 0)))
14735c4bbdfSmrg        return NULL;
14835c4bbdfSmrg
14905b261ecSmrg    srcBox.x1 = srcx;
15005b261ecSmrg    srcBox.y1 = srcy;
15135c4bbdfSmrg    srcBox.x2 = srcx + width;
15235c4bbdfSmrg    srcBox.y2 = srcy + height;
15335c4bbdfSmrg
15435c4bbdfSmrg    if (pSrcDrawable->type != DRAWABLE_PIXMAP) {
15535c4bbdfSmrg        BoxRec TsrcBox;
15635c4bbdfSmrg
15735c4bbdfSmrg        TsrcBox.x1 = srcx + pSrcDrawable->x;
15835c4bbdfSmrg        TsrcBox.y1 = srcy + pSrcDrawable->y;
15935c4bbdfSmrg        TsrcBox.x2 = TsrcBox.x1 + width;
16035c4bbdfSmrg        TsrcBox.y2 = TsrcBox.y1 + height;
16135c4bbdfSmrg        pSrcWin = (WindowPtr) pSrcDrawable;
16235c4bbdfSmrg        if (pGC->subWindowMode == IncludeInferiors) {
16335c4bbdfSmrg            prgnSrcClip = NotClippedByChildren(pSrcWin);
16435c4bbdfSmrg            if ((RegionContainsRect(prgnSrcClip, &TsrcBox)) == rgnIN) {
16535c4bbdfSmrg                RegionDestroy(prgnSrcClip);
16635c4bbdfSmrg                return NULL;
16735c4bbdfSmrg            }
16835c4bbdfSmrg        }
16935c4bbdfSmrg        else {
17035c4bbdfSmrg            if ((RegionContainsRect(&pSrcWin->clipList, &TsrcBox)) == rgnIN)
17135c4bbdfSmrg                return NULL;
17235c4bbdfSmrg            prgnSrcClip = &rgnSrcRec;
17335c4bbdfSmrg            RegionNull(prgnSrcClip);
17435c4bbdfSmrg            RegionCopy(prgnSrcClip, &pSrcWin->clipList);
17535c4bbdfSmrg        }
17635c4bbdfSmrg        RegionTranslate(prgnSrcClip, -pSrcDrawable->x, -pSrcDrawable->y);
17705b261ecSmrg    }
17835c4bbdfSmrg    else {
17935c4bbdfSmrg        BoxRec box;
18035c4bbdfSmrg
18135c4bbdfSmrg        if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
18235c4bbdfSmrg            (srcBox.x2 <= pSrcDrawable->width) &&
18335c4bbdfSmrg            (srcBox.y2 <= pSrcDrawable->height))
18435c4bbdfSmrg            return NULL;
18535c4bbdfSmrg
18635c4bbdfSmrg        box.x1 = 0;
18735c4bbdfSmrg        box.y1 = 0;
18835c4bbdfSmrg        box.x2 = pSrcDrawable->width;
18935c4bbdfSmrg        box.y2 = pSrcDrawable->height;
19035c4bbdfSmrg        prgnSrcClip = &rgnSrcRec;
19135c4bbdfSmrg        RegionInit(prgnSrcClip, &box, 1);
19235c4bbdfSmrg        pSrcWin = NULL;
19305b261ecSmrg    }
19405b261ecSmrg
19535c4bbdfSmrg    if (pDstDrawable == pSrcDrawable) {
19635c4bbdfSmrg        prgnDstClip = prgnSrcClip;
19705b261ecSmrg    }
19835c4bbdfSmrg    else if (pDstDrawable->type != DRAWABLE_PIXMAP) {
19935c4bbdfSmrg        if (pGC->subWindowMode == IncludeInferiors) {
20035c4bbdfSmrg            prgnDstClip = NotClippedByChildren((WindowPtr) pDstDrawable);
20135c4bbdfSmrg        }
20235c4bbdfSmrg        else {
20335c4bbdfSmrg            prgnDstClip = &rgnDstRec;
20435c4bbdfSmrg            RegionNull(prgnDstClip);
20535c4bbdfSmrg            RegionCopy(prgnDstClip, &((WindowPtr) pDstDrawable)->clipList);
20635c4bbdfSmrg        }
20735c4bbdfSmrg        RegionTranslate(prgnDstClip, -pDstDrawable->x, -pDstDrawable->y);
20805b261ecSmrg    }
20935c4bbdfSmrg    else {
21035c4bbdfSmrg        BoxRec box;
21135c4bbdfSmrg
21235c4bbdfSmrg        box.x1 = 0;
21335c4bbdfSmrg        box.y1 = 0;
21435c4bbdfSmrg        box.x2 = pDstDrawable->width;
21535c4bbdfSmrg        box.y2 = pDstDrawable->height;
21635c4bbdfSmrg        prgnDstClip = &rgnDstRec;
21735c4bbdfSmrg        RegionInit(prgnDstClip, &box, 1);
21805b261ecSmrg    }
21905b261ecSmrg
22005b261ecSmrg    /* drawable-relative source region */
2216747b715Smrg    RegionInit(&rgnExposed, &srcBox, 1);
22205b261ecSmrg
22335c4bbdfSmrg    /* now get the hidden parts of the source box */
2246747b715Smrg    RegionSubtract(&rgnExposed, &rgnExposed, prgnSrcClip);
22505b261ecSmrg
22605b261ecSmrg    /* move them over the destination */
22735c4bbdfSmrg    RegionTranslate(&rgnExposed, dstx - srcx, dsty - srcy);
22805b261ecSmrg
22905b261ecSmrg    /* intersect with visible areas of dest */
2306747b715Smrg    RegionIntersect(&rgnExposed, &rgnExposed, prgnDstClip);
2316747b715Smrg
2326747b715Smrg    /* intersect with client clip region. */
23335c4bbdfSmrg    if (pGC->clientClip)
23435c4bbdfSmrg        RegionIntersect(&rgnExposed, &rgnExposed, pGC->clientClip);
23505b261ecSmrg
23605b261ecSmrg    /*
23705b261ecSmrg     * If we have LOTS of rectangles, we decide to take the extents
23805b261ecSmrg     * and force an exposure on that.  This should require much less
23905b261ecSmrg     * work overall, on both client and server.  This is cheating, but
24005b261ecSmrg     * isn't prohibited by the protocol ("spontaneous combustion" :-)
24105b261ecSmrg     * for windows.
24205b261ecSmrg     */
24305b261ecSmrg    extents = pGC->graphicsExposures &&
24435c4bbdfSmrg        (RegionNumRects(&rgnExposed) > RECTLIMIT) &&
24535c4bbdfSmrg        (pDstDrawable->type != DRAWABLE_PIXMAP);
24635c4bbdfSmrg    if (pSrcWin) {
24735c4bbdfSmrg        RegionPtr region;
24835c4bbdfSmrg
24935c4bbdfSmrg        if (!(region = wClipShape(pSrcWin)))
25035c4bbdfSmrg            region = wBoundingShape(pSrcWin);
25135c4bbdfSmrg        /*
25235c4bbdfSmrg         * If you try to CopyArea the extents of a shaped window, compacting the
25335c4bbdfSmrg         * exposed region will undo all our work!
25435c4bbdfSmrg         */
25535c4bbdfSmrg        if (extents && pSrcWin && region &&
25635c4bbdfSmrg            (RegionContainsRect(region, &srcBox) != rgnIN))
25735c4bbdfSmrg            extents = FALSE;
25805b261ecSmrg    }
25935c4bbdfSmrg    if (extents) {
26035c4bbdfSmrg        expBox = *RegionExtents(&rgnExposed);
26135c4bbdfSmrg        RegionReset(&rgnExposed, &expBox);
26205b261ecSmrg    }
26305b261ecSmrg    if ((pDstDrawable->type != DRAWABLE_PIXMAP) &&
26435c4bbdfSmrg        (((WindowPtr) pDstDrawable)->backgroundState != None)) {
26535c4bbdfSmrg        WindowPtr pWin = (WindowPtr) pDstDrawable;
26605b261ecSmrg
26735c4bbdfSmrg        /* make the exposed area screen-relative */
26835c4bbdfSmrg        RegionTranslate(&rgnExposed, pDstDrawable->x, pDstDrawable->y);
26935c4bbdfSmrg
27035c4bbdfSmrg        if (extents) {
27135c4bbdfSmrg            /* PaintWindow doesn't clip, so we have to */
27235c4bbdfSmrg            RegionIntersect(&rgnExposed, &rgnExposed, &pWin->clipList);
27335c4bbdfSmrg        }
27435c4bbdfSmrg        pDstDrawable->pScreen->PaintWindow((WindowPtr) pDstDrawable,
27535c4bbdfSmrg                                           &rgnExposed, PW_BACKGROUND);
27635c4bbdfSmrg
27735c4bbdfSmrg        if (extents) {
27835c4bbdfSmrg            RegionReset(&rgnExposed, &expBox);
27935c4bbdfSmrg        }
28035c4bbdfSmrg        else
28135c4bbdfSmrg            RegionTranslate(&rgnExposed, -pDstDrawable->x, -pDstDrawable->y);
28235c4bbdfSmrg    }
28335c4bbdfSmrg    if (prgnDstClip == &rgnDstRec) {
28435c4bbdfSmrg        RegionUninit(prgnDstClip);
28505b261ecSmrg    }
28635c4bbdfSmrg    else if (prgnDstClip != prgnSrcClip) {
28735c4bbdfSmrg        RegionDestroy(prgnDstClip);
28805b261ecSmrg    }
28905b261ecSmrg
29035c4bbdfSmrg    if (prgnSrcClip == &rgnSrcRec) {
29135c4bbdfSmrg        RegionUninit(prgnSrcClip);
29205b261ecSmrg    }
29335c4bbdfSmrg    else {
29435c4bbdfSmrg        RegionDestroy(prgnSrcClip);
29505b261ecSmrg    }
29605b261ecSmrg
29735c4bbdfSmrg    if (pGC->graphicsExposures) {
29835c4bbdfSmrg        /* don't look */
29935c4bbdfSmrg        RegionPtr exposed = RegionCreate(NullBox, 0);
30005b261ecSmrg
30135c4bbdfSmrg        *exposed = rgnExposed;
30235c4bbdfSmrg        return exposed;
30305b261ecSmrg    }
30435c4bbdfSmrg    else {
30535c4bbdfSmrg        RegionUninit(&rgnExposed);
30635c4bbdfSmrg        return NULL;
30705b261ecSmrg    }
30805b261ecSmrg}
30905b261ecSmrg
31005b261ecSmrgvoid
31135c4bbdfSmrgmiSendExposures(WindowPtr pWin, RegionPtr pRgn, int dx, int dy)
31205b261ecSmrg{
31305b261ecSmrg    BoxPtr pBox;
31405b261ecSmrg    int numRects;
31505b261ecSmrg    xEvent *pEvent, *pe;
31605b261ecSmrg    int i;
31705b261ecSmrg
3186747b715Smrg    pBox = RegionRects(pRgn);
3196747b715Smrg    numRects = RegionNumRects(pRgn);
32035c4bbdfSmrg    if (!(pEvent = calloc(1, numRects * sizeof(xEvent))))
32135c4bbdfSmrg        return;
32235c4bbdfSmrg
32335c4bbdfSmrg    for (i = numRects, pe = pEvent; --i >= 0; pe++, pBox++) {
32435c4bbdfSmrg        pe->u.u.type = Expose;
32535c4bbdfSmrg        pe->u.expose.window = pWin->drawable.id;
32635c4bbdfSmrg        pe->u.expose.x = pBox->x1 - dx;
32735c4bbdfSmrg        pe->u.expose.y = pBox->y1 - dy;
32835c4bbdfSmrg        pe->u.expose.width = pBox->x2 - pBox->x1;
32935c4bbdfSmrg        pe->u.expose.height = pBox->y2 - pBox->y1;
33035c4bbdfSmrg        pe->u.expose.count = i;
33105b261ecSmrg    }
33205b261ecSmrg
33305b261ecSmrg#ifdef PANORAMIX
33435c4bbdfSmrg    if (!noPanoramiXExtension) {
33535c4bbdfSmrg        int scrnum = pWin->drawable.pScreen->myNum;
33635c4bbdfSmrg        int x = 0, y = 0;
33735c4bbdfSmrg        XID realWin = 0;
33835c4bbdfSmrg
33935c4bbdfSmrg        if (!pWin->parent) {
34035c4bbdfSmrg            x = screenInfo.screens[scrnum]->x;
34135c4bbdfSmrg            y = screenInfo.screens[scrnum]->y;
34235c4bbdfSmrg            pWin = screenInfo.screens[0]->root;
34335c4bbdfSmrg            realWin = pWin->drawable.id;
34435c4bbdfSmrg        }
34535c4bbdfSmrg        else if (scrnum) {
34635c4bbdfSmrg            PanoramiXRes *win;
34735c4bbdfSmrg
34835c4bbdfSmrg            win = PanoramiXFindIDByScrnum(XRT_WINDOW,
34935c4bbdfSmrg                                          pWin->drawable.id, scrnum);
35035c4bbdfSmrg            if (!win) {
35135c4bbdfSmrg                free(pEvent);
35235c4bbdfSmrg                return;
35335c4bbdfSmrg            }
35435c4bbdfSmrg            realWin = win->info[0].id;
35535c4bbdfSmrg            dixLookupWindow(&pWin, realWin, serverClient, DixSendAccess);
35635c4bbdfSmrg        }
35735c4bbdfSmrg        if (x || y || scrnum)
35835c4bbdfSmrg            for (i = 0; i < numRects; i++) {
35935c4bbdfSmrg                pEvent[i].u.expose.window = realWin;
36035c4bbdfSmrg                pEvent[i].u.expose.x += x;
36135c4bbdfSmrg                pEvent[i].u.expose.y += y;
36235c4bbdfSmrg            }
36305b261ecSmrg    }
36405b261ecSmrg#endif
36505b261ecSmrg
36605b261ecSmrg    DeliverEvents(pWin, pEvent, numRects, NullWindow);
36705b261ecSmrg
3686747b715Smrg    free(pEvent);
36905b261ecSmrg}
37005b261ecSmrg
3716747b715Smrgvoid
37235c4bbdfSmrgmiWindowExposures(WindowPtr pWin, RegionPtr prgn)
37305b261ecSmrg{
37435c4bbdfSmrg    RegionPtr exposures = prgn;
37535c4bbdfSmrg
37635c4bbdfSmrg    if (prgn && !RegionNil(prgn)) {
37735c4bbdfSmrg        RegionRec expRec;
37835c4bbdfSmrg        int clientInterested =
37935c4bbdfSmrg            (pWin->eventMask | wOtherEventMasks(pWin)) & ExposureMask;
38035c4bbdfSmrg        if (clientInterested && (RegionNumRects(prgn) > RECTLIMIT)) {
38135c4bbdfSmrg            /*
38235c4bbdfSmrg             * If we have LOTS of rectangles, we decide to take the extents
38335c4bbdfSmrg             * and force an exposure on that.  This should require much less
38435c4bbdfSmrg             * work overall, on both client and server.  This is cheating, but
38535c4bbdfSmrg             * isn't prohibited by the protocol ("spontaneous combustion" :-).
38635c4bbdfSmrg             */
38735c4bbdfSmrg            BoxRec box = *RegionExtents(prgn);
38835c4bbdfSmrg            exposures = &expRec;
38935c4bbdfSmrg            RegionInit(exposures, &box, 1);
39035c4bbdfSmrg            RegionReset(prgn, &box);
39135c4bbdfSmrg            /* miPaintWindow doesn't clip, so we have to */
39235c4bbdfSmrg            RegionIntersect(prgn, prgn, &pWin->clipList);
39335c4bbdfSmrg        }
39435c4bbdfSmrg        pWin->drawable.pScreen->PaintWindow(pWin, prgn, PW_BACKGROUND);
39535c4bbdfSmrg        if (clientInterested)
39635c4bbdfSmrg            miSendExposures(pWin, exposures,
39735c4bbdfSmrg                            pWin->drawable.x, pWin->drawable.y);
39835c4bbdfSmrg        if (exposures == &expRec)
39935c4bbdfSmrg            RegionUninit(exposures);
40035c4bbdfSmrg        RegionEmpty(prgn);
40105b261ecSmrg    }
40205b261ecSmrg}
40305b261ecSmrg
4044642e01fSmrgvoid
4054642e01fSmrgmiPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
40605b261ecSmrg{
40735c4bbdfSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
4086747b715Smrg    ChangeGCVal gcval[6];
40935c4bbdfSmrg    BITS32 gcmask;
41035c4bbdfSmrg    GCPtr pGC;
41135c4bbdfSmrg    int i;
41235c4bbdfSmrg    BoxPtr pbox;
41335c4bbdfSmrg    xRectangle *prect;
41435c4bbdfSmrg    int numRects;
41535c4bbdfSmrg
4164642e01fSmrg    /*
4174642e01fSmrg     * Distance from screen to destination drawable, use this
4184642e01fSmrg     * to adjust rendering coordinates which come in in screen space
4194642e01fSmrg     */
42035c4bbdfSmrg    int draw_x_off, draw_y_off;
42135c4bbdfSmrg
4224642e01fSmrg    /*
4234642e01fSmrg     * Tile offset for drawing; these need to align the tile
4244642e01fSmrg     * to the appropriate window origin
4254642e01fSmrg     */
42635c4bbdfSmrg    int tile_x_off, tile_y_off;
42735c4bbdfSmrg    PixUnion fill;
42835c4bbdfSmrg    Bool solid = TRUE;
42935c4bbdfSmrg    DrawablePtr drawable = &pWin->drawable;
43035c4bbdfSmrg
43135c4bbdfSmrg    if (what == PW_BACKGROUND) {
43235c4bbdfSmrg        while (pWin->backgroundState == ParentRelative)
43335c4bbdfSmrg            pWin = pWin->parent;
43435c4bbdfSmrg
43535c4bbdfSmrg        draw_x_off = drawable->x;
43635c4bbdfSmrg        draw_y_off = drawable->y;
43735c4bbdfSmrg
43835c4bbdfSmrg        tile_x_off = pWin->drawable.x - draw_x_off;
43935c4bbdfSmrg        tile_y_off = pWin->drawable.y - draw_y_off;
44035c4bbdfSmrg        fill = pWin->background;
44135c4bbdfSmrg#ifdef COMPOSITE
44235c4bbdfSmrg        if (pWin->inhibitBGPaint)
44335c4bbdfSmrg            return;
4446747b715Smrg#endif
44535c4bbdfSmrg        switch (pWin->backgroundState) {
44635c4bbdfSmrg        case None:
44735c4bbdfSmrg            return;
44835c4bbdfSmrg        case BackgroundPixmap:
44935c4bbdfSmrg            solid = FALSE;
45035c4bbdfSmrg            break;
45135c4bbdfSmrg        }
45205b261ecSmrg    }
45335c4bbdfSmrg    else {
45435c4bbdfSmrg        PixmapPtr pixmap;
45535c4bbdfSmrg
45635c4bbdfSmrg        fill = pWin->border;
45735c4bbdfSmrg        solid = pWin->borderIsPixel;
45835c4bbdfSmrg
45935c4bbdfSmrg        /* servers without pixmaps draw their own borders */
46035c4bbdfSmrg        if (!pScreen->GetWindowPixmap)
46135c4bbdfSmrg            return;
46235c4bbdfSmrg        pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable);
46335c4bbdfSmrg        drawable = &pixmap->drawable;
46435c4bbdfSmrg
46535c4bbdfSmrg        while (pWin->backgroundState == ParentRelative)
46635c4bbdfSmrg            pWin = pWin->parent;
46735c4bbdfSmrg
46835c4bbdfSmrg        tile_x_off = pWin->drawable.x;
46935c4bbdfSmrg        tile_y_off = pWin->drawable.y;
47035c4bbdfSmrg
4714642e01fSmrg#ifdef COMPOSITE
47235c4bbdfSmrg        draw_x_off = pixmap->screen_x;
47335c4bbdfSmrg        draw_y_off = pixmap->screen_y;
47435c4bbdfSmrg        tile_x_off -= draw_x_off;
47535c4bbdfSmrg        tile_y_off -= draw_y_off;
4764642e01fSmrg#else
47735c4bbdfSmrg        draw_x_off = 0;
47835c4bbdfSmrg        draw_y_off = 0;
4794642e01fSmrg#endif
48005b261ecSmrg    }
48135c4bbdfSmrg
4824642e01fSmrg    gcval[0].val = GXcopy;
4834642e01fSmrg    gcmask = GCFunction;
48405b261ecSmrg
4856747b715Smrg#ifdef ROOTLESS_SAFEALPHA
4866747b715Smrg/* Bit mask for alpha channel with a particular number of bits per
4876747b715Smrg * pixel. Note that we only care for 32bpp data. Mac OS X uses planar
4886747b715Smrg * alpha for 16bpp.
4896747b715Smrg */
4906747b715Smrg#define RootlessAlphaMask(bpp) ((bpp) == 32 ? 0xFF000000 : 0)
4916747b715Smrg#endif
49235c4bbdfSmrg
49335c4bbdfSmrg    if (solid) {
4946747b715Smrg#ifdef ROOTLESS_SAFEALPHA
49535c4bbdfSmrg        gcval[1].val =
49635c4bbdfSmrg            fill.pixel | RootlessAlphaMask(pWin->drawable.bitsPerPixel);
4976747b715Smrg#else
49835c4bbdfSmrg        gcval[1].val = fill.pixel;
4996747b715Smrg#endif
50035c4bbdfSmrg        gcval[2].val = FillSolid;
50135c4bbdfSmrg        gcmask |= GCForeground | GCFillStyle;
5024642e01fSmrg    }
50335c4bbdfSmrg    else {
50435c4bbdfSmrg        int c = 1;
50535c4bbdfSmrg
5066747b715Smrg#ifdef ROOTLESS_SAFEALPHA
50735c4bbdfSmrg        gcval[c++].val =
50835c4bbdfSmrg            ((CARD32) -1) & ~RootlessAlphaMask(pWin->drawable.bitsPerPixel);
50935c4bbdfSmrg        gcmask |= GCPlaneMask;
5106747b715Smrg#endif
51135c4bbdfSmrg        gcval[c++].val = FillTiled;
51235c4bbdfSmrg        gcval[c++].ptr = (void *) fill.pixmap;
51335c4bbdfSmrg        gcval[c++].val = tile_x_off;
51435c4bbdfSmrg        gcval[c++].val = tile_y_off;
51535c4bbdfSmrg        gcmask |= GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin;
5164642e01fSmrg    }
5174642e01fSmrg
51835c4bbdfSmrg    prect = xallocarray(RegionNumRects(prgn), sizeof(xRectangle));
51905b261ecSmrg    if (!prect)
52035c4bbdfSmrg        return;
52105b261ecSmrg
5224642e01fSmrg    pGC = GetScratchGC(drawable->depth, drawable->pScreen);
52335c4bbdfSmrg    if (!pGC) {
52435c4bbdfSmrg        free(prect);
52535c4bbdfSmrg        return;
52605b261ecSmrg    }
52735c4bbdfSmrg
52835c4bbdfSmrg    ChangeGC(NullClient, pGC, gcmask, gcval);
52935c4bbdfSmrg    ValidateGC(drawable, pGC);
53005b261ecSmrg
5316747b715Smrg    numRects = RegionNumRects(prgn);
5326747b715Smrg    pbox = RegionRects(prgn);
53335c4bbdfSmrg    for (i = numRects; --i >= 0; pbox++, prect++) {
53435c4bbdfSmrg        prect->x = pbox->x1 - draw_x_off;
53535c4bbdfSmrg        prect->y = pbox->y1 - draw_y_off;
53635c4bbdfSmrg        prect->width = pbox->x2 - pbox->x1;
53735c4bbdfSmrg        prect->height = pbox->y2 - pbox->y1;
53805b261ecSmrg    }
53905b261ecSmrg    prect -= numRects;
54035c4bbdfSmrg    (*pGC->ops->PolyFillRect) (drawable, pGC, numRects, prect);
5416747b715Smrg    free(prect);
54205b261ecSmrg
5434642e01fSmrg    FreeScratchGC(pGC);
54405b261ecSmrg}
54505b261ecSmrg
54605b261ecSmrg/* MICLEARDRAWABLE -- sets the entire drawable to the background color of
54735c4bbdfSmrg * the GC.  Useful when we have a scratch drawable and need to initialize
54805b261ecSmrg * it. */
5496747b715Smrgvoid
5504642e01fSmrgmiClearDrawable(DrawablePtr pDraw, GCPtr pGC)
55105b261ecSmrg{
5526747b715Smrg    ChangeGCVal fg, bg;
55305b261ecSmrg    xRectangle rect;
55405b261ecSmrg
5556747b715Smrg    fg.val = pGC->fgPixel;
5566747b715Smrg    bg.val = pGC->bgPixel;
55705b261ecSmrg    rect.x = 0;
55805b261ecSmrg    rect.y = 0;
55905b261ecSmrg    rect.width = pDraw->width;
56005b261ecSmrg    rect.height = pDraw->height;
5616747b715Smrg    ChangeGC(NullClient, pGC, GCForeground, &bg);
56205b261ecSmrg    ValidateGC(pDraw, pGC);
56335c4bbdfSmrg    (*pGC->ops->PolyFillRect) (pDraw, pGC, 1, &rect);
5646747b715Smrg    ChangeGC(NullClient, pGC, GCForeground, &fg);
56505b261ecSmrg    ValidateGC(pDraw, pGC);
56605b261ecSmrg}
567