void (*screen_root_pixmap_change)(d_screen_t *sc);
void (*window_show)(d_window_t *w);
void (*window_zombie_dead)(d_window_t *w);
+ void (*window_move)(d_window_t *w);
void (*window_resize)(d_window_t *w);
+ void (*window_reshape)(d_window_t *w);
+ void (*window_restack)(d_window_t *w, d_window_t *above);
void (*window_opacity_change)(d_window_t *w);
+ void (*window_damage)(d_window_t *w);
xcb_render_pictformat_t root_format;
xcb_render_pictformat_t argb32_format;
xcb_render_picture_t solid_bg;
xcb_xfixes_region_t all_region;
+ xcb_xfixes_region_t damaged_region;
xcb_xfixes_region_t paint_region;
- xcb_xfixes_region_t shadow_region;
+ xcb_xfixes_region_t shadow_paint_region;
uint16_t shadowalpha;
int xshadowoff;
typedef struct {
xcb_render_picture_t picture;
+ xcb_render_picture_t alpha_picture;
xcb_render_picture_t shadow_picture;
xcb_xfixes_region_t paint_clip;
+ xcb_xfixes_region_t shadow_region;
+ gboolean shadow_valid;
} window_data_t;
static void render_paint(d_screen_t *sc);
int height, int bwidth);
static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
int x, int y, int width, int height, int bwidth);
-static void render_update_shadow_picture(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_picture_t solid_picture(data_t *d, d_screen_t *sc,
uint16_t a, uint16_t r,
uint16_t g, uint16_t b);
+static void render_update_opacity(d_window_t *w, data_t *d, window_data_t *wd);
+static void render_update_shadow(d_window_t *w, data_t *d, window_data_t *wd);
static void render_window_show(d_window_t *window);
static void render_window_zombie_dead(d_window_t *window);
+static void render_window_move(d_window_t *window);
static void render_window_resize(d_window_t *window);
+static void render_window_reshape(d_window_t *window);
+static void render_window_restack(d_window_t *window, d_window_t *above);
static void render_window_opacity_change(d_window_t *w);
+static void render_window_damage(d_window_t *w);
void
render_init(d_screen_t *sc, int id)
d->screen_root_pixmap_change = sc->screen_root_pixmap_change;
d->window_show = sc->window_show;
d->window_zombie_dead = sc->window_zombie_dead;
+ d->window_move = sc->window_move;
d->window_resize = sc->window_resize;
+ d->window_reshape = sc->window_reshape;
+ d->window_restack = sc->window_restack;
d->window_opacity_change = sc->window_opacity_change;
+ d->window_damage = sc->window_damage;
screen_add_plugin_data(sc, plugin_id, d);
sc->screen_paint = render_paint;
sc->screen_root_pixmap_change = render_root_pixmap_change;
sc->window_show = render_window_show;
sc->window_zombie_dead = render_window_zombie_dead;
+ sc->window_move = render_window_move;
sc->window_resize = render_window_resize;
+ sc->window_reshape = render_window_reshape;
+ sc->window_restack = render_window_restack;
sc->window_opacity_change = render_window_opacity_change;
+ sc->window_damage = render_window_damage;
ck = xcb_render_query_pict_formats_unchecked(sc->dpy->conn);
d->pict_formats = xcb_render_query_pict_formats_reply(sc->dpy->conn, ck,
d->solid_bg = solid_picture(d, sc, 0xffff, 0x6060, 02020, 0x3030);
d->all_region = xcb_generate_id(sc->dpy->conn);
+ d->damaged_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);
+ d->shadow_paint_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->damaged_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);
+ xcb_xfixes_create_region(sc->dpy->conn, d->shadow_paint_region, 1, &rect);
d->shadowalpha = 0x3333; /* 20% */
d->xshadowoff = 2;
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->damaged_region);
xcb_xfixes_destroy_region(sc->dpy->conn, d->paint_region);
- xcb_xfixes_destroy_region(sc->dpy->conn, d->shadow_region);
+ xcb_xfixes_destroy_region(sc->dpy->conn, d->shadow_paint_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;
- }
+ xcb_render_free_picture(w->sc->dpy->conn, wd->alpha_picture);
+ xcb_render_free_picture(w->sc->dpy->conn, wd->shadow_picture);
+ xcb_xfixes_destroy_region(w->sc->dpy->conn, wd->paint_clip);
+ xcb_xfixes_destroy_region(w->sc->dpy->conn, wd->shadow_region);
free(wd);
}
wd->picture = XCB_NONE;
wd->paint_clip = xcb_generate_id(w->sc->dpy->conn);
- rect.x = rect.y = 0;
+ wd->shadow_region = xcb_generate_id(w->sc->dpy->conn);
+ rect.x = rect.y = -1;
rect.width = rect.height = 1;
xcb_xfixes_create_region(w->sc->dpy->conn, wd->paint_clip, 1, &rect);
+ xcb_xfixes_create_region(w->sc->dpy->conn, wd->shadow_region, 1, &rect);
- render_update_shadow_picture(w, d, wd);
+ wd->shadow_valid = FALSE;
+
+ wd->alpha_picture = solid_picture(d, w->sc, 0, 0, 0, 0);
+ wd->shadow_picture = solid_picture(d, w->sc, 0, 0, 0, 0);
+
+ render_update_opacity(w, d, wd);
window_add_plugin_data(w, plugin_id, wd);
}
+static void
+render_update_opacity(d_window_t *w, data_t *d, window_data_t *wd)
+{
+ static xcb_render_color_t c = { 0, 0, 0, 0 };
+ static xcb_rectangle_t rect = {0, 0, 1, 1};
+ unsigned long a;
+
+ /* make the window's shadow and alpha-map match its current opacity */
+ c.alpha = window_get_opacity(w);
+ xcb_render_fill_rectangles(w->sc->dpy->conn,
+ XCB_RENDER_PICT_OP_SRC,
+ wd->alpha_picture, c, 1, &rect);
+ a = d->shadowalpha;
+ a = a * window_get_opacity(w) / 0xffff;
+ //if (w->id == 0x1811453)
+ // printf("window opacity 0x%x\n", c.alpha);
+ c.alpha = a;
+ if (w->id == 0x1811453)
+ printf("shadow opacity 0x%04x\n", c.alpha);
+ xcb_render_fill_rectangles(w->sc->dpy->conn,
+ XCB_RENDER_PICT_OP_SRC,
+ wd->shadow_picture, c, 1, &rect);
+}
+
static void
render_window_zombie_dead(d_window_t *w)
{
d = screen_find_plugin_data(w->sc, plugin_id);
wd = window_find_plugin_data(w, plugin_id);
if (wd) {
+ /* make sure the shadow region is right */
+ render_update_shadow(w, d, wd);
+
+ /* redraw the window's area, and its shadow's as well */
+ xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
+ window_get_region(w), d->damaged_region);
+ xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
+ wd->shadow_region, d->damaged_region);
+
render_window_free(w, wd);
- xcb_xfixes_destroy_region(w->sc->dpy->conn, wd->paint_clip);
window_remove_plugin_data(w, plugin_id);
}
}
}
-static void
-render_update_shadow_picture(d_window_t *w, data_t *d, window_data_t *wd)
-{
- if (wd->shadow_picture)
- xcb_render_free_picture(w->sc->dpy->conn, wd->shadow_picture);
- wd->shadow_picture = solid_picture(d, w->sc,
- d->shadowalpha *
- window_get_opacity(w) / 0xffff,
- 0, 0, 0);
-}
-
static void
render_update_root_picture(d_screen_t *sc, data_t *d)
{
}
}
+static void
+render_window_move(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 */
+ d->window_move(w);
+
+ d = screen_find_plugin_data(w->sc, plugin_id);
+
+ /* redraw the screen */
+ xcb_xfixes_copy_region(w->sc->dpy->conn, d->all_region, d->damaged_region);
+ /* reget the shadow's shape */
+ wd->shadow_valid = FALSE;
+}
+
static void
render_window_resize(d_window_t *w)
{
assert(wd != NULL);
render_free_picture(w, wd);
+
+ /* redraw the screen */
+ xcb_xfixes_copy_region(w->sc->dpy->conn, d->all_region, d->damaged_region);
+ /* reget the shadow's shape */
+ wd->shadow_valid = FALSE;
+}
+
+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 */
+ d->window_reshape(w);
+
+ assert(wd != NULL);
+ render_free_picture(w, wd);
+
+ /* redraw the screen */
+ xcb_xfixes_copy_region(w->sc->dpy->conn, d->all_region, d->damaged_region);
+ /* reget the shadow's shape */
+ wd->shadow_valid = FALSE;
}
+static void
+render_window_restack(d_window_t *w, d_window_t *above)
+{
+ 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 */
+ d->window_restack(w, above);
+
+ assert(wd != NULL);
+
+ /* make sure the shadow region is right */
+ render_update_shadow(w, d, wd);
+
+ /* redraw the window's contents, and its shadow as well */
+ xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
+ window_get_region(w), d->damaged_region);
+ xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
+ wd->shadow_region, d->damaged_region);
+}
+
+static void
+render_update_shadow(d_window_t *w, data_t *d, window_data_t *wd)
+{
+ if (!wd->shadow_valid) {
+ xcb_xfixes_copy_region(w->sc->dpy->conn, window_get_region(w),
+ wd->shadow_region);
+ xcb_xfixes_translate_region(w->sc->dpy->conn, wd->shadow_region,
+ d->xshadowoff, d->yshadowoff);
+ wd->shadow_valid = TRUE;
+ }
+}
+
+
static void
render_window_opacity_change(d_window_t *w)
{
d->window_opacity_change(w);
assert(wd != NULL);
- render_update_shadow_picture(w, d, wd);
+
+ /* update the window and its shadows opacities */
+ render_update_opacity(w, d, wd);
+
+ /* make sure the shadow region is right */
+ render_update_shadow(w, d, wd);
+
+ /* redraw the window's contents, and its shadow as well */
+ xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
+ window_get_region(w), d->damaged_region);
+ xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
+ wd->shadow_region, d->damaged_region);
+
+ //printf("opacity change 0x%x\n", w->id);
+}
+
+static void
+render_window_damage(d_window_t *w)
+{
+ data_t *d;
+
+ d = screen_find_plugin_data(w->sc, plugin_id);
+
+ /* pass it on */
+ d->window_damage(w);
+
+ /* redraw the window's contents */
+ xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
+ window_get_region(w), d->damaged_region);
}
static void
/* pass it on */
d->screen_root_pixmap_change(sc);
+
+ /* redraw the screen */
+ xcb_xfixes_copy_region(sc->dpy->conn, d->all_region, d->damaged_region);
}
static void
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);
+ xcb_xfixes_copy_region(sc->dpy->conn, d->damaged_region, d->paint_region);
//printf("-- painting --\n");
for (it = list_top(sc->stacking); it; it = it->next) {
d_window_t *w = it->data;
- int x, y, width, height, bwidth;
-
- window_get_area(w, &x, &y, &width, &height, &bwidth);
if (!window_is_input_only(w) &&
- (window_is_mapped(w) || window_is_zombie(w)) &&
- x < sc->super.width_in_pixels &&
- y < sc->super.height_in_pixels &&
- x + width > 0 && y + height > 0)
+ (window_is_mapped(w) || window_is_zombie(w)))
{
- gboolean opaque = !(window_is_argb(w) ||
- window_get_opacity(w) < 0xffff);
+ int x, y, width, height, bwidth;
+ gboolean opaque;
window_data_t *wd;
+ window_get_area(w, &x, &y, &width, &height, &bwidth);
+
+ if (!(x < sc->super.width_in_pixels &&
+ y < sc->super.height_in_pixels &&
+ x + width > 0 && y + height > 0))
+ {
+ continue;
+ }
+
+ opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
+
wd = window_find_plugin_data(w, plugin_id);
if (opaque) {
- paint_window(w, d, wd, opaque, x, y, width, height, bwidth);
+ xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
+ d->overlay_buffer,
+ d->paint_region,
+ 0, 0);
+ paint_window(w, d, wd, opaque,
+ x, y, width, height, bwidth);
/* 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)
paint_root(sc, d);
- 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;
- int x, y, width, height, bwidth;
-
- window_get_area(w, &x, &y, &width, &height, &bwidth);
if (!window_is_input_only(w) &&
- (window_is_mapped(w) || window_is_zombie(w)) &&
- x < sc->super.width_in_pixels &&
- y < sc->super.height_in_pixels &&
- (x + width > 0 || x + width + d->xshadowoff > 0) &&
- (y + height > 0 || y + height + d->yshadowoff > 0))
+ (window_is_mapped(w) || window_is_zombie(w)))
{
+ int x, y, width, height, bwidth;
+ gboolean opaque;
window_data_t *wd;
- gboolean opaque = !(window_is_argb(w) ||
- window_get_opacity(w) < 0xffff);
+
+ window_get_area(w, &x, &y, &width, &height, &bwidth);
+
+ if (!(x < sc->super.width_in_pixels &&
+ y < sc->super.height_in_pixels &&
+ (x + width > 0 || x + width + d->xshadowoff > 0) &&
+ (y + height > 0 || y + height + d->yshadowoff > 0)))
+ {
+ continue;
+ }
+
+ opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
wd = window_find_plugin_data(w, plugin_id);
+ if (!wd->shadow_valid)
+ render_update_shadow(w, d, wd);
+
/* 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);
+ wd->paint_clip, wd->shadow_region,
+ d->shadow_paint_region);
xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
d->overlay_buffer,
- d->shadow_region,
+ d->shadow_paint_region,
0, 0);
paint_shadow(w, d, wd, x, y, width, height, bwidth);
sc->super.width_in_pixels,
sc->super.height_in_pixels);
+ /* empty the damaged region */
+ xcb_xfixes_subtract_region(sc->dpy->conn, d->all_region,
+ d->all_region, d->damaged_region);
+
/* call the function we replaced in the chain */
d->screen_paint(sc);
}
paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
int x, int y, int width, int height, int bwidth)
{
- xcb_render_picture_t alphamap;
-
if (!wd->picture)
render_update_picture(w, d, wd);
//printf("-- paint window 0x%x picture 0x%x --\n", w->id, wd->picture);
if (wd->picture) {
+ xcb_render_picture_t alphamap;
int op;
- op = !opaque ?
- XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC;
-
- if (opaque)
+ if (opaque) {
+ op = XCB_RENDER_PICT_OP_SRC;
alphamap = XCB_NONE;
- else
- alphamap = solid_picture(d, w->sc, window_get_opacity(w), 0, 0, 0);
+ }
+ else {
+ op = XCB_RENDER_PICT_OP_OVER;
+ alphamap = wd->alpha_picture;
+ }
xcb_render_composite(w->sc->dpy->conn,
op,