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