root/foundation-apps/xcomp-mgr-maxx/xcompmgr.c

Revision 10, 53.8 KB (checked in by emasson, 3 years ago)

initial import for the community edition

Line 
1/*
2 * $Id$
3 *
4 * Copyright © 2003 Keith Packard
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission.  Keith Packard makes no
13 * representations about the suitability of this software for any purpose.  It
14 * is provided "as is" without express or implied warranty.
15 *
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 */
24
25
26/* Modified by Matthew Hawn. I don't know what to say here so follow what it
27   says above. Not that I can really do anything about it
28*/
29
30
31#include <stdlib.h>
32#include <stdio.h>
33#include <string.h>
34#include <math.h>
35#include <sys/poll.h>
36#include <sys/time.h>
37#include <time.h>
38#include <unistd.h>
39#include <getopt.h>
40#include <X11/Xlib.h>
41#include <X11/Xutil.h>
42#include <X11/Xatom.h>
43#include <X11/extensions/Xcomposite.h>
44#include <X11/extensions/Xdamage.h>
45#include <X11/extensions/Xrender.h>
46#include <X11/extensions/shape.h>
47
48
49#if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2
50#define HAS_NAME_WINDOW_PIXMAP 1
51#endif
52
53#define CAN_DO_USABLE 0
54
55typedef struct _ignore {
56    struct _ignore      *next;
57    unsigned long       sequence;
58} ignore;
59
60typedef struct _win {
61    struct _win         *next;
62    Window              id;
63#if HAS_NAME_WINDOW_PIXMAP
64    Pixmap              pixmap;
65#endif
66    XWindowAttributes   a;
67#if CAN_DO_USABLE
68    Bool                usable;             /* mapped and all damaged at one point */
69    XRectangle          damage_bounds;      /* bounds of damage */
70#endif
71    int                 mode;
72        int             shaped;
73    int                 damaged;
74    Damage              damage;
75    Picture             picture;
76    Picture             alphaPict;
77    Picture             shadowPict;
78    XserverRegion       borderSize;
79    XserverRegion       extents;
80    Picture             shadow;
81    int                 shadow_dx;
82    int                 shadow_dy;
83    int                 shadow_width;
84    int                 shadow_height;
85    unsigned int        opacity;
86    Atom            windowType;
87    unsigned long       damage_sequence;    /* sequence when damage was created */
88
89    /* for drawing translucent windows */
90    XserverRegion       borderClip;
91    struct _win         *prev_trans;
92} win;
93
94typedef struct _conv {
95    int     size;
96    double  *data;
97} conv;
98
99typedef struct _fade {
100    struct _fade        *next;
101    win                 *w;
102    double              cur;
103    double              finish;
104    double              step;
105    void                (*callback) (Display *dpy, win *w, Bool gone);
106    Display             *dpy;
107    Bool                gone;
108} fade;
109
110static win              *list;
111static fade             *fades;
112static Display          *dpy;
113static int              scr;
114static Window           root;
115static Picture          rootPicture;
116static Picture          rootBuffer;
117static Picture          blackPicture;
118static Picture          transBlackPicture;
119static Picture          rootTile;
120static XserverRegion    allDamage;
121static Bool             clipChanged;
122#if HAS_NAME_WINDOW_PIXMAP
123static Bool             hasNamePixmap;
124#endif
125static int              root_height, root_width;
126static ignore           *ignore_head, **ignore_tail = &ignore_head;
127static int              xfixes_event, xfixes_error;
128static int              damage_event, damage_error;
129static int              composite_event, composite_error;
130static int              render_event, render_error;
131static Bool             synchronize;
132static int              composite_opcode;
133
134/* find these once and be done with it */
135static Atom             opacityAtom;
136static Atom             winTypeAtom;
137static Atom             winDesktopAtom;
138static Atom             winDockAtom;
139static Atom             winToolbarAtom;
140static Atom             winMenuAtom;
141static Atom             winUtilAtom;
142static Atom             winSplashAtom;
143static Atom             winDialogAtom;
144static Atom             winNormalAtom;
145
146/* opacity property name; sometime soon I'll write up an EWMH spec for it */
147#define OPACITY_PROP    "_NET_WM_WINDOW_OPACITY"
148
149#define TRANSLUCENT     0xe0000000
150#define OPAQUE          0xffffffff
151
152static conv             *gaussianMap;
153
154#define WINDOW_SOLID    0
155#define WINDOW_TRANS    1
156#define WINDOW_ARGB             2
157
158#define TRANS_OPACITY   0.60
159
160#define DEBUG_REPAINT   0
161#define DEBUG_EVENTS    0
162#define MONITOR_REPAINT 0
163
164#define SHADOWS                 1
165#define SHARP_SHADOW    0
166
167typedef enum _compMode {
168    CompSimple,         /* looks like a regular X server */
169    CompServerShadows,  /* use window alpha for shadow; sharp, but precise */
170    CompClientShadows,  /* use window extents for shadow, blurred */
171} CompMode;
172
173static void
174determine_mode(Display *dpy, win *w);
175   
176static double
177get_opacity_percent(Display *dpy, win *w, double def);
178
179static XserverRegion
180win_extents (Display *dpy, win *w);
181
182static Bool isShaped (Display *dpy, Window win);
183
184static  CompMode    compMode = CompClientShadows;
185
186static int              shadowRadius = 6;
187static int         shadowOffsetX = -8;
188static int         shadowOffsetY = -6;
189static double      shadowOpacity = .70;
190
191static double  fade_in_step =  0.15;
192static double  fade_out_step = 0.15;
193static int      fade_delta =    10;
194static int      fade_time =     0;
195static Bool     fadeWindows = False;
196static Bool    excludeDockShadows = True;
197static Bool     fadeTrans = False;
198
199static Bool             autoRedirect = False;
200
201/* For shadow precomputation */
202static int              Gsize = -1;
203static unsigned char    *shadowCorner = NULL;
204static unsigned char    *shadowTop = NULL;
205
206static int
207get_time_in_milliseconds (void)
208{
209    struct timeval  tv;
210
211    gettimeofday (&tv, NULL);
212    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
213}
214
215static fade *
216find_fade (win *w)
217{
218    fade    *f;
219   
220    for (f = fades; f; f = f->next)
221    {
222                if (f->w == w)
223                        return f;
224    }
225    return NULL;
226}
227
228static void
229dequeue_fade (Display *dpy, fade *f)
230{
231    fade    **prev;
232
233    for (prev = &fades; *prev; prev = &(*prev)->next)
234        if (*prev == f)
235        {
236            *prev = f->next;
237            if (f->callback)
238                        (*f->callback) (dpy, f->w, f->gone);
239           
240                free (f);
241            break;
242        }
243}
244
245static void
246cleanup_fade (Display *dpy, win *w)
247{
248    fade *f = find_fade (w);
249    if (f)
250                dequeue_fade (dpy, f);
251}
252
253static void
254enqueue_fade (Display *dpy, fade *f)
255{
256    if (!fades)
257                fade_time = get_time_in_milliseconds () + fade_delta;
258    f->next = fades;
259    fades = f;
260}
261
262static void
263set_fade (Display *dpy, win *w, double start, double finish, double step,
264          void (*callback) (Display *dpy, win *w, Bool gone),
265          Bool gone, Bool exec_callback, Bool override)
266{
267    fade    *f;
268
269    f = find_fade (w);
270    if (!f)
271    {
272                f = malloc (sizeof (fade));
273                f->next = NULL;
274                f->w = w;
275                f->cur = start;
276                enqueue_fade (dpy, f);
277    }
278    else if(!override)
279                return;
280    else
281    {
282        if (exec_callback)
283            if (f->callback)
284                (*f->callback)(dpy, f->w, f->gone);
285    }
286
287    if (finish < 0)
288                finish = 0;
289               
290    if (finish > 1)
291                finish = 1;
292               
293    f->finish = finish;
294       
295    if (f->cur < finish)
296        f->step = step;
297    else if 
298                (f->cur > finish)
299               
300        f->step = -step;
301    f->callback = callback;
302    f->gone = gone;
303    w->opacity = f->cur * OPAQUE;
304#if 0
305    printf ("set_fade start %g step %g\n", f->cur, f->step);
306#endif
307    determine_mode (dpy, w);
308    if (w->shadow)
309    {
310                XRenderFreePicture (dpy, w->shadow);
311                w->shadow = None;
312                w->extents = win_extents (dpy, w);
313    }
314}
315
316static int
317fade_timeout (void)
318{
319    int now;
320    int delta;
321   
322        if (!fades)
323                return -1;
324   
325        now = get_time_in_milliseconds();
326    delta = fade_time - now;
327   
328        if (delta < 0)
329        delta = 0;
330       
331/*    printf ("timeout %d\n", delta); */
332    return delta;
333}
334
335static void
336run_fades (Display *dpy)
337{
338    int     now = get_time_in_milliseconds();
339    fade    *next = fades;
340    int     steps;
341    Bool    need_dequeue;
342
343#if 0
344    printf ("run fades\n");
345#endif
346    if (fade_time - now > 0)
347        return;
348    steps = 1 + (now - fade_time) / fade_delta;
349
350    while (next)
351    {
352                fade *f = next;
353                win *w = f->w;
354                next = f->next;
355                f->cur += f->step * steps;
356        if (f->cur >= 1)
357                f->cur = 1;
358                else if (f->cur < 0)
359                f->cur = 0;
360#if 0
361        printf ("opacity now %g\n", f->cur);
362#endif
363        w->opacity = f->cur * OPAQUE;
364        need_dequeue = False;
365                if (f->step > 0)
366                {
367                if (f->cur >= f->finish)
368                {
369                                w->opacity = f->finish*OPAQUE;
370                need_dequeue = True;
371                }
372                }
373                else
374                {
375                if (f->cur <= f->finish)
376                {
377                                w->opacity = f->finish*OPAQUE;
378                need_dequeue = True;
379                }
380                }
381                determine_mode (dpy, w);
382                if (w->shadow)
383                {
384                XRenderFreePicture (dpy, w->shadow);
385                w->shadow = None;
386                w->extents = win_extents(dpy, w);
387                }
388        /* Must do this last as it might destroy f->w in callbacks */
389        if (need_dequeue)
390                dequeue_fade (dpy, f);
391    }
392    fade_time = now + fade_delta;
393}
394
395static double
396gaussian (double r, double x, double y)
397{
398    return ((1 / (sqrt (2 * M_PI * r))) *
399            exp ((- (x * x + y * y)) / (2 * r * r)));
400}
401
402
403static conv *
404make_gaussian_map (Display *dpy, double r)
405{
406    conv            *c;
407    int             size = ((int) ceil ((r * 3)) + 1) & ~1;
408    int             center = size / 2;
409    int             x, y;
410    double          t;
411    double          g;
412   
413    c = malloc (sizeof (conv) + size * size * sizeof (double));
414    c->size = size;
415    c->data = (double *) (c + 1);
416    t = 0.0;
417    for (y = 0; y < size; y++)
418                for (x = 0; x < size; x++)
419                {
420                g = gaussian (r, (double) (x - center), (double) (y - center));
421                t += g;
422                c->data[y * size + x] = g;
423                }
424/*    printf ("gaussian total %f\n", t); */
425    for (y = 0; y < size; y++)
426                for (x = 0; x < size; x++)
427                {
428                c->data[y*size + x] /= t;
429                }
430    return c;
431}
432
433/*
434 * A picture will help
435 *
436 *      -center   0                width  width+center
437 *  -center +-----+-------------------+-----+
438 *              |     |                   |     |
439 *              |     |                   |     |
440 *        0 +-----+-------------------+-----+
441         *          |     |                   |     |
442         *          |     |                   |     |
443         *          |     |                   |     |
444 *   height +-----+-------------------+-----+
445        *           |     |                   |     |
446 * height+  |     |                   |     |
447 *  center  +-----+-------------------+-----+
448 */
449 
450static unsigned char
451sum_gaussian (conv *map, double opacity, int x, int y, int width, int height)
452{
453    int     fx, fy;
454    double  *g_data;
455    double  *g_line = map->data;
456    int     g_size = map->size;
457    int     center = g_size / 2;
458    int     fx_start, fx_end;
459    int     fy_start, fy_end;
460    double  v;
461   
462    /*
463     * Compute set of filter values which are "in range",
464     * that's the set with:
465     *  0 <= x + (fx-center) && x + (fx-center) < width &&
466     *  0 <= y + (fy-center) && y + (fy-center) < height
467     *
468     *  0 <= x + (fx - center)  x + fx - center < width
469     *  center - x <= fx        fx < width + center - x
470     */
471
472    fx_start = center - x;
473       
474    if (fx_start < 0)
475                fx_start = 0;
476               
477    fx_end = width + center - x;
478   
479        if (fx_end > g_size)
480                fx_end = g_size;
481
482    fy_start = center - y;
483       
484    if (fy_start < 0)
485                fy_start = 0;
486       
487    fy_end = height + center - y;
488       
489    if (fy_end > g_size)
490                fy_end = g_size;
491
492    g_line = g_line + fy_start * g_size + fx_start;
493   
494    v = 0;
495    for (fy = fy_start; fy < fy_end; fy++)
496    {
497                g_data = g_line;
498                g_line += g_size;
499
500       
501                for (fx = fx_start; fx < fx_end; fx++)
502                v += *g_data++;
503    }
504    if (v > 1)
505                v = 1;
506   
507    return ((unsigned char) (v * opacity * 255.0));
508}
509
510/* precompute shadow corners and sides to save time for large windows */
511static void
512presum_gaussian (conv *map)
513{
514    int center = map->size/2;
515    int opacity, x, y;
516
517    Gsize = map->size;
518
519    if (shadowCorner)
520                free ((void *)shadowCorner);
521    if (shadowTop)
522                free ((void *)shadowTop);
523
524    shadowCorner = (unsigned char *)(malloc ((Gsize + 1) * (Gsize + 1) * 26));
525    shadowTop = (unsigned char *)(malloc ((Gsize + 1) * 26));
526   
527    for (x = 0; x <= Gsize; x++)
528    {
529                shadowTop[25 * (Gsize + 1) + x] = sum_gaussian (map, 1, x - center, center, Gsize * 2, Gsize * 2);
530
531                for(opacity = 0; opacity < 25; opacity++)
532                shadowTop[opacity * (Gsize + 1) + x] = shadowTop[25 * (Gsize + 1) + x] * opacity / 25;
533
534                for(y = 0; y <= x; y++)
535                {
536                shadowCorner[25 * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x]
537                                = sum_gaussian (map, 1, x - center, y - center, Gsize * 2, Gsize * 2);
538                               
539                shadowCorner[25 * (Gsize + 1) * (Gsize + 1) + x * (Gsize + 1) + y]
540                                = shadowCorner[25 * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x];
541                               
542                for(opacity = 0; opacity < 25; opacity++)
543                                shadowCorner[opacity * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x]
544                                = shadowCorner[opacity * (Gsize + 1) * (Gsize + 1) + x * (Gsize + 1) + y]
545                                = shadowCorner[25 * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x] * opacity / 25;
546                }
547    }
548}
549
550static XImage *
551make_shadow (Display *dpy, double opacity, int width, int height)
552{
553    XImage          *ximage;
554    unsigned char   *data;
555    int             gsize = gaussianMap->size;
556    int             ylimit, xlimit;
557    int             swidth = width + gsize;
558    int             sheight = height + gsize;
559    int             center = gsize / 2;
560    int             x, y;
561    unsigned char   d;
562    int             x_diff;
563    int             opacity_int = (int)(opacity * 25);
564    data = malloc (swidth * sheight * sizeof (unsigned char));
565   
566    if (!data)
567        return NULL;
568    ximage = XCreateImage (dpy,
569                           DefaultVisual(dpy, DefaultScreen(dpy)),
570                           8,
571                           ZPixmap,
572                           0,
573                           (char *) data,
574                           swidth, sheight, 8, swidth * sizeof (unsigned char));
575    if (!ximage)
576    {
577                free (data);
578                return NULL;
579    }
580    /*
581     * Build the gaussian in sections
582     */
583
584    /*
585     * center (fill the complete data array)
586     */
587    if (Gsize > 0)
588                d = shadowTop[opacity_int * (Gsize + 1) + Gsize];
589    else
590                d = sum_gaussian (gaussianMap, opacity, center, center, width, height);
591               
592    memset(data, d, sheight * swidth);
593   
594    /*
595     * corners
596     */
597    ylimit = gsize;
598    if (ylimit > sheight / 2)
599                ylimit = (sheight + 1) / 2;
600               
601    xlimit = gsize;
602       
603    if (xlimit > swidth / 2)
604                xlimit = (swidth + 1) / 2;
605
606    for (y = 0; y < ylimit; y++)
607                for (x = 0; x < xlimit; x++)
608                {
609                if (xlimit == Gsize && ylimit == Gsize)
610                                d = shadowCorner[opacity_int * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x];
611                else
612                                d = sum_gaussian (gaussianMap, opacity, x - center, y - center, width, height);
613                               
614                data[y * swidth + x] = d;
615                data[(sheight - y - 1) * swidth + x] = d;
616                data[(sheight - y - 1) * swidth + (swidth - x - 1)] = d;
617                data[y * swidth + (swidth - x - 1)] = d;
618                }
619
620    /*
621     * top/bottom
622     */
623    x_diff = swidth - (gsize * 2);
624    if (x_diff > 0 && ylimit > 0)
625    {
626                for (y = 0; y < ylimit; y++)
627                {
628                if (ylimit == Gsize)
629                                d = shadowTop[opacity_int * (Gsize + 1) + y];
630                else
631                                d = sum_gaussian (gaussianMap, opacity, center, y - center, width, height);
632                memset (&data[y * swidth + gsize], d, x_diff);
633                       
634                memset (&data[(sheight - y - 1) * swidth + gsize], d, x_diff);
635                }
636    }
637
638    /*
639     * sides
640     */
641   
642    for (x = 0; x < xlimit; x++)
643    {
644                if (xlimit == Gsize)
645                d = shadowTop[opacity_int * (Gsize + 1) + x];
646                else
647                d = sum_gaussian (gaussianMap, opacity, x - center, center, width, height);
648                       
649                for (y = gsize; y < sheight - gsize; y++)
650                {
651                data[y * swidth + x] = d;
652                data[y * swidth + (swidth - x - 1)] = d;
653                }
654    }
655
656    return ximage;
657}
658
659static Picture
660shadow_picture (Display *dpy, double opacity, Picture alpha_pict, int width, int height, int *wp, int *hp)
661{
662    XImage  *shadowImage;
663    Pixmap  shadowPixmap;
664    Picture shadowPicture;
665    GC      gc;
666   
667    shadowImage = make_shadow (dpy, opacity, width, height);
668       
669    if (!shadowImage)
670                return None;
671               
672    shadowPixmap = XCreatePixmap (dpy, root,
673                                  shadowImage->width,
674                                  shadowImage->height,
675                                  8);
676    if (!shadowPixmap)
677    {
678                XDestroyImage (shadowImage);
679                return None;
680    }
681
682    shadowPicture = XRenderCreatePicture (dpy, shadowPixmap,
683                                          XRenderFindStandardFormat (dpy, PictStandardA8),
684                                          0, NULL);
685    if (!shadowPicture)
686    {
687                XDestroyImage (shadowImage);
688                XFreePixmap (dpy, shadowPixmap);
689                return (Picture)None;
690    }
691
692    gc = XCreateGC (dpy, shadowPixmap, 0, NULL);
693    if (!gc)
694    {
695                XDestroyImage (shadowImage);
696                XFreePixmap (dpy, shadowPixmap);
697                XRenderFreePicture (dpy, shadowPicture);
698                return (Picture)None;
699    }
700   
701    XPutImage (dpy, shadowPixmap, gc, shadowImage, 0, 0, 0, 0,
702               shadowImage->width,
703               shadowImage->height);
704    *wp = shadowImage->width;
705    *hp = shadowImage->height;
706    XFreeGC (dpy, gc);
707    XDestroyImage (shadowImage);
708    XFreePixmap (dpy, shadowPixmap);
709   
710        return shadowPicture;
711}
712
713static Picture
714solid_picture (Display *dpy, Bool argb, double a, double r, double g, double b)
715{
716    Pixmap                      pixmap;
717    Picture                     picture;
718    XRenderPictureAttributes    pa;
719    XRenderColor                c;
720
721    pixmap = XCreatePixmap (dpy, root, 1, 1, argb ? 32 : 8);
722    if (!pixmap)
723                return None;
724
725    pa.repeat = True;
726    picture = XRenderCreatePicture (dpy, pixmap,
727                                    XRenderFindStandardFormat (dpy, argb ? PictStandardARGB32 : PictStandardA8),
728                                    CPRepeat,
729                                    &pa);
730    if (!picture)
731    {
732                XFreePixmap (dpy, pixmap);
733                return None;
734    }
735
736    c.alpha = a * 0xaaaaa;
737    c.red = r * 0xffff;
738    c.green = g * 0xffff;
739    c.blue = b * 0xffff;
740    XRenderFillRectangle (dpy, PictOpSrc, picture, &c, 0, 0, 1, 1);
741    XFreePixmap (dpy, pixmap);
742   
743        return picture;
744}
745
746static void
747discard_ignore (Display *dpy, unsigned long sequence)
748{
749    while (ignore_head)
750    {
751                if ((long) (sequence - ignore_head->sequence) > 0)
752                {
753                ignore  *next = ignore_head->next;
754                free (ignore_head);
755                ignore_head = next;
756                if (!ignore_head)
757                        ignore_tail = &ignore_head;
758                }
759                else
760                break;
761    }
762}
763
764static void
765set_ignore (Display *dpy, unsigned long sequence)
766{
767    ignore  *i = malloc (sizeof (ignore));
768   
769    if (!i)
770                return;
771   
772        i->sequence = sequence;
773    i->next = NULL;
774    *ignore_tail = i;
775    ignore_tail = &i->next;
776}
777
778static int
779should_ignore (Display *dpy, unsigned long sequence)
780{
781    discard_ignore (dpy, sequence);
782    return ignore_head && ignore_head->sequence == sequence;
783}
784
785static win *
786find_win (Display *dpy, Window id)
787{
788    win *w;
789
790    for (w = list; w; w = w->next)
791                if (w->id == id)
792                return w;
793   
794        return NULL;
795}
796
797static const char *backgroundProps[] = {
798    "_XROOTPMAP_ID",
799    "_XSETROOT_ID",
800    NULL,
801};
802   
803static Picture
804root_tile (Display *dpy)
805{
806    Picture         picture;
807    Atom            actual_type;
808    Pixmap          pixmap;
809    int             actual_format;
810    unsigned long   nitems;
811    unsigned long   bytes_after;
812    unsigned char   *prop;
813    Bool            fill;
814    XRenderPictureAttributes    pa;
815    int             p;
816
817    pixmap = None;
818    for (p = 0; backgroundProps[p]; p++)
819    {
820                if (XGetWindowProperty (dpy, root, XInternAtom (dpy, backgroundProps[p], False),
821                                        0, 4, False, AnyPropertyType,
822                                        &actual_type, &actual_format, &nitems, &bytes_after, &prop) == Success &&
823                actual_type == XInternAtom (dpy, "PIXMAP", False) && actual_format == 32 && nitems == 1)
824                {
825                memcpy (&pixmap, prop, 4);
826                XFree (prop);
827                fill = False;
828                break;
829                }
830    }
831   
832        if (!pixmap)
833    {
834                pixmap = XCreatePixmap (dpy, root, 1, 1, DefaultDepth (dpy, scr));
835                fill = True;
836    }
837    pa.repeat = True;
838    picture = XRenderCreatePicture (dpy, pixmap,
839                                    XRenderFindVisualFormat (dpy,
840                                                             DefaultVisual (dpy, scr)),
841                                    CPRepeat, &pa);
842    if (fill)
843    {
844                XRenderColor    c;
845       
846                c.red = c.green = c.blue = 0x8080;
847                c.alpha = 0xffff;
848                XRenderFillRectangle (dpy, PictOpSrc, picture, &c,
849                              0, 0, 1, 1);
850    }
851    return picture;
852}
853
854static void
855paint_root (Display *dpy)
856{
857    if (!rootTile)
858        rootTile = root_tile (dpy);
859   
860    XRenderComposite (dpy, PictOpSrc,
861                      rootTile, None, rootBuffer,
862                      0, 0, 0, 0, 0, 0, root_width, root_height);
863}
864
865static XserverRegion
866win_extents (Display *dpy, win *w)
867{
868    XRectangle r;
869                 
870    r.x = w->a.x;
871    r.y = w->a.y;
872    r.width = w->a.width + w->a.border_width * 2;
873    r.height = w->a.height + w->a.border_width * 2;
874
875    if(w->shaped)
876        return XFixesCreateRegion (dpy, &r, 1);
877       
878   if (w->windowType == winDockAtom && excludeDockShadows)
879        return XFixesCreateRegion (dpy, &r, 1);
880
881//    if (compMode != CompSimple && !(w->windowType == winDockAtom && excludeDockShadows))             
882    if (compMode != CompSimple )
883    {
884          if (compMode == CompServerShadows || w->mode != WINDOW_ARGB)
885          {
886            XRectangle  sr;
887
888            if (compMode == CompServerShadows)
889            {
890                        w->shadow_dx = 2;
891                        w->shadow_dy = 7;
892                        w->shadow_width = w->a.width;
893                        w->shadow_height = w->a.height;
894            }
895            else
896            {
897                        w->shadow_dx = shadowOffsetX;
898                        w->shadow_dy = shadowOffsetY;
899                        if (!w->shadow)
900                        {
901                        double  opacity = shadowOpacity;
902                        if (w->mode == WINDOW_TRANS)
903                                        opacity = opacity * ((double)w->opacity)/((double)OPAQUE);
904                                w->shadow = shadow_picture (dpy, opacity, w->alphaPict,
905                                                        w->a.width + w->a.border_width * 2,
906                                                        w->a.height + w->a.border_width * 2,
907                                                        &w->shadow_width, &w->shadow_height);
908                        }
909            }
910               
911            sr.x = w->a.x + w->shadow_dx;
912            sr.y = w->a.y + w->shadow_dy;
913            sr.width = w->shadow_width;
914            sr.height = w->shadow_height;
915               
916            if (sr.x < r.x)
917            {
918                        r.width = (r.x + r.width) - sr.x;
919                        r.x = sr.x;
920            }
921            if (sr.y < r.y)
922            {
923                        r.height = (r.y + r.height) - sr.y;
924                        r.y = sr.y;
925            }
926            if (sr.x + sr.width > r.x + r.width)
927                        r.width = sr.x + sr.width - r.x;
928            if (sr.y + sr.height > r.y + r.height)
929                        r.height = sr.y + sr.height - r.y;
930          }
931    }
932    return XFixesCreateRegion (dpy, &r, 1);
933}
934
935static XserverRegion
936border_size (Display *dpy, win *w)
937{
938    XserverRegion   border;
939    /*
940     * if window doesn't exist anymore,  this will generate an error
941     * as well as not generate a region.  Perhaps a better XFixes
942     * architecture would be to have a request that copies instead
943     * of creates, that way you'd just end up with an empty region
944     * instead of an invalid XID.
945     */
946         
947    set_ignore (dpy, NextRequest (dpy));
948    border = XFixesCreateRegionFromWindow (dpy, w->id, WindowRegionBounding);
949 
950    /* translate this */
951    set_ignore (dpy, NextRequest (dpy));
952 
953    XFixesTranslateRegion (dpy, border,
954                           w->a.x + w->a.border_width,
955                           w->a.y + w->a.border_width);
956    return border;
957}
958
959static void
960paint_all (Display *dpy, XserverRegion region)
961{
962    win *w;
963    win *t = NULL;
964   
965    if (!region)
966    {
967                XRectangle  r;
968                r.x = 0;
969                r.y = 0;
970                r.width = root_width;
971                r.height = root_height;
972                region = XFixesCreateRegion (dpy, &r, 1);
973    }
974#if MONITOR_REPAINT
975    rootBuffer = rootPicture;
976#else
977    if (!rootBuffer)
978    {
979                Pixmap  rootPixmap = XCreatePixmap (dpy, root, root_width, root_height,
980                                                DefaultDepth (dpy, scr));
981                rootBuffer = XRenderCreatePicture (dpy, rootPixmap,
982                                                   XRenderFindVisualFormat (dpy,
983                                                                        DefaultVisual (dpy, scr)),
984                                                   0, NULL);
985                XFreePixmap (dpy, rootPixmap);
986    }
987#endif
988    XFixesSetPictureClipRegion (dpy, rootPicture, 0, 0, region);
989#if MONITOR_REPAINT
990    XRenderComposite (dpy, PictOpSrc, blackPicture, None, rootPicture,
991                      0, 0, 0, 0, 0, 0, root_width, root_height);
992#endif
993#if DEBUG_REPAINT
994    printf ("paint:");
995#endif
996    for (w = list; w; w = w->next)
997    {
998#if CAN_DO_USABLE
999        if (!w->usable)
1000            continue;
1001#endif
1002        /* never painted, ignore it */
1003        if (!w->damaged)
1004            continue;
1005        /* if invisible, ignore it */
1006        if (w->a.x + w->a.width < 1 || w->a.y + w->a.height < 1
1007            || w->a.x >= root_width || w->a.y >= root_height)
1008            continue;
1009        if (!w->picture)
1010        {
1011            XRenderPictureAttributes    pa;
1012            XRenderPictFormat           *format;
1013            Drawable                    draw = w->id;
1014           
1015#if HAS_NAME_WINDOW_PIXMAP
1016            if (hasNamePixmap && !w->pixmap)
1017                        w->pixmap = XCompositeNameWindowPixmap (dpy, w->id);
1018           
1019                if (w->pixmap)
1020                        draw = w->pixmap;
1021#endif
1022            format = XRenderFindVisualFormat (dpy, w->a.visual);
1023            pa.subwindow_mode = IncludeInferiors;
1024            w->picture = XRenderCreatePicture (dpy, draw,
1025                                               format,
1026                                               CPSubwindowMode,
1027                                               &pa);
1028        }
1029#if DEBUG_REPAINT
1030        printf (" 0x%x", w->id);
1031#endif
1032        if (clipChanged)
1033        {
1034            if (w->borderSize)
1035            {
1036                        set_ignore (dpy, NextRequest (dpy));
1037                        XFixesDestroyRegion (dpy, w->borderSize);
1038                        w->borderSize = None;
1039            }
1040            if (w->extents)
1041            {
1042                        XFixesDestroyRegion (dpy, w->extents);
1043                        w->extents = None;
1044            }
1045            if (w->borderClip)
1046            {
1047                        XFixesDestroyRegion (dpy, w->borderClip);
1048                        w->borderClip = None;
1049            }
1050        }
1051        if (!w->borderSize)
1052            w->borderSize = border_size (dpy, w);
1053        if (!w->extents)
1054            w->extents = win_extents (dpy, w);
1055        if (w->mode == WINDOW_SOLID)
1056        {
1057            int x, y, wid, hei;
1058#if HAS_NAME_WINDOW_PIXMAP
1059            x = w->a.x;
1060            y = w->a.y;
1061            wid = w->a.width + w->a.border_width * 2;
1062            hei = w->a.height + w->a.border_width * 2;
1063#else
1064            x = w->a.x + w->a.border_width;
1065            y = w->a.y + w->a.border_width;
1066            wid = w->a.width;
1067            hei = w->a.height;
1068#endif
1069            XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, region);
1070            set_ignore (dpy, NextRequest (dpy));
1071            XFixesSubtractRegion (dpy, region, region, w->borderSize);
1072            set_ignore (dpy, NextRequest (dpy));
1073            XRenderComposite (dpy, PictOpSrc, w->picture, None, rootBuffer,
1074                              0, 0, 0, 0,
1075                              x, y, wid, hei);
1076        }
1077        if (!w->borderClip)
1078        {
1079            w->borderClip = XFixesCreateRegion (dpy, NULL, 0);
1080            XFixesCopyRegion (dpy, w->borderClip, region);
1081        }
1082        w->prev_trans = t;
1083        t = w;
1084    }
1085#if DEBUG_REPAINT
1086    printf ("\n");
1087    fflush (stdout);
1088#endif
1089    XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, region);
1090    paint_root (dpy);
1091    for (w = t; w; w = w->prev_trans)
1092    {
1093        XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, w->borderClip);
1094        switch (compMode) {
1095        case CompSimple:
1096            break;
1097        case CompServerShadows:
1098            /* dont' bother drawing shadows on desktop windows */
1099            if (w->windowType == winDesktopAtom)
1100                break;
1101            set_ignore (dpy, NextRequest (dpy));
1102            if (w->opacity != OPAQUE && !w->shadowPict)
1103                w->shadowPict = solid_picture (dpy, True,
1104                                               (double) w->opacity / OPAQUE * 0.3,
1105                                               0, 0, 0);
1106            XRenderComposite (dpy, PictOpOver,
1107                              w->shadowPict ? w->shadowPict : transBlackPicture,
1108                              w->picture, rootBuffer,
1109                              0, 0, 0, 0,
1110                              w->a.x + w->shadow_dx,
1111                              w->a.y + w->shadow_dy,
1112                              w->shadow_width, w->shadow_height);
1113            break;
1114        case CompClientShadows:
1115            /* don't bother drawing shadows on desktop windows */
1116            if (w->shadow && w->windowType != winDesktopAtom)
1117            {
1118                XRenderComposite (dpy, PictOpOver, blackPicture, w->shadow, rootBuffer,
1119                                  0, 0, 0, 0,
1120                                  w->a.x + w->shadow_dx,
1121                                  w->a.y + w->shadow_dy,
1122                                  w->shadow_width, w->shadow_height);
1123            }
1124            break;
1125        }
1126        if (w->opacity != OPAQUE && !w->alphaPict)
1127            w->alphaPict = solid_picture (dpy, False,
1128                                          (double) w->opacity / OPAQUE, 0, 0, 0);
1129        if (w->mode == WINDOW_TRANS)
1130        {
1131            int x, y, wid, hei;
1132#if HAS_NAME_WINDOW_PIXMAP
1133            x = w->a.x;
1134            y = w->a.y;
1135            wid = w->a.width + w->a.border_width * 2;
1136            hei = w->a.height + w->a.border_width * 2;
1137#else
1138            x = w->a.x + w->a.border_width;
1139            y = w->a.y + w->a.border_width;
1140            wid = w->a.width;
1141            hei = w->a.height;
1142#endif
1143            set_ignore (dpy, NextRequest (dpy));
1144            XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer,
1145                              0, 0, 0, 0,
1146                              x, y, wid, hei);
1147        }
1148        else if (w->mode == WINDOW_ARGB)
1149        {
1150            int x, y, wid, hei;
1151#if HAS_NAME_WINDOW_PIXMAP
1152            x = w->a.x;
1153            y = w->a.y;
1154            wid = w->a.width + w->a.border_width * 2;
1155            hei = w->a.height + w->a.border_width * 2;
1156#else
1157            x = w->a.x + w->a.border_width;
1158            y = w->a.y + w->a.border_width;
1159            wid = w->a.width;
1160            hei = w->a.height;
1161#endif
1162            set_ignore (dpy, NextRequest (dpy));
1163            XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer,
1164                              0, 0, 0, 0,
1165                              x, y, wid, hei);
1166        }
1167        XFixesDestroyRegion (dpy, w->borderClip);
1168        w->borderClip = None;
1169    }
1170   
1171        XFixesDestroyRegion (dpy, region);
1172    if (rootBuffer != rootPicture)
1173    {
1174                XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, None);
1175                XRenderComposite (dpy, PictOpSrc, rootBuffer, None, rootPicture,
1176                          0, 0, 0, 0, 0, 0, root_width, root_height);
1177    }
1178}
1179
1180static void
1181add_damage (Display *dpy, XserverRegion damage)
1182{
1183    if (allDamage)
1184    {
1185                XFixesUnionRegion (dpy, allDamage, allDamage, damage);
1186                XFixesDestroyRegion (dpy, damage);
1187    }
1188    else
1189                allDamage = damage;
1190}
1191
1192static void
1193repair_win (Display *dpy, win *w)
1194{
1195    XserverRegion   parts;
1196
1197
1198       
1199    if (!w->damaged)
1200    {
1201                parts = win_extents (dpy, w);
1202                set_ignore (dpy, NextRequest (dpy));
1203                XDamageSubtract (dpy, w->damage, None, None);
1204    }
1205    else
1206    {
1207                XserverRegion   o;
1208                parts = XFixesCreateRegion (dpy, NULL, 0);
1209                set_ignore (dpy, NextRequest (dpy));
1210                XDamageSubtract (dpy, w->damage, None, parts);
1211                XFixesTranslateRegion (dpy, parts,
1212                               w->a.x + w->a.border_width,
1213                               w->a.y + w->a.border_width);
1214                                   
1215                if (compMode == CompServerShadows)
1216                {
1217                o = XFixesCreateRegion (dpy, NULL, 0);
1218                XFixesCopyRegion (dpy, o, parts);
1219                XFixesTranslateRegion (dpy, o, w->shadow_dx, w->shadow_dy);
1220                XFixesUnionRegion (dpy, parts, parts, o);
1221                XFixesDestroyRegion (dpy, o);
1222                }
1223    }
1224    add_damage (dpy, parts);
1225    w->damaged = 1;
1226}
1227
1228static unsigned int
1229get_opacity_prop (Display *dpy, win *w, unsigned int def);
1230
1231static void
1232map_win (Display *dpy, Window id, unsigned long sequence, Bool fade)
1233{
1234    win         *w = find_win (dpy, id);
1235
1236    if (!w)
1237        return;
1238
1239    w->a.map_state = IsViewable;
1240   
1241    /* This needs to be here or else we lose transparency messages */
1242    XSelectInput (dpy, id, PropertyChangeMask);
1243
1244    /* This needs to be here since we don't get PropertyNotify when unmapped */
1245    w->opacity = get_opacity_prop (dpy, w, OPAQUE);
1246
1247    determine_mode (dpy, w);
1248
1249#if CAN_DO_USABLE
1250    w->damage_bounds.x = w->damage_bounds.y = 0;
1251    w->damage_bounds.width = w->damage_bounds.height = 0;
1252#endif
1253    w->damaged = 0;
1254
1255    if (fade && fadeWindows)
1256                set_fade (dpy, w, 0, get_opacity_percent (dpy, w, 1.0), fade_in_step, NULL, False, True, True);
1257}
1258
1259static void
1260finish_unmap_win (Display *dpy, win *w)
1261{
1262    w->damaged = 0;
1263#if CAN_DO_USABLE
1264    w->usable = False;
1265#endif
1266    if (w->extents != None)
1267    {
1268        add_damage (dpy, w->extents);    /* destroys region */
1269        w->extents = None;
1270    }
1271   
1272#if HAS_NAME_WINDOW_PIXMAP
1273    if (w->pixmap)
1274    {
1275        XFreePixmap (dpy, w->pixmap);
1276        w->pixmap = None;
1277    }
1278#endif
1279
1280    if (w->picture)
1281    {
1282        set_ignore (dpy, NextRequest (dpy));
1283        XRenderFreePicture (dpy, w->picture);
1284        w->picture = None;
1285    }
1286
1287    /* don't care about properties anymore */
1288    set_ignore (dpy, NextRequest (dpy));
1289    XSelectInput(dpy, w->id, 0);
1290
1291    if (w->borderSize)
1292    {
1293        set_ignore (dpy, NextRequest (dpy));
1294        XFixesDestroyRegion (dpy, w->borderSize);
1295        w->borderSize = None;
1296    }
1297    if (w->shadow)
1298    {
1299        XRenderFreePicture (dpy, w->shadow);
1300        w->shadow = None;
1301    }
1302    if (w->borderClip)
1303    {
1304        XFixesDestroyRegion (dpy, w->borderClip);
1305        w->borderClip = None;
1306    }
1307
1308    clipChanged = True;
1309}
1310
1311#if HAS_NAME_WINDOW_PIXMAP
1312static void
1313unmap_callback (Display *dpy, win *w, Bool gone)
1314{
1315    finish_unmap_win (dpy, w);
1316}
1317#endif
1318
1319static void
1320unmap_win (Display *dpy, Window id, Bool fade)
1321{
1322    win *w = find_win (dpy, id);
1323    if (!w)
1324        return;
1325    w->a.map_state = IsUnmapped;
1326#if HAS_NAME_WINDOW_PIXMAP
1327    if (w->pixmap && fade && fadeWindows)
1328        set_fade (dpy, w, w->opacity*1.0/OPAQUE, 0.0, fade_out_step, unmap_callback, False, False, True);
1329    else
1330#endif
1331        finish_unmap_win (dpy, w);
1332}
1333
1334/* Get the opacity prop from window
1335   not found: default
1336   otherwise the value
1337 */
1338
1339static unsigned int
1340get_opacity_prop(Display *dpy, win *w, unsigned int def)
1341{
1342    Atom actual;
1343    int format;
1344    unsigned long n, left;
1345
1346    unsigned char *data;
1347    int result = XGetWindowProperty(dpy, w->id, opacityAtom, 0L, 1L, False,
1348                       XA_CARDINAL, &actual, &format,
1349                                    &n, &left, &data);
1350    if (result == Success && data != NULL)
1351    {
1352                unsigned int i;
1353                memcpy (&i, data, sizeof (unsigned int));
1354                XFree( (void *) data);
1355                return i;
1356    }
1357    return def;
1358}
1359
1360/* Get the opacity property from the window in a percent format
1361   not found: default
1362   otherwise: the value
1363*/
1364static double
1365get_opacity_percent(Display *dpy, win *w, double def)
1366{
1367    unsigned int opacity = get_opacity_prop (dpy, w, (unsigned int)(OPAQUE*def));
1368
1369    return opacity*1.0/OPAQUE;
1370}
1371
1372/* determine mode for window all in one place.
1373   Future might check for menu flag and other cool things
1374*/
1375
1376static Atom
1377get_wintype_prop(Display * dpy, Window w)
1378{
1379    Atom actual;
1380    int format;
1381    unsigned long n, left;
1382
1383    unsigned char *data;
1384    int result = XGetWindowProperty (dpy, w, winTypeAtom, 0L, 1L, False,
1385                                     XA_ATOM, &actual,
1386                                         &format,
1387                                     &n, &left, &data);
1388
1389       
1390    if (result == Success && data != (unsigned char *)None)
1391    {
1392                Atom a;
1393                memcpy (&a, data, sizeof (Atom));
1394                XFree ( (void *) data);
1395                return a;
1396    }
1397    return winNormalAtom;
1398}
1399
1400static void
1401determine_mode(Display *dpy, win *w)
1402{
1403   
1404    int mode;
1405    XRenderPictFormat *format;
1406
1407    /* if trans prop == -1 fall back on  previous tests*/
1408
1409    if (w->alphaPict)
1410    {
1411                XRenderFreePicture (dpy, w->alphaPict);
1412                w->alphaPict = None;
1413    }
1414    if (w->shadowPict)
1415    {
1416                XRenderFreePicture (dpy, w->shadowPict);
1417                w->shadowPict = None;
1418    }
1419
1420    if (w->a.class == InputOnly)
1421    {
1422                format = NULL;
1423    }
1424    else
1425    {
1426                format = XRenderFindVisualFormat (dpy, w->a.visual);
1427    }
1428
1429    if (format && format->type == PictTypeDirect && format->direct.alphaMask)
1430    {
1431                mode = WINDOW_ARGB;
1432    }
1433    else if (w->opacity != OPAQUE)
1434    {
1435                mode = WINDOW_TRANS;
1436    }
1437    else
1438    {
1439                mode = WINDOW_SOLID;
1440    }
1441    w->mode = mode;
1442         
1443    if (w->extents)
1444    {
1445                XserverRegion damage;
1446                damage = XFixesCreateRegion (dpy, NULL, 0);
1447                XFixesCopyRegion (dpy, damage, w->extents);
1448                add_damage (dpy, damage);
1449    }
1450}
1451
1452static Bool
1453isShaped (Display *dpy, Window win)
1454{
1455  int xws, yws, xbs, ybs;
1456    unsigned wws, hws, wbs, hbs;
1457    int boundingShaped, clipShaped;
1458
1459    XShapeQueryExtents (dpy, win, &boundingShaped, &xws, &yws, &wws,
1460                            &hws, &clipShaped, &xbs, &ybs, &wbs, &hbs);
1461      return (boundingShaped != 0);
1462}
1463
1464static Atom
1465determine_wintype (Display *dpy, Window w)
1466{
1467    Window       root_return, parent_return;
1468    Window      *children = NULL;
1469    unsigned int nchildren, i;
1470    Atom         type;
1471
1472    type = get_wintype_prop (dpy, w);
1473   
1474        if (type != winNormalAtom)
1475        {
1476                return type;
1477        }
1478       
1479    if (!XQueryTree (dpy, w, &root_return, &parent_return, &children,
1480                            &nchildren))
1481    {
1482       
1483        /* XQueryTree failed. */
1484        if (children)
1485            XFree ((void *)children);
1486                return winNormalAtom;
1487    }
1488
1489    for (i = 0;i < nchildren;i++)
1490    {
1491                type = determine_wintype (dpy, children[i]);
1492                if (type != winNormalAtom)
1493             return type;
1494    }
1495
1496    if (children)
1497        XFree ((void *)children);
1498
1499    return winNormalAtom;
1500}
1501
1502static void
1503add_win (Display *dpy, Window id, Window prev)
1504{
1505    win *new = malloc (sizeof (win));
1506    win **p;
1507   
1508    if (!new)
1509                return;
1510               
1511    if (prev)
1512    {
1513                for (p = &list; *p; p = &(*p)->next)
1514                if ((*p)->id == prev)
1515                                break;
1516    }
1517    else
1518                p = &list;
1519               
1520    new->id = id;
1521    set_ignore (dpy, NextRequest (dpy));
1522    if (!XGetWindowAttributes (dpy, id, &new->a))
1523    {
1524        free (new);
1525        return;
1526    }
1527    new->damaged = 0;
1528#if CAN_DO_USABLE
1529    new->usable = False;
1530#endif
1531#if HAS_NAME_WINDOW_PIXMAP
1532    new->pixmap = None;
1533#endif
1534    new->picture = None;
1535    if (new->a.class == InputOnly)
1536    {
1537                new->damage_sequence = 0;
1538                new->damage = None;
1539    }
1540    else
1541    {
1542                new->damage_sequence = NextRequest (dpy);
1543                new->damage = XDamageCreate (dpy, id, XDamageReportNonEmpty);
1544    }
1545       
1546 
1547  /* check if the window has ShapeExtensions */
1548       
1549    if ( isShaped(dpy, id)) 
1550        new->shaped=1;
1551    else
1552        new->shaped = 0;
1553       
1554    new->alphaPict = None;
1555    new->shadowPict = None;
1556    new->borderSize = None;
1557    new->extents = None;
1558    new->shadow = None;
1559    new->shadow_dx = 0;
1560    new->shadow_dy = 0;
1561    new->shadow_width = 0;
1562    new->shadow_height = 0;
1563    new->opacity = OPAQUE;
1564
1565    new->borderClip = None;
1566    new->prev_trans = NULL;
1567
1568    new->windowType = determine_wintype (dpy, new->id);
1569   
1570    new->next = *p;
1571    *p = new;
1572    if (new->a.map_state == IsViewable)
1573        map_win (dpy, id, new->damage_sequence - 1, True);
1574}
1575
1576static void
1577restack_win (Display *dpy, win *w, Window new_above)
1578{
1579    Window  old_above;
1580   
1581    if (w->next)
1582        old_above = w->next->id;
1583    else
1584        old_above = None;
1585    if (old_above != new_above)
1586    {
1587        win **prev;
1588
1589        /* unhook */
1590        for (prev = &list; *prev; prev = &(*prev)->next)
1591            if ((*prev) == w)
1592                break;
1593        *prev = w->next;
1594       
1595        /* rehook */
1596        for (prev = &list; *prev; prev = &(*prev)->next)
1597        {
1598            if ((*prev)->id == new_above)
1599                break;
1600        }
1601        w->next = *prev;
1602        *prev = w;
1603    }
1604}
1605
1606static void
1607configure_win (Display *dpy, XConfigureEvent *ce)
1608{
1609    win             *w = find_win (dpy, ce->window);
1610    XserverRegion   damage = None;
1611   
1612    if (!w)
1613    {
1614        if (ce->window == root)
1615        {
1616            if (rootBuffer)
1617            {
1618                XRenderFreePicture (dpy, rootBuffer);
1619                rootBuffer = None;
1620            }
1621            root_width = ce->width;
1622            root_height = ce->height;
1623        }
1624        return;
1625    }
1626#if CAN_DO_USABLE
1627    if (w->usable)
1628#endif
1629    {
1630        damage = XFixesCreateRegion (dpy, NULL, 0);
1631        if (w->extents != None)
1632            XFixesCopyRegion (dpy, damage, w->extents);
1633    }
1634   
1635      /* check if the window has ShapeExtensions */
1636       
1637    if ( isShaped(dpy, ce->window)) 
1638                w->shaped=1;
1639    else
1640        w->shaped = 0;
1641       
1642    w->a.x = ce->x;
1643    w->a.y = ce->y;
1644    if (w->a.width != ce->width || w->a.height != ce->height)
1645    {
1646#if HAS_NAME_WINDOW_PIXMAP
1647        if (w->pixmap)
1648        {
1649            XFreePixmap (dpy, w->pixmap);
1650            w->pixmap = None;
1651            if (w->picture)
1652            {
1653                XRenderFreePicture (dpy, w->picture);
1654                w->picture = None;
1655            }
1656        }
1657#endif
1658        if (w->shadow)
1659        {
1660            XRenderFreePicture (dpy, w->shadow);
1661            w->shadow = None;
1662        }
1663    }
1664    w->a.width = ce->width;
1665    w->a.height = ce->height;
1666    w->a.border_width = ce->border_width;
1667    w->a.override_redirect = ce->override_redirect;
1668    restack_win (dpy, w, ce->above);
1669    if (damage)
1670    {
1671        XserverRegion   extents = win_extents (dpy, w);
1672        XFixesUnionRegion (dpy, damage, damage, extents);
1673        XFixesDestroyRegion (dpy, extents);
1674        add_damage (dpy, damage);
1675    }
1676    clipChanged = True;
1677}
1678
1679static void
1680circulate_win (Display *dpy, XCirculateEvent *ce)
1681{
1682    win     *w = find_win (dpy, ce->window);
1683    Window  new_above;
1684
1685    if (!w)
1686        return;
1687
1688    if (ce->place == PlaceOnTop)
1689        new_above = list->id;
1690    else
1691        new_above = None;
1692    restack_win (dpy, w, new_above);
1693    clipChanged = True;
1694}
1695
1696static void
1697finish_destroy_win (Display *dpy, Window id, Bool gone)
1698{
1699    win **prev, *w;
1700
1701    for (prev = &list; (w = *prev); prev = &w->next)
1702        if (w->id == id)
1703        {
1704            if (gone)
1705                finish_unmap_win (dpy, w);
1706            *prev = w->next;
1707            if (w->picture)
1708            {
1709                set_ignore (dpy, NextRequest (dpy));
1710                XRenderFreePicture (dpy, w->picture);
1711                w->picture = None;
1712            }
1713            if (w->alphaPict)
1714            {
1715                XRenderFreePicture (dpy, w->alphaPict);
1716                w->alphaPict = None;
1717            }
1718            if (w->shadowPict)
1719            {
1720                XRenderFreePicture (dpy, w->shadowPict);
1721                w->shadowPict = None;
1722            }
1723            if (w->shadow)
1724            {
1725                XRenderFreePicture (dpy, w->shadow);
1726                w->shadow = None;
1727            }
1728            if (w->damage != None)
1729            {
1730                set_ignore (dpy, NextRequest (dpy));
1731                XDamageDestroy (dpy, w->damage);
1732                w->damage = None;
1733            }
1734            cleanup_fade (dpy, w);
1735            free (w);
1736            break;
1737        }
1738}
1739
1740#if HAS_NAME_WINDOW_PIXMAP
1741static void
1742destroy_callback (Display *dpy, win *w, Bool gone)
1743{
1744    finish_destroy_win (dpy, w->id, gone);
1745}
1746#endif
1747
1748static void
1749destroy_win (Display *dpy, Window id, Bool gone, Bool fade)
1750{
1751    win *w = find_win (dpy, id);
1752#if HAS_NAME_WINDOW_PIXMAP
1753    if (w && w->pixmap && fade && fadeWindows)
1754        set_fade (dpy, w, w->opacity*1.0/OPAQUE, 0.0, fade_out_step, destroy_callback, gone, False, True);
1755    else
1756#endif
1757    {
1758        finish_destroy_win (dpy, id, gone);
1759    }
1760}
1761
1762/*
1763static void
1764dump_win (win *w)
1765{
1766    printf ("\t%08lx: %d x %d + %d + %d (%d)\n", w->id,
1767            w->a.width, w->a.height, w->a.x, w->a.y, w->a.border_width);
1768}
1769
1770
1771static void
1772dump_wins (void)
1773{
1774    win *w;
1775
1776    printf ("windows:\n");
1777    for (w = list; w; w = w->next)
1778        dump_win (w);
1779}
1780*/
1781
1782static void
1783damage_win (Display *dpy, XDamageNotifyEvent *de)
1784{
1785    win *w = find_win (dpy, de->drawable);
1786
1787    if (!w)
1788        return;
1789#if CAN_DO_USABLE
1790    if (!w->usable)
1791    {
1792        if (w->damage_bounds.width == 0 || w->damage_bounds.height == 0)
1793        {
1794            w->damage_bounds = de->area;
1795        }
1796        else
1797        {
1798            if (de->area.x < w->damage_bounds.x)
1799            {
1800                w->damage_bounds.width += (w->damage_bounds.x - de->area.x);
1801                w->damage_bounds.x = de->area.x;
1802            }
1803            if (de->area.y < w->damage_bounds.y)
1804            {
1805                w->damage_bounds.height += (w->damage_bounds.y - de->area.y);
1806                w->damage_bounds.y = de->area.y;
1807            }
1808            if (de->area.x + de->area.width > w->damage_bounds.x + w->damage_bounds.width)
1809                w->damage_bounds.width = de->area.x + de->area.width - w->damage_bounds.x;
1810            if (de->area.y + de->area.height > w->damage_bounds.y + w->damage_bounds.height)
1811                w->damage_bounds.height = de->area.y + de->area.height - w->damage_bounds.y;
1812        }
1813#if 0
1814        printf ("unusable damage %d, %d: %d x %d bounds %d, %d: %d x %d\n",
1815                de->area.x,
1816                de->area.y,
1817                de->area.width,
1818                de->area.height,
1819                w->damage_bounds.x,
1820                w->damage_bounds.y,
1821                w->damage_bounds.width,
1822                w->damage_bounds.height);
1823#endif
1824        if (w->damage_bounds.x <= 0 &&
1825            w->damage_bounds.y <= 0 &&
1826            w->a.width <= w->damage_bounds.x + w->damage_bounds.width &&
1827            w->a.height <= w->damage_bounds.y + w->damage_bounds.height)
1828        {
1829            clipChanged = True;
1830            if (fadeWindows)
1831                set_fade (dpy, w, 0, get_opacity_percent (dpy, w, 1.0), fade_in_step, 0, False, True, True);
1832            w->usable = True;
1833        }
1834    }
1835    if (w->usable)
1836#endif
1837        repair_win (dpy, w);
1838}
1839
1840static int
1841error (Display *dpy, XErrorEvent *ev)
1842{
1843    int     o;
1844    const char    *name = NULL;
1845   
1846    if (should_ignore (dpy, ev->serial))
1847        return 0;
1848   
1849    if (ev->request_code == composite_opcode &&
1850        ev->minor_code == X_CompositeRedirectSubwindows)
1851    {
1852        fprintf (stderr, "Another composite manager is already running\n");
1853        exit (1);
1854    }
1855   
1856    o = ev->error_code - xfixes_error;
1857    switch (o) {
1858    case BadRegion: name = "BadRegion"; break;
1859    default: break;
1860    }
1861    o = ev->error_code - damage_error;
1862    switch (o) {
1863    case BadDamage: name = "BadDamage"; break;
1864    default: break;
1865    }
1866    o = ev->error_code - render_error;
1867    switch (o) {
1868    case BadPictFormat: name ="BadPictFormat"; break;
1869    case BadPicture: name ="BadPicture"; break;
1870    case BadPictOp: name ="BadPictOp"; break;
1871    case BadGlyphSet: name ="BadGlyphSet"; break;
1872    case BadGlyph: name ="BadGlyph"; break;
1873    default: break;
1874    }
1875       
1876    printf ("error %d request %d minor %d serial %lu\n",
1877            ev->error_code, ev->request_code, ev->minor_code, ev->serial);
1878
1879/*    abort ();     this is just annoying to most people */
1880    return 0;
1881}
1882
1883static void
1884expose_root (Display *dpy, Window root, XRectangle *rects, int nrects)
1885{
1886    XserverRegion  region = XFixesCreateRegion (dpy, rects, nrects);
1887   
1888    add_damage (dpy, region);
1889}
1890
1891#if DEBUG_EVENTS
1892static int
1893ev_serial (XEvent *ev)
1894{
1895    if (ev->type & 0x7f != KeymapNotify)
1896        return ev->xany.serial;
1897    return NextRequest (ev->xany.display);
1898}
1899
1900static char *
1901ev_name (XEvent *ev)
1902{
1903    static char buf[128];
1904    switch (ev->type & 0x7f) {
1905    case Expose:
1906        return "Expose";
1907    case MapNotify:
1908        return "Map";
1909    case UnmapNotify:
1910        return "Unmap";
1911    case ReparentNotify:
1912        return "Reparent";
1913    case CirculateNotify:
1914        return "Circulate";
1915    default:
1916        if (ev->type == damage_event + XDamageNotify)
1917            return "Damage";
1918        sprintf (buf, "Event %d", ev->type);
1919        return buf;
1920    }
1921}
1922
1923static Window
1924ev_window (XEvent *ev)
1925{
1926    switch (ev->type) {
1927    case Expose:
1928        return ev->xexpose.window;
1929    case MapNotify:
1930        return ev->xmap.window;
1931    case UnmapNotify:
1932        return ev->xunmap.window;
1933    case ReparentNotify:
1934        return ev->xreparent.window;
1935    case CirculateNotify:
1936        return ev->xcirculate.window;
1937    default:
1938        if (ev->type == damage_event + XDamageNotify)
1939            return ((XDamageNotifyEvent *) ev)->drawable;
1940        return 0;
1941    }
1942}
1943
1944#endif
1945
1946void
1947usage (char *program)
1948{
1949    fprintf (stderr, "%s v1.1.5 beta MaXX Desktop Edition\n", program);
1950    fprintf (stderr, "usage: %s [options]\n", program);
1951    fprintf (stderr, "Options\n");
1952    fprintf (stderr, "   -d display\n      Specifies which display should be managed.\n");
1953    fprintf (stderr, "   -r radius\n      Specifies the blur radius for client-side shadows. (default 12)\n");
1954    fprintf (stderr, "   -o opacity\n      Specifies the translucency for client-side shadows. (default .75)\n");
1955    fprintf (stderr, "   -l left-offset\n      Specifies the left offset for client-side shadows. (default -15)\n");
1956    fprintf (stderr, "   -t top-offset\n      Specifies the top offset for clinet-side shadows. (default -15)\n");
1957    fprintf (stderr, "   -I fade-in-step\n      Specifies the opacity change between steps while fading in. (default 0.028)\n");
1958    fprintf (stderr, "   -O fade-out-step\n      Specifies the opacity change between steps while fading out. (default 0.03)\n");
1959    fprintf (stderr, "   -D fade-delta-time\n      Specifies the time between steps in a fade in milliseconds. (default 10)\n");
1960    fprintf (stderr, "   -a\n      Use automatic server-side compositing. Faster, but no special effects.\n");
1961    fprintf (stderr, "   -c\n      Draw client-side shadows with fuzzy edges.\n");
1962    fprintf (stderr, "   -C\n      Avoid drawing shadows on dock/panel windows.\n");
1963    fprintf (stderr, "   -f\n      Fade windows in/out when opening/closing.\n");
1964    fprintf (stderr, "   -F\n      Fade windows during opacity changes.\n");
1965    fprintf (stderr, "   -n\n      Normal client-side compositing with transparency support\n");
1966    fprintf (stderr, "   -s\n      Draw server-side shadows with sharp edges.\n");
1967    fprintf (stderr, "   -S\n      Enable synchronous operation (for debugging).\n");
1968    exit (1);
1969}
1970
1971static void
1972register_cm (void)
1973{
1974    Window w;
1975    Atom a;
1976
1977    w = XCreateSimpleWindow (dpy, RootWindow (dpy, 0), 0, 0, 1, 1, 0, None,
1978                             None);
1979
1980    Xutf8SetWMProperties (dpy, w, "xcompmgr", "xcompmgr", NULL, 0, NULL, NULL,
1981                          NULL);
1982
1983    /* FIXME: Don't hard code the screen number */
1984    a = XInternAtom (dpy, "_NET_WM_CM_S0", False);
1985
1986    XSetSelectionOwner (dpy, a, w, 0);
1987}
1988
1989int
1990main (int argc, char **argv)
1991{
1992    XEvent              ev;
1993    Window              root_return, parent_return;
1994    Window              *children;
1995    unsigned int    nchildren;
1996    int                 i;
1997    XRenderPictureAttributes    pa;
1998    XRectangle      *expose_rects = NULL;
1999    int                 size_expose = 0;
2000    int                          n_expose = 0;
2001    struct pollfd   ufd;
2002    int                 p;
2003    int                 composite_major, composite_minor;
2004    char                *display = NULL;
2005    int                 o;
2006
2007    while ((o = getopt (argc, argv, "D:I:O:d:r:o:l:t:scnfFCaS")) != -1)
2008    {
2009                switch (o)
2010                {
2011                        case 'd':
2012                        display = optarg;
2013                        break;
2014                               
2015                        case 'D':
2016                        fade_delta = atoi (optarg);
2017                        if (fade_delta < 1)
2018                                fade_delta = 10;
2019                        break;
2020                               
2021                        case 'I':
2022                        fade_in_step = atof (optarg);
2023                        if (fade_in_step <= 0)
2024                                fade_in_step = 0.01;
2025                        break;
2026                               
2027                        case 'O':
2028                        fade_out_step = atof (optarg);
2029                        if (fade_out_step <= 0)
2030                                fade_out_step = 0.01;
2031                        break;
2032                               
2033                        case 's':
2034                        compMode = CompServerShadows;
2035                        break;
2036                               
2037                        case 'c':
2038                        compMode = CompClientShadows;
2039                        break;
2040                               
2041                        case 'C':
2042                        excludeDockShadows = True;
2043                        break;
2044                               
2045                        case 'n':
2046                        compMode = CompSimple;
2047                        break;
2048                               
2049                        case 'f':
2050                        fadeWindows = True;
2051                        break;
2052                               
2053                        case 'F':
2054                        fadeTrans = True;
2055                        break;
2056                               
2057                        case 'a':
2058                        autoRedirect = True;
2059                        break;
2060                               
2061                        case 'S':
2062                        synchronize = True;
2063                        break;
2064                               
2065                        case 'r':
2066                        shadowRadius = atoi (optarg);
2067                        break;
2068                               
2069                        case 'o':
2070                        shadowOpacity = atof (optarg);
2071                        break;
2072                               
2073                        case 'l':
2074                        shadowOffsetX = atoi (optarg);
2075                        break;
2076                               
2077                        case 't':
2078                        shadowOffsetY = atoi (optarg);
2079                        break;
2080                               
2081                        default:
2082                        usage (argv[0]);
2083                        break;
2084                }
2085    }
2086   
2087    dpy = XOpenDisplay (display);
2088    if (!dpy)
2089    {
2090                fprintf (stderr, "Can't open display\n");
2091                exit (1);
2092    }
2093       
2094    XSetErrorHandler (error);
2095    if (synchronize)
2096                XSynchronize (dpy, 1);
2097               
2098    scr = DefaultScreen (dpy);
2099    root = RootWindow (dpy, scr);
2100
2101    if (!XRenderQueryExtension (dpy, &render_event, &render_error))
2102    {
2103                fprintf (stderr, "No render extension\n");
2104                exit (1);
2105    }
2106       
2107    if (!XQueryExtension (dpy, COMPOSITE_NAME, &composite_opcode,
2108                          &composite_event, &composite_error))
2109    {
2110                fprintf (stderr, "No composite extension\n");
2111                exit (1);
2112    }
2113       
2114    XCompositeQueryVersion (dpy, &composite_major, &composite_minor);
2115       
2116#if HAS_NAME_WINDOW_PIXMAP
2117    if (composite_major > 0 || composite_minor >= 2)
2118                hasNamePixmap = True;
2119#endif
2120
2121    if (!XDamageQueryExtension (dpy, &damage_event, &damage_error))
2122    {
2123                fprintf (stderr, "No damage extension\n");
2124                exit (1);
2125    }
2126       
2127    if (!XFixesQueryExtension (dpy, &xfixes_event, &xfixes_error))
2128    {
2129                fprintf (stderr, "No XFixes extension\n");
2130                exit (1);
2131    }
2132       
2133    register_cm();
2134
2135
2136    /* get atoms */
2137    opacityAtom = XInternAtom (dpy, OPACITY_PROP, False);
2138    winTypeAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE", False);
2139    winDesktopAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
2140    winDockAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
2141    winToolbarAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_TOOLBAR", False);
2142    winMenuAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_MENU", False);
2143    winUtilAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_UTILITY", False);
2144    winSplashAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_SPLASH", False);
2145    winDialogAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
2146    winNormalAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False);
2147
2148    pa.subwindow_mode = IncludeInferiors;
2149
2150    if (compMode == CompClientShadows)
2151    {
2152                gaussianMap = make_gaussian_map(dpy, shadowRadius);
2153                presum_gaussian (gaussianMap);
2154    }
2155
2156    root_width = DisplayWidth (dpy, scr);
2157    root_height = DisplayHeight (dpy, scr);
2158
2159    rootPicture = XRenderCreatePicture (dpy, root,
2160                                        XRenderFindVisualFormat (dpy,
2161                                                                 DefaultVisual (dpy, scr)),
2162                                        CPSubwindowMode,
2163                                        &pa);
2164                                       
2165    blackPicture = solid_picture (dpy, True, 1, 0, 0, 0);
2166   
2167        if (compMode == CompServerShadows)
2168                transBlackPicture = solid_picture (dpy, True, 0.3, 0, 0, 0);
2169   
2170        allDamage = None;
2171    clipChanged = True;
2172    XGrabServer (dpy);
2173       
2174    if (autoRedirect)
2175                XCompositeRedirectSubwindows (dpy, root, CompositeRedirectAutomatic);
2176    else
2177    {
2178                XCompositeRedirectSubwindows (dpy, root, CompositeRedirectManual);                     
2179                XSelectInput (dpy, root,
2180                          SubstructureNotifyMask|
2181                          ExposureMask|
2182                          StructureNotifyMask|
2183                          PropertyChangeMask);
2184                XQueryTree (dpy, root, &root_return, &parent_return, &children, &nchildren);
2185               
2186                for (i = 0; i < nchildren; i++)
2187                add_win (dpy, children[i], i ? children[i-1] : None);
2188                       
2189                XFree (children);
2190    }
2191       
2192    XUngrabServer (dpy);
2193    ufd.fd = ConnectionNumber (dpy);
2194    ufd.events = POLLIN;
2195       
2196    if (!autoRedirect)
2197                paint_all (dpy, None);
2198   
2199                for (;;)
2200        {
2201               
2202                /*      dump_wins (); */
2203                        do {
2204                        if (autoRedirect)
2205                                        XFlush (dpy);
2206                                       
2207                if (!QLength (dpy))
2208                {
2209                                        if (poll (&ufd, 1, fade_timeout()) == 0)
2210                                        {
2211                                        run_fades (dpy);
2212                                        break;
2213                                        }
2214                        }
2215
2216
2217            XNextEvent (dpy, &ev);
2218            if ((ev.type & 0x7f) != KeymapNotify)
2219                discard_ignore (dpy, ev.xany.serial);
2220#if DEBUG_EVENTS
2221            printf ("event %10.10s serial 0x%08x window 0x%08x\n",
2222                    ev_name(&ev), ev_serial (&ev), ev_window (&ev));
2223#endif
2224            if (!autoRedirect) switch (ev.type) {
2225            case CreateNotify:
2226                add_win (dpy, ev.xcreatewindow.window, 0);
2227                break;
2228            case ConfigureNotify:
2229                configure_win (dpy, &ev.xconfigure);
2230                break;
2231            case DestroyNotify:
2232                destroy_win (dpy, ev.xdestroywindow.window, True, True);
2233                break;
2234            case MapNotify:
2235                map_win (dpy, ev.xmap.window, ev.xmap.serial, True);
2236                break;
2237            case UnmapNotify:
2238                unmap_win (dpy, ev.xunmap.window, True);
2239                break;
2240            case ReparentNotify:
2241                if (ev.xreparent.parent == root)
2242                    add_win (dpy, ev.xreparent.window, 0);
2243                else
2244                    destroy_win (dpy, ev.xreparent.window, False, True);
2245                break;
2246            case CirculateNotify:
2247                circulate_win (dpy, &ev.xcirculate);
2248                break;
2249            case Expose:
2250                if (ev.xexpose.window == root)
2251                {
2252                    int more = ev.xexpose.count + 1;
2253                    if (n_expose == size_expose)
2254                    {
2255                        if (expose_rects)
2256                        {
2257                            expose_rects = realloc (expose_rects,
2258                                                    (size_expose + more) *
2259                                                    sizeof (XRectangle));
2260                            size_expose += more;
2261                        }
2262                        else
2263                        {
2264                            expose_rects = malloc (more * sizeof (XRectangle));
2265                            size_expose = more;
2266                        }
2267                    }
2268                    expose_rects[n_expose].x = ev.xexpose.x;
2269                    expose_rects[n_expose].y = ev.xexpose.y;
2270                    expose_rects[n_expose].width = ev.xexpose.width;
2271                    expose_rects[n_expose].height = ev.xexpose.height;
2272                    n_expose++;
2273                    if (ev.xexpose.count == 0)
2274                    {
2275                        expose_root (dpy, root, expose_rects, n_expose);
2276                        n_expose = 0;
2277                    }
2278                }
2279                break;
2280            case PropertyNotify:
2281                for (p = 0; backgroundProps[p]; p++)
2282                {
2283                    if (ev.xproperty.atom == XInternAtom (dpy, backgroundProps[p], False))
2284                    {
2285                        if (rootTile)
2286                        {
2287                            XClearArea (dpy, root, 0, 0, 0, 0, True);
2288                            XRenderFreePicture (dpy, rootTile);
2289                            rootTile = None;
2290                            break;
2291                        }
2292                    }
2293                }
2294                /* check if Trans property was changed */
2295                if (ev.xproperty.atom == opacityAtom)
2296                {
2297                    /* reset mode and redraw window */
2298                    win * w = find_win(dpy, ev.xproperty.window);
2299                    if (w)
2300                    {
2301                        if (fadeTrans)
2302                            set_fade (dpy, w, w->opacity*1.0/OPAQUE, get_opacity_percent (dpy, w, 1.0),
2303                                      fade_out_step, NULL, False, True, False);
2304                        else
2305                        {
2306                        w->opacity = get_opacity_prop(dpy, w, OPAQUE);
2307                        determine_mode(dpy, w);
2308                            if (w->shadow)
2309                            {
2310                                XRenderFreePicture (dpy, w->shadow);
2311                                w->shadow = None;
2312                                w->extents = win_extents (dpy, w);
2313                            }
2314                        }
2315                    }
2316                }
2317                break;
2318            default:
2319                if (ev.type == damage_event + XDamageNotify)
2320                    damage_win (dpy, (XDamageNotifyEvent *) &ev);
2321                break;
2322            }
2323        } while (QLength (dpy));
2324        if (allDamage && !autoRedirect)
2325        {
2326            static int  paint;
2327            paint_all (dpy, allDamage);
2328            paint++;
2329            XSync (dpy, False);
2330            allDamage = None;
2331            clipChanged = False;
2332        }
2333    }
2334}
2335
Note: See TracBrowser for help on using the browser.