1706f2543Smrg/***********************************************************
2706f2543Smrg
3706f2543SmrgCopyright 1987, 1998  The Open Group
4706f2543Smrg
5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its
6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that
7706f2543Smrgthe above copyright notice appear in all copies and that both that
8706f2543Smrgcopyright notice and this permission notice appear in supporting
9706f2543Smrgdocumentation.
10706f2543Smrg
11706f2543SmrgThe above copyright notice and this permission notice shall be included in
12706f2543Smrgall copies or substantial portions of the Software.
13706f2543Smrg
14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20706f2543Smrg
21706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be
22706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings
23706f2543Smrgin this Software without prior written authorization from The Open Group.
24706f2543Smrg
25706f2543Smrg
26706f2543SmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
27706f2543Smrg
28706f2543Smrg                        All Rights Reserved
29706f2543Smrg
30706f2543SmrgPermission to use, copy, modify, and distribute this software and its
31706f2543Smrgdocumentation for any purpose and without fee is hereby granted,
32706f2543Smrgprovided that the above copyright notice appear in all copies and that
33706f2543Smrgboth that copyright notice and this permission notice appear in
34706f2543Smrgsupporting documentation, and that the name of Digital not be
35706f2543Smrgused in advertising or publicity pertaining to distribution of the
36706f2543Smrgsoftware without specific, written prior permission.
37706f2543Smrg
38706f2543SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39706f2543SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40706f2543SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41706f2543SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43706f2543SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44706f2543SmrgSOFTWARE.
45706f2543Smrg
46706f2543Smrg******************************************************************/
47706f2543Smrg/*****************************************************************
48706f2543Smrg
49706f2543SmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
50706f2543Smrg
51706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a copy
52706f2543Smrgof this software and associated documentation files (the "Software"), to deal
53706f2543Smrgin the Software without restriction, including without limitation the rights
54706f2543Smrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
55706f2543Smrgcopies of the Software.
56706f2543Smrg
57706f2543SmrgThe above copyright notice and this permission notice shall be included in
58706f2543Smrgall copies or substantial portions of the Software.
59706f2543Smrg
60706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
61706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
63706f2543SmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
64706f2543SmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
65706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
66706f2543SmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
67706f2543Smrg
68706f2543SmrgExcept as contained in this notice, the name of Digital Equipment Corporation
69706f2543Smrgshall not be used in advertising or otherwise to promote the sale, use or other
70706f2543Smrgdealings in this Software without prior written authorization from Digital
71706f2543SmrgEquipment Corporation.
72706f2543Smrg
73706f2543Smrg******************************************************************/
74706f2543Smrg
75706f2543Smrg
76706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
77706f2543Smrg#include <dix-config.h>
78706f2543Smrg#endif
79706f2543Smrg
80706f2543Smrg#include <X11/X.h>
81706f2543Smrg#include <X11/Xproto.h>
82706f2543Smrg#include <X11/Xprotostr.h>
83706f2543Smrg
84706f2543Smrg#include "misc.h"
85706f2543Smrg#include "regionstr.h"
86706f2543Smrg#include "scrnintstr.h"
87706f2543Smrg#include "gcstruct.h"
88706f2543Smrg#include "windowstr.h"
89706f2543Smrg#include "pixmap.h"
90706f2543Smrg#include "input.h"
91706f2543Smrg
92706f2543Smrg#include "dixstruct.h"
93706f2543Smrg#include "mi.h"
94706f2543Smrg#include <X11/Xmd.h>
95706f2543Smrg
96706f2543Smrg#include "globals.h"
97706f2543Smrg
98706f2543Smrg#ifdef PANORAMIX
99706f2543Smrg#include "panoramiX.h"
100706f2543Smrg#include "panoramiXsrv.h"
101706f2543Smrg#endif
102706f2543Smrg
103706f2543Smrg/*
104706f2543Smrg    machine-independent graphics exposure code.  any device that uses
105706f2543Smrgthe region package can call this.
106706f2543Smrg*/
107706f2543Smrg
108706f2543Smrg#ifndef RECTLIMIT
109706f2543Smrg#define RECTLIMIT 25		/* pick a number, any number > 8 */
110706f2543Smrg#endif
111706f2543Smrg
112706f2543Smrg/* miHandleExposures
113706f2543Smrg    generate a region for exposures for areas that were copied from obscured or
114706f2543Smrgnon-existent areas to non-obscured areas of the destination.  Paint the
115706f2543Smrgbackground for the region, if the destination is a window.
116706f2543Smrg
117706f2543SmrgNOTE:
118706f2543Smrg     this should generally be called, even if graphicsExposures is false,
119706f2543Smrgbecause this is where bits get recovered from backing store.
120706f2543Smrg
121706f2543SmrgNOTE:
122706f2543Smrg     added argument 'plane' is used to indicate how exposures from backing
123706f2543Smrgstore should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea
124706f2543Smrgshould be used, else a CopyPlane of the indicated plane will be used. The
125706f2543Smrgexposing is done by the backing store's GraphicsExpose function, of course.
126706f2543Smrg
127706f2543Smrg*/
128706f2543Smrg
129706f2543SmrgRegionPtr
130706f2543SmrgmiHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
131706f2543Smrg		  GCPtr pGC, int srcx, int srcy, int width, int height,
132706f2543Smrg		  int dstx, int dsty, unsigned long plane)
133706f2543Smrg{
134706f2543Smrg    RegionPtr prgnSrcClip;	/* drawable-relative source clip */
135706f2543Smrg    RegionRec rgnSrcRec;
136706f2543Smrg    RegionPtr prgnDstClip;	/* drawable-relative dest clip */
137706f2543Smrg    RegionRec rgnDstRec;
138706f2543Smrg    BoxRec srcBox;		/* unclipped source */
139706f2543Smrg    RegionRec rgnExposed;	/* exposed region, calculated source-
140706f2543Smrg				   relative, made dst relative to
141706f2543Smrg				   intersect with visible parts of
142706f2543Smrg				   dest and send events to client,
143706f2543Smrg				   and then screen relative to paint
144706f2543Smrg				   the window background
145706f2543Smrg				*/
146706f2543Smrg    WindowPtr pSrcWin;
147706f2543Smrg    BoxRec expBox;
148706f2543Smrg    Bool extents;
149706f2543Smrg
150706f2543Smrg    /* avoid work if we can */
151706f2543Smrg    if (!pGC->graphicsExposures &&
152706f2543Smrg	(pDstDrawable->type == DRAWABLE_PIXMAP) &&
153706f2543Smrg	((pSrcDrawable->type == DRAWABLE_PIXMAP) ||
154706f2543Smrg	 (((WindowPtr)pSrcDrawable)->backStorage == NULL)))
155706f2543Smrg	return NULL;
156706f2543Smrg
157706f2543Smrg    srcBox.x1 = srcx;
158706f2543Smrg    srcBox.y1 = srcy;
159706f2543Smrg    srcBox.x2 = srcx+width;
160706f2543Smrg    srcBox.y2 = srcy+height;
161706f2543Smrg
162706f2543Smrg    if (pSrcDrawable->type != DRAWABLE_PIXMAP)
163706f2543Smrg    {
164706f2543Smrg	BoxRec TsrcBox;
165706f2543Smrg
166706f2543Smrg	TsrcBox.x1 = srcx + pSrcDrawable->x;
167706f2543Smrg	TsrcBox.y1 = srcy + pSrcDrawable->y;
168706f2543Smrg	TsrcBox.x2 = TsrcBox.x1 + width;
169706f2543Smrg	TsrcBox.y2 = TsrcBox.y1 + height;
170706f2543Smrg	pSrcWin = (WindowPtr) pSrcDrawable;
171706f2543Smrg	if (pGC->subWindowMode == IncludeInferiors)
172706f2543Smrg 	{
173706f2543Smrg	    prgnSrcClip = NotClippedByChildren (pSrcWin);
174706f2543Smrg	    if ((RegionContainsRect(prgnSrcClip, &TsrcBox)) == rgnIN)
175706f2543Smrg	    {
176706f2543Smrg		RegionDestroy(prgnSrcClip);
177706f2543Smrg		return NULL;
178706f2543Smrg	    }
179706f2543Smrg	}
180706f2543Smrg 	else
181706f2543Smrg 	{
182706f2543Smrg	    if ((RegionContainsRect(&pSrcWin->clipList, &TsrcBox)) == rgnIN)
183706f2543Smrg		return NULL;
184706f2543Smrg	    prgnSrcClip = &rgnSrcRec;
185706f2543Smrg	    RegionNull(prgnSrcClip);
186706f2543Smrg	    RegionCopy(prgnSrcClip, &pSrcWin->clipList);
187706f2543Smrg	}
188706f2543Smrg	RegionTranslate(prgnSrcClip,
189706f2543Smrg				-pSrcDrawable->x, -pSrcDrawable->y);
190706f2543Smrg    }
191706f2543Smrg    else
192706f2543Smrg    {
193706f2543Smrg	BoxRec	box;
194706f2543Smrg
195706f2543Smrg	if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
196706f2543Smrg	    (srcBox.x2 <= pSrcDrawable->width) &&
197706f2543Smrg 	    (srcBox.y2 <= pSrcDrawable->height))
198706f2543Smrg	    return NULL;
199706f2543Smrg
200706f2543Smrg	box.x1 = 0;
201706f2543Smrg	box.y1 = 0;
202706f2543Smrg	box.x2 = pSrcDrawable->width;
203706f2543Smrg	box.y2 = pSrcDrawable->height;
204706f2543Smrg	prgnSrcClip = &rgnSrcRec;
205706f2543Smrg	RegionInit(prgnSrcClip, &box, 1);
206706f2543Smrg	pSrcWin = NULL;
207706f2543Smrg    }
208706f2543Smrg
209706f2543Smrg    if (pDstDrawable == pSrcDrawable)
210706f2543Smrg    {
211706f2543Smrg	prgnDstClip = prgnSrcClip;
212706f2543Smrg    }
213706f2543Smrg    else if (pDstDrawable->type != DRAWABLE_PIXMAP)
214706f2543Smrg    {
215706f2543Smrg	if (pGC->subWindowMode == IncludeInferiors)
216706f2543Smrg	{
217706f2543Smrg	    prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable);
218706f2543Smrg	}
219706f2543Smrg	else
220706f2543Smrg	{
221706f2543Smrg	    prgnDstClip = &rgnDstRec;
222706f2543Smrg	    RegionNull(prgnDstClip);
223706f2543Smrg	    RegionCopy(prgnDstClip,
224706f2543Smrg				&((WindowPtr)pDstDrawable)->clipList);
225706f2543Smrg	}
226706f2543Smrg	RegionTranslate(prgnDstClip,
227706f2543Smrg				 -pDstDrawable->x, -pDstDrawable->y);
228706f2543Smrg    }
229706f2543Smrg    else
230706f2543Smrg    {
231706f2543Smrg	BoxRec	box;
232706f2543Smrg
233706f2543Smrg	box.x1 = 0;
234706f2543Smrg	box.y1 = 0;
235706f2543Smrg	box.x2 = pDstDrawable->width;
236706f2543Smrg	box.y2 = pDstDrawable->height;
237706f2543Smrg	prgnDstClip = &rgnDstRec;
238706f2543Smrg	RegionInit(prgnDstClip, &box, 1);
239706f2543Smrg    }
240706f2543Smrg
241706f2543Smrg    /* drawable-relative source region */
242706f2543Smrg    RegionInit(&rgnExposed, &srcBox, 1);
243706f2543Smrg
244706f2543Smrg    /* now get the hidden parts of the source box*/
245706f2543Smrg    RegionSubtract(&rgnExposed, &rgnExposed, prgnSrcClip);
246706f2543Smrg
247706f2543Smrg    /* move them over the destination */
248706f2543Smrg    RegionTranslate(&rgnExposed, dstx-srcx, dsty-srcy);
249706f2543Smrg
250706f2543Smrg    /* intersect with visible areas of dest */
251706f2543Smrg    RegionIntersect(&rgnExposed, &rgnExposed, prgnDstClip);
252706f2543Smrg
253706f2543Smrg    /* intersect with client clip region. */
254706f2543Smrg    if (pGC->clientClipType == CT_REGION)
255706f2543Smrg	RegionIntersect(&rgnExposed, &rgnExposed, pGC->clientClip);
256706f2543Smrg
257706f2543Smrg    /*
258706f2543Smrg     * If we have LOTS of rectangles, we decide to take the extents
259706f2543Smrg     * and force an exposure on that.  This should require much less
260706f2543Smrg     * work overall, on both client and server.  This is cheating, but
261706f2543Smrg     * isn't prohibited by the protocol ("spontaneous combustion" :-)
262706f2543Smrg     * for windows.
263706f2543Smrg     */
264706f2543Smrg    extents = pGC->graphicsExposures &&
265706f2543Smrg	      (RegionNumRects(&rgnExposed) > RECTLIMIT) &&
266706f2543Smrg	      (pDstDrawable->type != DRAWABLE_PIXMAP);
267706f2543Smrg    if (pSrcWin)
268706f2543Smrg    {
269706f2543Smrg	RegionPtr	region;
270706f2543Smrg    	if (!(region = wClipShape (pSrcWin)))
271706f2543Smrg    	    region = wBoundingShape (pSrcWin);
272706f2543Smrg    	/*
273706f2543Smrg     	 * If you try to CopyArea the extents of a shaped window, compacting the
274706f2543Smrg     	 * exposed region will undo all our work!
275706f2543Smrg     	 */
276706f2543Smrg    	if (extents && pSrcWin && region &&
277706f2543Smrg	    (RegionContainsRect(region, &srcBox) != rgnIN))
278706f2543Smrg	    	extents = FALSE;
279706f2543Smrg    }
280706f2543Smrg    if (extents)
281706f2543Smrg    {
282706f2543Smrg	expBox = *RegionExtents(&rgnExposed);
283706f2543Smrg	RegionReset(&rgnExposed, &expBox);
284706f2543Smrg    }
285706f2543Smrg    if ((pDstDrawable->type != DRAWABLE_PIXMAP) &&
286706f2543Smrg	(((WindowPtr)pDstDrawable)->backgroundState != None))
287706f2543Smrg    {
288706f2543Smrg	WindowPtr pWin = (WindowPtr)pDstDrawable;
289706f2543Smrg
290706f2543Smrg	/* make the exposed area screen-relative */
291706f2543Smrg	RegionTranslate(&rgnExposed,
292706f2543Smrg				 pDstDrawable->x, pDstDrawable->y);
293706f2543Smrg
294706f2543Smrg	if (extents)
295706f2543Smrg	{
296706f2543Smrg	    /* miPaintWindow doesn't clip, so we have to */
297706f2543Smrg	    RegionIntersect(&rgnExposed, &rgnExposed, &pWin->clipList);
298706f2543Smrg	}
299706f2543Smrg	miPaintWindow((WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND);
300706f2543Smrg
301706f2543Smrg	if (extents)
302706f2543Smrg	{
303706f2543Smrg	    RegionReset(&rgnExposed, &expBox);
304706f2543Smrg	}
305706f2543Smrg	else
306706f2543Smrg	    RegionTranslate(&rgnExposed,
307706f2543Smrg				     -pDstDrawable->x, -pDstDrawable->y);
308706f2543Smrg    }
309706f2543Smrg    if (prgnDstClip == &rgnDstRec)
310706f2543Smrg    {
311706f2543Smrg	RegionUninit(prgnDstClip);
312706f2543Smrg    }
313706f2543Smrg    else if (prgnDstClip != prgnSrcClip)
314706f2543Smrg    {
315706f2543Smrg	RegionDestroy(prgnDstClip);
316706f2543Smrg    }
317706f2543Smrg
318706f2543Smrg    if (prgnSrcClip == &rgnSrcRec)
319706f2543Smrg    {
320706f2543Smrg	RegionUninit(prgnSrcClip);
321706f2543Smrg    }
322706f2543Smrg    else
323706f2543Smrg    {
324706f2543Smrg	RegionDestroy(prgnSrcClip);
325706f2543Smrg    }
326706f2543Smrg
327706f2543Smrg    if (pGC->graphicsExposures)
328706f2543Smrg    {
329706f2543Smrg	/* don't look */
330706f2543Smrg	RegionPtr exposed = RegionCreate(NullBox, 0);
331706f2543Smrg	*exposed = rgnExposed;
332706f2543Smrg	return exposed;
333706f2543Smrg    }
334706f2543Smrg    else
335706f2543Smrg    {
336706f2543Smrg	RegionUninit(&rgnExposed);
337706f2543Smrg	return NULL;
338706f2543Smrg    }
339706f2543Smrg}
340706f2543Smrg
341706f2543Smrg/* send GraphicsExpose events, or a NoExpose event, based on the region */
342706f2543Smrg
343706f2543Smrgvoid
344706f2543SmrgmiSendGraphicsExpose (ClientPtr client, RegionPtr pRgn, XID drawable,
345706f2543Smrg                      int major, int minor)
346706f2543Smrg{
347706f2543Smrg    if (pRgn && !RegionNil(pRgn))
348706f2543Smrg    {
349706f2543Smrg        xEvent *pEvent;
350706f2543Smrg	xEvent *pe;
351706f2543Smrg	BoxPtr pBox;
352706f2543Smrg	int i;
353706f2543Smrg	int numRects;
354706f2543Smrg
355706f2543Smrg	numRects = RegionNumRects(pRgn);
356706f2543Smrg	pBox = RegionRects(pRgn);
357706f2543Smrg	if(!(pEvent = malloc(numRects * sizeof(xEvent))))
358706f2543Smrg		return;
359706f2543Smrg	pe = pEvent;
360706f2543Smrg
361706f2543Smrg	for (i=1; i<=numRects; i++, pe++, pBox++)
362706f2543Smrg	{
363706f2543Smrg	    pe->u.u.type = GraphicsExpose;
364706f2543Smrg	    pe->u.graphicsExposure.drawable = drawable;
365706f2543Smrg	    pe->u.graphicsExposure.x = pBox->x1;
366706f2543Smrg	    pe->u.graphicsExposure.y = pBox->y1;
367706f2543Smrg	    pe->u.graphicsExposure.width = pBox->x2 - pBox->x1;
368706f2543Smrg	    pe->u.graphicsExposure.height = pBox->y2 - pBox->y1;
369706f2543Smrg	    pe->u.graphicsExposure.count = numRects - i;
370706f2543Smrg	    pe->u.graphicsExposure.majorEvent = major;
371706f2543Smrg	    pe->u.graphicsExposure.minorEvent = minor;
372706f2543Smrg	}
373706f2543Smrg	/* GraphicsExpose is a "critical event", which TryClientEvents
374706f2543Smrg	 * handles specially. */
375706f2543Smrg	TryClientEvents(client, NULL, pEvent, numRects,
376706f2543Smrg			    (Mask)0, NoEventMask, NullGrab);
377706f2543Smrg	free(pEvent);
378706f2543Smrg    }
379706f2543Smrg    else
380706f2543Smrg    {
381706f2543Smrg        xEvent event;
382706f2543Smrg	memset(&event, 0, sizeof(xEvent));
383706f2543Smrg	event.u.u.type = NoExpose;
384706f2543Smrg	event.u.noExposure.drawable = drawable;
385706f2543Smrg	event.u.noExposure.majorEvent = major;
386706f2543Smrg	event.u.noExposure.minorEvent = minor;
387706f2543Smrg	WriteEventsToClient(client, 1, &event);
388706f2543Smrg    }
389706f2543Smrg}
390706f2543Smrg
391706f2543Smrg
392706f2543Smrgvoid
393706f2543SmrgmiSendExposures( WindowPtr pWin, RegionPtr pRgn, int dx, int dy)
394706f2543Smrg{
395706f2543Smrg    BoxPtr pBox;
396706f2543Smrg    int numRects;
397706f2543Smrg    xEvent *pEvent, *pe;
398706f2543Smrg    int i;
399706f2543Smrg
400706f2543Smrg    pBox = RegionRects(pRgn);
401706f2543Smrg    numRects = RegionNumRects(pRgn);
402706f2543Smrg    if(!(pEvent = calloc(1, numRects * sizeof(xEvent))))
403706f2543Smrg	return;
404706f2543Smrg
405706f2543Smrg    for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++)
406706f2543Smrg    {
407706f2543Smrg	pe->u.u.type = Expose;
408706f2543Smrg	pe->u.expose.window = pWin->drawable.id;
409706f2543Smrg	pe->u.expose.x = pBox->x1 - dx;
410706f2543Smrg	pe->u.expose.y = pBox->y1 - dy;
411706f2543Smrg	pe->u.expose.width = pBox->x2 - pBox->x1;
412706f2543Smrg	pe->u.expose.height = pBox->y2 - pBox->y1;
413706f2543Smrg	pe->u.expose.count = i;
414706f2543Smrg    }
415706f2543Smrg
416706f2543Smrg#ifdef PANORAMIX
417706f2543Smrg    if(!noPanoramiXExtension) {
418706f2543Smrg	int scrnum = pWin->drawable.pScreen->myNum;
419706f2543Smrg	int x = 0, y = 0;
420706f2543Smrg	XID realWin = 0;
421706f2543Smrg
422706f2543Smrg	if(!pWin->parent) {
423706f2543Smrg	    x = screenInfo.screens[scrnum]->x;
424706f2543Smrg	    y = screenInfo.screens[scrnum]->y;
425706f2543Smrg	    pWin = screenInfo.screens[0]->root;
426706f2543Smrg	    realWin = pWin->drawable.id;
427706f2543Smrg	} else if (scrnum) {
428706f2543Smrg	    PanoramiXRes *win;
429706f2543Smrg	    win = PanoramiXFindIDByScrnum(XRT_WINDOW,
430706f2543Smrg			pWin->drawable.id, scrnum);
431706f2543Smrg	    if(!win) {
432706f2543Smrg		free(pEvent);
433706f2543Smrg		return;
434706f2543Smrg	    }
435706f2543Smrg	    realWin = win->info[0].id;
436706f2543Smrg	    dixLookupWindow(&pWin, realWin, serverClient, DixSendAccess);
437706f2543Smrg	}
438706f2543Smrg	if(x || y || scrnum)
439706f2543Smrg	  for (i = 0; i < numRects; i++) {
440706f2543Smrg	      pEvent[i].u.expose.window = realWin;
441706f2543Smrg	      pEvent[i].u.expose.x += x;
442706f2543Smrg	      pEvent[i].u.expose.y += y;
443706f2543Smrg	  }
444706f2543Smrg    }
445706f2543Smrg#endif
446706f2543Smrg
447706f2543Smrg    DeliverEvents(pWin, pEvent, numRects, NullWindow);
448706f2543Smrg
449706f2543Smrg    free(pEvent);
450706f2543Smrg}
451706f2543Smrg
452706f2543Smrgvoid
453706f2543SmrgmiWindowExposures( WindowPtr pWin, RegionPtr prgn, RegionPtr other_exposed)
454706f2543Smrg{
455706f2543Smrg    RegionPtr   exposures = prgn;
456706f2543Smrg    if ((prgn && !RegionNil(prgn)) ||
457706f2543Smrg	(exposures && !RegionNil(exposures)) || other_exposed)
458706f2543Smrg    {
459706f2543Smrg	RegionRec   expRec;
460706f2543Smrg	int	    clientInterested;
461706f2543Smrg
462706f2543Smrg	/*
463706f2543Smrg	 * Restore from backing-store FIRST.
464706f2543Smrg	 */
465706f2543Smrg	clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask;
466706f2543Smrg	if (other_exposed)
467706f2543Smrg	{
468706f2543Smrg	    if (exposures)
469706f2543Smrg	    {
470706f2543Smrg		RegionUnion(other_exposed,
471706f2543Smrg						  exposures,
472706f2543Smrg					          other_exposed);
473706f2543Smrg		if (exposures != prgn)
474706f2543Smrg		    RegionDestroy(exposures);
475706f2543Smrg	    }
476706f2543Smrg	    exposures = other_exposed;
477706f2543Smrg	}
478706f2543Smrg	if (clientInterested && exposures && (RegionNumRects(exposures) > RECTLIMIT))
479706f2543Smrg	{
480706f2543Smrg	    /*
481706f2543Smrg	     * If we have LOTS of rectangles, we decide to take the extents
482706f2543Smrg	     * and force an exposure on that.  This should require much less
483706f2543Smrg	     * work overall, on both client and server.  This is cheating, but
484706f2543Smrg	     * isn't prohibited by the protocol ("spontaneous combustion" :-).
485706f2543Smrg	     */
486706f2543Smrg	    BoxRec box;
487706f2543Smrg
488706f2543Smrg	    box = *RegionExtents(exposures);
489706f2543Smrg	    if (exposures == prgn) {
490706f2543Smrg		exposures = &expRec;
491706f2543Smrg		RegionInit(exposures, &box, 1);
492706f2543Smrg		RegionReset(prgn, &box);
493706f2543Smrg	    } else {
494706f2543Smrg		RegionReset(exposures, &box);
495706f2543Smrg		RegionUnion(prgn, prgn, exposures);
496706f2543Smrg	    }
497706f2543Smrg	    /* miPaintWindow doesn't clip, so we have to */
498706f2543Smrg	    RegionIntersect(prgn, prgn, &pWin->clipList);
499706f2543Smrg	}
500706f2543Smrg	if (prgn && !RegionNil(prgn))
501706f2543Smrg	    miPaintWindow(pWin, prgn, PW_BACKGROUND);
502706f2543Smrg	if (clientInterested && exposures && !RegionNil(exposures))
503706f2543Smrg	    miSendExposures(pWin, exposures,
504706f2543Smrg			    pWin->drawable.x, pWin->drawable.y);
505706f2543Smrg	if (exposures == &expRec)
506706f2543Smrg	{
507706f2543Smrg	    RegionUninit(exposures);
508706f2543Smrg	}
509706f2543Smrg	else if (exposures && exposures != prgn && exposures != other_exposed)
510706f2543Smrg	    RegionDestroy(exposures);
511706f2543Smrg	if (prgn)
512706f2543Smrg	    RegionEmpty(prgn);
513706f2543Smrg    }
514706f2543Smrg    else if (exposures && exposures != prgn)
515706f2543Smrg	RegionDestroy(exposures);
516706f2543Smrg}
517706f2543Smrg
518706f2543Smrg#ifdef ROOTLESS
519706f2543Smrg/* Ugly, ugly, but we lost our hooks into miPaintWindow... =/ */
520706f2543Smrgvoid RootlessSetPixmapOfAncestors(WindowPtr pWin);
521706f2543Smrgvoid RootlessStartDrawing(WindowPtr pWin);
522706f2543Smrgvoid RootlessDamageRegion(WindowPtr pWin, RegionPtr prgn);
523706f2543SmrgBool IsFramedWindow(WindowPtr pWin);
524706f2543Smrg#endif
525706f2543Smrg
526706f2543Smrgvoid
527706f2543SmrgmiPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
528706f2543Smrg{
529706f2543Smrg    ScreenPtr	pScreen = pWin->drawable.pScreen;
530706f2543Smrg    ChangeGCVal gcval[6];
531706f2543Smrg    BITS32	gcmask;
532706f2543Smrg    GCPtr	pGC;
533706f2543Smrg    int		i;
534706f2543Smrg    BoxPtr	pbox;
535706f2543Smrg    xRectangle	*prect;
536706f2543Smrg    int		numRects;
537706f2543Smrg    /*
538706f2543Smrg     * Distance from screen to destination drawable, use this
539706f2543Smrg     * to adjust rendering coordinates which come in in screen space
540706f2543Smrg     */
541706f2543Smrg    int		draw_x_off, draw_y_off;
542706f2543Smrg    /*
543706f2543Smrg     * Tile offset for drawing; these need to align the tile
544706f2543Smrg     * to the appropriate window origin
545706f2543Smrg     */
546706f2543Smrg    int		tile_x_off, tile_y_off;
547706f2543Smrg    PixUnion	fill;
548706f2543Smrg    Bool	solid = TRUE;
549706f2543Smrg    DrawablePtr	drawable = &pWin->drawable;
550706f2543Smrg
551706f2543Smrg#ifdef ROOTLESS
552706f2543Smrg    if(!drawable || drawable->type == UNDRAWABLE_WINDOW)
553706f2543Smrg	return;
554706f2543Smrg
555706f2543Smrg    if(IsFramedWindow(pWin)) {
556706f2543Smrg        RootlessStartDrawing(pWin);
557706f2543Smrg        RootlessDamageRegion(pWin, prgn);
558706f2543Smrg
559706f2543Smrg        if(pWin->backgroundState == ParentRelative) {
560706f2543Smrg            if((what == PW_BACKGROUND) ||
561706f2543Smrg               (what == PW_BORDER && !pWin->borderIsPixel))
562706f2543Smrg                RootlessSetPixmapOfAncestors(pWin);
563706f2543Smrg        }
564706f2543Smrg    }
565706f2543Smrg#endif
566706f2543Smrg
567706f2543Smrg    if (what == PW_BACKGROUND)
568706f2543Smrg    {
569706f2543Smrg	while (pWin->backgroundState == ParentRelative)
570706f2543Smrg	    pWin = pWin->parent;
571706f2543Smrg
572706f2543Smrg	draw_x_off = drawable->x;
573706f2543Smrg	draw_y_off = drawable->y;
574706f2543Smrg
575706f2543Smrg	tile_x_off = pWin->drawable.x - draw_x_off;
576706f2543Smrg	tile_y_off = pWin->drawable.y - draw_y_off;
577706f2543Smrg	fill = pWin->background;
578706f2543Smrg	switch (pWin->backgroundState) {
579706f2543Smrg	case None:
580706f2543Smrg	    return;
581706f2543Smrg	case BackgroundPixmap:
582706f2543Smrg	    solid = FALSE;
583706f2543Smrg	    break;
584706f2543Smrg	}
585706f2543Smrg    }
586706f2543Smrg    else
587706f2543Smrg    {
588706f2543Smrg	PixmapPtr   pixmap;
589706f2543Smrg
590706f2543Smrg	tile_x_off = drawable->x;
591706f2543Smrg	tile_y_off = drawable->y;
592706f2543Smrg
593706f2543Smrg	/* servers without pixmaps draw their own borders */
594706f2543Smrg	if (!pScreen->GetWindowPixmap)
595706f2543Smrg	    return;
596706f2543Smrg	pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable);
597706f2543Smrg	drawable = &pixmap->drawable;
598706f2543Smrg#ifdef COMPOSITE
599706f2543Smrg	draw_x_off = pixmap->screen_x;
600706f2543Smrg	draw_y_off = pixmap->screen_y;
601706f2543Smrg	tile_x_off -= draw_x_off;
602706f2543Smrg	tile_y_off -= draw_y_off;
603706f2543Smrg#else
604706f2543Smrg	draw_x_off = 0;
605706f2543Smrg	draw_y_off = 0;
606706f2543Smrg#endif
607706f2543Smrg	fill = pWin->border;
608706f2543Smrg	solid = pWin->borderIsPixel;
609706f2543Smrg    }
610706f2543Smrg
611706f2543Smrg    gcval[0].val = GXcopy;
612706f2543Smrg    gcmask = GCFunction;
613706f2543Smrg
614706f2543Smrg#ifdef ROOTLESS_SAFEALPHA
615706f2543Smrg/* Bit mask for alpha channel with a particular number of bits per
616706f2543Smrg * pixel. Note that we only care for 32bpp data. Mac OS X uses planar
617706f2543Smrg * alpha for 16bpp.
618706f2543Smrg */
619706f2543Smrg#define RootlessAlphaMask(bpp) ((bpp) == 32 ? 0xFF000000 : 0)
620706f2543Smrg#endif
621706f2543Smrg
622706f2543Smrg    if (solid)
623706f2543Smrg    {
624706f2543Smrg#ifdef ROOTLESS_SAFEALPHA
625706f2543Smrg	gcval[1].val = fill.pixel | RootlessAlphaMask(pWin->drawable.bitsPerPixel);
626706f2543Smrg#else
627706f2543Smrg	gcval[1].val = fill.pixel;
628706f2543Smrg#endif
629706f2543Smrg	gcval[2].val  = FillSolid;
630706f2543Smrg	gcmask |= GCForeground | GCFillStyle;
631706f2543Smrg    }
632706f2543Smrg    else
633706f2543Smrg    {
634706f2543Smrg	int c=1;
635706f2543Smrg#ifdef ROOTLESS_SAFEALPHA
636706f2543Smrg	gcval[c++].val = ((CARD32)-1) & ~RootlessAlphaMask(pWin->drawable.bitsPerPixel);
637706f2543Smrg	gcmask |= GCPlaneMask;
638706f2543Smrg#endif
639706f2543Smrg	gcval[c++].val = FillTiled;
640706f2543Smrg	gcval[c++].ptr = (pointer)fill.pixmap;
641706f2543Smrg	gcval[c++].val = tile_x_off;
642706f2543Smrg	gcval[c++].val = tile_y_off;
643706f2543Smrg	gcmask |= GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin;
644706f2543Smrg    }
645706f2543Smrg
646706f2543Smrg    prect = malloc(RegionNumRects(prgn) * sizeof(xRectangle));
647706f2543Smrg    if (!prect)
648706f2543Smrg	return;
649706f2543Smrg
650706f2543Smrg    pGC = GetScratchGC(drawable->depth, drawable->pScreen);
651706f2543Smrg    if (!pGC)
652706f2543Smrg    {
653706f2543Smrg	free(prect);
654706f2543Smrg	return;
655706f2543Smrg    }
656706f2543Smrg
657706f2543Smrg    ChangeGC (NullClient, pGC, gcmask, gcval);
658706f2543Smrg    ValidateGC (drawable, pGC);
659706f2543Smrg
660706f2543Smrg    numRects = RegionNumRects(prgn);
661706f2543Smrg    pbox = RegionRects(prgn);
662706f2543Smrg    for (i= numRects; --i >= 0; pbox++, prect++)
663706f2543Smrg    {
664706f2543Smrg	prect->x = pbox->x1 - draw_x_off;
665706f2543Smrg	prect->y = pbox->y1 - draw_y_off;
666706f2543Smrg	prect->width = pbox->x2 - pbox->x1;
667706f2543Smrg	prect->height = pbox->y2 - pbox->y1;
668706f2543Smrg    }
669706f2543Smrg    prect -= numRects;
670706f2543Smrg    (*pGC->ops->PolyFillRect)(drawable, pGC, numRects, prect);
671706f2543Smrg    free(prect);
672706f2543Smrg
673706f2543Smrg    FreeScratchGC(pGC);
674706f2543Smrg}
675706f2543Smrg
676706f2543Smrg
677706f2543Smrg/* MICLEARDRAWABLE -- sets the entire drawable to the background color of
678706f2543Smrg * the GC.  Useful when we have a scratch drawable and need to initialize
679706f2543Smrg * it. */
680706f2543Smrgvoid
681706f2543SmrgmiClearDrawable(DrawablePtr pDraw, GCPtr pGC)
682706f2543Smrg{
683706f2543Smrg    ChangeGCVal fg, bg;
684706f2543Smrg    xRectangle rect;
685706f2543Smrg
686706f2543Smrg    fg.val = pGC->fgPixel;
687706f2543Smrg    bg.val = pGC->bgPixel;
688706f2543Smrg    rect.x = 0;
689706f2543Smrg    rect.y = 0;
690706f2543Smrg    rect.width = pDraw->width;
691706f2543Smrg    rect.height = pDraw->height;
692706f2543Smrg    ChangeGC(NullClient, pGC, GCForeground, &bg);
693706f2543Smrg    ValidateGC(pDraw, pGC);
694706f2543Smrg    (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect);
695706f2543Smrg    ChangeGC(NullClient, pGC, GCForeground, &fg);
696706f2543Smrg    ValidateGC(pDraw, pGC);
697706f2543Smrg}
698