update for changes in XCB (iterator no longer exists, must manually iterate on an...
[dana/dcompmgr.git] / render.c
1 #include "efence.h"
2
3 #include "render.h"
4 #include "screen.h"
5 #include "window.h"
6 #include "display.h"
7 #include "list.h"
8 #include <stdio.h>
9 #include <assert.h>
10 #include <stdlib.h>
11 #include <xcb/render.h>
12
13 static int plugin_id;
14
15 /* if defined, it will not use double buffering */
16 #undef MONITOR_REPAINT
17
18 typedef struct {
19     void (*screen_paint)(d_screen_t *sc);
20     void (*screen_root_pixmap_change)(d_screen_t *sc);
21     void (*window_show)(d_window_t *w);
22     void (*window_zombie_dead)(d_window_t *w);
23     void (*window_move)(d_window_t *w);
24     void (*window_resize)(d_window_t *w);
25     void (*window_reshape)(d_window_t *w);
26     void (*window_restack)(d_window_t *w, d_window_t *above);
27     void (*window_opacity_change)(d_window_t *w);
28     void (*window_damage)(d_window_t *w);
29
30     xcb_render_pictformat_t root_format;
31     xcb_render_pictformat_t argb32_format;
32     xcb_render_query_pict_formats_reply_t *pict_formats;
33     xcb_render_picture_t overlay_picture;
34     xcb_render_picture_t overlay_buffer;
35     xcb_render_picture_t root_picture;
36     xcb_render_picture_t solid_bg;
37
38     xcb_xfixes_region_t all_region;
39     xcb_xfixes_region_t damaged_region;
40     xcb_xfixes_region_t paint_region;
41     xcb_xfixes_region_t shadow_paint_region;
42
43     uint16_t shadowalpha;
44     int xshadowoff;
45     int yshadowoff;
46 } data_t;
47
48 typedef struct {
49     xcb_render_picture_t picture;
50     xcb_render_picture_t alpha_picture;
51     xcb_render_picture_t shadow_picture;
52     xcb_xfixes_region_t paint_clip;
53     xcb_xfixes_region_t shadow_region;
54     gboolean shadow_valid;
55 } window_data_t;
56
57 static void render_paint(d_screen_t *sc);
58 static void render_root_pixmap_change(d_screen_t *sc);
59 static void paint_root(d_screen_t *sc, data_t *d);
60 static void paint_window(d_window_t *window, data_t *d, window_data_t *wd,
61                          gboolean opaque, int x, int y, int width,
62                          int height, int bwidth);
63 static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
64                          int x, int y, int width, int height, int bwidth);
65 static void render_update_picture(d_window_t *w, data_t *d, window_data_t *wd);
66 static void render_update_root_picture(d_screen_t *sc, data_t *d);
67 static void render_free_picture(d_window_t *w, window_data_t *wd);
68 static void render_redraw_window(d_window_t *w, data_t *d,
69                                  gboolean shadow, window_data_t *wd);
70 static xcb_render_pictformat_t find_visual_format(data_t *d,
71                                                   xcb_visualid_t visual);
72 static xcb_render_pictformat_t find_argb32_format(data_t *d);
73 static xcb_render_picture_t solid_picture(data_t *d, d_screen_t *sc,
74                                           uint16_t a, uint16_t r,
75                                           uint16_t g, uint16_t b);
76 static void render_update_opacity(d_window_t *w, data_t *d, window_data_t *wd);
77 static void render_update_shadow(d_window_t *w, data_t *d, window_data_t *wd);
78
79 static void render_window_show(d_window_t *window);
80 static void render_window_zombie_dead(d_window_t *window);
81 static void render_window_move(d_window_t *window);
82 static void render_window_resize(d_window_t *window);
83 static void render_window_reshape(d_window_t *window);
84 static void render_window_restack(d_window_t *window, d_window_t *above);
85 static void render_window_opacity_change(d_window_t *w);
86 static void render_window_damage(d_window_t *w);
87
88 void
89 render_init(d_screen_t *sc, int id)
90 {
91     xcb_render_query_pict_formats_cookie_t ck;
92     xcb_pixmap_t px;
93     xcb_rectangle_t rect;
94
95     plugin_id = id;
96
97     data_t *d = malloc(sizeof(data_t));
98     d->screen_paint = sc->screen_paint;
99     d->screen_root_pixmap_change = sc->screen_root_pixmap_change;
100     d->window_show = sc->window_show;
101     d->window_zombie_dead = sc->window_zombie_dead;
102     d->window_move = sc->window_move;
103     d->window_resize = sc->window_resize;
104     d->window_reshape = sc->window_reshape;
105     d->window_restack = sc->window_restack;
106     d->window_opacity_change = sc->window_opacity_change;
107     d->window_damage = sc->window_damage;
108     screen_add_plugin_data(sc, plugin_id, d);
109
110     sc->screen_paint = render_paint;
111     sc->screen_root_pixmap_change = render_root_pixmap_change;
112     sc->window_show = render_window_show;
113     sc->window_zombie_dead = render_window_zombie_dead;
114     sc->window_move = render_window_move;
115     sc->window_resize = render_window_resize;
116     sc->window_reshape = render_window_reshape;
117     sc->window_restack = render_window_restack;
118     sc->window_opacity_change = render_window_opacity_change;
119     sc->window_damage = render_window_damage;
120
121     d->shadowalpha = 0x3333; /* 20% */
122     d->xshadowoff = 2;
123     d->yshadowoff = 2;
124
125     ck = xcb_render_query_pict_formats_unchecked(sc->dpy->conn);
126     d->pict_formats = xcb_render_query_pict_formats_reply(sc->dpy->conn, ck,
127                                                           NULL);
128
129     d->root_format = find_visual_format(d, sc->super->root_visual);
130     d->argb32_format = find_argb32_format(d);
131     d->root_picture = XCB_NONE;
132
133     d->solid_bg = solid_picture(d, sc, 0xffff, 0x6060, 02020, 0x3030);
134
135     d->overlay_picture = xcb_generate_id(sc->dpy->conn);
136     xcb_render_create_picture(sc->dpy->conn,
137                               d->overlay_picture, sc->overlay, d->root_format,
138                               0, NULL);
139
140     /* make the double buffer */
141     px = xcb_generate_id(sc->dpy->conn);
142     xcb_create_pixmap(sc->dpy->conn, sc->super->root_depth, px,
143                       sc->super->root, sc->super->width_in_pixels,
144                       sc->super->height_in_pixels);
145     d->overlay_buffer = xcb_generate_id(sc->dpy->conn);
146 #ifdef MONITOR_REPAINT
147     xcb_render_create_picture(sc->dpy->conn,
148                               d->overlay_buffer, sc->overlay, d->root_format,
149                               0, NULL);
150 #else
151     xcb_render_create_picture(sc->dpy->conn, d->overlay_buffer, px,
152                               d->root_format, 0, 0);
153 #endif
154     xcb_free_pixmap(sc->dpy->conn, px);
155
156     d->all_region = xcb_generate_id(sc->dpy->conn);
157     d->damaged_region = xcb_generate_id(sc->dpy->conn);
158     d->paint_region = xcb_generate_id(sc->dpy->conn);
159     d->shadow_paint_region = xcb_generate_id(sc->dpy->conn);
160     rect.x = rect.y = 0;
161     rect.width = sc->super->width_in_pixels;
162     rect.height = sc->super->height_in_pixels;
163     xcb_xfixes_create_region(sc->dpy->conn, d->all_region, 1, &rect);
164     xcb_xfixes_create_region(sc->dpy->conn, d->damaged_region, 1, &rect);
165     xcb_xfixes_create_region(sc->dpy->conn, d->paint_region, 1, &rect);
166     xcb_xfixes_create_region(sc->dpy->conn, d->shadow_paint_region, 1, &rect);
167 }
168
169 void
170 render_free(d_screen_t *sc)
171 {
172     data_t *d = screen_find_plugin_data(sc, plugin_id);
173     if (d) {
174         free(d->pict_formats);
175         xcb_render_free_picture(sc->dpy->conn, d->solid_bg);
176         if (d->root_picture)
177             xcb_render_free_picture(sc->dpy->conn, d->root_picture);
178         xcb_render_free_picture(sc->dpy->conn, d->overlay_picture);
179         xcb_render_free_picture(sc->dpy->conn, d->overlay_buffer);
180         xcb_xfixes_destroy_region(sc->dpy->conn, d->all_region);
181         xcb_xfixes_destroy_region(sc->dpy->conn, d->damaged_region);
182         xcb_xfixes_destroy_region(sc->dpy->conn, d->paint_region);
183         xcb_xfixes_destroy_region(sc->dpy->conn, d->shadow_paint_region);
184         free(d);
185     }
186     screen_remove_plugin_data(sc, plugin_id);
187 }
188
189 int
190 render_next_timeout(struct d_screen *sc, struct timeval *tv)
191 {
192     (void)sc;
193     (void)tv;
194     return FALSE;
195 }
196
197 void
198 render_timeout(struct d_screen *sc, const struct timeval *now)
199 {
200     (void)sc; (void)now;
201 }
202
203 void
204 render_window_free(d_window_t *w, window_data_t *wd)
205 {
206     render_free_picture(w, wd);
207     xcb_render_free_picture(w->sc->dpy->conn, wd->alpha_picture);
208     xcb_render_free_picture(w->sc->dpy->conn, wd->shadow_picture);
209     xcb_xfixes_destroy_region(w->sc->dpy->conn, wd->paint_clip);
210     xcb_xfixes_destroy_region(w->sc->dpy->conn, wd->shadow_region);
211     free(wd);
212 }
213
214 static void
215 render_window_show(d_window_t *w)
216 {
217     data_t *d;
218     window_data_t *wd;
219     xcb_rectangle_t rect;
220
221     d = screen_find_plugin_data(w->sc, plugin_id);
222
223     /* pass it on */
224     d->window_show(w);
225
226     wd = window_find_plugin_data(w, plugin_id);
227     if (wd) {
228         render_window_free(w, wd);
229         window_add_plugin_data(w, plugin_id, wd);
230     }
231    
232     wd = malloc(sizeof(window_data_t));
233     wd->picture = XCB_NONE;
234
235     wd->paint_clip = xcb_generate_id(w->sc->dpy->conn);
236     wd->shadow_region = xcb_generate_id(w->sc->dpy->conn);
237     rect.x = rect.y = -1;
238     rect.width = rect.height = 1;
239     xcb_xfixes_create_region(w->sc->dpy->conn, wd->paint_clip, 1, &rect);
240     xcb_xfixes_create_region(w->sc->dpy->conn, wd->shadow_region, 1, &rect);
241
242     wd->shadow_valid = FALSE;
243
244     wd->alpha_picture = solid_picture(d, w->sc, 0, 0, 0, 0);
245     wd->shadow_picture = solid_picture(d, w->sc, 0, 0, 0, 0);
246
247     render_update_opacity(w, d, wd);
248
249     window_add_plugin_data(w, plugin_id, wd);
250 }
251
252 static void 
253 render_update_opacity(d_window_t *w, data_t *d, window_data_t *wd)
254 {
255     static xcb_render_color_t c = { 0, 0, 0, 0 };
256     static xcb_rectangle_t rect = {0, 0, 1, 1};
257     unsigned long a;
258
259     /* make the window's shadow and alpha-map match its current opacity */
260     c.alpha = window_get_opacity(w);
261     xcb_render_fill_rectangles(w->sc->dpy->conn,
262                                XCB_RENDER_PICT_OP_SRC,
263                                wd->alpha_picture, c, 1, &rect);
264     a = d->shadowalpha;
265     a = a * window_get_opacity(w) / 0xffff;
266     c.alpha = a;
267     xcb_render_fill_rectangles(w->sc->dpy->conn,
268                                XCB_RENDER_PICT_OP_SRC,
269                                wd->shadow_picture, c, 1, &rect);
270 }
271
272 static void
273 render_window_zombie_dead(d_window_t *w)
274 {
275     data_t *d;
276     window_data_t *wd;
277
278     d = screen_find_plugin_data(w->sc, plugin_id);
279     wd = window_find_plugin_data(w, plugin_id);
280     if (wd) {
281         /* redraw the window and its shadow */
282         render_redraw_window(w, d, TRUE, wd);
283
284         render_window_free(w, wd);
285         window_remove_plugin_data(w, plugin_id);
286     }
287
288     /* pass it on */
289     d->window_zombie_dead(w);
290 }
291
292 static xcb_render_picture_t
293 solid_picture(data_t *d, d_screen_t *sc, uint16_t a, uint16_t r,
294               uint16_t g, uint16_t b)
295 {
296     xcb_pixmap_t pixmap;
297     xcb_render_picture_t picture;
298     xcb_render_color_t   c;
299     const uint32_t vals = XCB_RENDER_REPEAT_NORMAL;
300     const xcb_rectangle_t rect = { 0, 0, 1, 1 };
301
302     pixmap = xcb_generate_id(sc->dpy->conn);
303     picture = xcb_generate_id(sc->dpy->conn);
304
305     xcb_create_pixmap(sc->dpy->conn, 32, pixmap, sc->super->root, 1, 1);
306     xcb_render_create_picture(sc->dpy->conn, picture, pixmap, d->argb32_format,
307                               XCB_RENDER_CP_REPEAT, &vals);
308
309     c.alpha = a;
310     c.red   = r;
311     c.green = g;
312     c.blue  = b;
313
314     xcb_render_fill_rectangles(sc->dpy->conn, XCB_RENDER_PICT_OP_SRC,
315                                picture, c, 1, &rect);
316     xcb_free_pixmap(sc->dpy->conn, pixmap);
317
318     return picture;
319 }
320
321 static xcb_render_pictformat_t
322 find_argb32_format(data_t *d)
323 {
324     xcb_render_pictforminfo_iterator_t it;
325
326     for (it = xcb_render_query_pict_formats_formats_iterator(d->pict_formats);
327          it.rem; xcb_render_pictforminfo_next(&it))
328     {
329         xcb_render_pictforminfo_t *format = it.data;
330         if (format->type == XCB_RENDER_PICT_TYPE_DIRECT) {
331             if (format->depth              == 32   &&
332                 format->direct.alpha_mask  == 0xff &&
333                 format->direct.red_mask    == 0xff &&
334                 format->direct.green_mask  == 0xff &&
335                 format->direct.blue_mask   == 0xff &&
336                 format->direct.alpha_shift == 24   &&
337                 format->direct.red_shift   == 16   &&
338                 format->direct.green_shift == 8    &&
339                 format->direct.blue_shift  == 0)
340                 return format->id;
341         }
342     }
343     return XCB_NONE;
344 }
345
346 static xcb_render_pictformat_t
347 find_visual_format(data_t *d, xcb_visualid_t visual)
348 {
349     xcb_render_pictscreen_iterator_t si;
350     xcb_render_pictdepth_iterator_t di;
351     xcb_render_pictvisual_iterator_t vi;
352
353     if (!visual) return XCB_NONE;
354
355     /* go through all the screens */
356     si = xcb_render_query_pict_formats_screens_iterator(d->pict_formats);
357     for (; si.rem; xcb_render_pictscreen_next(&si)) {
358         di = xcb_render_pictscreen_depths_iterator(si.data);
359         for (; di.rem; xcb_render_pictdepth_next(&di)) {
360             vi = xcb_render_pictdepth_visuals_iterator(di.data);
361             for (; vi.rem; xcb_render_pictvisual_next(&vi)) {
362                 if (vi.data->visual == visual)
363                     return vi.data->format;
364             }
365         }
366     }
367     return XCB_NONE;
368 }
369
370 static void
371 render_free_picture(d_window_t *w, window_data_t *wd)
372 {
373     /* this might cause an error, oh well */
374     if (wd->picture) {
375         xcb_render_free_picture(w->sc->dpy->conn, wd->picture);
376         wd->picture = XCB_NONE;
377     }
378 }
379
380 static void
381 render_update_root_picture(d_screen_t *sc, data_t *d)
382 {
383     xcb_pixmap_t px;
384
385     px = screen_get_root_pixmap(sc);
386     if (px) {
387         d->root_picture = xcb_generate_id(sc->dpy->conn);
388         xcb_render_create_picture(sc->dpy->conn,
389                                   d->root_picture, px,
390                                   d->root_format, 0, NULL);
391     }
392 }
393
394 static void
395 render_update_picture(d_window_t *w, data_t *d, window_data_t *wd)
396 {
397     xcb_pixmap_t px;
398
399     px = window_get_pixmap(w);
400     //printf("got pixmap 0x%x\n", px);
401     if (px) {
402         xcb_render_pictformat_t format;
403         const uint32_t vals = XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS;
404
405         render_free_picture(w, wd);
406
407         wd->picture = xcb_generate_id(w->sc->dpy->conn);
408         format = find_visual_format(d, window_get_visual(w));
409         /* we don't need to check this.  if it fails, we'll just be drawing
410            an invalid picture and creating some X errors but that's no big
411            deal really */
412         xcb_render_create_picture(w->sc->dpy->conn,
413                                   wd->picture, px, format,
414                                   XCB_RENDER_CP_SUBWINDOW_MODE,
415                                   &vals);
416     }
417 }
418
419 static void
420 render_window_move(d_window_t *w)
421 {
422     data_t *d;
423     window_data_t *wd;
424
425     d = screen_find_plugin_data(w->sc, plugin_id);
426     wd = window_find_plugin_data(w, plugin_id);
427
428     /* pass it on */
429     d->window_move(w);
430
431     /* redraw the screen */
432     xcb_xfixes_copy_region(w->sc->dpy->conn, d->all_region, d->damaged_region);
433     /* reget the shadow's shape */
434     wd->shadow_valid = FALSE;
435 }
436
437 static void
438 render_window_resize(d_window_t *w)
439 {
440     data_t *d;
441     window_data_t *wd;
442
443     d = screen_find_plugin_data(w->sc, plugin_id);
444     wd = window_find_plugin_data(w, plugin_id);
445
446     /* pass it on */
447     d->window_resize(w);
448
449     assert(wd != NULL);
450     render_free_picture(w, wd);
451
452     /* redraw the screen */
453     xcb_xfixes_copy_region(w->sc->dpy->conn, d->all_region, d->damaged_region);
454     /* reget the shadow's shape */
455     wd->shadow_valid = FALSE;
456 }
457
458 static void
459 render_window_reshape(d_window_t *w)
460 {
461     data_t *d;
462     window_data_t *wd;
463
464     d = screen_find_plugin_data(w->sc, plugin_id);
465     wd = window_find_plugin_data(w, plugin_id);
466
467     /* pass it on */
468     d->window_reshape(w);
469
470     assert(wd != NULL);
471     //render_free_picture(w, wd);
472
473     /* redraw the screen */
474     xcb_xfixes_copy_region(w->sc->dpy->conn, d->all_region, d->damaged_region);
475     /* reget the shadow's shape */
476     wd->shadow_valid = FALSE;
477 }
478
479 static void
480 render_window_restack(d_window_t *w, d_window_t *above)
481 {
482     data_t *d;
483     window_data_t *wd;
484
485     d = screen_find_plugin_data(w->sc, plugin_id);
486     wd = window_find_plugin_data(w, plugin_id);
487
488     /* pass it on */
489     d->window_restack(w, above);
490
491     /* the window might not be visible */
492     if (wd == NULL) return;
493
494     /* redraw the window and its shadow */
495     render_redraw_window(w, d, TRUE, wd);
496 }
497
498 /* wd is only needed if redrawing the shadow */
499 static void
500 render_redraw_window(d_window_t *w, data_t *d,
501                      gboolean shadow, window_data_t *wd)
502 {
503     xcb_xfixes_region_t region = window_get_region(w);
504
505     if (region) {
506         /* redraw the window's contents, and its shadow as well */
507         xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
508                                 region, d->damaged_region);
509
510         if (shadow) {
511             /* make sure the shadow region is right */
512             render_update_shadow(w, d, wd);
513             xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
514                                     wd->shadow_region, d->damaged_region);
515         }
516     }
517     else {
518         /* redraw the screen */
519         xcb_xfixes_copy_region(w->sc->dpy->conn, d->all_region,
520                                d->damaged_region);
521     }
522 }
523
524 static void
525 render_update_shadow(d_window_t *w, data_t *d, window_data_t *wd)
526 {
527     if (!wd->shadow_valid) {
528         xcb_xfixes_copy_region(w->sc->dpy->conn, window_get_region(w),
529                                wd->shadow_region);
530         xcb_xfixes_translate_region(w->sc->dpy->conn, wd->shadow_region,
531                                     d->xshadowoff, d->yshadowoff);
532         wd->shadow_valid = TRUE;
533     }
534 }
535
536
537 static void
538 render_window_opacity_change(d_window_t *w)
539 {
540     data_t *d;
541     window_data_t *wd;
542
543     d = screen_find_plugin_data(w->sc, plugin_id);
544     wd = window_find_plugin_data(w, plugin_id);
545
546     /* pass it on */
547     d->window_opacity_change(w);
548
549     assert(wd != NULL);
550
551     /* update the window and its shadows opacities */
552     render_update_opacity(w, d, wd);
553
554     /* redraw the window and its shadow */
555     render_redraw_window(w, d, TRUE, wd);
556
557     //printf("opacity change 0x%x\n", w->id);
558 }
559
560 static void
561 render_window_damage(d_window_t *w)
562 {
563     data_t *d;
564
565     d = screen_find_plugin_data(w->sc, plugin_id);
566
567     /* pass it on */
568     d->window_damage(w);
569
570     /* redraw the window not not its shadow */
571     render_redraw_window(w, d, FALSE, NULL);
572 }
573
574 static void
575 render_root_pixmap_change(d_screen_t *sc)
576 {
577     data_t *d;
578
579     d = screen_find_plugin_data(sc, plugin_id);
580     if (d->root_picture) {
581         xcb_render_free_picture(sc->dpy->conn, d->root_picture);
582         d->root_picture = XCB_NONE;
583     }
584
585     /* pass it on */
586     d->screen_root_pixmap_change(sc);
587
588     /* redraw the screen */
589     xcb_xfixes_copy_region(sc->dpy->conn, d->all_region, d->damaged_region);
590 }
591
592 static void
593 render_paint(d_screen_t *sc)
594 {
595     data_t *d = screen_find_plugin_data(sc, plugin_id);
596     d_list_it_t *it;
597
598     xcb_xfixes_copy_region(sc->dpy->conn, d->damaged_region, d->paint_region);
599
600     //printf("-- painting --\n");
601     for (it = list_top(sc->stacking); it; it = it->next) {
602         d_window_t *w = it->data;
603
604         if (!window_is_input_only(w) &&
605             (window_is_mapped(w) || window_is_zombie(w)))
606         {
607             int x, y, width, height, bwidth;
608             gboolean opaque;
609             window_data_t *wd;
610
611             window_get_area(w, &x, &y, &width, &height, &bwidth);
612
613             if (!(x < sc->super->width_in_pixels &&
614                   y < sc->super->height_in_pixels &&
615                   x + width > 0 && y + height > 0))
616             {
617                 continue;
618             }
619
620             opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
621
622             wd = window_find_plugin_data(w, plugin_id);
623
624             if (opaque) {
625                 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
626                                                    d->overlay_buffer,
627                                                    d->paint_region,
628                                                    0, 0);
629                 paint_window(w, d, wd, opaque,
630                              x, y, width, height, bwidth);
631
632                 /* remove this window from the paint region, as nothing is
633                    above it, so nothing should draw to this space again */
634                 xcb_xfixes_subtract_region(sc->dpy->conn, d->paint_region,
635                                            window_get_region(w),
636                                            d->paint_region);
637             }
638
639             /* save the clip region, when drawing windows (and shadows)
640                below this window, they should use this clip region */
641             xcb_xfixes_copy_region(sc->dpy->conn, d->paint_region,
642                                    wd->paint_clip);
643         }
644     }
645
646     xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
647                                        d->overlay_buffer,
648                                        d->paint_region,
649                                        0, 0);
650     paint_root(sc, d);
651
652     for (it = list_bottom(sc->stacking); it; it = it->prev) {
653         d_window_t *w = it->data;
654
655         if (!window_is_input_only(w) &&
656             (window_is_mapped(w) || window_is_zombie(w)))
657         {
658             int x, y, width, height, bwidth;
659             gboolean opaque;
660             window_data_t *wd;
661
662             window_get_area(w, &x, &y, &width, &height, &bwidth);
663
664             if (!(x < sc->super->width_in_pixels &&
665                   y < sc->super->height_in_pixels &&
666                   (x + width > 0 || x + width + d->xshadowoff > 0) &&
667                   (y + height > 0 || y + height + d->yshadowoff > 0)))
668             {
669                 continue;
670             }
671
672             opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
673
674             wd = window_find_plugin_data(w, plugin_id);
675
676             if (!wd->shadow_valid)
677                 render_update_shadow(w, d, wd);
678
679             /* shape the shadow to the window */
680             xcb_xfixes_intersect_region(sc->dpy->conn,
681                                         wd->paint_clip, wd->shadow_region,
682                                         d->shadow_paint_region);
683             xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
684                                                d->overlay_buffer,
685                                                d->shadow_paint_region,
686                                                0, 0);
687             paint_shadow(w, d, wd, x, y, width, height, bwidth);
688
689             if (!opaque) {
690                 /* use the clip region of the highest opaque window seen so
691                    far, as nothing should be able to draw on top of that region
692                 */
693                 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
694                                                    d->overlay_buffer,
695                                                    wd->paint_clip,
696                                                    0, 0);
697                 paint_window(w, d, wd, opaque, x, y, width, height, bwidth);
698             }
699         }
700     }
701
702     xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
703                                        d->overlay_buffer,
704                                        d->all_region,
705                                        0, 0);
706
707     /* copy the double buffer to the overlay window */
708 #ifndef MONITOR_REPAINT
709     xcb_render_composite(sc->dpy->conn,
710                          XCB_RENDER_PICT_OP_SRC,
711                          d->overlay_buffer,
712                          XCB_NONE,
713                          d->overlay_picture,
714                          0, 0, 0, 0,
715                          0, 0,
716                          sc->super->width_in_pixels,
717                          sc->super->height_in_pixels);
718 #endif
719
720     /* empty the damaged region */
721     xcb_xfixes_subtract_region(sc->dpy->conn, d->all_region,
722                                d->all_region, d->damaged_region);
723
724     /* call the function we replaced in the chain */
725     d->screen_paint(sc);
726 }
727
728 static void
729 paint_root(d_screen_t *sc, data_t *d)
730 {
731     xcb_render_picture_t src;
732     int op;
733
734     if (!d->root_picture)
735         render_update_root_picture(sc, d);
736
737     if (d->root_picture) {
738         src = d->root_picture;
739         op = XCB_RENDER_PICT_OP_SRC;
740     }
741     else {
742         src = d->solid_bg;
743         op = XCB_RENDER_PICT_OP_CLEAR;
744     }
745
746     xcb_render_composite(sc->dpy->conn,
747                          op,
748                          src,
749                          XCB_NONE,
750                          d->overlay_buffer,
751                          0, 0, 0, 0,
752                          0, 0,
753                          sc->super->width_in_pixels,
754                          sc->super->height_in_pixels);
755 }
756
757 static void
758 paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
759              int x, int y, int width, int height, int bwidth)
760 {
761     if (!wd->picture)
762         render_update_picture(w, d, wd);
763
764     //printf("-- paint window 0x%x picture 0x%x --\n", w->id, wd->picture);
765     if (wd->picture) {
766         xcb_render_picture_t alphamap;
767         int op;
768
769         if (opaque) {
770             op = XCB_RENDER_PICT_OP_SRC;
771             alphamap = XCB_NONE;
772         }
773         else {
774             op = XCB_RENDER_PICT_OP_OVER;
775             alphamap = wd->alpha_picture;
776         }
777
778         xcb_render_composite(w->sc->dpy->conn,
779                              op,
780                              wd->picture,
781                              alphamap,
782                              d->overlay_buffer,
783                              0, 0, 0, 0,
784                              x, y, width + bwidth*2, height + bwidth *2);
785     }
786 }
787
788 static void
789 paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
790              int x, int y, int width, int height, int bwidth)
791 {
792     xcb_render_composite(w->sc->dpy->conn,
793                          XCB_RENDER_PICT_OP_OVER,
794                          wd->shadow_picture,
795                          wd->picture,
796                          d->overlay_buffer,
797                          0, 0, 0, 0,
798                          x+d->xshadowoff, y+d->yshadowoff,
799                          width + bwidth*2, height + bwidth *2);
800
801 }