~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to mi/miexpose.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $XdotOrg: xserver/xorg/mi/miexpose.c,v 1.6 2005/07/03 08:53:51 daniels Exp $ */
 
2
/* $XFree86: xc/programs/Xserver/mi/miexpose.c,v 3.9tsi Exp $ */
 
3
/***********************************************************
 
4
 
 
5
Copyright 1987, 1998  The Open Group
 
6
 
 
7
Permission to use, copy, modify, distribute, and sell this software and its
 
8
documentation for any purpose is hereby granted without fee, provided that
 
9
the above copyright notice appear in all copies and that both that
 
10
copyright notice and this permission notice appear in supporting
 
11
documentation.
 
12
 
 
13
The above copyright notice and this permission notice shall be included in
 
14
all copies or substantial portions of the Software.
 
15
 
 
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
17
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
19
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
20
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
21
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
22
 
 
23
Except as contained in this notice, the name of The Open Group shall not be
 
24
used in advertising or otherwise to promote the sale, use or other dealings
 
25
in this Software without prior written authorization from The Open Group.
 
26
 
 
27
 
 
28
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 
29
 
 
30
                        All Rights Reserved
 
31
 
 
32
Permission to use, copy, modify, and distribute this software and its 
 
33
documentation for any purpose and without fee is hereby granted, 
 
34
provided that the above copyright notice appear in all copies and that
 
35
both that copyright notice and this permission notice appear in 
 
36
supporting documentation, and that the name of Digital not be
 
37
used in advertising or publicity pertaining to distribution of the
 
38
software without specific, written prior permission.  
 
39
 
 
40
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 
41
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 
42
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 
43
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 
44
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 
45
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 
46
SOFTWARE.
 
47
 
 
48
******************************************************************/
 
49
/*****************************************************************
 
50
 
 
51
Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
 
52
 
 
53
Permission is hereby granted, free of charge, to any person obtaining a copy
 
54
of this software and associated documentation files (the "Software"), to deal
 
55
in the Software without restriction, including without limitation the rights
 
56
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
57
copies of the Software.
 
58
 
 
59
The above copyright notice and this permission notice shall be included in
 
60
all copies or substantial portions of the Software.
 
61
 
 
62
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
63
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
64
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
65
DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
 
66
BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
 
67
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
 
68
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
69
 
 
70
Except as contained in this notice, the name of Digital Equipment Corporation
 
71
shall not be used in advertising or otherwise to promote the sale, use or other
 
72
dealings in this Software without prior written authorization from Digital
 
73
Equipment Corporation.
 
74
 
 
75
******************************************************************/
 
76
 
 
77
/* $Xorg: miexpose.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */
 
78
 
 
79
#ifdef HAVE_DIX_CONFIG_H
 
80
#include <dix-config.h>
 
81
#endif
 
82
 
 
83
#include <X11/X.h>
 
84
#define NEED_EVENTS
 
85
#include <X11/Xproto.h>
 
86
#include <X11/Xprotostr.h>
 
87
 
 
88
#include "misc.h"
 
89
#include "regionstr.h"
 
90
#include "scrnintstr.h"
 
91
#include "gcstruct.h"
 
92
#include "windowstr.h"
 
93
#include "pixmap.h"
 
94
#include "input.h"
 
95
 
 
96
#include "dixstruct.h"
 
97
#include "mi.h"
 
98
#include <X11/Xmd.h>
 
99
 
 
100
#include "globals.h"
 
101
 
 
102
#ifdef PANORAMIX
 
103
#include "panoramiX.h"
 
104
#include "panoramiXsrv.h"
 
105
#endif
 
106
 
 
107
/*
 
108
    machine-independent graphics exposure code.  any device that uses
 
109
the region package can call this.
 
110
*/
 
111
 
 
112
#ifndef RECTLIMIT
 
113
#define RECTLIMIT 25            /* pick a number, any number > 8 */
 
114
#endif
 
115
 
 
116
/* miHandleExposures 
 
117
    generate a region for exposures for areas that were copied from obscured or
 
118
non-existent areas to non-obscured areas of the destination.  Paint the
 
119
background for the region, if the destination is a window.
 
120
 
 
121
NOTE:
 
122
     this should generally be called, even if graphicsExposures is false,
 
123
because this is where bits get recovered from backing store.
 
124
 
 
125
NOTE:
 
126
     added argument 'plane' is used to indicate how exposures from backing
 
127
store should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea
 
128
should be used, else a CopyPlane of the indicated plane will be used. The
 
129
exposing is done by the backing store's GraphicsExpose function, of course.
 
130
 
 
131
*/
 
132
 
 
133
RegionPtr
 
134
miHandleExposures(pSrcDrawable, pDstDrawable,
 
135
                  pGC, srcx, srcy, width, height, dstx, dsty, plane)
 
136
    register DrawablePtr        pSrcDrawable;
 
137
    register DrawablePtr        pDstDrawable;
 
138
    GCPtr                       pGC;
 
139
    int                         srcx, srcy;
 
140
    int                         width, height;
 
141
    int                         dstx, dsty;
 
142
    unsigned long               plane;
 
143
{
 
144
    register ScreenPtr pscr;
 
145
    RegionPtr prgnSrcClip;      /* drawable-relative source clip */
 
146
    RegionRec rgnSrcRec;
 
147
    RegionPtr prgnDstClip;      /* drawable-relative dest clip */
 
148
    RegionRec rgnDstRec;
 
149
    BoxRec srcBox;              /* unclipped source */
 
150
    RegionRec rgnExposed;       /* exposed region, calculated source-
 
151
                                   relative, made dst relative to
 
152
                                   intersect with visible parts of
 
153
                                   dest and send events to client, 
 
154
                                   and then screen relative to paint 
 
155
                                   the window background
 
156
                                */
 
157
    WindowPtr pSrcWin;
 
158
    BoxRec expBox;
 
159
    Bool extents;
 
160
 
 
161
    /* This prevents warning about pscr not being used. */
 
162
    pGC->pScreen = pscr = pGC->pScreen;
 
163
 
 
164
    /* avoid work if we can */
 
165
    if (!pGC->graphicsExposures &&
 
166
        (pDstDrawable->type == DRAWABLE_PIXMAP) &&
 
167
        ((pSrcDrawable->type == DRAWABLE_PIXMAP) ||
 
168
         (((WindowPtr)pSrcDrawable)->backStorage == NULL)))
 
169
        return NULL;
 
170
        
 
171
    srcBox.x1 = srcx;
 
172
    srcBox.y1 = srcy;
 
173
    srcBox.x2 = srcx+width;
 
174
    srcBox.y2 = srcy+height;
 
175
 
 
176
    if (pSrcDrawable->type != DRAWABLE_PIXMAP)
 
177
    {
 
178
        BoxRec TsrcBox;
 
179
 
 
180
        TsrcBox.x1 = srcx + pSrcDrawable->x;
 
181
        TsrcBox.y1 = srcy + pSrcDrawable->y;
 
182
        TsrcBox.x2 = TsrcBox.x1 + width;
 
183
        TsrcBox.y2 = TsrcBox.y1 + height;
 
184
        pSrcWin = (WindowPtr) pSrcDrawable;
 
185
        if (pGC->subWindowMode == IncludeInferiors)
 
186
        {
 
187
            prgnSrcClip = NotClippedByChildren (pSrcWin);
 
188
            if ((RECT_IN_REGION(pscr, prgnSrcClip, &TsrcBox)) == rgnIN)
 
189
            {
 
190
                REGION_DESTROY(pscr, prgnSrcClip);
 
191
                return NULL;
 
192
            }
 
193
        }
 
194
        else
 
195
        {
 
196
            if ((RECT_IN_REGION(pscr, &pSrcWin->clipList, &TsrcBox)) == rgnIN)
 
197
                return NULL;
 
198
            prgnSrcClip = &rgnSrcRec;
 
199
            REGION_NULL(pscr, prgnSrcClip);
 
200
            REGION_COPY(pscr, prgnSrcClip, &pSrcWin->clipList);
 
201
        }
 
202
        REGION_TRANSLATE(pscr, prgnSrcClip,
 
203
                                -pSrcDrawable->x, -pSrcDrawable->y);
 
204
    }
 
205
    else
 
206
    {
 
207
        BoxRec  box;
 
208
 
 
209
        if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
 
210
            (srcBox.x2 <= pSrcDrawable->width) &&
 
211
            (srcBox.y2 <= pSrcDrawable->height))
 
212
            return NULL;
 
213
 
 
214
        box.x1 = 0;
 
215
        box.y1 = 0;
 
216
        box.x2 = pSrcDrawable->width;
 
217
        box.y2 = pSrcDrawable->height;
 
218
        prgnSrcClip = &rgnSrcRec;
 
219
        REGION_INIT(pscr, prgnSrcClip, &box, 1);
 
220
        pSrcWin = (WindowPtr)NULL;
 
221
    }
 
222
 
 
223
    if (pDstDrawable == pSrcDrawable)
 
224
    {
 
225
        prgnDstClip = prgnSrcClip;
 
226
    }
 
227
    else if (pDstDrawable->type != DRAWABLE_PIXMAP)
 
228
    {
 
229
        if (pGC->subWindowMode == IncludeInferiors)
 
230
        {
 
231
            prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable);
 
232
        }
 
233
        else
 
234
        {
 
235
            prgnDstClip = &rgnDstRec;
 
236
            REGION_NULL(pscr, prgnDstClip);
 
237
            REGION_COPY(pscr, prgnDstClip,
 
238
                                &((WindowPtr)pDstDrawable)->clipList);
 
239
        }
 
240
        REGION_TRANSLATE(pscr, prgnDstClip,
 
241
                                 -pDstDrawable->x, -pDstDrawable->y);
 
242
    }
 
243
    else
 
244
    {
 
245
        BoxRec  box;
 
246
 
 
247
        box.x1 = 0;
 
248
        box.y1 = 0;
 
249
        box.x2 = pDstDrawable->width;
 
250
        box.y2 = pDstDrawable->height;
 
251
        prgnDstClip = &rgnDstRec;
 
252
        REGION_INIT(pscr, prgnDstClip, &box, 1);
 
253
    }
 
254
 
 
255
    /* drawable-relative source region */
 
256
    REGION_INIT(pscr, &rgnExposed, &srcBox, 1);
 
257
 
 
258
    /* now get the hidden parts of the source box*/
 
259
    REGION_SUBTRACT(pscr, &rgnExposed, &rgnExposed, prgnSrcClip);
 
260
 
 
261
    if (pSrcWin && pSrcWin->backStorage)
 
262
    {
 
263
        /*
 
264
         * Copy any areas from the source backing store. Modifies
 
265
         * rgnExposed.
 
266
         */
 
267
        (* pSrcWin->drawable.pScreen->ExposeCopy) ((WindowPtr)pSrcDrawable,
 
268
                                              pDstDrawable,
 
269
                                              pGC,
 
270
                                              &rgnExposed,
 
271
                                              srcx, srcy,
 
272
                                              dstx, dsty,
 
273
                                              plane);
 
274
    }
 
275
    
 
276
    /* move them over the destination */
 
277
    REGION_TRANSLATE(pscr, &rgnExposed, dstx-srcx, dsty-srcy);
 
278
 
 
279
    /* intersect with visible areas of dest */
 
280
    REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, prgnDstClip);
 
281
 
 
282
    /*
 
283
     * If we have LOTS of rectangles, we decide to take the extents
 
284
     * and force an exposure on that.  This should require much less
 
285
     * work overall, on both client and server.  This is cheating, but
 
286
     * isn't prohibited by the protocol ("spontaneous combustion" :-)
 
287
     * for windows.
 
288
     */
 
289
    extents = pGC->graphicsExposures &&
 
290
              (REGION_NUM_RECTS(&rgnExposed) > RECTLIMIT) &&
 
291
              (pDstDrawable->type != DRAWABLE_PIXMAP);
 
292
#ifdef SHAPE
 
293
    if (pSrcWin)
 
294
    {
 
295
        RegionPtr       region;
 
296
        if (!(region = wClipShape (pSrcWin)))
 
297
            region = wBoundingShape (pSrcWin);
 
298
        /*
 
299
         * If you try to CopyArea the extents of a shaped window, compacting the
 
300
         * exposed region will undo all our work!
 
301
         */
 
302
        if (extents && pSrcWin && region &&
 
303
            (RECT_IN_REGION(pscr, region, &srcBox) != rgnIN))
 
304
                extents = FALSE;
 
305
    }
 
306
#endif
 
307
    if (extents)
 
308
    {
 
309
        WindowPtr pWin = (WindowPtr)pDstDrawable;
 
310
 
 
311
        expBox = *REGION_EXTENTS(pscr, &rgnExposed);
 
312
        REGION_RESET(pscr, &rgnExposed, &expBox);
 
313
        /* need to clear out new areas of backing store */
 
314
        if (pWin->backStorage)
 
315
            (void) (* pWin->drawable.pScreen->ClearBackingStore)(
 
316
                                         pWin,
 
317
                                         expBox.x1,
 
318
                                         expBox.y1,
 
319
                                         expBox.x2 - expBox.x1,
 
320
                                         expBox.y2 - expBox.y1,
 
321
                                         FALSE);
 
322
    }
 
323
    if ((pDstDrawable->type != DRAWABLE_PIXMAP) &&
 
324
        (((WindowPtr)pDstDrawable)->backgroundState != None))
 
325
    {
 
326
        WindowPtr pWin = (WindowPtr)pDstDrawable;
 
327
 
 
328
        /* make the exposed area screen-relative */
 
329
        REGION_TRANSLATE(pscr, &rgnExposed, 
 
330
                                 pDstDrawable->x, pDstDrawable->y);
 
331
 
 
332
        if (extents)
 
333
        {
 
334
            /* PaintWindowBackground doesn't clip, so we have to */
 
335
            REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, &pWin->clipList);
 
336
        }
 
337
        (*pWin->drawable.pScreen->PaintWindowBackground)(
 
338
                        (WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND);
 
339
 
 
340
        if (extents)
 
341
        {
 
342
            REGION_RESET(pscr, &rgnExposed, &expBox);
 
343
        }
 
344
        else
 
345
            REGION_TRANSLATE(pscr, &rgnExposed,
 
346
                                     -pDstDrawable->x, -pDstDrawable->y);
 
347
    }
 
348
    if (prgnDstClip == &rgnDstRec)
 
349
    {
 
350
        REGION_UNINIT(pscr, prgnDstClip);
 
351
    }
 
352
    else if (prgnDstClip != prgnSrcClip)
 
353
    {
 
354
        REGION_DESTROY(pscr, prgnDstClip);
 
355
    }
 
356
 
 
357
    if (prgnSrcClip == &rgnSrcRec)
 
358
    {
 
359
        REGION_UNINIT(pscr, prgnSrcClip);
 
360
    }
 
361
    else
 
362
    {
 
363
        REGION_DESTROY(pscr, prgnSrcClip);
 
364
    }
 
365
 
 
366
    if (pGC->graphicsExposures)
 
367
    {
 
368
        /* don't look */
 
369
        RegionPtr exposed = REGION_CREATE(pscr, NullBox, 0);
 
370
        *exposed = rgnExposed;
 
371
        return exposed;
 
372
    }
 
373
    else
 
374
    {
 
375
        REGION_UNINIT(pscr, &rgnExposed);
 
376
        return NULL;
 
377
    }
 
378
}
 
379
 
 
380
/* send GraphicsExpose events, or a NoExpose event, based on the region */
 
381
 
 
382
void
 
383
miSendGraphicsExpose (client, pRgn, drawable, major, minor)
 
384
    ClientPtr   client;
 
385
    RegionPtr   pRgn;
 
386
    XID         drawable;
 
387
    int major;
 
388
    int minor;
 
389
{
 
390
    if (pRgn && !REGION_NIL(pRgn))
 
391
    {
 
392
        xEvent *pEvent;
 
393
        register xEvent *pe;
 
394
        register BoxPtr pBox;
 
395
        register int i;
 
396
        int numRects;
 
397
 
 
398
        numRects = REGION_NUM_RECTS(pRgn);
 
399
        pBox = REGION_RECTS(pRgn);
 
400
        if(!(pEvent = (xEvent *)ALLOCATE_LOCAL(numRects * sizeof(xEvent))))
 
401
                return;
 
402
        pe = pEvent;
 
403
 
 
404
        for (i=1; i<=numRects; i++, pe++, pBox++)
 
405
        {
 
406
            pe->u.u.type = GraphicsExpose;
 
407
            pe->u.graphicsExposure.drawable = drawable;
 
408
            pe->u.graphicsExposure.x = pBox->x1;
 
409
            pe->u.graphicsExposure.y = pBox->y1;
 
410
            pe->u.graphicsExposure.width = pBox->x2 - pBox->x1;
 
411
            pe->u.graphicsExposure.height = pBox->y2 - pBox->y1;
 
412
            pe->u.graphicsExposure.count = numRects - i;
 
413
            pe->u.graphicsExposure.majorEvent = major;
 
414
            pe->u.graphicsExposure.minorEvent = minor;
 
415
        }
 
416
        TryClientEvents(client, pEvent, numRects,
 
417
                            (Mask)0, NoEventMask, NullGrab);
 
418
        DEALLOCATE_LOCAL(pEvent);
 
419
    }
 
420
    else
 
421
    {
 
422
        xEvent event;
 
423
        event.u.u.type = NoExpose;
 
424
        event.u.noExposure.drawable = drawable;
 
425
        event.u.noExposure.majorEvent = major;
 
426
        event.u.noExposure.minorEvent = minor;
 
427
        TryClientEvents(client, &event, 1,
 
428
            (Mask)0, NoEventMask, NullGrab);
 
429
    }
 
430
}
 
431
 
 
432
 
 
433
void
 
434
miSendExposures(pWin, pRgn, dx, dy)
 
435
    WindowPtr pWin;
 
436
    RegionPtr pRgn;
 
437
    register int dx, dy;
 
438
{
 
439
    register BoxPtr pBox;
 
440
    int numRects;
 
441
    register xEvent *pEvent, *pe;
 
442
    register int i;
 
443
 
 
444
    pBox = REGION_RECTS(pRgn);
 
445
    numRects = REGION_NUM_RECTS(pRgn);
 
446
    if(!(pEvent = (xEvent *) ALLOCATE_LOCAL(numRects * sizeof(xEvent))))
 
447
        return;
 
448
 
 
449
    for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++)
 
450
    {
 
451
        pe->u.u.type = Expose;
 
452
        pe->u.expose.window = pWin->drawable.id;
 
453
        pe->u.expose.x = pBox->x1 - dx;
 
454
        pe->u.expose.y = pBox->y1 - dy;
 
455
        pe->u.expose.width = pBox->x2 - pBox->x1;
 
456
        pe->u.expose.height = pBox->y2 - pBox->y1;
 
457
        pe->u.expose.count = i;
 
458
    }
 
459
 
 
460
#ifdef PANORAMIX
 
461
    if(!noPanoramiXExtension) {
 
462
        int scrnum = pWin->drawable.pScreen->myNum;
 
463
        int x = 0, y = 0;
 
464
        XID realWin = 0;
 
465
 
 
466
        if(!pWin->parent) {
 
467
            x = panoramiXdataPtr[scrnum].x;
 
468
            y = panoramiXdataPtr[scrnum].y;
 
469
            pWin = WindowTable[0];
 
470
            realWin = pWin->drawable.id;
 
471
        } else if (scrnum) {
 
472
            PanoramiXRes *win;
 
473
            win = PanoramiXFindIDByScrnum(XRT_WINDOW, 
 
474
                        pWin->drawable.id, scrnum);
 
475
            if(!win) {
 
476
                DEALLOCATE_LOCAL(pEvent);
 
477
                return;
 
478
            }
 
479
            realWin = win->info[0].id;
 
480
            pWin = LookupIDByType(realWin, RT_WINDOW);
 
481
        }
 
482
        if(x || y || scrnum)
 
483
          for (i = 0; i < numRects; i++) {
 
484
              pEvent[i].u.expose.window = realWin;
 
485
              pEvent[i].u.expose.x += x;
 
486
              pEvent[i].u.expose.y += y;
 
487
          }
 
488
    }
 
489
#endif
 
490
 
 
491
    DeliverEvents(pWin, pEvent, numRects, NullWindow);
 
492
 
 
493
    DEALLOCATE_LOCAL(pEvent);
 
494
}
 
495
 
 
496
void 
 
497
miWindowExposures(pWin, prgn, other_exposed)
 
498
    WindowPtr pWin;
 
499
    register RegionPtr prgn, other_exposed;
 
500
{
 
501
    RegionPtr   exposures = prgn;
 
502
    if (pWin->backStorage && prgn)
 
503
        /*
 
504
         * in some cases, backing store will cause a different
 
505
         * region to be exposed than needs to be repainted
 
506
         * (like when a window is mapped).  RestoreAreas is
 
507
         * allowed to return a region other than prgn,
 
508
         * in which case this routine will free the resultant
 
509
         * region.  If exposures is null, then no events will
 
510
         * be sent to the client; if prgn is empty
 
511
         * no areas will be repainted.
 
512
         */
 
513
        exposures = (*pWin->drawable.pScreen->RestoreAreas)(pWin, prgn);
 
514
    if ((prgn && !REGION_NIL(prgn)) || 
 
515
        (exposures && !REGION_NIL(exposures)) || other_exposed)
 
516
    {
 
517
        RegionRec   expRec;
 
518
        int         clientInterested;
 
519
 
 
520
        /*
 
521
         * Restore from backing-store FIRST.
 
522
         */
 
523
        clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask;
 
524
        if (other_exposed)
 
525
        {
 
526
            if (exposures)
 
527
            {
 
528
                REGION_UNION(pWin->drawable.pScreen, other_exposed,
 
529
                                                  exposures,
 
530
                                                  other_exposed);
 
531
                if (exposures != prgn)
 
532
                    REGION_DESTROY(pWin->drawable.pScreen, exposures);
 
533
            }
 
534
            exposures = other_exposed;
 
535
        }
 
536
        if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT))
 
537
        {
 
538
            /*
 
539
             * If we have LOTS of rectangles, we decide to take the extents
 
540
             * and force an exposure on that.  This should require much less
 
541
             * work overall, on both client and server.  This is cheating, but
 
542
             * isn't prohibited by the protocol ("spontaneous combustion" :-).
 
543
             */
 
544
            BoxRec box;
 
545
 
 
546
            box = *REGION_EXTENTS( pWin->drawable.pScreen, exposures);
 
547
            if (exposures == prgn) {
 
548
                exposures = &expRec;
 
549
                REGION_INIT( pWin->drawable.pScreen, exposures, &box, 1);
 
550
                REGION_RESET( pWin->drawable.pScreen, prgn, &box);
 
551
            } else {
 
552
                REGION_RESET( pWin->drawable.pScreen, exposures, &box);
 
553
                REGION_UNION( pWin->drawable.pScreen, prgn, prgn, exposures);
 
554
            }
 
555
            /* PaintWindowBackground doesn't clip, so we have to */
 
556
            REGION_INTERSECT( pWin->drawable.pScreen, prgn, prgn, &pWin->clipList);
 
557
            /* need to clear out new areas of backing store, too */
 
558
            if (pWin->backStorage)
 
559
                (void) (* pWin->drawable.pScreen->ClearBackingStore)(
 
560
                                             pWin,
 
561
                                             box.x1 - pWin->drawable.x,
 
562
                                             box.y1 - pWin->drawable.y,
 
563
                                             box.x2 - box.x1,
 
564
                                             box.y2 - box.y1,
 
565
                                             FALSE);
 
566
        }
 
567
        if (prgn && !REGION_NIL(prgn))
 
568
            (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, prgn, PW_BACKGROUND);
 
569
        if (clientInterested && exposures && !REGION_NIL(exposures))
 
570
            miSendExposures(pWin, exposures,
 
571
                            pWin->drawable.x, pWin->drawable.y);
 
572
        if (exposures == &expRec)
 
573
        {
 
574
            REGION_UNINIT( pWin->drawable.pScreen, exposures);
 
575
        }
 
576
        else if (exposures && exposures != prgn && exposures != other_exposed)
 
577
            REGION_DESTROY( pWin->drawable.pScreen, exposures);
 
578
        if (prgn)
 
579
            REGION_EMPTY( pWin->drawable.pScreen, prgn);
 
580
    }
 
581
    else if (exposures && exposures != prgn)
 
582
        REGION_DESTROY( pWin->drawable.pScreen, exposures);
 
583
}
 
584
 
 
585
 
 
586
/*
 
587
    this code is highly unlikely.  it is not haile selassie.
 
588
 
 
589
    there is some hair here.  we can't just use the window's
 
590
clip region as it is, because if we are painting the border,
 
591
the border is not in the client area and so we will be excluded
 
592
when we validate the GC, and if we are painting a parent-relative
 
593
background, the area we want to paint is in some other window.
 
594
since we trust the code calling us to tell us to paint only areas
 
595
that are really ours, we will temporarily give the window a
 
596
clipList the size of the whole screen and an origin at (0,0).
 
597
this more or less assumes that ddX code will do translation
 
598
based on the window's absolute position, and that ValidateGC will
 
599
look at clipList, and that no other fields from the
 
600
window will be used.  it's not possible to just draw
 
601
in the root because it may be a different depth.
 
602
 
 
603
to get the tile to align correctly we set the GC's tile origin to
 
604
be the (x,y) of the window's upper left corner, after which we
 
605
get the right bits when drawing into the root.
 
606
 
 
607
because the clip_mask is being set to None, we may call DoChangeGC with
 
608
fPointer set true, thus we no longer need to install the background or
 
609
border tile in the resource table.
 
610
*/
 
611
 
 
612
static RESTYPE ResType = 0;
 
613
static int numGCs = 0;
 
614
static GCPtr    screenContext[MAXSCREENS];
 
615
 
 
616
/*ARGSUSED*/
 
617
static int
 
618
tossGC (
 
619
    pointer value,
 
620
    XID id)
 
621
{
 
622
    GCPtr pGC = (GCPtr)value;
 
623
    screenContext[pGC->pScreen->myNum] = (GCPtr)NULL;
 
624
    FreeGC (pGC, id);
 
625
    numGCs--;
 
626
    if (!numGCs)
 
627
        ResType = 0;
 
628
 
 
629
    return 0;
 
630
}
 
631
 
 
632
 
 
633
void
 
634
miPaintWindow(pWin, prgn, what)
 
635
register WindowPtr pWin;
 
636
RegionPtr prgn;
 
637
int what;
 
638
{
 
639
    int status;
 
640
 
 
641
    Bool usingScratchGC = FALSE;
 
642
    WindowPtr pRoot;
 
643
        
 
644
#define FUNCTION        0
 
645
#define FOREGROUND      1
 
646
#define TILE            2
 
647
#define FILLSTYLE       3
 
648
#define ABSX            4
 
649
#define ABSY            5
 
650
#define CLIPMASK        6
 
651
#define SUBWINDOW       7
 
652
#define COUNT_BITS      8
 
653
 
 
654
    ChangeGCVal gcval[7];
 
655
    ChangeGCVal newValues [COUNT_BITS];
 
656
 
 
657
    BITS32 gcmask, index, mask;
 
658
    RegionRec prgnWin;
 
659
    DDXPointRec oldCorner;
 
660
    BoxRec box;
 
661
    WindowPtr   pBgWin;
 
662
    GCPtr pGC;
 
663
    register int i;
 
664
    register BoxPtr pbox;
 
665
    register ScreenPtr pScreen = pWin->drawable.pScreen;
 
666
    register xRectangle *prect;
 
667
    int numRects;
 
668
 
 
669
    gcmask = 0;
 
670
 
 
671
    if (what == PW_BACKGROUND)
 
672
    {
 
673
        switch (pWin->backgroundState) {
 
674
        case None:
 
675
            return;
 
676
        case ParentRelative:
 
677
            (*pWin->parent->drawable.pScreen->PaintWindowBackground)(pWin->parent, prgn, what);
 
678
            return;
 
679
        case BackgroundPixel:
 
680
            newValues[FOREGROUND].val = pWin->background.pixel;
 
681
            newValues[FILLSTYLE].val  = FillSolid;
 
682
            gcmask |= GCForeground | GCFillStyle;
 
683
            break;
 
684
        case BackgroundPixmap:
 
685
            newValues[TILE].ptr = (pointer)pWin->background.pixmap;
 
686
            newValues[FILLSTYLE].val = FillTiled;
 
687
            gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin;
 
688
            break;
 
689
        }
 
690
    }
 
691
    else
 
692
    {
 
693
        if (pWin->borderIsPixel)
 
694
        {
 
695
            newValues[FOREGROUND].val = pWin->border.pixel;
 
696
            newValues[FILLSTYLE].val  = FillSolid;
 
697
            gcmask |= GCForeground | GCFillStyle;
 
698
        }
 
699
        else
 
700
        {
 
701
            newValues[TILE].ptr = (pointer)pWin->border.pixmap;
 
702
            newValues[FILLSTYLE].val = FillTiled;
 
703
            gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin;
 
704
        }
 
705
    }
 
706
 
 
707
    prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn) *
 
708
                                         sizeof(xRectangle));
 
709
    if (!prect)
 
710
        return;
 
711
 
 
712
    newValues[FUNCTION].val = GXcopy;
 
713
    gcmask |= GCFunction | GCClipMask;
 
714
 
 
715
    i = pScreen->myNum;
 
716
    pRoot = WindowTable[i];
 
717
 
 
718
    pBgWin = pWin;
 
719
    if (what == PW_BORDER)
 
720
    {
 
721
        while (pBgWin->backgroundState == ParentRelative)
 
722
            pBgWin = pBgWin->parent;
 
723
    }
 
724
 
 
725
    if ((pWin->drawable.depth != pRoot->drawable.depth) ||
 
726
        (pWin->drawable.bitsPerPixel != pRoot->drawable.bitsPerPixel))
 
727
    {
 
728
        usingScratchGC = TRUE;
 
729
        pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen);
 
730
        if (!pGC)
 
731
        {
 
732
            DEALLOCATE_LOCAL(prect);
 
733
            return;
 
734
        }
 
735
        /*
 
736
         * mash the clip list so we can paint the border by
 
737
         * mangling the window in place, pretending it
 
738
         * spans the entire screen
 
739
         */
 
740
        if (what == PW_BORDER)
 
741
        {
 
742
            prgnWin = pWin->clipList;
 
743
            oldCorner.x = pWin->drawable.x;
 
744
            oldCorner.y = pWin->drawable.y;
 
745
            pWin->drawable.x = pWin->drawable.y = 0;
 
746
            box.x1 = 0;
 
747
            box.y1 = 0;
 
748
            box.x2 = pScreen->width;
 
749
            box.y2 = pScreen->height;
 
750
            REGION_INIT(pScreen, &pWin->clipList, &box, 1);
 
751
            pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
 
752
            newValues[ABSX].val = pBgWin->drawable.x;
 
753
            newValues[ABSY].val = pBgWin->drawable.y;
 
754
        }
 
755
        else
 
756
        {
 
757
            newValues[ABSX].val = 0;
 
758
            newValues[ABSY].val = 0;
 
759
        }
 
760
    } else {
 
761
        /*
 
762
         * draw the background to the root window
 
763
         */
 
764
        if (screenContext[i] == (GCPtr)NULL)
 
765
        {
 
766
            if (!ResType && !(ResType = CreateNewResourceType(tossGC)))
 
767
                return;
 
768
            screenContext[i] = CreateGC((DrawablePtr)pWin, (BITS32) 0,
 
769
                                        (XID *)NULL, &status);
 
770
            if (!screenContext[i])
 
771
                return;
 
772
            numGCs++;
 
773
            if (!AddResource(FakeClientID(0), ResType,
 
774
                             (pointer)screenContext[i]))
 
775
                return;
 
776
        }
 
777
        pGC = screenContext[i];
 
778
        newValues[SUBWINDOW].val = IncludeInferiors;
 
779
        newValues[ABSX].val = pBgWin->drawable.x;
 
780
        newValues[ABSY].val = pBgWin->drawable.y;
 
781
        gcmask |= GCSubwindowMode;
 
782
        pWin = pRoot;
 
783
    }
 
784
    
 
785
    if (pWin->backStorage)
 
786
        (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack);
 
787
 
 
788
    mask = gcmask;
 
789
    gcmask = 0;
 
790
    i = 0;
 
791
    while (mask) {
 
792
        index = lowbit (mask);
 
793
        mask &= ~index;
 
794
        switch (index) {
 
795
        case GCFunction:
 
796
            if (pGC->alu != newValues[FUNCTION].val) {
 
797
                gcmask |= index;
 
798
                gcval[i++].val = newValues[FUNCTION].val;
 
799
            }
 
800
            break;
 
801
        case GCTileStipXOrigin:
 
802
            if ( pGC->patOrg.x != newValues[ABSX].val) {
 
803
                gcmask |= index;
 
804
                gcval[i++].val = newValues[ABSX].val;
 
805
            }
 
806
            break;
 
807
        case GCTileStipYOrigin:
 
808
            if ( pGC->patOrg.y != newValues[ABSY].val) {
 
809
                gcmask |= index;
 
810
                gcval[i++].val = newValues[ABSY].val;
 
811
            }
 
812
            break;
 
813
        case GCClipMask:
 
814
            if ( pGC->clientClipType != CT_NONE) {
 
815
                gcmask |= index;
 
816
                gcval[i++].val = CT_NONE;
 
817
            }
 
818
            break;
 
819
        case GCSubwindowMode:
 
820
            if ( pGC->subWindowMode != newValues[SUBWINDOW].val) {
 
821
                gcmask |= index;
 
822
                gcval[i++].val = newValues[SUBWINDOW].val;
 
823
            }
 
824
            break;
 
825
        case GCTile:
 
826
            if (pGC->tileIsPixel || pGC->tile.pixmap != newValues[TILE].ptr)
 
827
            {
 
828
                gcmask |= index;
 
829
                gcval[i++].ptr = newValues[TILE].ptr;
 
830
            }
 
831
            break;
 
832
        case GCFillStyle:
 
833
            if ( pGC->fillStyle != newValues[FILLSTYLE].val) {
 
834
                gcmask |= index;
 
835
                gcval[i++].val = newValues[FILLSTYLE].val;
 
836
            }
 
837
            break;
 
838
        case GCForeground:
 
839
            if ( pGC->fgPixel != newValues[FOREGROUND].val) {
 
840
                gcmask |= index;
 
841
                gcval[i++].val = newValues[FOREGROUND].val;
 
842
            }
 
843
            break;
 
844
        }
 
845
    }
 
846
 
 
847
    if (gcmask)
 
848
        dixChangeGC(NullClient, pGC, gcmask, NULL, gcval);
 
849
 
 
850
    if (pWin->drawable.serialNumber != pGC->serialNumber)
 
851
        ValidateGC((DrawablePtr)pWin, pGC);
 
852
 
 
853
    numRects = REGION_NUM_RECTS(prgn);
 
854
    pbox = REGION_RECTS(prgn);
 
855
    for (i= numRects; --i >= 0; pbox++, prect++)
 
856
    {
 
857
        prect->x = pbox->x1 - pWin->drawable.x;
 
858
        prect->y = pbox->y1 - pWin->drawable.y;
 
859
        prect->width = pbox->x2 - pbox->x1;
 
860
        prect->height = pbox->y2 - pbox->y1;
 
861
    }
 
862
    prect -= numRects;
 
863
    (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect);
 
864
    DEALLOCATE_LOCAL(prect);
 
865
 
 
866
    if (pWin->backStorage)
 
867
        (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing);
 
868
 
 
869
    if (usingScratchGC)
 
870
    {
 
871
        if (what == PW_BORDER)
 
872
        {
 
873
            REGION_UNINIT(pScreen, &pWin->clipList);
 
874
            pWin->clipList = prgnWin;
 
875
            pWin->drawable.x = oldCorner.x;
 
876
            pWin->drawable.y = oldCorner.y;
 
877
            pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
 
878
        }
 
879
        FreeScratchGC(pGC);
 
880
    }
 
881
}
 
882
 
 
883
 
 
884
/* MICLEARDRAWABLE -- sets the entire drawable to the background color of
 
885
 * the GC.  Useful when we have a scratch drawable and need to initialize 
 
886
 * it. */
 
887
void
 
888
miClearDrawable(pDraw, pGC)
 
889
    DrawablePtr pDraw;
 
890
    GCPtr       pGC;
 
891
{
 
892
    XID fg = pGC->fgPixel;
 
893
    XID bg = pGC->bgPixel;
 
894
    xRectangle rect;
 
895
 
 
896
    rect.x = 0;
 
897
    rect.y = 0;
 
898
    rect.width = pDraw->width;
 
899
    rect.height = pDraw->height;
 
900
    DoChangeGC(pGC, GCForeground, &bg, 0);
 
901
    ValidateGC(pDraw, pGC);
 
902
    (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect);
 
903
    DoChangeGC(pGC, GCForeground, &fg, 0);
 
904
    ValidateGC(pDraw, pGC);
 
905
}