miexpose.c revision 6747b715
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#include <X11/Xproto.h>
8205b261ecSmrg#include <X11/Xprotostr.h>
8305b261ecSmrg
8405b261ecSmrg#include "misc.h"
8505b261ecSmrg#include "regionstr.h"
8605b261ecSmrg#include "scrnintstr.h"
8705b261ecSmrg#include "gcstruct.h"
8805b261ecSmrg#include "windowstr.h"
8905b261ecSmrg#include "pixmap.h"
9005b261ecSmrg#include "input.h"
9105b261ecSmrg
9205b261ecSmrg#include "dixstruct.h"
9305b261ecSmrg#include "mi.h"
9405b261ecSmrg#include <X11/Xmd.h>
9505b261ecSmrg
9605b261ecSmrg#include "globals.h"
9705b261ecSmrg
9805b261ecSmrg#ifdef PANORAMIX
9905b261ecSmrg#include "panoramiX.h"
10005b261ecSmrg#include "panoramiXsrv.h"
10105b261ecSmrg#endif
10205b261ecSmrg
10305b261ecSmrg/*
10405b261ecSmrg    machine-independent graphics exposure code.  any device that uses
10505b261ecSmrgthe region package can call this.
10605b261ecSmrg*/
10705b261ecSmrg
10805b261ecSmrg#ifndef RECTLIMIT
10905b261ecSmrg#define RECTLIMIT 25		/* pick a number, any number > 8 */
11005b261ecSmrg#endif
11105b261ecSmrg
11205b261ecSmrg/* miHandleExposures
11305b261ecSmrg    generate a region for exposures for areas that were copied from obscured or
11405b261ecSmrgnon-existent areas to non-obscured areas of the destination.  Paint the
11505b261ecSmrgbackground for the region, if the destination is a window.
11605b261ecSmrg
11705b261ecSmrgNOTE:
11805b261ecSmrg     this should generally be called, even if graphicsExposures is false,
11905b261ecSmrgbecause this is where bits get recovered from backing store.
12005b261ecSmrg
12105b261ecSmrgNOTE:
12205b261ecSmrg     added argument 'plane' is used to indicate how exposures from backing
12305b261ecSmrgstore should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea
12405b261ecSmrgshould be used, else a CopyPlane of the indicated plane will be used. The
12505b261ecSmrgexposing is done by the backing store's GraphicsExpose function, of course.
12605b261ecSmrg
12705b261ecSmrg*/
12805b261ecSmrg
1296747b715SmrgRegionPtr
1304642e01fSmrgmiHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
1314642e01fSmrg		  GCPtr pGC, int srcx, int srcy, int width, int height,
1324642e01fSmrg		  int dstx, int dsty, unsigned long plane)
13305b261ecSmrg{
13405b261ecSmrg    RegionPtr prgnSrcClip;	/* drawable-relative source clip */
13505b261ecSmrg    RegionRec rgnSrcRec;
13605b261ecSmrg    RegionPtr prgnDstClip;	/* drawable-relative dest clip */
13705b261ecSmrg    RegionRec rgnDstRec;
13805b261ecSmrg    BoxRec srcBox;		/* unclipped source */
13905b261ecSmrg    RegionRec rgnExposed;	/* exposed region, calculated source-
14005b261ecSmrg				   relative, made dst relative to
14105b261ecSmrg				   intersect with visible parts of
14205b261ecSmrg				   dest and send events to client,
14305b261ecSmrg				   and then screen relative to paint
14405b261ecSmrg				   the window background
14505b261ecSmrg				*/
14605b261ecSmrg    WindowPtr pSrcWin;
14705b261ecSmrg    BoxRec expBox;
14805b261ecSmrg    Bool extents;
14905b261ecSmrg
15005b261ecSmrg    /* avoid work if we can */
15105b261ecSmrg    if (!pGC->graphicsExposures &&
15205b261ecSmrg	(pDstDrawable->type == DRAWABLE_PIXMAP) &&
15305b261ecSmrg	((pSrcDrawable->type == DRAWABLE_PIXMAP) ||
15405b261ecSmrg	 (((WindowPtr)pSrcDrawable)->backStorage == NULL)))
15505b261ecSmrg	return NULL;
15605b261ecSmrg
15705b261ecSmrg    srcBox.x1 = srcx;
15805b261ecSmrg    srcBox.y1 = srcy;
15905b261ecSmrg    srcBox.x2 = srcx+width;
16005b261ecSmrg    srcBox.y2 = srcy+height;
16105b261ecSmrg
16205b261ecSmrg    if (pSrcDrawable->type != DRAWABLE_PIXMAP)
16305b261ecSmrg    {
16405b261ecSmrg	BoxRec TsrcBox;
16505b261ecSmrg
16605b261ecSmrg	TsrcBox.x1 = srcx + pSrcDrawable->x;
16705b261ecSmrg	TsrcBox.y1 = srcy + pSrcDrawable->y;
16805b261ecSmrg	TsrcBox.x2 = TsrcBox.x1 + width;
16905b261ecSmrg	TsrcBox.y2 = TsrcBox.y1 + height;
17005b261ecSmrg	pSrcWin = (WindowPtr) pSrcDrawable;
17105b261ecSmrg	if (pGC->subWindowMode == IncludeInferiors)
17205b261ecSmrg 	{
17305b261ecSmrg	    prgnSrcClip = NotClippedByChildren (pSrcWin);
1746747b715Smrg	    if ((RegionContainsRect(prgnSrcClip, &TsrcBox)) == rgnIN)
17505b261ecSmrg	    {
1766747b715Smrg		RegionDestroy(prgnSrcClip);
17705b261ecSmrg		return NULL;
17805b261ecSmrg	    }
17905b261ecSmrg	}
18005b261ecSmrg 	else
18105b261ecSmrg 	{
1826747b715Smrg	    if ((RegionContainsRect(&pSrcWin->clipList, &TsrcBox)) == rgnIN)
18305b261ecSmrg		return NULL;
18405b261ecSmrg	    prgnSrcClip = &rgnSrcRec;
1856747b715Smrg	    RegionNull(prgnSrcClip);
1866747b715Smrg	    RegionCopy(prgnSrcClip, &pSrcWin->clipList);
18705b261ecSmrg	}
1886747b715Smrg	RegionTranslate(prgnSrcClip,
18905b261ecSmrg				-pSrcDrawable->x, -pSrcDrawable->y);
19005b261ecSmrg    }
19105b261ecSmrg    else
19205b261ecSmrg    {
19305b261ecSmrg	BoxRec	box;
19405b261ecSmrg
19505b261ecSmrg	if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
19605b261ecSmrg	    (srcBox.x2 <= pSrcDrawable->width) &&
19705b261ecSmrg 	    (srcBox.y2 <= pSrcDrawable->height))
19805b261ecSmrg	    return NULL;
19905b261ecSmrg
20005b261ecSmrg	box.x1 = 0;
20105b261ecSmrg	box.y1 = 0;
20205b261ecSmrg	box.x2 = pSrcDrawable->width;
20305b261ecSmrg	box.y2 = pSrcDrawable->height;
20405b261ecSmrg	prgnSrcClip = &rgnSrcRec;
2056747b715Smrg	RegionInit(prgnSrcClip, &box, 1);
2066747b715Smrg	pSrcWin = NULL;
20705b261ecSmrg    }
20805b261ecSmrg
20905b261ecSmrg    if (pDstDrawable == pSrcDrawable)
21005b261ecSmrg    {
21105b261ecSmrg	prgnDstClip = prgnSrcClip;
21205b261ecSmrg    }
21305b261ecSmrg    else if (pDstDrawable->type != DRAWABLE_PIXMAP)
21405b261ecSmrg    {
21505b261ecSmrg	if (pGC->subWindowMode == IncludeInferiors)
21605b261ecSmrg	{
21705b261ecSmrg	    prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable);
21805b261ecSmrg	}
21905b261ecSmrg	else
22005b261ecSmrg	{
22105b261ecSmrg	    prgnDstClip = &rgnDstRec;
2226747b715Smrg	    RegionNull(prgnDstClip);
2236747b715Smrg	    RegionCopy(prgnDstClip,
22405b261ecSmrg				&((WindowPtr)pDstDrawable)->clipList);
22505b261ecSmrg	}
2266747b715Smrg	RegionTranslate(prgnDstClip,
22705b261ecSmrg				 -pDstDrawable->x, -pDstDrawable->y);
22805b261ecSmrg    }
22905b261ecSmrg    else
23005b261ecSmrg    {
23105b261ecSmrg	BoxRec	box;
23205b261ecSmrg
23305b261ecSmrg	box.x1 = 0;
23405b261ecSmrg	box.y1 = 0;
23505b261ecSmrg	box.x2 = pDstDrawable->width;
23605b261ecSmrg	box.y2 = pDstDrawable->height;
23705b261ecSmrg	prgnDstClip = &rgnDstRec;
2386747b715Smrg	RegionInit(prgnDstClip, &box, 1);
23905b261ecSmrg    }
24005b261ecSmrg
24105b261ecSmrg    /* drawable-relative source region */
2426747b715Smrg    RegionInit(&rgnExposed, &srcBox, 1);
24305b261ecSmrg
24405b261ecSmrg    /* now get the hidden parts of the source box*/
2456747b715Smrg    RegionSubtract(&rgnExposed, &rgnExposed, prgnSrcClip);
24605b261ecSmrg
24705b261ecSmrg    /* move them over the destination */
2486747b715Smrg    RegionTranslate(&rgnExposed, dstx-srcx, dsty-srcy);
24905b261ecSmrg
25005b261ecSmrg    /* intersect with visible areas of dest */
2516747b715Smrg    RegionIntersect(&rgnExposed, &rgnExposed, prgnDstClip);
2526747b715Smrg
2536747b715Smrg    /* intersect with client clip region. */
2546747b715Smrg    if (pGC->clientClipType == CT_REGION)
2556747b715Smrg	RegionIntersect(&rgnExposed, &rgnExposed, pGC->clientClip);
25605b261ecSmrg
25705b261ecSmrg    /*
25805b261ecSmrg     * If we have LOTS of rectangles, we decide to take the extents
25905b261ecSmrg     * and force an exposure on that.  This should require much less
26005b261ecSmrg     * work overall, on both client and server.  This is cheating, but
26105b261ecSmrg     * isn't prohibited by the protocol ("spontaneous combustion" :-)
26205b261ecSmrg     * for windows.
26305b261ecSmrg     */
26405b261ecSmrg    extents = pGC->graphicsExposures &&
2656747b715Smrg	      (RegionNumRects(&rgnExposed) > RECTLIMIT) &&
26605b261ecSmrg	      (pDstDrawable->type != DRAWABLE_PIXMAP);
26705b261ecSmrg    if (pSrcWin)
26805b261ecSmrg    {
26905b261ecSmrg	RegionPtr	region;
27005b261ecSmrg    	if (!(region = wClipShape (pSrcWin)))
27105b261ecSmrg    	    region = wBoundingShape (pSrcWin);
27205b261ecSmrg    	/*
27305b261ecSmrg     	 * If you try to CopyArea the extents of a shaped window, compacting the
27405b261ecSmrg     	 * exposed region will undo all our work!
27505b261ecSmrg     	 */
27605b261ecSmrg    	if (extents && pSrcWin && region &&
2776747b715Smrg	    (RegionContainsRect(region, &srcBox) != rgnIN))
27805b261ecSmrg	    	extents = FALSE;
27905b261ecSmrg    }
28005b261ecSmrg    if (extents)
28105b261ecSmrg    {
2826747b715Smrg	expBox = *RegionExtents(&rgnExposed);
2836747b715Smrg	RegionReset(&rgnExposed, &expBox);
28405b261ecSmrg    }
28505b261ecSmrg    if ((pDstDrawable->type != DRAWABLE_PIXMAP) &&
28605b261ecSmrg	(((WindowPtr)pDstDrawable)->backgroundState != None))
28705b261ecSmrg    {
28805b261ecSmrg	WindowPtr pWin = (WindowPtr)pDstDrawable;
28905b261ecSmrg
29005b261ecSmrg	/* make the exposed area screen-relative */
2916747b715Smrg	RegionTranslate(&rgnExposed,
29205b261ecSmrg				 pDstDrawable->x, pDstDrawable->y);
29305b261ecSmrg
29405b261ecSmrg	if (extents)
29505b261ecSmrg	{
2966747b715Smrg	    /* miPaintWindow doesn't clip, so we have to */
2976747b715Smrg	    RegionIntersect(&rgnExposed, &rgnExposed, &pWin->clipList);
29805b261ecSmrg	}
2994642e01fSmrg	miPaintWindow((WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND);
30005b261ecSmrg
30105b261ecSmrg	if (extents)
30205b261ecSmrg	{
3036747b715Smrg	    RegionReset(&rgnExposed, &expBox);
30405b261ecSmrg	}
30505b261ecSmrg	else
3066747b715Smrg	    RegionTranslate(&rgnExposed,
30705b261ecSmrg				     -pDstDrawable->x, -pDstDrawable->y);
30805b261ecSmrg    }
30905b261ecSmrg    if (prgnDstClip == &rgnDstRec)
31005b261ecSmrg    {
3116747b715Smrg	RegionUninit(prgnDstClip);
31205b261ecSmrg    }
31305b261ecSmrg    else if (prgnDstClip != prgnSrcClip)
31405b261ecSmrg    {
3156747b715Smrg	RegionDestroy(prgnDstClip);
31605b261ecSmrg    }
31705b261ecSmrg
31805b261ecSmrg    if (prgnSrcClip == &rgnSrcRec)
31905b261ecSmrg    {
3206747b715Smrg	RegionUninit(prgnSrcClip);
32105b261ecSmrg    }
32205b261ecSmrg    else
32305b261ecSmrg    {
3246747b715Smrg	RegionDestroy(prgnSrcClip);
32505b261ecSmrg    }
32605b261ecSmrg
32705b261ecSmrg    if (pGC->graphicsExposures)
32805b261ecSmrg    {
32905b261ecSmrg	/* don't look */
3306747b715Smrg	RegionPtr exposed = RegionCreate(NullBox, 0);
33105b261ecSmrg	*exposed = rgnExposed;
33205b261ecSmrg	return exposed;
33305b261ecSmrg    }
33405b261ecSmrg    else
33505b261ecSmrg    {
3366747b715Smrg	RegionUninit(&rgnExposed);
33705b261ecSmrg	return NULL;
33805b261ecSmrg    }
33905b261ecSmrg}
34005b261ecSmrg
34105b261ecSmrg/* send GraphicsExpose events, or a NoExpose event, based on the region */
34205b261ecSmrg
3434642e01fSmrgvoid
3444642e01fSmrgmiSendGraphicsExpose (ClientPtr client, RegionPtr pRgn, XID drawable,
3454642e01fSmrg                      int major, int minor)
34605b261ecSmrg{
3476747b715Smrg    if (pRgn && !RegionNil(pRgn))
34805b261ecSmrg    {
34905b261ecSmrg        xEvent *pEvent;
35005b261ecSmrg	xEvent *pe;
35105b261ecSmrg	BoxPtr pBox;
35205b261ecSmrg	int i;
35305b261ecSmrg	int numRects;
35405b261ecSmrg
3556747b715Smrg	numRects = RegionNumRects(pRgn);
3566747b715Smrg	pBox = RegionRects(pRgn);
3576747b715Smrg	if(!(pEvent = malloc(numRects * sizeof(xEvent))))
35805b261ecSmrg		return;
35905b261ecSmrg	pe = pEvent;
36005b261ecSmrg
36105b261ecSmrg	for (i=1; i<=numRects; i++, pe++, pBox++)
36205b261ecSmrg	{
36305b261ecSmrg	    pe->u.u.type = GraphicsExpose;
36405b261ecSmrg	    pe->u.graphicsExposure.drawable = drawable;
36505b261ecSmrg	    pe->u.graphicsExposure.x = pBox->x1;
36605b261ecSmrg	    pe->u.graphicsExposure.y = pBox->y1;
36705b261ecSmrg	    pe->u.graphicsExposure.width = pBox->x2 - pBox->x1;
36805b261ecSmrg	    pe->u.graphicsExposure.height = pBox->y2 - pBox->y1;
36905b261ecSmrg	    pe->u.graphicsExposure.count = numRects - i;
37005b261ecSmrg	    pe->u.graphicsExposure.majorEvent = major;
37105b261ecSmrg	    pe->u.graphicsExposure.minorEvent = minor;
37205b261ecSmrg	}
3736747b715Smrg	/* GraphicsExpose is a "critical event", which TryClientEvents
3746747b715Smrg	 * handles specially. */
3754642e01fSmrg	TryClientEvents(client, NULL, pEvent, numRects,
37605b261ecSmrg			    (Mask)0, NoEventMask, NullGrab);
3776747b715Smrg	free(pEvent);
37805b261ecSmrg    }
37905b261ecSmrg    else
38005b261ecSmrg    {
38105b261ecSmrg        xEvent event;
3826747b715Smrg	memset(&event, 0, sizeof(xEvent));
38305b261ecSmrg	event.u.u.type = NoExpose;
38405b261ecSmrg	event.u.noExposure.drawable = drawable;
38505b261ecSmrg	event.u.noExposure.majorEvent = major;
38605b261ecSmrg	event.u.noExposure.minorEvent = minor;
3876747b715Smrg	WriteEventsToClient(client, 1, &event);
38805b261ecSmrg    }
38905b261ecSmrg}
39005b261ecSmrg
39105b261ecSmrg
39205b261ecSmrgvoid
3934642e01fSmrgmiSendExposures( WindowPtr pWin, RegionPtr pRgn, int dx, int dy)
39405b261ecSmrg{
39505b261ecSmrg    BoxPtr pBox;
39605b261ecSmrg    int numRects;
39705b261ecSmrg    xEvent *pEvent, *pe;
39805b261ecSmrg    int i;
39905b261ecSmrg
4006747b715Smrg    pBox = RegionRects(pRgn);
4016747b715Smrg    numRects = RegionNumRects(pRgn);
4026747b715Smrg    if(!(pEvent = calloc(1, numRects * sizeof(xEvent))))
40305b261ecSmrg	return;
40405b261ecSmrg
40505b261ecSmrg    for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++)
40605b261ecSmrg    {
40705b261ecSmrg	pe->u.u.type = Expose;
40805b261ecSmrg	pe->u.expose.window = pWin->drawable.id;
40905b261ecSmrg	pe->u.expose.x = pBox->x1 - dx;
41005b261ecSmrg	pe->u.expose.y = pBox->y1 - dy;
41105b261ecSmrg	pe->u.expose.width = pBox->x2 - pBox->x1;
41205b261ecSmrg	pe->u.expose.height = pBox->y2 - pBox->y1;
41305b261ecSmrg	pe->u.expose.count = i;
41405b261ecSmrg    }
41505b261ecSmrg
41605b261ecSmrg#ifdef PANORAMIX
41705b261ecSmrg    if(!noPanoramiXExtension) {
41805b261ecSmrg	int scrnum = pWin->drawable.pScreen->myNum;
41905b261ecSmrg	int x = 0, y = 0;
42005b261ecSmrg	XID realWin = 0;
42105b261ecSmrg
42205b261ecSmrg	if(!pWin->parent) {
4236747b715Smrg	    x = screenInfo.screens[scrnum]->x;
4246747b715Smrg	    y = screenInfo.screens[scrnum]->y;
4256747b715Smrg	    pWin = screenInfo.screens[0]->root;
42605b261ecSmrg	    realWin = pWin->drawable.id;
42705b261ecSmrg	} else if (scrnum) {
42805b261ecSmrg	    PanoramiXRes *win;
42905b261ecSmrg	    win = PanoramiXFindIDByScrnum(XRT_WINDOW,
43005b261ecSmrg			pWin->drawable.id, scrnum);
43105b261ecSmrg	    if(!win) {
4326747b715Smrg		free(pEvent);
43305b261ecSmrg		return;
43405b261ecSmrg	    }
43505b261ecSmrg	    realWin = win->info[0].id;
4366747b715Smrg	    dixLookupWindow(&pWin, realWin, serverClient, DixSendAccess);
43705b261ecSmrg	}
43805b261ecSmrg	if(x || y || scrnum)
43905b261ecSmrg	  for (i = 0; i < numRects; i++) {
44005b261ecSmrg	      pEvent[i].u.expose.window = realWin;
44105b261ecSmrg	      pEvent[i].u.expose.x += x;
44205b261ecSmrg	      pEvent[i].u.expose.y += y;
44305b261ecSmrg	  }
44405b261ecSmrg    }
44505b261ecSmrg#endif
44605b261ecSmrg
44705b261ecSmrg    DeliverEvents(pWin, pEvent, numRects, NullWindow);
44805b261ecSmrg
4496747b715Smrg    free(pEvent);
45005b261ecSmrg}
45105b261ecSmrg
4526747b715Smrgvoid
4534642e01fSmrgmiWindowExposures( WindowPtr pWin, RegionPtr prgn, RegionPtr other_exposed)
45405b261ecSmrg{
45505b261ecSmrg    RegionPtr   exposures = prgn;
4566747b715Smrg    if ((prgn && !RegionNil(prgn)) ||
4576747b715Smrg	(exposures && !RegionNil(exposures)) || other_exposed)
45805b261ecSmrg    {
45905b261ecSmrg	RegionRec   expRec;
46005b261ecSmrg	int	    clientInterested;
46105b261ecSmrg
46205b261ecSmrg	/*
46305b261ecSmrg	 * Restore from backing-store FIRST.
46405b261ecSmrg	 */
46505b261ecSmrg	clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask;
46605b261ecSmrg	if (other_exposed)
46705b261ecSmrg	{
46805b261ecSmrg	    if (exposures)
46905b261ecSmrg	    {
4706747b715Smrg		RegionUnion(other_exposed,
47105b261ecSmrg						  exposures,
47205b261ecSmrg					          other_exposed);
47305b261ecSmrg		if (exposures != prgn)
4746747b715Smrg		    RegionDestroy(exposures);
47505b261ecSmrg	    }
47605b261ecSmrg	    exposures = other_exposed;
47705b261ecSmrg	}
4786747b715Smrg	if (clientInterested && exposures && (RegionNumRects(exposures) > RECTLIMIT))
47905b261ecSmrg	{
48005b261ecSmrg	    /*
48105b261ecSmrg	     * If we have LOTS of rectangles, we decide to take the extents
48205b261ecSmrg	     * and force an exposure on that.  This should require much less
48305b261ecSmrg	     * work overall, on both client and server.  This is cheating, but
48405b261ecSmrg	     * isn't prohibited by the protocol ("spontaneous combustion" :-).
48505b261ecSmrg	     */
48605b261ecSmrg	    BoxRec box;
48705b261ecSmrg
4886747b715Smrg	    box = *RegionExtents(exposures);
48905b261ecSmrg	    if (exposures == prgn) {
49005b261ecSmrg		exposures = &expRec;
4916747b715Smrg		RegionInit(exposures, &box, 1);
4926747b715Smrg		RegionReset(prgn, &box);
49305b261ecSmrg	    } else {
4946747b715Smrg		RegionReset(exposures, &box);
4956747b715Smrg		RegionUnion(prgn, prgn, exposures);
49605b261ecSmrg	    }
4976747b715Smrg	    /* miPaintWindow doesn't clip, so we have to */
4986747b715Smrg	    RegionIntersect(prgn, prgn, &pWin->clipList);
49905b261ecSmrg	}
5006747b715Smrg	if (prgn && !RegionNil(prgn))
5014642e01fSmrg	    miPaintWindow(pWin, prgn, PW_BACKGROUND);
5026747b715Smrg	if (clientInterested && exposures && !RegionNil(exposures))
50305b261ecSmrg	    miSendExposures(pWin, exposures,
50405b261ecSmrg			    pWin->drawable.x, pWin->drawable.y);
50505b261ecSmrg	if (exposures == &expRec)
50605b261ecSmrg	{
5076747b715Smrg	    RegionUninit(exposures);
50805b261ecSmrg	}
50905b261ecSmrg	else if (exposures && exposures != prgn && exposures != other_exposed)
5106747b715Smrg	    RegionDestroy(exposures);
51105b261ecSmrg	if (prgn)
5126747b715Smrg	    RegionEmpty(prgn);
51305b261ecSmrg    }
51405b261ecSmrg    else if (exposures && exposures != prgn)
5156747b715Smrg	RegionDestroy(exposures);
51605b261ecSmrg}
51705b261ecSmrg
5186747b715Smrg#ifdef ROOTLESS
5196747b715Smrg/* Ugly, ugly, but we lost our hooks into miPaintWindow... =/ */
5206747b715Smrgvoid RootlessSetPixmapOfAncestors(WindowPtr pWin);
5216747b715Smrgvoid RootlessStartDrawing(WindowPtr pWin);
5226747b715Smrgvoid RootlessDamageRegion(WindowPtr pWin, RegionPtr prgn);
5236747b715SmrgBool IsFramedWindow(WindowPtr pWin);
5246747b715Smrg#endif
5256747b715Smrg
5264642e01fSmrgvoid
5274642e01fSmrgmiPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
52805b261ecSmrg{
5294642e01fSmrg    ScreenPtr	pScreen = pWin->drawable.pScreen;
5306747b715Smrg    ChangeGCVal gcval[6];
5314642e01fSmrg    BITS32	gcmask;
5324642e01fSmrg    GCPtr	pGC;
5334642e01fSmrg    int		i;
5344642e01fSmrg    BoxPtr	pbox;
5354642e01fSmrg    xRectangle	*prect;
5364642e01fSmrg    int		numRects;
5374642e01fSmrg    /*
5384642e01fSmrg     * Distance from screen to destination drawable, use this
5394642e01fSmrg     * to adjust rendering coordinates which come in in screen space
5404642e01fSmrg     */
5414642e01fSmrg    int		draw_x_off, draw_y_off;
5424642e01fSmrg    /*
5434642e01fSmrg     * Tile offset for drawing; these need to align the tile
5444642e01fSmrg     * to the appropriate window origin
5454642e01fSmrg     */
5464642e01fSmrg    int		tile_x_off, tile_y_off;
5474642e01fSmrg    PixUnion	fill;
5484642e01fSmrg    Bool	solid = TRUE;
5494642e01fSmrg    DrawablePtr	drawable = &pWin->drawable;
55005b261ecSmrg
5516747b715Smrg#ifdef ROOTLESS
5526747b715Smrg    if(!drawable || drawable->type == UNDRAWABLE_WINDOW)
5536747b715Smrg	return;
5546747b715Smrg
5556747b715Smrg    if(IsFramedWindow(pWin)) {
5566747b715Smrg        RootlessStartDrawing(pWin);
5576747b715Smrg        RootlessDamageRegion(pWin, prgn);
5586747b715Smrg
5596747b715Smrg        if(pWin->backgroundState == ParentRelative) {
5606747b715Smrg            if((what == PW_BACKGROUND) ||
5616747b715Smrg               (what == PW_BORDER && !pWin->borderIsPixel))
5626747b715Smrg                RootlessSetPixmapOfAncestors(pWin);
5636747b715Smrg        }
5646747b715Smrg    }
5656747b715Smrg#endif
5666747b715Smrg
56705b261ecSmrg    if (what == PW_BACKGROUND)
56805b261ecSmrg    {
5694642e01fSmrg	while (pWin->backgroundState == ParentRelative)
5704642e01fSmrg	    pWin = pWin->parent;
5714642e01fSmrg
5724642e01fSmrg	draw_x_off = drawable->x;
5734642e01fSmrg	draw_y_off = drawable->y;
5744642e01fSmrg
5754642e01fSmrg	tile_x_off = pWin->drawable.x - draw_x_off;
5764642e01fSmrg	tile_y_off = pWin->drawable.y - draw_y_off;
5774642e01fSmrg	fill = pWin->background;
57805b261ecSmrg	switch (pWin->backgroundState) {
57905b261ecSmrg	case None:
58005b261ecSmrg	    return;
58105b261ecSmrg	case BackgroundPixmap:
5824642e01fSmrg	    solid = FALSE;
58305b261ecSmrg	    break;
58405b261ecSmrg	}
58505b261ecSmrg    }
58605b261ecSmrg    else
58705b261ecSmrg    {
5884642e01fSmrg	PixmapPtr   pixmap;
5894642e01fSmrg
5904642e01fSmrg	tile_x_off = drawable->x;
5914642e01fSmrg	tile_y_off = drawable->y;
5924642e01fSmrg
5934642e01fSmrg	/* servers without pixmaps draw their own borders */
5944642e01fSmrg	if (!pScreen->GetWindowPixmap)
5954642e01fSmrg	    return;
5964642e01fSmrg	pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable);
5974642e01fSmrg	drawable = &pixmap->drawable;
5984642e01fSmrg#ifdef COMPOSITE
5994642e01fSmrg	draw_x_off = pixmap->screen_x;
6004642e01fSmrg	draw_y_off = pixmap->screen_y;
6014642e01fSmrg	tile_x_off -= draw_x_off;
6024642e01fSmrg	tile_y_off -= draw_y_off;
6034642e01fSmrg#else
6044642e01fSmrg	draw_x_off = 0;
6054642e01fSmrg	draw_y_off = 0;
6064642e01fSmrg#endif
6074642e01fSmrg	fill = pWin->border;
6084642e01fSmrg	solid = pWin->borderIsPixel;
60905b261ecSmrg    }
6104642e01fSmrg
6114642e01fSmrg    gcval[0].val = GXcopy;
6124642e01fSmrg    gcmask = GCFunction;
61305b261ecSmrg
6146747b715Smrg#ifdef ROOTLESS_SAFEALPHA
6156747b715Smrg/* Bit mask for alpha channel with a particular number of bits per
6166747b715Smrg * pixel. Note that we only care for 32bpp data. Mac OS X uses planar
6176747b715Smrg * alpha for 16bpp.
6186747b715Smrg */
6196747b715Smrg#define RootlessAlphaMask(bpp) ((bpp) == 32 ? 0xFF000000 : 0)
6206747b715Smrg#endif
6216747b715Smrg
6224642e01fSmrg    if (solid)
6234642e01fSmrg    {
6246747b715Smrg#ifdef ROOTLESS_SAFEALPHA
6256747b715Smrg	gcval[1].val = fill.pixel | RootlessAlphaMask(pWin->drawable.bitsPerPixel);
6266747b715Smrg#else
6274642e01fSmrg	gcval[1].val = fill.pixel;
6286747b715Smrg#endif
6294642e01fSmrg	gcval[2].val  = FillSolid;
6304642e01fSmrg	gcmask |= GCForeground | GCFillStyle;
6314642e01fSmrg    }
6324642e01fSmrg    else
6334642e01fSmrg    {
6346747b715Smrg	int c=1;
6356747b715Smrg#ifdef ROOTLESS_SAFEALPHA
6366747b715Smrg	gcval[c++].val = ((CARD32)-1) & ~RootlessAlphaMask(pWin->drawable.bitsPerPixel);
6376747b715Smrg	gcmask |= GCPlaneMask;
6386747b715Smrg#endif
6396747b715Smrg	gcval[c++].val = FillTiled;
6406747b715Smrg	gcval[c++].ptr = (pointer)fill.pixmap;
6416747b715Smrg	gcval[c++].val = tile_x_off;
6426747b715Smrg	gcval[c++].val = tile_y_off;
6434642e01fSmrg	gcmask |= GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin;
6444642e01fSmrg    }
6454642e01fSmrg
6466747b715Smrg    prect = malloc(RegionNumRects(prgn) * sizeof(xRectangle));
64705b261ecSmrg    if (!prect)
64805b261ecSmrg	return;
64905b261ecSmrg
6504642e01fSmrg    pGC = GetScratchGC(drawable->depth, drawable->pScreen);
6514642e01fSmrg    if (!pGC)
65205b261ecSmrg    {
6536747b715Smrg	free(prect);
6544642e01fSmrg	return;
65505b261ecSmrg    }
65605b261ecSmrg
6576747b715Smrg    ChangeGC (NullClient, pGC, gcmask, gcval);
6584642e01fSmrg    ValidateGC (drawable, pGC);
65905b261ecSmrg
6606747b715Smrg    numRects = RegionNumRects(prgn);
6616747b715Smrg    pbox = RegionRects(prgn);
66205b261ecSmrg    for (i= numRects; --i >= 0; pbox++, prect++)
66305b261ecSmrg    {
6644642e01fSmrg	prect->x = pbox->x1 - draw_x_off;
6654642e01fSmrg	prect->y = pbox->y1 - draw_y_off;
66605b261ecSmrg	prect->width = pbox->x2 - pbox->x1;
66705b261ecSmrg	prect->height = pbox->y2 - pbox->y1;
66805b261ecSmrg    }
66905b261ecSmrg    prect -= numRects;
6704642e01fSmrg    (*pGC->ops->PolyFillRect)(drawable, pGC, numRects, prect);
6716747b715Smrg    free(prect);
67205b261ecSmrg
6734642e01fSmrg    FreeScratchGC(pGC);
67405b261ecSmrg}
67505b261ecSmrg
67605b261ecSmrg
67705b261ecSmrg/* MICLEARDRAWABLE -- sets the entire drawable to the background color of
67805b261ecSmrg * the GC.  Useful when we have a scratch drawable and need to initialize
67905b261ecSmrg * it. */
6806747b715Smrgvoid
6814642e01fSmrgmiClearDrawable(DrawablePtr pDraw, GCPtr pGC)
68205b261ecSmrg{
6836747b715Smrg    ChangeGCVal fg, bg;
68405b261ecSmrg    xRectangle rect;
68505b261ecSmrg
6866747b715Smrg    fg.val = pGC->fgPixel;
6876747b715Smrg    bg.val = pGC->bgPixel;
68805b261ecSmrg    rect.x = 0;
68905b261ecSmrg    rect.y = 0;
69005b261ecSmrg    rect.width = pDraw->width;
69105b261ecSmrg    rect.height = pDraw->height;
6926747b715Smrg    ChangeGC(NullClient, pGC, GCForeground, &bg);
69305b261ecSmrg    ValidateGC(pDraw, pGC);
69405b261ecSmrg    (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect);
6956747b715Smrg    ChangeGC(NullClient, pGC, GCForeground, &fg);
69605b261ecSmrg    ValidateGC(pDraw, pGC);
69705b261ecSmrg}
698