excess
[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     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     /* 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     assert(wd != NULL);
492
493     /* make sure the shadow region is right */
494     render_update_shadow(w, d, wd);
495
496     /* redraw the window's contents, and its shadow as well */
497     xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
498                             window_get_region(w), d->damaged_region);
499     xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
500                             wd->shadow_region, d->damaged_region);
501 }
502
503 static void
504 render_update_shadow(d_window_t *w, data_t *d, window_data_t *wd)
505 {
506     if (!wd->shadow_valid) {
507         xcb_xfixes_copy_region(w->sc->dpy->conn, window_get_region(w),
508                                wd->shadow_region);
509         xcb_xfixes_translate_region(w->sc->dpy->conn, wd->shadow_region,
510                                     d->xshadowoff, d->yshadowoff);
511         wd->shadow_valid = TRUE;
512     }
513 }
514
515
516 static void
517 render_window_opacity_change(d_window_t *w)
518 {
519     data_t *d;
520     window_data_t *wd;
521
522     d = screen_find_plugin_data(w->sc, plugin_id);
523     wd = window_find_plugin_data(w, plugin_id);
524
525     /* pass it on */
526     d->window_opacity_change(w);
527
528     assert(wd != NULL);
529
530     /* update the window and its shadows opacities */
531     render_update_opacity(w, d, wd);
532
533     /* make sure the shadow region is right */
534     render_update_shadow(w, d, wd);
535
536     /* redraw the window's contents, and its shadow as well */
537     xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
538                             window_get_region(w), d->damaged_region);
539     xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
540                             wd->shadow_region, d->damaged_region);
541
542     //printf("opacity change 0x%x\n", w->id);
543 }
544
545 static void
546 render_window_damage(d_window_t *w)
547 {
548     data_t *d;
549
550     d = screen_find_plugin_data(w->sc, plugin_id);
551
552     /* pass it on */
553     d->window_damage(w);
554
555     /* redraw the window's contents */
556     xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
557                             window_get_region(w), d->damaged_region);
558 }
559
560 static void
561 render_root_pixmap_change(d_screen_t *sc)
562 {
563     data_t *d;
564
565     d = screen_find_plugin_data(sc, plugin_id);
566     if (d->root_picture) {
567         xcb_render_free_picture(sc->dpy->conn, d->root_picture);
568         d->root_picture = XCB_NONE;
569     }
570
571     /* pass it on */
572     d->screen_root_pixmap_change(sc);
573
574     /* redraw the screen */
575     xcb_xfixes_copy_region(sc->dpy->conn, d->all_region, d->damaged_region);
576 }
577
578 static void
579 render_paint(d_screen_t *sc)
580 {
581     data_t *d = screen_find_plugin_data(sc, plugin_id);
582     d_list_it_t *it;
583
584     xcb_xfixes_copy_region(sc->dpy->conn, d->damaged_region, d->paint_region);
585
586     //printf("-- painting --\n");
587     for (it = list_top(sc->stacking); it; it = it->next) {
588         d_window_t *w = it->data;
589
590         if (!window_is_input_only(w) &&
591             (window_is_mapped(w) || window_is_zombie(w)))
592         {
593             int x, y, width, height, bwidth;
594             gboolean opaque;
595             window_data_t *wd;
596
597             window_get_area(w, &x, &y, &width, &height, &bwidth);
598
599             if (!(x < sc->super.width_in_pixels &&
600                   y < sc->super.height_in_pixels &&
601                   x + width > 0 && y + height > 0))
602             {
603                 continue;
604             }
605
606             opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
607
608             wd = window_find_plugin_data(w, plugin_id);
609
610             if (opaque) {
611                 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
612                                                    d->overlay_buffer,
613                                                    d->paint_region,
614                                                    0, 0);
615                 paint_window(w, d, wd, opaque,
616                              x, y, width, height, bwidth);
617
618                 /* remove this window from the paint region, as nothing is
619                    above it, so nothing should draw to this space again */
620                 xcb_xfixes_subtract_region(sc->dpy->conn, d->paint_region,
621                                            window_get_region(w),
622                                            d->paint_region);
623             }
624
625             /* save the clip region, when drawing windows (and shadows)
626                below this window, they should use this clip region */
627             xcb_xfixes_copy_region(sc->dpy->conn, d->paint_region,
628                                    wd->paint_clip);
629         }
630     }
631
632     xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
633                                        d->overlay_buffer,
634                                        d->paint_region,
635                                        0, 0);
636     paint_root(sc, d);
637
638     for (it = list_bottom(sc->stacking); it; it = it->prev) {
639         d_window_t *w = it->data;
640
641         if (!window_is_input_only(w) &&
642             (window_is_mapped(w) || window_is_zombie(w)))
643         {
644             int x, y, width, height, bwidth;
645             gboolean opaque;
646             window_data_t *wd;
647
648             window_get_area(w, &x, &y, &width, &height, &bwidth);
649
650             if (!(x < sc->super.width_in_pixels &&
651                   y < sc->super.height_in_pixels &&
652                   (x + width > 0 || x + width + d->xshadowoff > 0) &&
653                   (y + height > 0 || y + height + d->yshadowoff > 0)))
654             {
655                 continue;
656             }
657
658             opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
659
660             wd = window_find_plugin_data(w, plugin_id);
661
662             if (!wd->shadow_valid)
663                 render_update_shadow(w, d, wd);
664
665             /* shape the shadow to the window */
666             xcb_xfixes_intersect_region(sc->dpy->conn,
667                                         wd->paint_clip, wd->shadow_region,
668                                         d->shadow_paint_region);
669             xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
670                                                d->overlay_buffer,
671                                                d->shadow_paint_region,
672                                                0, 0);
673             paint_shadow(w, d, wd, x, y, width, height, bwidth);
674
675             if (!opaque) {
676                 /* use the clip region of the highest opaque window seen so
677                    far, as nothing should be able to draw on top of that region
678                 */
679                 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
680                                                    d->overlay_buffer,
681                                                    wd->paint_clip,
682                                                    0, 0);
683                 paint_window(w, d, wd, opaque, x, y, width, height, bwidth);
684             }
685         }
686     }
687
688     xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
689                                        d->overlay_buffer,
690                                        d->all_region,
691                                        0, 0);
692
693     /* copy the double buffer to the overlay window */
694 #ifndef MONITOR_REPAINT
695     xcb_render_composite(sc->dpy->conn,
696                          XCB_RENDER_PICT_OP_SRC,
697                          d->overlay_buffer,
698                          XCB_NONE,
699                          d->overlay_picture,
700                          0, 0, 0, 0,
701                          0, 0,
702                          sc->super.width_in_pixels,
703                          sc->super.height_in_pixels);
704 #endif
705
706     /* empty the damaged region */
707     xcb_xfixes_subtract_region(sc->dpy->conn, d->all_region,
708                                d->all_region, d->damaged_region);
709
710     /* call the function we replaced in the chain */
711     d->screen_paint(sc);
712 }
713
714 static void
715 paint_root(d_screen_t *sc, data_t *d)
716 {
717     xcb_render_picture_t src;
718     int op;
719
720     if (!d->root_picture)
721         render_update_root_picture(sc, d);
722
723     if (d->root_picture) {
724         src = d->root_picture;
725         op = XCB_RENDER_PICT_OP_SRC;
726     }
727     else {
728         src = d->solid_bg;
729         op = XCB_RENDER_PICT_OP_CLEAR;
730     }
731
732     xcb_render_composite(sc->dpy->conn,
733                          op,
734                          src,
735                          XCB_NONE,
736                          d->overlay_buffer,
737                          0, 0, 0, 0,
738                          0, 0,
739                          sc->super.width_in_pixels,
740                          sc->super.height_in_pixels);
741 }
742
743 static void
744 paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
745              int x, int y, int width, int height, int bwidth)
746 {
747     if (!wd->picture)
748         render_update_picture(w, d, wd);
749
750     //printf("-- paint window 0x%x picture 0x%x --\n", w->id, wd->picture);
751     if (wd->picture) {
752         xcb_render_picture_t alphamap;
753         int op;
754
755         if (opaque) {
756             op = XCB_RENDER_PICT_OP_SRC;
757             alphamap = XCB_NONE;
758         }
759         else {
760             op = XCB_RENDER_PICT_OP_OVER;
761             alphamap = wd->alpha_picture;
762         }
763
764         xcb_render_composite(w->sc->dpy->conn,
765                              op,
766                              wd->picture,
767                              alphamap,
768                              d->overlay_buffer,
769                              0, 0, 0, 0,
770                              x, y, width + bwidth*2, height + bwidth *2);
771     }
772 }
773
774 static void
775 paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
776              int x, int y, int width, int height, int bwidth)
777 {
778     xcb_render_composite(w->sc->dpy->conn,
779                          XCB_RENDER_PICT_OP_OVER,
780                          wd->shadow_picture,
781                          wd->picture,
782                          d->overlay_buffer,
783                          0, 0, 0, 0,
784                          x+d->xshadowoff, y+d->yshadowoff,
785                          width + bwidth*2, height + bwidth *2);
786
787 }