miexpose.c revision 4642e01f
1/***********************************************************
2
3Copyright 1987, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25
26Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
27
28                        All Rights Reserved
29
30Permission to use, copy, modify, and distribute this software and its
31documentation for any purpose and without fee is hereby granted,
32provided that the above copyright notice appear in all copies and that
33both that copyright notice and this permission notice appear in
34supporting documentation, and that the name of Digital not be
35used in advertising or publicity pertaining to distribution of the
36software without specific, written prior permission.
37
38DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44SOFTWARE.
45
46******************************************************************/
47/*****************************************************************
48
49Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
50
51Permission is hereby granted, free of charge, to any person obtaining a copy
52of this software and associated documentation files (the "Software"), to deal
53in the Software without restriction, including without limitation the rights
54to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
55copies of the Software.
56
57The above copyright notice and this permission notice shall be included in
58all copies or substantial portions of the Software.
59
60THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
61IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
63DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
64BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
65WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
66IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
67
68Except as contained in this notice, the name of Digital Equipment Corporation
69shall not be used in advertising or otherwise to promote the sale, use or other
70dealings in this Software without prior written authorization from Digital
71Equipment Corporation.
72
73******************************************************************/
74
75
76#ifdef HAVE_DIX_CONFIG_H
77#include <dix-config.h>
78#endif
79
80#include <X11/X.h>
81#define NEED_EVENTS
82#include <X11/Xproto.h>
83#include <X11/Xprotostr.h>
84
85#include "misc.h"
86#include "regionstr.h"
87#include "scrnintstr.h"
88#include "gcstruct.h"
89#include "windowstr.h"
90#include "pixmap.h"
91#include "input.h"
92
93#include "dixstruct.h"
94#include "mi.h"
95#include <X11/Xmd.h>
96
97#include "globals.h"
98
99#ifdef PANORAMIX
100#include "panoramiX.h"
101#include "panoramiXsrv.h"
102#endif
103
104/*
105    machine-independent graphics exposure code.  any device that uses
106the region package can call this.
107*/
108
109#ifndef RECTLIMIT
110#define RECTLIMIT 25		/* pick a number, any number > 8 */
111#endif
112
113/* miHandleExposures
114    generate a region for exposures for areas that were copied from obscured or
115non-existent areas to non-obscured areas of the destination.  Paint the
116background for the region, if the destination is a window.
117
118NOTE:
119     this should generally be called, even if graphicsExposures is false,
120because this is where bits get recovered from backing store.
121
122NOTE:
123     added argument 'plane' is used to indicate how exposures from backing
124store should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea
125should be used, else a CopyPlane of the indicated plane will be used. The
126exposing is done by the backing store's GraphicsExpose function, of course.
127
128*/
129
130_X_EXPORT RegionPtr
131miHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
132		  GCPtr pGC, int srcx, int srcy, int width, int height,
133		  int dstx, int dsty, unsigned long plane)
134{
135    ScreenPtr pscr;
136    RegionPtr prgnSrcClip;	/* drawable-relative source clip */
137    RegionRec rgnSrcRec;
138    RegionPtr prgnDstClip;	/* drawable-relative dest clip */
139    RegionRec rgnDstRec;
140    BoxRec srcBox;		/* unclipped source */
141    RegionRec rgnExposed;	/* exposed region, calculated source-
142				   relative, made dst relative to
143				   intersect with visible parts of
144				   dest and send events to client,
145				   and then screen relative to paint
146				   the window background
147				*/
148    WindowPtr pSrcWin;
149    BoxRec expBox;
150    Bool extents;
151
152    /* This prevents warning about pscr not being used. */
153    pGC->pScreen = pscr = pGC->pScreen;
154
155    /* avoid work if we can */
156    if (!pGC->graphicsExposures &&
157	(pDstDrawable->type == DRAWABLE_PIXMAP) &&
158	((pSrcDrawable->type == DRAWABLE_PIXMAP) ||
159	 (((WindowPtr)pSrcDrawable)->backStorage == NULL)))
160	return NULL;
161
162    srcBox.x1 = srcx;
163    srcBox.y1 = srcy;
164    srcBox.x2 = srcx+width;
165    srcBox.y2 = srcy+height;
166
167    if (pSrcDrawable->type != DRAWABLE_PIXMAP)
168    {
169	BoxRec TsrcBox;
170
171	TsrcBox.x1 = srcx + pSrcDrawable->x;
172	TsrcBox.y1 = srcy + pSrcDrawable->y;
173	TsrcBox.x2 = TsrcBox.x1 + width;
174	TsrcBox.y2 = TsrcBox.y1 + height;
175	pSrcWin = (WindowPtr) pSrcDrawable;
176	if (pGC->subWindowMode == IncludeInferiors)
177 	{
178	    prgnSrcClip = NotClippedByChildren (pSrcWin);
179	    if ((RECT_IN_REGION(pscr, prgnSrcClip, &TsrcBox)) == rgnIN)
180	    {
181		REGION_DESTROY(pscr, prgnSrcClip);
182		return NULL;
183	    }
184	}
185 	else
186 	{
187	    if ((RECT_IN_REGION(pscr, &pSrcWin->clipList, &TsrcBox)) == rgnIN)
188		return NULL;
189	    prgnSrcClip = &rgnSrcRec;
190	    REGION_NULL(pscr, prgnSrcClip);
191	    REGION_COPY(pscr, prgnSrcClip, &pSrcWin->clipList);
192	}
193	REGION_TRANSLATE(pscr, prgnSrcClip,
194				-pSrcDrawable->x, -pSrcDrawable->y);
195    }
196    else
197    {
198	BoxRec	box;
199
200	if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
201	    (srcBox.x2 <= pSrcDrawable->width) &&
202 	    (srcBox.y2 <= pSrcDrawable->height))
203	    return NULL;
204
205	box.x1 = 0;
206	box.y1 = 0;
207	box.x2 = pSrcDrawable->width;
208	box.y2 = pSrcDrawable->height;
209	prgnSrcClip = &rgnSrcRec;
210	REGION_INIT(pscr, prgnSrcClip, &box, 1);
211	pSrcWin = (WindowPtr)NULL;
212    }
213
214    if (pDstDrawable == pSrcDrawable)
215    {
216	prgnDstClip = prgnSrcClip;
217    }
218    else if (pDstDrawable->type != DRAWABLE_PIXMAP)
219    {
220	if (pGC->subWindowMode == IncludeInferiors)
221	{
222	    prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable);
223	}
224	else
225	{
226	    prgnDstClip = &rgnDstRec;
227	    REGION_NULL(pscr, prgnDstClip);
228	    REGION_COPY(pscr, prgnDstClip,
229				&((WindowPtr)pDstDrawable)->clipList);
230	}
231	REGION_TRANSLATE(pscr, prgnDstClip,
232				 -pDstDrawable->x, -pDstDrawable->y);
233    }
234    else
235    {
236	BoxRec	box;
237
238	box.x1 = 0;
239	box.y1 = 0;
240	box.x2 = pDstDrawable->width;
241	box.y2 = pDstDrawable->height;
242	prgnDstClip = &rgnDstRec;
243	REGION_INIT(pscr, prgnDstClip, &box, 1);
244    }
245
246    /* drawable-relative source region */
247    REGION_INIT(pscr, &rgnExposed, &srcBox, 1);
248
249    /* now get the hidden parts of the source box*/
250    REGION_SUBTRACT(pscr, &rgnExposed, &rgnExposed, prgnSrcClip);
251
252    /* move them over the destination */
253    REGION_TRANSLATE(pscr, &rgnExposed, dstx-srcx, dsty-srcy);
254
255    /* intersect with visible areas of dest */
256    REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, prgnDstClip);
257
258    /*
259     * If we have LOTS of rectangles, we decide to take the extents
260     * and force an exposure on that.  This should require much less
261     * work overall, on both client and server.  This is cheating, but
262     * isn't prohibited by the protocol ("spontaneous combustion" :-)
263     * for windows.
264     */
265    extents = pGC->graphicsExposures &&
266	      (REGION_NUM_RECTS(&rgnExposed) > RECTLIMIT) &&
267	      (pDstDrawable->type != DRAWABLE_PIXMAP);
268    if (pSrcWin)
269    {
270	RegionPtr	region;
271    	if (!(region = wClipShape (pSrcWin)))
272    	    region = wBoundingShape (pSrcWin);
273    	/*
274     	 * If you try to CopyArea the extents of a shaped window, compacting the
275     	 * exposed region will undo all our work!
276     	 */
277    	if (extents && pSrcWin && region &&
278    	    (RECT_IN_REGION(pscr, region, &srcBox) != rgnIN))
279	    	extents = FALSE;
280    }
281    if (extents)
282    {
283	expBox = *REGION_EXTENTS(pscr, &rgnExposed);
284	REGION_RESET(pscr, &rgnExposed, &expBox);
285    }
286    if ((pDstDrawable->type != DRAWABLE_PIXMAP) &&
287	(((WindowPtr)pDstDrawable)->backgroundState != None))
288    {
289	WindowPtr pWin = (WindowPtr)pDstDrawable;
290
291	/* make the exposed area screen-relative */
292	REGION_TRANSLATE(pscr, &rgnExposed,
293				 pDstDrawable->x, pDstDrawable->y);
294
295	if (extents)
296	{
297	    /* PaintWindowBackground doesn't clip, so we have to */
298	    REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, &pWin->clipList);
299	}
300	miPaintWindow((WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND);
301
302	if (extents)
303	{
304	    REGION_RESET(pscr, &rgnExposed, &expBox);
305	}
306	else
307	    REGION_TRANSLATE(pscr, &rgnExposed,
308				     -pDstDrawable->x, -pDstDrawable->y);
309    }
310    if (prgnDstClip == &rgnDstRec)
311    {
312	REGION_UNINIT(pscr, prgnDstClip);
313    }
314    else if (prgnDstClip != prgnSrcClip)
315    {
316	REGION_DESTROY(pscr, prgnDstClip);
317    }
318
319    if (prgnSrcClip == &rgnSrcRec)
320    {
321	REGION_UNINIT(pscr, prgnSrcClip);
322    }
323    else
324    {
325	REGION_DESTROY(pscr, prgnSrcClip);
326    }
327
328    if (pGC->graphicsExposures)
329    {
330	/* don't look */
331	RegionPtr exposed = REGION_CREATE(pscr, NullBox, 0);
332	*exposed = rgnExposed;
333	return exposed;
334    }
335    else
336    {
337	REGION_UNINIT(pscr, &rgnExposed);
338	return NULL;
339    }
340}
341
342/* send GraphicsExpose events, or a NoExpose event, based on the region */
343
344void
345miSendGraphicsExpose (ClientPtr client, RegionPtr pRgn, XID drawable,
346                      int major, int minor)
347{
348    if (pRgn && !REGION_NIL(pRgn))
349    {
350        xEvent *pEvent;
351	xEvent *pe;
352	BoxPtr pBox;
353	int i;
354	int numRects;
355
356	numRects = REGION_NUM_RECTS(pRgn);
357	pBox = REGION_RECTS(pRgn);
358	if(!(pEvent = (xEvent *)xalloc(numRects * sizeof(xEvent))))
359		return;
360	pe = pEvent;
361
362	for (i=1; i<=numRects; i++, pe++, pBox++)
363	{
364	    pe->u.u.type = GraphicsExpose;
365	    pe->u.graphicsExposure.drawable = drawable;
366	    pe->u.graphicsExposure.x = pBox->x1;
367	    pe->u.graphicsExposure.y = pBox->y1;
368	    pe->u.graphicsExposure.width = pBox->x2 - pBox->x1;
369	    pe->u.graphicsExposure.height = pBox->y2 - pBox->y1;
370	    pe->u.graphicsExposure.count = numRects - i;
371	    pe->u.graphicsExposure.majorEvent = major;
372	    pe->u.graphicsExposure.minorEvent = minor;
373	}
374	TryClientEvents(client, NULL, pEvent, numRects,
375			    (Mask)0, NoEventMask, NullGrab);
376	xfree(pEvent);
377    }
378    else
379    {
380        xEvent event;
381	event.u.u.type = NoExpose;
382	event.u.noExposure.drawable = drawable;
383	event.u.noExposure.majorEvent = major;
384	event.u.noExposure.minorEvent = minor;
385	TryClientEvents(client, NULL, &event, 1,
386	    (Mask)0, NoEventMask, NullGrab);
387    }
388}
389
390
391void
392miSendExposures( WindowPtr pWin, RegionPtr pRgn, int dx, int dy)
393{
394    BoxPtr pBox;
395    int numRects;
396    xEvent *pEvent, *pe;
397    int i;
398
399    pBox = REGION_RECTS(pRgn);
400    numRects = REGION_NUM_RECTS(pRgn);
401    if(!(pEvent = (xEvent *) xalloc(numRects * sizeof(xEvent))))
402	return;
403
404    for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++)
405    {
406	pe->u.u.type = Expose;
407	pe->u.expose.window = pWin->drawable.id;
408	pe->u.expose.x = pBox->x1 - dx;
409	pe->u.expose.y = pBox->y1 - dy;
410	pe->u.expose.width = pBox->x2 - pBox->x1;
411	pe->u.expose.height = pBox->y2 - pBox->y1;
412	pe->u.expose.count = i;
413    }
414
415#ifdef PANORAMIX
416    if(!noPanoramiXExtension) {
417	int scrnum = pWin->drawable.pScreen->myNum;
418	int x = 0, y = 0;
419	XID realWin = 0;
420
421	if(!pWin->parent) {
422	    x = panoramiXdataPtr[scrnum].x;
423	    y = panoramiXdataPtr[scrnum].y;
424	    pWin = WindowTable[0];
425	    realWin = pWin->drawable.id;
426	} else if (scrnum) {
427	    PanoramiXRes *win;
428	    win = PanoramiXFindIDByScrnum(XRT_WINDOW,
429			pWin->drawable.id, scrnum);
430	    if(!win) {
431		xfree(pEvent);
432		return;
433	    }
434	    realWin = win->info[0].id;
435	    pWin = LookupIDByType(realWin, RT_WINDOW);
436	}
437	if(x || y || scrnum)
438	  for (i = 0; i < numRects; i++) {
439	      pEvent[i].u.expose.window = realWin;
440	      pEvent[i].u.expose.x += x;
441	      pEvent[i].u.expose.y += y;
442	  }
443    }
444#endif
445
446    DeliverEvents(pWin, pEvent, numRects, NullWindow);
447
448    xfree(pEvent);
449}
450
451_X_EXPORT void
452miWindowExposures( WindowPtr pWin, RegionPtr prgn, RegionPtr other_exposed)
453{
454    RegionPtr   exposures = prgn;
455    if ((prgn && !REGION_NIL(prgn)) ||
456	(exposures && !REGION_NIL(exposures)) || other_exposed)
457    {
458	RegionRec   expRec;
459	int	    clientInterested;
460
461	/*
462	 * Restore from backing-store FIRST.
463	 */
464	clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask;
465	if (other_exposed)
466	{
467	    if (exposures)
468	    {
469		REGION_UNION(pWin->drawable.pScreen, other_exposed,
470						  exposures,
471					          other_exposed);
472		if (exposures != prgn)
473		    REGION_DESTROY(pWin->drawable.pScreen, exposures);
474	    }
475	    exposures = other_exposed;
476	}
477	if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT))
478	{
479	    /*
480	     * If we have LOTS of rectangles, we decide to take the extents
481	     * and force an exposure on that.  This should require much less
482	     * work overall, on both client and server.  This is cheating, but
483	     * isn't prohibited by the protocol ("spontaneous combustion" :-).
484	     */
485	    BoxRec box;
486
487	    box = *REGION_EXTENTS( pWin->drawable.pScreen, exposures);
488	    if (exposures == prgn) {
489		exposures = &expRec;
490		REGION_INIT( pWin->drawable.pScreen, exposures, &box, 1);
491		REGION_RESET( pWin->drawable.pScreen, prgn, &box);
492	    } else {
493		REGION_RESET( pWin->drawable.pScreen, exposures, &box);
494		REGION_UNION( pWin->drawable.pScreen, prgn, prgn, exposures);
495	    }
496	    /* PaintWindowBackground doesn't clip, so we have to */
497	    REGION_INTERSECT( pWin->drawable.pScreen, prgn, prgn, &pWin->clipList);
498	}
499	if (prgn && !REGION_NIL(prgn))
500	    miPaintWindow(pWin, prgn, PW_BACKGROUND);
501	if (clientInterested && exposures && !REGION_NIL(exposures))
502	    miSendExposures(pWin, exposures,
503			    pWin->drawable.x, pWin->drawable.y);
504	if (exposures == &expRec)
505	{
506	    REGION_UNINIT( pWin->drawable.pScreen, exposures);
507	}
508	else if (exposures && exposures != prgn && exposures != other_exposed)
509	    REGION_DESTROY( pWin->drawable.pScreen, exposures);
510	if (prgn)
511	    REGION_EMPTY( pWin->drawable.pScreen, prgn);
512    }
513    else if (exposures && exposures != prgn)
514	REGION_DESTROY( pWin->drawable.pScreen, exposures);
515}
516
517void
518miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
519{
520    ScreenPtr	pScreen = pWin->drawable.pScreen;
521    ChangeGCVal gcval[5];
522    BITS32	gcmask;
523    GCPtr	pGC;
524    int		i;
525    BoxPtr	pbox;
526    xRectangle	*prect;
527    int		numRects;
528    /*
529     * Distance from screen to destination drawable, use this
530     * to adjust rendering coordinates which come in in screen space
531     */
532    int		draw_x_off, draw_y_off;
533    /*
534     * Tile offset for drawing; these need to align the tile
535     * to the appropriate window origin
536     */
537    int		tile_x_off, tile_y_off;
538    PixUnion	fill;
539    Bool	solid = TRUE;
540    DrawablePtr	drawable = &pWin->drawable;
541
542    if (what == PW_BACKGROUND)
543    {
544	while (pWin->backgroundState == ParentRelative)
545	    pWin = pWin->parent;
546
547	draw_x_off = drawable->x;
548	draw_y_off = drawable->y;
549
550	tile_x_off = pWin->drawable.x - draw_x_off;
551	tile_y_off = pWin->drawable.y - draw_y_off;
552	fill = pWin->background;
553	switch (pWin->backgroundState) {
554	case None:
555	    return;
556	case BackgroundPixmap:
557	    solid = FALSE;
558	    break;
559	}
560    }
561    else
562    {
563	PixmapPtr   pixmap;
564
565	tile_x_off = drawable->x;
566	tile_y_off = drawable->y;
567
568	/* servers without pixmaps draw their own borders */
569	if (!pScreen->GetWindowPixmap)
570	    return;
571	pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable);
572	drawable = &pixmap->drawable;
573#ifdef COMPOSITE
574	draw_x_off = pixmap->screen_x;
575	draw_y_off = pixmap->screen_y;
576	tile_x_off -= draw_x_off;
577	tile_y_off -= draw_y_off;
578#else
579	draw_x_off = 0;
580	draw_y_off = 0;
581#endif
582	fill = pWin->border;
583	solid = pWin->borderIsPixel;
584    }
585
586    gcval[0].val = GXcopy;
587    gcmask = GCFunction;
588
589    if (solid)
590    {
591	gcval[1].val = fill.pixel;
592	gcval[2].val  = FillSolid;
593	gcmask |= GCForeground | GCFillStyle;
594    }
595    else
596    {
597	gcval[1].val = FillTiled;
598	gcval[2].ptr = (pointer)fill.pixmap;
599	gcval[3].val = tile_x_off;
600	gcval[4].val = tile_y_off;
601	gcmask |= GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin;
602    }
603
604    prect = (xRectangle *)xalloc(REGION_NUM_RECTS(prgn) *
605					 sizeof(xRectangle));
606    if (!prect)
607	return;
608
609    pGC = GetScratchGC(drawable->depth, drawable->pScreen);
610    if (!pGC)
611    {
612	xfree(prect);
613	return;
614    }
615
616    dixChangeGC (NullClient, pGC, gcmask, NULL, gcval);
617    ValidateGC (drawable, pGC);
618
619    numRects = REGION_NUM_RECTS(prgn);
620    pbox = REGION_RECTS(prgn);
621    for (i= numRects; --i >= 0; pbox++, prect++)
622    {
623	prect->x = pbox->x1 - draw_x_off;
624	prect->y = pbox->y1 - draw_y_off;
625	prect->width = pbox->x2 - pbox->x1;
626	prect->height = pbox->y2 - pbox->y1;
627    }
628    prect -= numRects;
629    (*pGC->ops->PolyFillRect)(drawable, pGC, numRects, prect);
630    xfree(prect);
631
632    FreeScratchGC(pGC);
633}
634
635
636/* MICLEARDRAWABLE -- sets the entire drawable to the background color of
637 * the GC.  Useful when we have a scratch drawable and need to initialize
638 * it. */
639_X_EXPORT void
640miClearDrawable(DrawablePtr pDraw, GCPtr pGC)
641{
642    XID fg = pGC->fgPixel;
643    XID bg = pGC->bgPixel;
644    xRectangle rect;
645
646    rect.x = 0;
647    rect.y = 0;
648    rect.width = pDraw->width;
649    rect.height = pDraw->height;
650    DoChangeGC(pGC, GCForeground, &bg, 0);
651    ValidateGC(pDraw, pGC);
652    (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect);
653    DoChangeGC(pGC, GCForeground, &fg, 0);
654    ValidateGC(pDraw, pGC);
655}
656