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