ad0b8dec99ac336e293ec553ccdbb0ffc0d863af
[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     ck = xcb_render_query_pict_formats_unchecked(sc->dpy->conn);
120     d->pict_formats = xcb_render_query_pict_formats_reply(sc->dpy->conn, ck,
121                                                           NULL);
122
123     d->root_format = find_visual_format(d, sc->super.root_visual);
124     d->argb32_format = find_argb32_format(d);
125     d->root_picture = XCB_NONE;
126
127     d->overlay_picture = xcb_generate_id(sc->dpy->conn);
128     xcb_render_create_picture(sc->dpy->conn,
129                               d->overlay_picture, sc->overlay, d->root_format,
130                               0, NULL);
131
132     /* make the double buffer */
133     px = xcb_generate_id(sc->dpy->conn);
134     xcb_create_pixmap(sc->dpy->conn, sc->super.root_depth, px,
135                       sc->super.root, sc->super.width_in_pixels,
136                       sc->super.height_in_pixels);
137     d->overlay_buffer = xcb_generate_id(sc->dpy->conn);
138 #ifdef MONITOR_REPAINT
139     xcb_render_create_picture(sc->dpy->conn,
140                               d->overlay_buffer, sc->overlay, d->root_format,
141                               0, NULL);
142 #else
143     xcb_render_create_picture(sc->dpy->conn, d->overlay_buffer, px,
144                               d->root_format, 0, 0);
145 #endif
146     xcb_free_pixmap(sc->dpy->conn, px);
147
148     d->solid_bg = solid_picture(d, sc, 0xffff, 0x6060, 02020, 0x3030);
149
150     d->all_region = xcb_generate_id(sc->dpy->conn);
151     d->damaged_region = xcb_generate_id(sc->dpy->conn);
152     d->paint_region = xcb_generate_id(sc->dpy->conn);
153     d->shadow_paint_region = xcb_generate_id(sc->dpy->conn);
154     rect.x = rect.y = 0;
155     rect.width = sc->super.width_in_pixels;
156     rect.height = sc->super.height_in_pixels;
157     xcb_xfixes_create_region(sc->dpy->conn, d->all_region, 1, &rect);
158     xcb_xfixes_create_region(sc->dpy->conn, d->damaged_region, 1, &rect);
159     xcb_xfixes_create_region(sc->dpy->conn, d->paint_region, 1, &rect);
160     xcb_xfixes_create_region(sc->dpy->conn, d->shadow_paint_region, 1, &rect);
161
162     d->shadowalpha = 0x3333; /* 20% */
163     d->xshadowoff = 2;
164     d->yshadowoff = 2;
165 }
166
167 void
168 render_free(d_screen_t *sc)
169 {
170     data_t *d = screen_find_plugin_data(sc, plugin_id);
171     free(d->pict_formats);
172     xcb_render_free_picture(sc->dpy->conn, d->solid_bg);
173     if (d->root_picture)
174         xcb_render_free_picture(sc->dpy->conn, d->root_picture);
175     xcb_render_free_picture(sc->dpy->conn, d->overlay_picture);
176     xcb_render_free_picture(sc->dpy->conn, d->overlay_buffer);
177     xcb_xfixes_destroy_region(sc->dpy->conn, d->all_region);
178     xcb_xfixes_destroy_region(sc->dpy->conn, d->damaged_region);
179     xcb_xfixes_destroy_region(sc->dpy->conn, d->paint_region);
180     xcb_xfixes_destroy_region(sc->dpy->conn, d->shadow_paint_region);
181     free(d);
182     screen_remove_plugin_data(sc, plugin_id);
183 }
184
185 int
186 render_next_timeout(struct d_screen *sc, struct timeval *tv)
187 {
188     (void)sc;
189     (void)tv;
190     return FALSE;
191 }
192
193 void
194 render_timeout(struct d_screen *sc, const struct timeval *now)
195 {
196     (void)sc; (void)now;
197 }
198
199 void
200 render_window_free(d_window_t *w, window_data_t *wd)
201 {
202     render_free_picture(w, wd);
203     xcb_render_free_picture(w->sc->dpy->conn, wd->alpha_picture);
204     xcb_render_free_picture(w->sc->dpy->conn, wd->shadow_picture);
205     xcb_xfixes_destroy_region(w->sc->dpy->conn, wd->paint_clip);
206     xcb_xfixes_destroy_region(w->sc->dpy->conn, wd->shadow_region);
207     free(wd);
208 }
209
210 static void
211 render_window_show(d_window_t *w)
212 {
213     data_t *d;
214     window_data_t *wd;
215     xcb_rectangle_t rect;
216
217     d = screen_find_plugin_data(w->sc, plugin_id);
218
219     /* pass it on */
220     d->window_show(w);
221
222     wd = window_find_plugin_data(w, plugin_id);
223     if (wd)
224         render_window_free(w, wd);
225    
226     wd = malloc(sizeof(window_data_t));
227     wd->picture = XCB_NONE;
228
229     wd->paint_clip = xcb_generate_id(w->sc->dpy->conn);
230     wd->shadow_region = xcb_generate_id(w->sc->dpy->conn);
231     rect.x = rect.y = -1;
232     rect.width = rect.height = 1;
233     xcb_xfixes_create_region(w->sc->dpy->conn, wd->paint_clip, 1, &rect);
234     xcb_xfixes_create_region(w->sc->dpy->conn, wd->shadow_region, 1, &rect);
235
236     wd->shadow_valid = FALSE;
237
238     wd->alpha_picture = solid_picture(d, w->sc, 0, 0, 0, 0);
239     wd->shadow_picture = solid_picture(d, w->sc, 0, 0, 0, 0);
240
241     render_update_opacity(w, d, wd);
242
243     window_add_plugin_data(w, plugin_id, wd);
244 }
245
246 static void 
247 render_update_opacity(d_window_t *w, data_t *d, window_data_t *wd)
248 {
249     static xcb_render_color_t c = { 0, 0, 0, 0 };
250     static xcb_rectangle_t rect = {0, 0, 1, 1};
251     unsigned long a;
252
253     /* make the window's shadow and alpha-map match its current opacity */
254     c.alpha = window_get_opacity(w);
255     xcb_render_fill_rectangles(w->sc->dpy->conn,
256                                XCB_RENDER_PICT_OP_SRC,
257                                wd->alpha_picture, c, 1, &rect);
258     a = d->shadowalpha;
259     a = a * window_get_opacity(w) / 0xffff;
260     c.alpha = a;
261     xcb_render_fill_rectangles(w->sc->dpy->conn,
262                                XCB_RENDER_PICT_OP_SRC,
263                                wd->shadow_picture, c, 1, &rect);
264 }
265
266 static void
267 render_window_zombie_dead(d_window_t *w)
268 {
269     data_t *d;
270     window_data_t *wd;
271
272     d = screen_find_plugin_data(w->sc, plugin_id);
273     wd = window_find_plugin_data(w, plugin_id);
274     if (wd) {
275         /* make sure the shadow region is right */
276         render_update_shadow(w, d, wd);
277
278         /* redraw the window's area, and its shadow's as well */
279         xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
280                                 window_get_region(w), d->damaged_region);
281         xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
282                                 wd->shadow_region, d->damaged_region);
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     d = screen_find_plugin_data(w->sc, plugin_id);
432
433     /* redraw the screen */
434     xcb_xfixes_copy_region(w->sc->dpy->conn, d->all_region, d->damaged_region);
435     /* reget the shadow's shape */
436     wd->shadow_valid = FALSE;
437 }
438
439 static void
440 render_window_resize(d_window_t *w)
441 {
442     data_t *d;
443     window_data_t *wd;
444
445     d = screen_find_plugin_data(w->sc, plugin_id);
446     wd = window_find_plugin_data(w, plugin_id);
447
448     /* pass it on */
449     d->window_resize(w);
450
451     assert(wd != NULL);
452     render_free_picture(w, wd);
453
454     /* redraw the screen */
455     xcb_xfixes_copy_region(w->sc->dpy->conn, d->all_region, d->damaged_region);
456     /* reget the shadow's shape */
457     wd->shadow_valid = FALSE;
458 }
459
460 static void
461 render_window_reshape(d_window_t *w)
462 {
463     data_t *d;
464     window_data_t *wd;
465
466     d = screen_find_plugin_data(w->sc, plugin_id);
467     wd = window_find_plugin_data(w, plugin_id);
468
469     /* pass it on */
470     d->window_reshape(w);
471
472     assert(wd != NULL);
473     render_free_picture(w, wd);
474
475     /* redraw the screen */
476     xcb_xfixes_copy_region(w->sc->dpy->conn, d->all_region, d->damaged_region);
477     /* reget the shadow's shape */
478     wd->shadow_valid = FALSE;
479 }
480
481 static void
482 render_window_restack(d_window_t *w, d_window_t *above)
483 {
484     data_t *d;
485     window_data_t *wd;
486
487     d = screen_find_plugin_data(w->sc, plugin_id);
488     wd = window_find_plugin_data(w, plugin_id);
489
490     /* pass it on */
491     d->window_restack(w, above);
492
493     assert(wd != NULL);
494
495     /* make sure the shadow region is right */
496     render_update_shadow(w, d, wd);
497
498     /* redraw the window's contents, and its shadow as well */
499     xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
500                             window_get_region(w), d->damaged_region);
501     xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
502                             wd->shadow_region, d->damaged_region);
503 }
504
505 static void
506 render_update_shadow(d_window_t *w, data_t *d, window_data_t *wd)
507 {
508     if (!wd->shadow_valid) {
509         xcb_xfixes_copy_region(w->sc->dpy->conn, window_get_region(w),
510                                wd->shadow_region);
511         xcb_xfixes_translate_region(w->sc->dpy->conn, wd->shadow_region,
512                                     d->xshadowoff, d->yshadowoff);
513         wd->shadow_valid = TRUE;
514     }
515 }
516
517
518 static void
519 render_window_opacity_change(d_window_t *w)
520 {
521     data_t *d;
522     window_data_t *wd;
523
524     d = screen_find_plugin_data(w->sc, plugin_id);
525     wd = window_find_plugin_data(w, plugin_id);
526
527     /* pass it on */
528     d->window_opacity_change(w);
529
530     assert(wd != NULL);
531
532     /* update the window and its shadows opacities */
533     render_update_opacity(w, d, wd);
534
535     /* make sure the shadow region is right */
536     render_update_shadow(w, d, wd);
537
538     /* redraw the window's contents, and its shadow as well */
539     xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
540                             window_get_region(w), d->damaged_region);
541     xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
542                             wd->shadow_region, d->damaged_region);
543
544     //printf("opacity change 0x%x\n", w->id);
545 }
546
547 static void
548 render_window_damage(d_window_t *w)
549 {
550     data_t *d;
551
552     d = screen_find_plugin_data(w->sc, plugin_id);
553
554     /* pass it on */
555     d->window_damage(w);
556
557     /* redraw the window's contents */
558     xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
559                             window_get_region(w), d->damaged_region);
560 }
561
562 static void
563 render_root_pixmap_change(d_screen_t *sc)
564 {
565     data_t *d;
566
567     d = screen_find_plugin_data(sc, plugin_id);
568     if (d->root_picture) {
569         xcb_render_free_picture(sc->dpy->conn, d->root_picture);
570         d->root_picture = XCB_NONE;
571     }
572
573     /* pass it on */
574     d->screen_root_pixmap_change(sc);
575
576     /* redraw the screen */
577     xcb_xfixes_copy_region(sc->dpy->conn, d->all_region, d->damaged_region);
578 }
579
580 static void
581 render_paint(d_screen_t *sc)
582 {
583     data_t *d = screen_find_plugin_data(sc, plugin_id);
584     d_list_it_t *it;
585
586     xcb_xfixes_copy_region(sc->dpy->conn, d->damaged_region, d->paint_region);
587
588     //printf("-- painting --\n");
589     for (it = list_top(sc->stacking); it; it = it->next) {
590         d_window_t *w = it->data;
591
592         if (!window_is_input_only(w) &&
593             (window_is_mapped(w) || window_is_zombie(w)))
594         {
595             int x, y, width, height, bwidth;
596             gboolean opaque;
597             window_data_t *wd;
598
599             window_get_area(w, &x, &y, &width, &height, &bwidth);
600
601             if (!(x < sc->super.width_in_pixels &&
602                   y < sc->super.height_in_pixels &&
603                   x + width > 0 && y + height > 0))
604             {
605                 continue;
606             }
607
608             opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
609
610             wd = window_find_plugin_data(w, plugin_id);
611
612             if (opaque) {
613                 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
614                                                    d->overlay_buffer,
615                                                    d->paint_region,
616                                                    0, 0);
617                 paint_window(w, d, wd, opaque,
618                              x, y, width, height, bwidth);
619
620                 /* remove this window from the paint region, as nothing is
621                    above it, so nothing should draw to this space again */
622                 xcb_xfixes_subtract_region(sc->dpy->conn, d->paint_region,
623                                            window_get_region(w),
624                                            d->paint_region);
625             }
626
627             /* save the clip region, when drawing windows (and shadows)
628                below this window, they should use this clip region */
629             xcb_xfixes_copy_region(sc->dpy->conn, d->paint_region,
630                                    wd->paint_clip);
631         }
632     }
633
634     xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
635                                        d->overlay_buffer,
636                                        d->paint_region,
637                                        0, 0);
638     paint_root(sc, d);
639
640     for (it = list_bottom(sc->stacking); it; it = it->prev) {
641         d_window_t *w = it->data;
642
643         if (!window_is_input_only(w) &&
644             (window_is_mapped(w) || window_is_zombie(w)))
645         {
646             int x, y, width, height, bwidth;
647             gboolean opaque;
648             window_data_t *wd;
649
650             window_get_area(w, &x, &y, &width, &height, &bwidth);
651
652             if (!(x < sc->super.width_in_pixels &&
653                   y < sc->super.height_in_pixels &&
654                   (x + width > 0 || x + width + d->xshadowoff > 0) &&
655                   (y + height > 0 || y + height + d->yshadowoff > 0)))
656             {
657                 continue;
658             }
659
660             opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
661
662             wd = window_find_plugin_data(w, plugin_id);
663
664             if (!wd->shadow_valid)
665                 render_update_shadow(w, d, wd);
666
667             /* shape the shadow to the window */
668             xcb_xfixes_intersect_region(sc->dpy->conn,
669                                         wd->paint_clip, wd->shadow_region,
670                                         d->shadow_paint_region);
671             xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
672                                                d->overlay_buffer,
673                                                d->shadow_paint_region,
674                                                0, 0);
675             paint_shadow(w, d, wd, x, y, width, height, bwidth);
676
677             if (!opaque) {
678                 /* use the clip region of the highest opaque window seen so
679                    far, as nothing should be able to draw on top of that region
680                 */
681                 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
682                                                    d->overlay_buffer,
683                                                    wd->paint_clip,
684                                                    0, 0);
685                 paint_window(w, d, wd, opaque, x, y, width, height, bwidth);
686             }
687         }
688     }
689
690     xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
691                                        d->overlay_buffer,
692                                        d->all_region,
693                                        0, 0);
694
695     /* copy the double buffer to the overlay window */
696 #ifndef MONITOR_REPAINT
697     xcb_render_composite(sc->dpy->conn,
698                          XCB_RENDER_PICT_OP_SRC,
699                          d->overlay_buffer,
700                          XCB_NONE,
701                          d->overlay_picture,
702                          0, 0, 0, 0,
703                          0, 0,
704                          sc->super.width_in_pixels,
705                          sc->super.height_in_pixels);
706 #endif
707
708     /* empty the damaged region */
709     xcb_xfixes_subtract_region(sc->dpy->conn, d->all_region,
710                                d->all_region, d->damaged_region);
711
712     /* call the function we replaced in the chain */
713     d->screen_paint(sc);
714 }
715
716 static void
717 paint_root(d_screen_t *sc, data_t *d)
718 {
719     xcb_render_picture_t src;
720     int op;
721
722     if (!d->root_picture)
723         render_update_root_picture(sc, d);
724
725     if (d->root_picture) {
726         src = d->root_picture;
727         op = XCB_RENDER_PICT_OP_SRC;
728     }
729     else {
730         src = d->solid_bg;
731         op = XCB_RENDER_PICT_OP_CLEAR;
732     }
733
734     xcb_render_composite(sc->dpy->conn,
735                          op,
736                          src,
737                          XCB_NONE,
738                          d->overlay_buffer,
739                          0, 0, 0, 0,
740                          0, 0,
741                          sc->super.width_in_pixels,
742                          sc->super.height_in_pixels);
743 }
744
745 static void
746 paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
747              int x, int y, int width, int height, int bwidth)
748 {
749     if (!wd->picture)
750         render_update_picture(w, d, wd);
751
752     //printf("-- paint window 0x%x picture 0x%x --\n", w->id, wd->picture);
753     if (wd->picture) {
754         xcb_render_picture_t alphamap;
755         int op;
756
757         if (opaque) {
758             op = XCB_RENDER_PICT_OP_SRC;
759             alphamap = XCB_NONE;
760         }
761         else {
762             op = XCB_RENDER_PICT_OP_OVER;
763             alphamap = wd->alpha_picture;
764         }
765
766         xcb_render_composite(w->sc->dpy->conn,
767                              op,
768                              wd->picture,
769                              alphamap,
770                              d->overlay_buffer,
771                              0, 0, 0, 0,
772                              x, y, width + bwidth*2, height + bwidth *2);
773     }
774 }
775
776 static void
777 paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
778              int x, int y, int width, int height, int bwidth)
779 {
780     xcb_render_composite(w->sc->dpy->conn,
781                          XCB_RENDER_PICT_OP_OVER,
782                          wd->shadow_picture,
783                          wd->picture,
784                          d->overlay_buffer,
785                          0, 0, 0, 0,
786                          x+d->xshadowoff, y+d->yshadowoff,
787                          width + bwidth*2, height + bwidth *2);
788
789 }