the callback for restack is called even when window is not visible now (and disabling...
[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    
228     wd = malloc(sizeof(window_data_t));
229     wd->picture = XCB_NONE;
230
231     wd->paint_clip = xcb_generate_id(w->sc->dpy->conn);
232     wd->shadow_region = xcb_generate_id(w->sc->dpy->conn);
233     rect.x = rect.y = -1;
234     rect.width = rect.height = 1;
235     xcb_xfixes_create_region(w->sc->dpy->conn, wd->paint_clip, 1, &rect);
236     xcb_xfixes_create_region(w->sc->dpy->conn, wd->shadow_region, 1, &rect);
237
238     wd->shadow_valid = FALSE;
239
240     wd->alpha_picture = solid_picture(d, w->sc, 0, 0, 0, 0);
241     wd->shadow_picture = solid_picture(d, w->sc, 0, 0, 0, 0);
242
243     render_update_opacity(w, d, wd);
244
245     window_add_plugin_data(w, plugin_id, wd);
246 }
247
248 static void 
249 render_update_opacity(d_window_t *w, data_t *d, window_data_t *wd)
250 {
251     static xcb_render_color_t c = { 0, 0, 0, 0 };
252     static xcb_rectangle_t rect = {0, 0, 1, 1};
253     unsigned long a;
254
255     /* make the window's shadow and alpha-map match its current opacity */
256     c.alpha = window_get_opacity(w);
257     xcb_render_fill_rectangles(w->sc->dpy->conn,
258                                XCB_RENDER_PICT_OP_SRC,
259                                wd->alpha_picture, c, 1, &rect);
260     a = d->shadowalpha;
261     a = a * window_get_opacity(w) / 0xffff;
262     c.alpha = a;
263     xcb_render_fill_rectangles(w->sc->dpy->conn,
264                                XCB_RENDER_PICT_OP_SRC,
265                                wd->shadow_picture, c, 1, &rect);
266 }
267
268 static void
269 render_window_zombie_dead(d_window_t *w)
270 {
271     data_t *d;
272     window_data_t *wd;
273
274     d = screen_find_plugin_data(w->sc, plugin_id);
275     wd = window_find_plugin_data(w, plugin_id);
276     if (wd) {
277         /* make sure the shadow region is right */
278         render_update_shadow(w, d, wd);
279
280         /* redraw the window's area, and its shadow's as well */
281         xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
282                                 window_get_region(w), d->damaged_region);
283         xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
284                                 wd->shadow_region, d->damaged_region);
285
286         render_window_free(w, wd);
287         window_remove_plugin_data(w, plugin_id);
288     }
289
290     /* pass it on */
291     d->window_zombie_dead(w);
292 }
293
294 static xcb_render_picture_t
295 solid_picture(data_t *d, d_screen_t *sc, uint16_t a, uint16_t r,
296               uint16_t g, uint16_t b)
297 {
298     xcb_pixmap_t pixmap;
299     xcb_render_picture_t picture;
300     xcb_render_color_t   c;
301     const uint32_t vals = XCB_RENDER_REPEAT_NORMAL;
302     const xcb_rectangle_t rect = { 0, 0, 1, 1 };
303
304     pixmap = xcb_generate_id(sc->dpy->conn);
305     picture = xcb_generate_id(sc->dpy->conn);
306
307     xcb_create_pixmap(sc->dpy->conn, 32, pixmap, sc->super->root, 1, 1);
308     xcb_render_create_picture(sc->dpy->conn, picture, pixmap, d->argb32_format,
309                               XCB_RENDER_CP_REPEAT, &vals);
310
311     c.alpha = a;
312     c.red   = r;
313     c.green = g;
314     c.blue  = b;
315
316     xcb_render_fill_rectangles(sc->dpy->conn, XCB_RENDER_PICT_OP_SRC,
317                                picture, c, 1, &rect);
318     xcb_free_pixmap(sc->dpy->conn, pixmap);
319
320     return picture;
321 }
322
323 static xcb_render_pictformat_t
324 find_argb32_format(data_t *d)
325 {
326     xcb_render_pictforminfo_iterator_t it;
327
328     for (it = xcb_render_query_pict_formats_formats_iterator(d->pict_formats);
329          it.rem; xcb_render_pictforminfo_next(&it))
330     {
331         xcb_render_pictforminfo_t *format = it.data;
332         if (format->type == XCB_RENDER_PICT_TYPE_DIRECT) {
333             if (format->depth              == 32   &&
334                 format->direct.alpha_mask  == 0xff &&
335                 format->direct.red_mask    == 0xff &&
336                 format->direct.green_mask  == 0xff &&
337                 format->direct.blue_mask   == 0xff &&
338                 format->direct.alpha_shift == 24   &&
339                 format->direct.red_shift   == 16   &&
340                 format->direct.green_shift == 8    &&
341                 format->direct.blue_shift  == 0)
342                 return format->id;
343         }
344     }
345     return XCB_NONE;
346 }
347
348 static xcb_render_pictformat_t
349 find_visual_format(data_t *d, xcb_visualid_t visual)
350 {
351     xcb_render_pictscreen_iterator_t si;
352     xcb_render_pictdepth_iterator_t di;
353     xcb_render_pictvisual_iterator_t vi;
354
355     if (!visual) return XCB_NONE;
356
357     /* go through all the screens */
358     si = xcb_render_query_pict_formats_screens_iterator(d->pict_formats);
359     for (; si.rem; xcb_render_pictscreen_next(&si)) {
360         di = xcb_render_pictscreen_depths_iterator(si.data);
361         for (; di.rem; xcb_render_pictdepth_next(&di)) {
362             vi = xcb_render_pictdepth_visuals_iterator(di.data);
363             for (; vi.rem; xcb_render_pictvisual_next(&vi)) {
364                 if (vi.data->visual == visual)
365                     return vi.data->format;
366             }
367         }
368     }
369     return XCB_NONE;
370 }
371
372 static void
373 render_free_picture(d_window_t *w, window_data_t *wd)
374 {
375     /* this might cause an error, oh well */
376     if (wd->picture) {
377         xcb_render_free_picture(w->sc->dpy->conn, wd->picture);
378         wd->picture = XCB_NONE;
379     }
380 }
381
382 static void
383 render_update_root_picture(d_screen_t *sc, data_t *d)
384 {
385     xcb_pixmap_t px;
386
387     px = screen_get_root_pixmap(sc);
388     if (px) {
389         d->root_picture = xcb_generate_id(sc->dpy->conn);
390         xcb_render_create_picture(sc->dpy->conn,
391                                   d->root_picture, px,
392                                   d->root_format, 0, NULL);
393     }
394 }
395
396 static void
397 render_update_picture(d_window_t *w, data_t *d, window_data_t *wd)
398 {
399     xcb_pixmap_t px;
400
401     px = window_get_pixmap(w);
402     //printf("got pixmap 0x%x\n", px);
403     if (px) {
404         xcb_render_pictformat_t format;
405         const uint32_t vals = XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS;
406
407         render_free_picture(w, wd);
408
409         wd->picture = xcb_generate_id(w->sc->dpy->conn);
410         format = find_visual_format(d, window_get_visual(w));
411         /* we don't need to check this.  if it fails, we'll just be drawing
412            an invalid picture and creating some X errors but that's no big
413            deal really */
414         xcb_render_create_picture(w->sc->dpy->conn,
415                                   wd->picture, px, format,
416                                   XCB_RENDER_CP_SUBWINDOW_MODE,
417                                   &vals);
418     }
419 }
420
421 static void
422 render_window_move(d_window_t *w)
423 {
424     data_t *d;
425     window_data_t *wd;
426
427     d = screen_find_plugin_data(w->sc, plugin_id);
428     wd = window_find_plugin_data(w, plugin_id);
429
430     /* pass it on */
431     d->window_move(w);
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     /* the window might not be visible */
494     if (wd == NULL) return;
495
496     /* make sure the shadow region is right */
497     render_update_shadow(w, d, wd);
498
499     /* redraw the window's contents, and its shadow as well */
500     xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
501                             window_get_region(w), d->damaged_region);
502     xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
503                             wd->shadow_region, d->damaged_region);
504 }
505
506 static void
507 render_update_shadow(d_window_t *w, data_t *d, window_data_t *wd)
508 {
509     if (!wd->shadow_valid) {
510         xcb_xfixes_copy_region(w->sc->dpy->conn, window_get_region(w),
511                                wd->shadow_region);
512         xcb_xfixes_translate_region(w->sc->dpy->conn, wd->shadow_region,
513                                     d->xshadowoff, d->yshadowoff);
514         wd->shadow_valid = TRUE;
515     }
516 }
517
518
519 static void
520 render_window_opacity_change(d_window_t *w)
521 {
522     data_t *d;
523     window_data_t *wd;
524
525     d = screen_find_plugin_data(w->sc, plugin_id);
526     wd = window_find_plugin_data(w, plugin_id);
527
528     /* pass it on */
529     d->window_opacity_change(w);
530
531     assert(wd != NULL);
532
533     /* update the window and its shadows opacities */
534     render_update_opacity(w, d, wd);
535
536     /* make sure the shadow region is right */
537     render_update_shadow(w, d, wd);
538
539     /* redraw the window's contents, and its shadow as well */
540     xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
541                             window_get_region(w), d->damaged_region);
542     xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
543                             wd->shadow_region, d->damaged_region);
544
545     //printf("opacity change 0x%x\n", w->id);
546 }
547
548 static void
549 render_window_damage(d_window_t *w)
550 {
551     data_t *d;
552
553     d = screen_find_plugin_data(w->sc, plugin_id);
554
555     /* pass it on */
556     d->window_damage(w);
557
558     /* redraw the window's contents */
559     xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
560                             window_get_region(w), d->damaged_region);
561 }
562
563 static void
564 render_root_pixmap_change(d_screen_t *sc)
565 {
566     data_t *d;
567
568     d = screen_find_plugin_data(sc, plugin_id);
569     if (d->root_picture) {
570         xcb_render_free_picture(sc->dpy->conn, d->root_picture);
571         d->root_picture = XCB_NONE;
572     }
573
574     /* pass it on */
575     d->screen_root_pixmap_change(sc);
576
577     /* redraw the screen */
578     xcb_xfixes_copy_region(sc->dpy->conn, d->all_region, d->damaged_region);
579 }
580
581 static void
582 render_paint(d_screen_t *sc)
583 {
584     data_t *d = screen_find_plugin_data(sc, plugin_id);
585     d_list_it_t *it;
586
587     xcb_xfixes_copy_region(sc->dpy->conn, d->damaged_region, d->paint_region);
588
589     //printf("-- painting --\n");
590     for (it = list_top(sc->stacking); it; it = it->next) {
591         d_window_t *w = it->data;
592
593         if (!window_is_input_only(w) &&
594             (window_is_mapped(w) || window_is_zombie(w)))
595         {
596             int x, y, width, height, bwidth;
597             gboolean opaque;
598             window_data_t *wd;
599
600             window_get_area(w, &x, &y, &width, &height, &bwidth);
601
602             if (!(x < sc->super->width_in_pixels &&
603                   y < sc->super->height_in_pixels &&
604                   x + width > 0 && y + height > 0))
605             {
606                 continue;
607             }
608
609             opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
610
611             wd = window_find_plugin_data(w, plugin_id);
612
613             if (opaque) {
614                 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
615                                                    d->overlay_buffer,
616                                                    d->paint_region,
617                                                    0, 0);
618                 paint_window(w, d, wd, opaque,
619                              x, y, width, height, bwidth);
620
621                 /* remove this window from the paint region, as nothing is
622                    above it, so nothing should draw to this space again */
623                 xcb_xfixes_subtract_region(sc->dpy->conn, d->paint_region,
624                                            window_get_region(w),
625                                            d->paint_region);
626             }
627
628             /* save the clip region, when drawing windows (and shadows)
629                below this window, they should use this clip region */
630             xcb_xfixes_copy_region(sc->dpy->conn, d->paint_region,
631                                    wd->paint_clip);
632         }
633     }
634
635     xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
636                                        d->overlay_buffer,
637                                        d->paint_region,
638                                        0, 0);
639     paint_root(sc, d);
640
641     for (it = list_bottom(sc->stacking); it; it = it->prev) {
642         d_window_t *w = it->data;
643
644         if (!window_is_input_only(w) &&
645             (window_is_mapped(w) || window_is_zombie(w)))
646         {
647             int x, y, width, height, bwidth;
648             gboolean opaque;
649             window_data_t *wd;
650
651             window_get_area(w, &x, &y, &width, &height, &bwidth);
652
653             if (!(x < sc->super->width_in_pixels &&
654                   y < sc->super->height_in_pixels &&
655                   (x + width > 0 || x + width + d->xshadowoff > 0) &&
656                   (y + height > 0 || y + height + d->yshadowoff > 0)))
657             {
658                 continue;
659             }
660
661             opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
662
663             wd = window_find_plugin_data(w, plugin_id);
664
665             if (!wd->shadow_valid)
666                 render_update_shadow(w, d, wd);
667
668             /* shape the shadow to the window */
669             xcb_xfixes_intersect_region(sc->dpy->conn,
670                                         wd->paint_clip, wd->shadow_region,
671                                         d->shadow_paint_region);
672             xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
673                                                d->overlay_buffer,
674                                                d->shadow_paint_region,
675                                                0, 0);
676             paint_shadow(w, d, wd, x, y, width, height, bwidth);
677
678             if (!opaque) {
679                 /* use the clip region of the highest opaque window seen so
680                    far, as nothing should be able to draw on top of that region
681                 */
682                 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
683                                                    d->overlay_buffer,
684                                                    wd->paint_clip,
685                                                    0, 0);
686                 paint_window(w, d, wd, opaque, x, y, width, height, bwidth);
687             }
688         }
689     }
690
691     xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
692                                        d->overlay_buffer,
693                                        d->all_region,
694                                        0, 0);
695
696     /* copy the double buffer to the overlay window */
697 #ifndef MONITOR_REPAINT
698     xcb_render_composite(sc->dpy->conn,
699                          XCB_RENDER_PICT_OP_SRC,
700                          d->overlay_buffer,
701                          XCB_NONE,
702                          d->overlay_picture,
703                          0, 0, 0, 0,
704                          0, 0,
705                          sc->super->width_in_pixels,
706                          sc->super->height_in_pixels);
707 #endif
708
709     /* empty the damaged region */
710     xcb_xfixes_subtract_region(sc->dpy->conn, d->all_region,
711                                d->all_region, d->damaged_region);
712
713     /* call the function we replaced in the chain */
714     d->screen_paint(sc);
715 }
716
717 static void
718 paint_root(d_screen_t *sc, data_t *d)
719 {
720     xcb_render_picture_t src;
721     int op;
722
723     if (!d->root_picture)
724         render_update_root_picture(sc, d);
725
726     if (d->root_picture) {
727         src = d->root_picture;
728         op = XCB_RENDER_PICT_OP_SRC;
729     }
730     else {
731         src = d->solid_bg;
732         op = XCB_RENDER_PICT_OP_CLEAR;
733     }
734
735     xcb_render_composite(sc->dpy->conn,
736                          op,
737                          src,
738                          XCB_NONE,
739                          d->overlay_buffer,
740                          0, 0, 0, 0,
741                          0, 0,
742                          sc->super->width_in_pixels,
743                          sc->super->height_in_pixels);
744 }
745
746 static void
747 paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
748              int x, int y, int width, int height, int bwidth)
749 {
750     if (!wd->picture)
751         render_update_picture(w, d, wd);
752
753     //printf("-- paint window 0x%x picture 0x%x --\n", w->id, wd->picture);
754     if (wd->picture) {
755         xcb_render_picture_t alphamap;
756         int op;
757
758         if (opaque) {
759             op = XCB_RENDER_PICT_OP_SRC;
760             alphamap = XCB_NONE;
761         }
762         else {
763             op = XCB_RENDER_PICT_OP_OVER;
764             alphamap = wd->alpha_picture;
765         }
766
767         xcb_render_composite(w->sc->dpy->conn,
768                              op,
769                              wd->picture,
770                              alphamap,
771                              d->overlay_buffer,
772                              0, 0, 0, 0,
773                              x, y, width + bwidth*2, height + bwidth *2);
774     }
775 }
776
777 static void
778 paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
779              int x, int y, int width, int height, int bwidth)
780 {
781     xcb_render_composite(w->sc->dpy->conn,
782                          XCB_RENDER_PICT_OP_OVER,
783                          wd->shadow_picture,
784                          wd->picture,
785                          d->overlay_buffer,
786                          0, 0, 0, 0,
787                          x+d->xshadowoff, y+d->yshadowoff,
788                          width + bwidth*2, height + bwidth *2);
789
790 }