miexpose.c revision 4642e01f
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
2505b261ecSmrg
2605b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
2705b261ecSmrg
2805b261ecSmrg                        All Rights Reserved
2905b261ecSmrg
3005b261ecSmrgPermission to use, copy, modify, and distribute this software and its
3105b261ecSmrgdocumentation for any purpose and without fee is hereby granted,
3205b261ecSmrgprovided that the above copyright notice appear in all copies and that
3305b261ecSmrgboth that copyright notice and this permission notice appear in
3405b261ecSmrgsupporting documentation, and that the name of Digital not be
3505b261ecSmrgused in advertising or publicity pertaining to distribution of the
3605b261ecSmrgsoftware without specific, written prior permission.
3705b261ecSmrg
3805b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
3905b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
4005b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4105b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4205b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4305b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4405b261ecSmrgSOFTWARE.
4505b261ecSmrg
4605b261ecSmrg******************************************************************/
4705b261ecSmrg/*****************************************************************
4805b261ecSmrg
4905b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
5005b261ecSmrg
5105b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy
5205b261ecSmrgof this software and associated documentation files (the "Software"), to deal
5305b261ecSmrgin the Software without restriction, including without limitation the rights
5405b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5505b261ecSmrgcopies of the Software.
5605b261ecSmrg
5705b261ecSmrgThe above copyright notice and this permission notice shall be included in
5805b261ecSmrgall copies or substantial portions of the Software.
5905b261ecSmrg
6005b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6105b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6205b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
6305b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
6405b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
6505b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
6605b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6705b261ecSmrg
6805b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation
6905b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other
7005b261ecSmrgdealings in this Software without prior written authorization from Digital
7105b261ecSmrgEquipment Corporation.
7205b261ecSmrg
7305b261ecSmrg******************************************************************/
7405b261ecSmrg
7505b261ecSmrg
7605b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
7705b261ecSmrg#include <dix-config.h>
7805b261ecSmrg#endif
7905b261ecSmrg
8005b261ecSmrg#include <X11/X.h>
8105b261ecSmrg#define NEED_EVENTS
8205b261ecSmrg#include <X11/Xproto.h>
8305b261ecSmrg#include <X11/Xprotostr.h>
8405b261ecSmrg
8505b261ecSmrg#include "misc.h"
8605b261ecSmrg#include "regionstr.h"
8705b261ecSmrg#include "scrnintstr.h"
8805b261ecSmrg#include "gcstruct.h"
8905b261ecSmrg#include "windowstr.h"
9005b261ecSmrg#include "pixmap.h"
9105b261ecSmrg#include "input.h"
9205b261ecSmrg
9305b261ecSmrg#include "dixstruct.h"
9405b261ecSmrg#include "mi.h"
9505b261ecSmrg#include <X11/Xmd.h>
9605b261ecSmrg
9705b261ecSmrg#include "globals.h"
9805b261ecSmrg
9905b261ecSmrg#ifdef PANORAMIX
10005b261ecSmrg#include "panoramiX.h"
10105b261ecSmrg#include "panoramiXsrv.h"
10205b261ecSmrg#endif
10305b261ecSmrg
10405b261ecSmrg/*
10505b261ecSmrg    machine-independent graphics exposure code.  any device that uses
10605b261ecSmrgthe region package can call this.
10705b261ecSmrg*/
10805b261ecSmrg
10905b261ecSmrg#ifndef RECTLIMIT
11005b261ecSmrg#define RECTLIMIT 25		/* pick a number, any number > 8 */
11105b261ecSmrg#endif
11205b261ecSmrg
11305b261ecSmrg/* miHandleExposures
11405b261ecSmrg    generate a region for exposures for areas that were copied from obscured or
11505b261ecSmrgnon-existent areas to non-obscured areas of the destination.  Paint the
11605b261ecSmrgbackground for the region, if the destination is a window.
11705b261ecSmrg
11805b261ecSmrgNOTE:
11905b261ecSmrg     this should generally be called, even if graphicsExposures is false,
12005b261ecSmrgbecause this is where bits get recovered from backing store.
12105b261ecSmrg
12205b261ecSmrgNOTE:
12305b261ecSmrg     added argument 'plane' is used to indicate how exposures from backing
12405b261ecSmrgstore should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea
12505b261ecSmrgshould be used, else a CopyPlane of the indicated plane will be used. The
12605b261ecSmrgexposing is done by the backing store's GraphicsExpose function, of course.
12705b261ecSmrg
12805b261ecSmrg*/
12905b261ecSmrg
13005b261ecSmrg_X_EXPORT RegionPtr
1314642e01fSmrgmiHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
1324642e01fSmrg		  GCPtr pGC, int srcx, int srcy, int width, int height,
1334642e01fSmrg		  int dstx, int dsty, unsigned long plane)
13405b261ecSmrg{
13505b261ecSmrg    ScreenPtr pscr;
13605b261ecSmrg    RegionPtr prgnSrcClip;	/* drawable-relative source clip */
13705b261ecSmrg    RegionRec rgnSrcRec;
13805b261ecSmrg    RegionPtr prgnDstClip;	/* drawable-relative dest clip */
13905b261ecSmrg    RegionRec rgnDstRec;
14005b261ecSmrg    BoxRec srcBox;		/* unclipped source */
14105b261ecSmrg    RegionRec rgnExposed;	/* exposed region, calculated source-
14205b261ecSmrg				   relative, made dst relative to
14305b261ecSmrg				   intersect with visible parts of
14405b261ecSmrg				   dest and send events to client,
14505b261ecSmrg				   and then screen relative to paint
14605b261ecSmrg				   the window background
14705b261ecSmrg				*/
14805b261ecSmrg    WindowPtr pSrcWin;
14905b261ecSmrg    BoxRec expBox;
15005b261ecSmrg    Bool extents;
15105b261ecSmrg
15205b261ecSmrg    /* This prevents warning about pscr not being used. */
15305b261ecSmrg    pGC->pScreen = pscr = pGC->pScreen;
15405b261ecSmrg
15505b261ecSmrg    /* avoid work if we can */
15605b261ecSmrg    if (!pGC->graphicsExposures &&
15705b261ecSmrg	(pDstDrawable->type == DRAWABLE_PIXMAP) &&
15805b261ecSmrg	((pSrcDrawable->type == DRAWABLE_PIXMAP) ||
15905b261ecSmrg	 (((WindowPtr)pSrcDrawable)->backStorage == NULL)))
16005b261ecSmrg	return NULL;
16105b261ecSmrg
16205b261ecSmrg    srcBox.x1 = srcx;
16305b261ecSmrg    srcBox.y1 = srcy;
16405b261ecSmrg    srcBox.x2 = srcx+width;
16505b261ecSmrg    srcBox.y2 = srcy+height;
16605b261ecSmrg
16705b261ecSmrg    if (pSrcDrawable->type != DRAWABLE_PIXMAP)
16805b261ecSmrg    {
16905b261ecSmrg	BoxRec TsrcBox;
17005b261ecSmrg
17105b261ecSmrg	TsrcBox.x1 = srcx + pSrcDrawable->x;
17205b261ecSmrg	TsrcBox.y1 = srcy + pSrcDrawable->y;
17305b261ecSmrg	TsrcBox.x2 = TsrcBox.x1 + width;
17405b261ecSmrg	TsrcBox.y2 = TsrcBox.y1 + height;
17505b261ecSmrg	pSrcWin = (WindowPtr) pSrcDrawable;
17605b261ecSmrg	if (pGC->subWindowMode == IncludeInferiors)
17705b261ecSmrg 	{
17805b261ecSmrg	    prgnSrcClip = NotClippedByChildren (pSrcWin);
17905b261ecSmrg	    if ((RECT_IN_REGION(pscr, prgnSrcClip, &TsrcBox)) == rgnIN)
18005b261ecSmrg	    {
18105b261ecSmrg		REGION_DESTROY(pscr, prgnSrcClip);
18205b261ecSmrg		return NULL;
18305b261ecSmrg	    }
18405b261ecSmrg	}
18505b261ecSmrg 	else
18605b261ecSmrg 	{
18705b261ecSmrg	    if ((RECT_IN_REGION(pscr, &pSrcWin->clipList, &TsrcBox)) == rgnIN)
18805b261ecSmrg		return NULL;
18905b261ecSmrg	    prgnSrcClip = &rgnSrcRec;
19005b261ecSmrg	    REGION_NULL(pscr, prgnSrcClip);
19105b261ecSmrg	    REGION_COPY(pscr, prgnSrcClip, &pSrcWin->clipList);
19205b261ecSmrg	}
19305b261ecSmrg	REGION_TRANSLATE(pscr, prgnSrcClip,
19405b261ecSmrg				-pSrcDrawable->x, -pSrcDrawable->y);
19505b261ecSmrg    }
19605b261ecSmrg    else
19705b261ecSmrg    {
19805b261ecSmrg	BoxRec	box;
19905b261ecSmrg
20005b261ecSmrg	if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
20105b261ecSmrg	    (srcBox.x2 <= pSrcDrawable->width) &&
20205b261ecSmrg 	    (srcBox.y2 <= pSrcDrawable->height))
20305b261ecSmrg	    return NULL;
20405b261ecSmrg
20505b261ecSmrg	box.x1 = 0;
20605b261ecSmrg	box.y1 = 0;
20705b261ecSmrg	box.x2 = pSrcDrawable->width;
20805b261ecSmrg	box.y2 = pSrcDrawable->height;
20905b261ecSmrg	prgnSrcClip = &rgnSrcRec;
21005b261ecSmrg	REGION_INIT(pscr, prgnSrcClip, &box, 1);
21105b261ecSmrg	pSrcWin = (WindowPtr)NULL;
21205b261ecSmrg    }
21305b261ecSmrg
21405b261ecSmrg    if (pDstDrawable == pSrcDrawable)
21505b261ecSmrg    {
21605b261ecSmrg	prgnDstClip = prgnSrcClip;
21705b261ecSmrg    }
21805b261ecSmrg    else if (pDstDrawable->type != DRAWABLE_PIXMAP)
21905b261ecSmrg    {
22005b261ecSmrg	if (pGC->subWindowMode == IncludeInferiors)
22105b261ecSmrg	{
22205b261ecSmrg	    prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable);
22305b261ecSmrg	}
22405b261ecSmrg	else
22505b261ecSmrg	{
22605b261ecSmrg	    prgnDstClip = &rgnDstRec;
22705b261ecSmrg	    REGION_NULL(pscr, prgnDstClip);
22805b261ecSmrg	    REGION_COPY(pscr, prgnDstClip,
22905b261ecSmrg				&((WindowPtr)pDstDrawable)->clipList);
23005b261ecSmrg	}
23105b261ecSmrg	REGION_TRANSLATE(pscr, prgnDstClip,
23205b261ecSmrg				 -pDstDrawable->x, -pDstDrawable->y);
23305b261ecSmrg    }
23405b261ecSmrg    else
23505b261ecSmrg    {
23605b261ecSmrg	BoxRec	box;
23705b261ecSmrg
23805b261ecSmrg	box.x1 = 0;
23905b261ecSmrg	box.y1 = 0;
24005b261ecSmrg	box.x2 = pDstDrawable->width;
24105b261ecSmrg	box.y2 = pDstDrawable->height;
24205b261ecSmrg	prgnDstClip = &rgnDstRec;
24305b261ecSmrg	REGION_INIT(pscr, prgnDstClip, &box, 1);
24405b261ecSmrg    }
24505b261ecSmrg
24605b261ecSmrg    /* drawable-relative source region */
24705b261ecSmrg    REGION_INIT(pscr, &rgnExposed, &srcBox, 1);
24805b261ecSmrg
24905b261ecSmrg    /* now get the hidden parts of the source box*/
25005b261ecSmrg    REGION_SUBTRACT(pscr, &rgnExposed, &rgnExposed, prgnSrcClip);
25105b261ecSmrg
25205b261ecSmrg    /* move them over the destination */
25305b261ecSmrg    REGION_TRANSLATE(pscr, &rgnExposed, dstx-srcx, dsty-srcy);
25405b261ecSmrg
25505b261ecSmrg    /* intersect with visible areas of dest */
25605b261ecSmrg    REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, prgnDstClip);
25705b261ecSmrg
25805b261ecSmrg    /*
25905b261ecSmrg     * If we have LOTS of rectangles, we decide to take the extents
26005b261ecSmrg     * and force an exposure on that.  This should require much less
26105b261ecSmrg     * work overall, on both client and server.  This is cheating, but
26205b261ecSmrg     * isn't prohibited by the protocol ("spontaneous combustion" :-)
26305b261ecSmrg     * for windows.
26405b261ecSmrg     */
26505b261ecSmrg    extents = pGC->graphicsExposures &&
26605b261ecSmrg	      (REGION_NUM_RECTS(&rgnExposed) > RECTLIMIT) &&
26705b261ecSmrg	      (pDstDrawable->type != DRAWABLE_PIXMAP);
26805b261ecSmrg    if (pSrcWin)
26905b261ecSmrg    {
27005b261ecSmrg	RegionPtr	region;
27105b261ecSmrg    	if (!(region = wClipShape (pSrcWin)))
27205b261ecSmrg    	    region = wBoundingShape (pSrcWin);
27305b261ecSmrg    	/*
27405b261ecSmrg     	 * If you try to CopyArea the extents of a shaped window, compacting the
27505b261ecSmrg     	 * exposed region will undo all our work!
27605b261ecSmrg     	 */
27705b261ecSmrg    	if (extents && pSrcWin && region &&
27805b261ecSmrg    	    (RECT_IN_REGION(pscr, region, &srcBox) != rgnIN))
27905b261ecSmrg	    	extents = FALSE;
28005b261ecSmrg    }
28105b261ecSmrg    if (extents)
28205b261ecSmrg    {
28305b261ecSmrg	expBox = *REGION_EXTENTS(pscr, &rgnExposed);
28405b261ecSmrg	REGION_RESET(pscr, &rgnExposed, &expBox);
28505b261ecSmrg    }
28605b261ecSmrg    if ((pDstDrawable->type != DRAWABLE_PIXMAP) &&
28705b261ecSmrg	(((WindowPtr)pDstDrawable)->backgroundState != None))
28805b261ecSmrg    {
28905b261ecSmrg	WindowPtr pWin = (WindowPtr)pDstDrawable;
29005b261ecSmrg
29105b261ecSmrg	/* make the exposed area screen-relative */
29205b261ecSmrg	REGION_TRANSLATE(pscr, &rgnExposed,
29305b261ecSmrg				 pDstDrawable->x, pDstDrawable->y);
29405b261ecSmrg
29505b261ecSmrg	if (extents)
29605b261ecSmrg	{
29705b261ecSmrg	    /* PaintWindowBackground doesn't clip, so we have to */
29805b261ecSmrg	    REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, &pWin->clipList);
29905b261ecSmrg	}
3004642e01fSmrg	miPaintWindow((WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND);
30105b261ecSmrg
30205b261ecSmrg	if (extents)
30305b261ecSmrg	{
30405b261ecSmrg	    REGION_RESET(pscr, &rgnExposed, &expBox);
30505b261ecSmrg	}
30605b261ecSmrg	else
30705b261ecSmrg	    REGION_TRANSLATE(pscr, &rgnExposed,
30805b261ecSmrg				     -pDstDrawable->x, -pDstDrawable->y);
30905b261ecSmrg    }
31005b261ecSmrg    if (prgnDstClip == &rgnDstRec)
31105b261ecSmrg    {
31205b261ecSmrg	REGION_UNINIT(pscr, prgnDstClip);
31305b261ecSmrg    }
31405b261ecSmrg    else if (prgnDstClip != prgnSrcClip)
31505b261ecSmrg    {
31605b261ecSmrg	REGION_DESTROY(pscr, prgnDstClip);
31705b261ecSmrg    }
31805b261ecSmrg
31905b261ecSmrg    if (prgnSrcClip == &rgnSrcRec)
32005b261ecSmrg    {
32105b261ecSmrg	REGION_UNINIT(pscr, prgnSrcClip);
32205b261ecSmrg    }
32305b261ecSmrg    else
32405b261ecSmrg    {
32505b261ecSmrg	REGION_DESTROY(pscr, prgnSrcClip);
32605b261ecSmrg    }
32705b261ecSmrg
32805b261ecSmrg    if (pGC->graphicsExposures)
32905b261ecSmrg    {
33005b261ecSmrg	/* don't look */
33105b261ecSmrg	RegionPtr exposed = REGION_CREATE(pscr, NullBox, 0);
33205b261ecSmrg	*exposed = rgnExposed;
33305b261ecSmrg	return exposed;
33405b261ecSmrg    }
33505b261ecSmrg    else
33605b261ecSmrg    {
33705b261ecSmrg	REGION_UNINIT(pscr, &rgnExposed);
33805b261ecSmrg	return NULL;
33905b261ecSmrg    }
34005b261ecSmrg}
34105b261ecSmrg
34205b261ecSmrg/* send GraphicsExpose events, or a NoExpose event, based on the region */
34305b261ecSmrg
3444642e01fSmrgvoid
3454642e01fSmrgmiSendGraphicsExpose (ClientPtr client, RegionPtr pRgn, XID drawable,
3464642e01fSmrg                      int major, int minor)
34705b261ecSmrg{
34805b261ecSmrg    if (pRgn && !REGION_NIL(pRgn))
34905b261ecSmrg    {
35005b261ecSmrg        xEvent *pEvent;
35105b261ecSmrg	xEvent *pe;
35205b261ecSmrg	BoxPtr pBox;
35305b261ecSmrg	int i;
35405b261ecSmrg	int numRects;
35505b261ecSmrg
35605b261ecSmrg	numRects = REGION_NUM_RECTS(pRgn);
35705b261ecSmrg	pBox = REGION_RECTS(pRgn);
3584642e01fSmrg	if(!(pEvent = (xEvent *)xalloc(numRects * sizeof(xEvent))))
35905b261ecSmrg		return;
36005b261ecSmrg	pe = pEvent;
36105b261ecSmrg
36205b261ecSmrg	for (i=1; i<=numRects; i++, pe++, pBox++)
36305b261ecSmrg	{
36405b261ecSmrg	    pe->u.u.type = GraphicsExpose;
36505b261ecSmrg	    pe->u.graphicsExposure.drawable = drawable;
36605b261ecSmrg	    pe->u.graphicsExposure.x = pBox->x1;
36705b261ecSmrg	    pe->u.graphicsExposure.y = pBox->y1;
36805b261ecSmrg	    pe->u.graphicsExposure.width = pBox->x2 - pBox->x1;
36905b261ecSmrg	    pe->u.graphicsExposure.height = pBox->y2 - pBox->y1;
37005b261ecSmrg	    pe->u.graphicsExposure.count = numRects - i;
37105b261ecSmrg	    pe->u.graphicsExposure.majorEvent = major;
37205b261ecSmrg	    pe->u.graphicsExposure.minorEvent = minor;
37305b261ecSmrg	}
3744642e01fSmrg	TryClientEvents(client, NULL, pEvent, numRects,
37505b261ecSmrg			    (Mask)0, NoEventMask, NullGrab);
3764642e01fSmrg	xfree(pEvent);
37705b261ecSmrg    }
37805b261ecSmrg    else
37905b261ecSmrg    {
38005b261ecSmrg        xEvent event;
38105b261ecSmrg	event.u.u.type = NoExpose;
38205b261ecSmrg	event.u.noExposure.drawable = drawable;
38305b261ecSmrg	event.u.noExposure.majorEvent = major;
38405b261ecSmrg	event.u.noExposure.minorEvent = minor;
3854642e01fSmrg	TryClientEvents(client, NULL, &event, 1,
38605b261ecSmrg	    (Mask)0, NoEventMask, NullGrab);
38705b261ecSmrg    }
38805b261ecSmrg}
38905b261ecSmrg
39005b261ecSmrg
39105b261ecSmrgvoid
3924642e01fSmrgmiSendExposures( WindowPtr pWin, RegionPtr pRgn, int dx, int dy)
39305b261ecSmrg{
39405b261ecSmrg    BoxPtr pBox;
39505b261ecSmrg    int numRects;
39605b261ecSmrg    xEvent *pEvent, *pe;
39705b261ecSmrg    int i;
39805b261ecSmrg
39905b261ecSmrg    pBox = REGION_RECTS(pRgn);
40005b261ecSmrg    numRects = REGION_NUM_RECTS(pRgn);
4014642e01fSmrg    if(!(pEvent = (xEvent *) xalloc(numRects * sizeof(xEvent))))
40205b261ecSmrg	return;
40305b261ecSmrg
40405b261ecSmrg    for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++)
40505b261ecSmrg    {
40605b261ecSmrg	pe->u.u.type = Expose;
40705b261ecSmrg	pe->u.expose.window = pWin->drawable.id;
40805b261ecSmrg	pe->u.expose.x = pBox->x1 - dx;
40905b261ecSmrg	pe->u.expose.y = pBox->y1 - dy;
41005b261ecSmrg	pe->u.expose.width = pBox->x2 - pBox->x1;
41105b261ecSmrg	pe->u.expose.height = pBox->y2 - pBox->y1;
41205b261ecSmrg	pe->u.expose.count = i;
41305b261ecSmrg    }
41405b261ecSmrg
41505b261ecSmrg#ifdef PANORAMIX
41605b261ecSmrg    if(!noPanoramiXExtension) {
41705b261ecSmrg	int scrnum = pWin->drawable.pScreen->myNum;
41805b261ecSmrg	int x = 0, y = 0;
41905b261ecSmrg	XID realWin = 0;
42005b261ecSmrg
42105b261ecSmrg	if(!pWin->parent) {
42205b261ecSmrg	    x = panoramiXdataPtr[scrnum].x;
42305b261ecSmrg	    y = panoramiXdataPtr[scrnum].y;
42405b261ecSmrg	    pWin = WindowTable[0];
42505b261ecSmrg	    realWin = pWin->drawable.id;
42605b261ecSmrg	} else if (scrnum) {
42705b261ecSmrg	    PanoramiXRes *win;
42805b261ecSmrg	    win = PanoramiXFindIDByScrnum(XRT_WINDOW,
42905b261ecSmrg			pWin->drawable.id, scrnum);
43005b261ecSmrg	    if(!win) {
4314642e01fSmrg		xfree(pEvent);
43205b261ecSmrg		return;
43305b261ecSmrg	    }
43405b261ecSmrg	    realWin = win->info[0].id;
43505b261ecSmrg	    pWin = LookupIDByType(realWin, RT_WINDOW);
43605b261ecSmrg	}
43705b261ecSmrg	if(x || y || scrnum)
43805b261ecSmrg	  for (i = 0; i < numRects; i++) {
43905b261ecSmrg	      pEvent[i].u.expose.window = realWin;
44005b261ecSmrg	      pEvent[i].u.expose.x += x;
44105b261ecSmrg	      pEvent[i].u.expose.y += y;
44205b261ecSmrg	  }
44305b261ecSmrg    }
44405b261ecSmrg#endif
44505b261ecSmrg
44605b261ecSmrg    DeliverEvents(pWin, pEvent, numRects, NullWindow);
44705b261ecSmrg
4484642e01fSmrg    xfree(pEvent);
44905b261ecSmrg}
45005b261ecSmrg
45105b261ecSmrg_X_EXPORT void
4524642e01fSmrgmiWindowExposures( WindowPtr pWin, RegionPtr prgn, RegionPtr other_exposed)
45305b261ecSmrg{
45405b261ecSmrg    RegionPtr   exposures = prgn;
45505b261ecSmrg    if ((prgn && !REGION_NIL(prgn)) ||
45605b261ecSmrg	(exposures && !REGION_NIL(exposures)) || other_exposed)
45705b261ecSmrg    {
45805b261ecSmrg	RegionRec   expRec;
45905b261ecSmrg	int	    clientInterested;
46005b261ecSmrg
46105b261ecSmrg	/*
46205b261ecSmrg	 * Restore from backing-store FIRST.
46305b261ecSmrg	 */
46405b261ecSmrg	clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask;
46505b261ecSmrg	if (other_exposed)
46605b261ecSmrg	{
46705b261ecSmrg	    if (exposures)
46805b261ecSmrg	    {
46905b261ecSmrg		REGION_UNION(pWin->drawable.pScreen, other_exposed,
47005b261ecSmrg						  exposures,
47105b261ecSmrg					          other_exposed);
47205b261ecSmrg		if (exposures != prgn)
47305b261ecSmrg		    REGION_DESTROY(pWin->drawable.pScreen, exposures);
47405b261ecSmrg	    }
47505b261ecSmrg	    exposures = other_exposed;
47605b261ecSmrg	}
47705b261ecSmrg	if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT))
47805b261ecSmrg	{
47905b261ecSmrg	    /*
48005b261ecSmrg	     * If we have LOTS of rectangles, we decide to take the extents
48105b261ecSmrg	     * and force an exposure on that.  This should require much less
48205b261ecSmrg	     * work overall, on both client and server.  This is cheating, but
48305b261ecSmrg	     * isn't prohibited by the protocol ("spontaneous combustion" :-).
48405b261ecSmrg	     */
48505b261ecSmrg	    BoxRec box;
48605b261ecSmrg
48705b261ecSmrg	    box = *REGION_EXTENTS( pWin->drawable.pScreen, exposures);
48805b261ecSmrg	    if (exposures == prgn) {
48905b261ecSmrg		exposures = &expRec;
49005b261ecSmrg		REGION_INIT( pWin->drawable.pScreen, exposures, &box, 1);
49105b261ecSmrg		REGION_RESET( pWin->drawable.pScreen, prgn, &box);
49205b261ecSmrg	    } else {
49305b261ecSmrg		REGION_RESET( pWin->drawable.pScreen, exposures, &box);
49405b261ecSmrg		REGION_UNION( pWin->drawable.pScreen, prgn, prgn, exposures);
49505b261ecSmrg	    }
49605b261ecSmrg	    /* PaintWindowBackground doesn't clip, so we have to */
49705b261ecSmrg	    REGION_INTERSECT( pWin->drawable.pScreen, prgn, prgn, &pWin->clipList);
49805b261ecSmrg	}
49905b261ecSmrg	if (prgn && !REGION_NIL(prgn))
5004642e01fSmrg	    miPaintWindow(pWin, prgn, PW_BACKGROUND);
50105b261ecSmrg	if (clientInterested && exposures && !REGION_NIL(exposures))
50205b261ecSmrg	    miSendExposures(pWin, exposures,
50305b261ecSmrg			    pWin->drawable.x, pWin->drawable.y);
50405b261ecSmrg	if (exposures == &expRec)
50505b261ecSmrg	{
50605b261ecSmrg	    REGION_UNINIT( pWin->drawable.pScreen, exposures);
50705b261ecSmrg	}
50805b261ecSmrg	else if (exposures && exposures != prgn && exposures != other_exposed)
50905b261ecSmrg	    REGION_DESTROY( pWin->drawable.pScreen, exposures);
51005b261ecSmrg	if (prgn)
51105b261ecSmrg	    REGION_EMPTY( pWin->drawable.pScreen, prgn);
51205b261ecSmrg    }
51305b261ecSmrg    else if (exposures && exposures != prgn)
51405b261ecSmrg	REGION_DESTROY( pWin->drawable.pScreen, exposures);
51505b261ecSmrg}
51605b261ecSmrg
5174642e01fSmrgvoid
5184642e01fSmrgmiPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
51905b261ecSmrg{
5204642e01fSmrg    ScreenPtr	pScreen = pWin->drawable.pScreen;
5214642e01fSmrg    ChangeGCVal gcval[5];
5224642e01fSmrg    BITS32	gcmask;
5234642e01fSmrg    GCPtr	pGC;
5244642e01fSmrg    int		i;
5254642e01fSmrg    BoxPtr	pbox;
5264642e01fSmrg    xRectangle	*prect;
5274642e01fSmrg    int		numRects;
5284642e01fSmrg    /*
5294642e01fSmrg     * Distance from screen to destination drawable, use this
5304642e01fSmrg     * to adjust rendering coordinates which come in in screen space
5314642e01fSmrg     */
5324642e01fSmrg    int		draw_x_off, draw_y_off;
5334642e01fSmrg    /*
5344642e01fSmrg     * Tile offset for drawing; these need to align the tile
5354642e01fSmrg     * to the appropriate window origin
5364642e01fSmrg     */
5374642e01fSmrg    int		tile_x_off, tile_y_off;
5384642e01fSmrg    PixUnion	fill;
5394642e01fSmrg    Bool	solid = TRUE;
5404642e01fSmrg    DrawablePtr	drawable = &pWin->drawable;
54105b261ecSmrg
54205b261ecSmrg    if (what == PW_BACKGROUND)
54305b261ecSmrg    {
5444642e01fSmrg	while (pWin->backgroundState == ParentRelative)
5454642e01fSmrg	    pWin = pWin->parent;
5464642e01fSmrg
5474642e01fSmrg	draw_x_off = drawable->x;
5484642e01fSmrg	draw_y_off = drawable->y;
5494642e01fSmrg
5504642e01fSmrg	tile_x_off = pWin->drawable.x - draw_x_off;
5514642e01fSmrg	tile_y_off = pWin->drawable.y - draw_y_off;
5524642e01fSmrg	fill = pWin->background;
55305b261ecSmrg	switch (pWin->backgroundState) {
55405b261ecSmrg	case None:
55505b261ecSmrg	    return;
55605b261ecSmrg	case BackgroundPixmap:
5574642e01fSmrg	    solid = FALSE;
55805b261ecSmrg	    break;
55905b261ecSmrg	}
56005b261ecSmrg    }
56105b261ecSmrg    else
56205b261ecSmrg    {
5634642e01fSmrg	PixmapPtr   pixmap;
5644642e01fSmrg
5654642e01fSmrg	tile_x_off = drawable->x;
5664642e01fSmrg	tile_y_off = drawable->y;
5674642e01fSmrg
5684642e01fSmrg	/* servers without pixmaps draw their own borders */
5694642e01fSmrg	if (!pScreen->GetWindowPixmap)
5704642e01fSmrg	    return;
5714642e01fSmrg	pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable);
5724642e01fSmrg	drawable = &pixmap->drawable;
5734642e01fSmrg#ifdef COMPOSITE
5744642e01fSmrg	draw_x_off = pixmap->screen_x;
5754642e01fSmrg	draw_y_off = pixmap->screen_y;
5764642e01fSmrg	tile_x_off -= draw_x_off;
5774642e01fSmrg	tile_y_off -= draw_y_off;
5784642e01fSmrg#else
5794642e01fSmrg	draw_x_off = 0;
5804642e01fSmrg	draw_y_off = 0;
5814642e01fSmrg#endif
5824642e01fSmrg	fill = pWin->border;
5834642e01fSmrg	solid = pWin->borderIsPixel;
58405b261ecSmrg    }
5854642e01fSmrg
5864642e01fSmrg    gcval[0].val = GXcopy;
5874642e01fSmrg    gcmask = GCFunction;
58805b261ecSmrg
5894642e01fSmrg    if (solid)
5904642e01fSmrg    {
5914642e01fSmrg	gcval[1].val = fill.pixel;
5924642e01fSmrg	gcval[2].val  = FillSolid;
5934642e01fSmrg	gcmask |= GCForeground | GCFillStyle;
5944642e01fSmrg    }
5954642e01fSmrg    else
5964642e01fSmrg    {
5974642e01fSmrg	gcval[1].val = FillTiled;
5984642e01fSmrg	gcval[2].ptr = (pointer)fill.pixmap;
5994642e01fSmrg	gcval[3].val = tile_x_off;
6004642e01fSmrg	gcval[4].val = tile_y_off;
6014642e01fSmrg	gcmask |= GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin;
6024642e01fSmrg    }
6034642e01fSmrg
6044642e01fSmrg    prect = (xRectangle *)xalloc(REGION_NUM_RECTS(prgn) *
60505b261ecSmrg					 sizeof(xRectangle));
60605b261ecSmrg    if (!prect)
60705b261ecSmrg	return;
60805b261ecSmrg
6094642e01fSmrg    pGC = GetScratchGC(drawable->depth, drawable->pScreen);
6104642e01fSmrg    if (!pGC)
61105b261ecSmrg    {
6124642e01fSmrg	xfree(prect);
6134642e01fSmrg	return;
61405b261ecSmrg    }
61505b261ecSmrg
6164642e01fSmrg    dixChangeGC (NullClient, pGC, gcmask, NULL, gcval);
6174642e01fSmrg    ValidateGC (drawable, pGC);
61805b261ecSmrg
61905b261ecSmrg    numRects = REGION_NUM_RECTS(prgn);
62005b261ecSmrg    pbox = REGION_RECTS(prgn);
62105b261ecSmrg    for (i= numRects; --i >= 0; pbox++, prect++)
62205b261ecSmrg    {
6234642e01fSmrg	prect->x = pbox->x1 - draw_x_off;
6244642e01fSmrg	prect->y = pbox->y1 - draw_y_off;
62505b261ecSmrg	prect->width = pbox->x2 - pbox->x1;
62605b261ecSmrg	prect->height = pbox->y2 - pbox->y1;
62705b261ecSmrg    }
62805b261ecSmrg    prect -= numRects;
6294642e01fSmrg    (*pGC->ops->PolyFillRect)(drawable, pGC, numRects, prect);
6304642e01fSmrg    xfree(prect);
63105b261ecSmrg
6324642e01fSmrg    FreeScratchGC(pGC);
63305b261ecSmrg}
63405b261ecSmrg
63505b261ecSmrg
63605b261ecSmrg/* MICLEARDRAWABLE -- sets the entire drawable to the background color of
63705b261ecSmrg * the GC.  Useful when we have a scratch drawable and need to initialize
63805b261ecSmrg * it. */
63905b261ecSmrg_X_EXPORT void
6404642e01fSmrgmiClearDrawable(DrawablePtr pDraw, GCPtr pGC)
64105b261ecSmrg{
64205b261ecSmrg    XID fg = pGC->fgPixel;
64305b261ecSmrg    XID bg = pGC->bgPixel;
64405b261ecSmrg    xRectangle rect;
64505b261ecSmrg
64605b261ecSmrg    rect.x = 0;
64705b261ecSmrg    rect.y = 0;
64805b261ecSmrg    rect.width = pDraw->width;
64905b261ecSmrg    rect.height = pDraw->height;
65005b261ecSmrg    DoChangeGC(pGC, GCForeground, &bg, 0);
65105b261ecSmrg    ValidateGC(pDraw, pGC);
65205b261ecSmrg    (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect);
65305b261ecSmrg    DoChangeGC(pGC, GCForeground, &fg, 0);
65405b261ecSmrg    ValidateGC(pDraw, pGC);
65505b261ecSmrg}
656