void (*window_show)(d_window_t *w);
void (*window_hide)(d_window_t *w);
void (*window_resize)(d_window_t *w);
- void (*window_reshape)(d_window_t *w);
xcb_render_pictformat_t root_format;
+ xcb_render_pictformat_t argb32_format;
xcb_render_query_pict_formats_reply_t *pict_formats;
xcb_render_picture_t overlay_picture;
xcb_render_picture_t overlay_buffer;
xcb_render_picture_t root_picture;
xcb_render_picture_t solid_bg;
+
+ xcb_xfixes_region_t all_region;
+ xcb_xfixes_region_t paint_region;
+ xcb_xfixes_region_t shadow_region;
+
+ double shadowalpha;
+ int xshadowoff;
+ int yshadowoff;
} data_t;
typedef struct {
xcb_render_picture_t picture;
+ xcb_render_picture_t shadow_picture;
+ xcb_xfixes_region_t paint_clip;
} window_data_t;
static void render_paint(d_screen_t *sc);
static void render_root_pixmap_changed(d_screen_t *sc);
static void paint_root(d_screen_t *sc, data_t *d);
-static void paint_window(d_window_t *window, data_t *d);
+static void paint_window(d_window_t *window, data_t *d, window_data_t *wd,
+ gboolean opaque);
+static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd);
static void render_update_picture(d_window_t *w, data_t *d, window_data_t *wd);
static void render_update_root_picture(d_screen_t *sc, data_t *d);
static void render_free_picture(d_window_t *w, window_data_t *wd);
static xcb_render_pictformat_t find_visual_format(data_t *d,
xcb_visualid_t visual);
-static xcb_render_picture_t solid_picture(d_screen_t *sc,
+static xcb_render_pictformat_t find_argb32_format(data_t *d);
+static xcb_render_picture_t solid_picture(data_t *d, d_screen_t *sc,
double a, double r,
double g, double b);
static void render_window_show(d_window_t *window);
static void render_window_hide(d_window_t *window);
static void render_window_resize(d_window_t *window);
-static void render_window_reshape(d_window_t *window);
void
render_init(d_screen_t *sc, int id)
{
xcb_render_query_pict_formats_cookie_t ck;
xcb_pixmap_t px;
+ xcb_rectangle_t rect;
plugin_id = id;
d->window_show = sc->window_show;
d->window_hide = sc->window_hide;
d->window_resize = sc->window_resize;
- d->window_reshape = sc->window_reshape;
screen_add_plugin_data(sc, plugin_id, d);
sc->screen_paint = render_paint;
sc->window_show = render_window_show;
sc->window_hide = render_window_hide;
sc->window_resize = render_window_resize;
- sc->window_reshape = render_window_reshape;
ck = xcb_render_query_pict_formats_unchecked(sc->dpy->conn);
d->pict_formats = xcb_render_query_pict_formats_reply(sc->dpy->conn, ck,
NULL);
d->root_format = find_visual_format(d, sc->super.root_visual);
+ d->argb32_format = find_argb32_format(d);
d->root_picture = XCB_NONE;
d->overlay_picture = xcb_generate_id(sc->dpy->conn);
d->root_format, 0, 0);
xcb_free_pixmap(sc->dpy->conn, px);
- d->solid_bg = solid_picture(sc, 1.0, 0.0, 0.0, 0.0);
+ d->solid_bg = solid_picture(d, sc, 1.0, 0.0, 0.0, 0.0);
+
+ d->all_region = xcb_generate_id(sc->dpy->conn);
+ d->paint_region = xcb_generate_id(sc->dpy->conn);
+ d->shadow_region = xcb_generate_id(sc->dpy->conn);
+ rect.x = rect.y = 0;
+ rect.width = sc->super.width_in_pixels;
+ rect.height = sc->super.height_in_pixels;
+ xcb_xfixes_create_region(sc->dpy->conn, d->all_region, 1, &rect);
+ xcb_xfixes_create_region(sc->dpy->conn, d->paint_region, 1, &rect);
+ xcb_xfixes_create_region(sc->dpy->conn, d->shadow_region, 1, &rect);
+
+ d->shadowalpha = 0.2;
+ d->xshadowoff = 2;
+ d->yshadowoff = 2;
}
void
xcb_render_free_picture(sc->dpy->conn, d->root_picture);
xcb_render_free_picture(sc->dpy->conn, d->overlay_picture);
xcb_render_free_picture(sc->dpy->conn, d->overlay_buffer);
+ xcb_xfixes_destroy_region(sc->dpy->conn, d->all_region);
+ xcb_xfixes_destroy_region(sc->dpy->conn, d->paint_region);
+ xcb_xfixes_destroy_region(sc->dpy->conn, d->shadow_region);
free(d);
screen_remove_plugin_data(sc, plugin_id);
}
render_window_free(d_window_t *w, window_data_t *wd)
{
render_free_picture(w, wd);
+ if (wd->shadow_picture) {
+ xcb_render_free_picture(w->sc->dpy->conn, wd->shadow_picture);
+ wd->shadow_picture = XCB_NONE;
+ }
free(wd);
}
{
data_t *d;
window_data_t *wd;
+ xcb_rectangle_t rect;
d = screen_find_plugin_data(w->sc, plugin_id);
wd = malloc(sizeof(window_data_t));
wd->picture = XCB_NONE;
+ wd->shadow_picture = solid_picture(d, w->sc, d->shadowalpha,
+ 0.0, 0.0, 0.0);
+
+ wd->paint_clip = xcb_generate_id(w->sc->dpy->conn);
+ rect.x = rect.y = 0;
+ rect.width = rect.height = 1;
+ xcb_xfixes_create_region(w->sc->dpy->conn, wd->paint_clip, 1, &rect);
+
window_add_plugin_data(w, plugin_id, wd);
window_ref(w);
wd = window_find_plugin_data(w, plugin_id);
if (wd) {
render_window_free(w, wd);
+ xcb_xfixes_destroy_region(w->sc->dpy->conn, wd->paint_clip);
window_remove_plugin_data(w, plugin_id);
}
}
static xcb_render_picture_t
-solid_picture(d_screen_t *sc, double a, double r, double g, double b)
+solid_picture(data_t *d, d_screen_t *sc,
+ double a, double r, double g, double b)
{
+ xcb_pixmap_t pixmap;
xcb_render_picture_t picture;
xcb_render_color_t c;
+ const uint32_t vals = XCB_RENDER_REPEAT_NORMAL;
+ const xcb_rectangle_t rect = { 0, 0, 1, 1 };
+
+ pixmap = xcb_generate_id(sc->dpy->conn);
+ picture = xcb_generate_id(sc->dpy->conn);
- picture = xcb_generate_id (sc->dpy->conn);
+ xcb_create_pixmap(sc->dpy->conn, 32, pixmap, sc->super.root, 1, 1);
+ xcb_render_create_picture(sc->dpy->conn, picture, pixmap, d->argb32_format,
+ XCB_RENDER_CP_REPEAT, &vals);
c.alpha = a * 0xffff;
- c.red = a * r * 0xffff;
- c.green = a * g * 0xffff;
- c.blue = a * b * 0xffff;
+ c.red = r * 0xffff;
+ c.green = g * 0xffff;
+ c.blue = b * 0xffff;
+
+ xcb_render_fill_rectangles(sc->dpy->conn, XCB_RENDER_PICT_OP_SRC,
+ picture, c, 1, &rect);
+ xcb_free_pixmap(sc->dpy->conn, pixmap);
- xcb_render_create_solid_fill (sc->dpy->conn, picture, c);
return picture;
}
static xcb_render_pictformat_t
+find_argb32_format(data_t *d)
+{
+ xcb_render_pictforminfo_iterator_t it;
+
+ for (it = xcb_render_query_pict_formats_formats_iterator(d->pict_formats);
+ it.rem; xcb_render_pictforminfo_next(&it))
+ {
+ xcb_render_pictforminfo_t *format = it.data;
+ if (format->type == XCB_RENDER_PICT_TYPE_DIRECT) {
+ if (format->depth == 32 &&
+ format->direct.alpha_mask == 0xff &&
+ format->direct.red_mask == 0xff &&
+ format->direct.green_mask == 0xff &&
+ format->direct.blue_mask == 0xff &&
+ format->direct.alpha_shift == 24 &&
+ format->direct.red_shift == 16 &&
+ format->direct.green_shift == 8 &&
+ format->direct.blue_shift == 0)
+ return format->id;
+ }
+ }
+ return XCB_NONE;
+}
+
+static xcb_render_pictformat_t
find_visual_format(data_t *d, xcb_visualid_t visual)
{
xcb_render_pictscreen_iterator_t si;
wd->picture, px, format,
XCB_RENDER_CP_SUBWINDOW_MODE,
&vals);
-
- xcb_xfixes_set_picture_clip_region(w->sc->dpy->conn,
- wd->picture,
- window_get_region(w),
- 0, 0);
-
}
}
static void
-render_window_reshape(d_window_t *w)
-{
- data_t *d;
- window_data_t *wd;
-
- d = screen_find_plugin_data(w->sc, plugin_id);
- wd = window_find_plugin_data(w, plugin_id);
-
- /* pass it on, and let the window update it's region before we query
- it */
- d->window_reshape(w);
-
- if (wd->picture)
- xcb_xfixes_set_picture_clip_region(w->sc->dpy->conn,
- wd->picture,
- window_get_region(w),
- 0, 0);
-}
-
-static void
render_window_resize(d_window_t *w)
{
data_t *d;
data_t *d = screen_find_plugin_data(sc, plugin_id);
d_list_it_t *it;
+ xcb_xfixes_copy_region(sc->dpy->conn, d->all_region, d->paint_region);
+
//printf("-- painting --\n");
+ for (it = list_top(sc->stacking); it; it = it->next) {
+ d_window_t *w = it->data;
+
+ if (!window_is_input_only(w) && window_is_mapped(w)) {
+ gboolean opaque = !window_is_argb(w);
+ window_data_t *wd;
+
+ wd = window_find_plugin_data(w, plugin_id);
+
+ if (opaque) {
+
+ paint_window(w, d, wd, opaque);
+
+ /* remove this window from the paint region, as nothing is
+ above it, so nothing should draw to this space again */
+ xcb_xfixes_subtract_region(sc->dpy->conn, d->paint_region,
+ window_get_region(w),
+ d->paint_region);
+ xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
+ d->overlay_buffer,
+ d->paint_region,
+ 0, 0);
+ }
+
+ /* save the clip region, when drawing windows (and shadows)
+ below this window, they should use this clip region */
+ xcb_xfixes_copy_region(sc->dpy->conn, d->paint_region,
+ wd->paint_clip);
+ }
+ }
+
paint_root(sc, d);
-#if 1
+
+ xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
+ d->overlay_buffer,
+ d->paint_region,
+ 0, 0);
+
for (it = list_bottom(sc->stacking); it; it = it->prev) {
d_window_t *w = it->data;
- if (!window_is_input_only(w) && window_is_mapped(w))
- paint_window(w, d);
+
+ if (!window_is_input_only(w) && window_is_mapped(w)) {
+ window_data_t *wd;
+ gboolean opaque = !window_is_argb(w);
+
+ wd = window_find_plugin_data(w, plugin_id);
+
+ if (opaque) {
+ /* shape the shadow to the window */
+ xcb_xfixes_copy_region(sc->dpy->conn, window_get_region(w),
+ d->shadow_region);
+ xcb_xfixes_translate_region(sc->dpy->conn, d->shadow_region,
+ d->xshadowoff, d->yshadowoff);
+ xcb_xfixes_intersect_region(sc->dpy->conn,
+ wd->paint_clip, d->shadow_region,
+ d->shadow_region);
+ xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
+ d->overlay_buffer,
+ d->shadow_region,
+ 0, 0);
+ paint_shadow(w, d, wd);
+ }
+ else {
+ /* use the clip region of the highest opaque window seen so
+ far, as nothing should be able to draw on top of that region
+ */
+ xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
+ d->overlay_buffer,
+ wd->paint_clip,
+ 0, 0);
+ paint_window(w, d, wd, opaque);
+ }
+ }
}
-#endif
+
+ xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
+ d->overlay_buffer,
+ d->all_region,
+ 0, 0);
/* copy the double buffer to the overlay window */
xcb_render_composite(sc->dpy->conn,
}
static void
-paint_window(d_window_t *w, data_t *d)
+paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque)
{
- window_data_t *wd;
-
- wd = window_find_plugin_data(w, plugin_id);
-
if (!wd->picture)
render_update_picture(w, d, wd);
int op;
window_get_area(w, &x, &y, &width, &height, &bwidth);
- op = (window_is_argb(w) ?
- XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC);
+ op = !opaque ?
+ XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC;
xcb_render_composite(w->sc->dpy->conn,
op,
x, y, width + bwidth*2, height + bwidth *2);
}
}
+
+static void
+paint_shadow(d_window_t *w, data_t *d, window_data_t *wd)
+{
+ int x, y, width, height, bwidth;
+
+ window_get_area(w, &x, &y, &width, &height, &bwidth);
+ xcb_render_composite(w->sc->dpy->conn,
+ XCB_RENDER_PICT_OP_OVER,
+ wd->shadow_picture,
+ XCB_NONE,
+ d->overlay_buffer,
+ 0, 0, 0, 0,
+ x+d->xshadowoff, y+d->yshadowoff,
+ width + bwidth*2, height + bwidth *2);
+
+}