From: Dana Jansens Date: Thu, 6 Mar 2008 09:55:56 +0000 (-0500) Subject: make the render code use the window's opacity X-Git-Url: http://git.openbox.org/?a=commitdiff_plain;h=e6f285535ef0d29cacca4a29ad0f7ca3deae2181;p=dana%2Fdcompmgr.git make the render code use the window's opacity --- diff --git a/dcompmgr.c b/dcompmgr.c index 175abde..b3619ba 100644 --- a/dcompmgr.c +++ b/dcompmgr.c @@ -190,7 +190,7 @@ event(d_display_t *dpy) pev->atom == dpy->a.esetroot_pmap_id || pev->atom == dpy->a.xsetroot_id) { - sc->screen_root_pixmap_changed(sc); + sc->screen_root_pixmap_change(sc); } break; } diff --git a/render.c b/render.c index 267f81a..795d824 100644 --- a/render.c +++ b/render.c @@ -14,10 +14,11 @@ static int plugin_id; typedef struct { void (*screen_paint)(d_screen_t *sc); - void (*screen_root_pixmap_changed)(d_screen_t *sc); + void (*screen_root_pixmap_change)(d_screen_t *sc); void (*window_show)(d_window_t *w); void (*window_hide)(d_window_t *w); void (*window_resize)(d_window_t *w); + void (*window_opacity_change)(d_window_t *w); xcb_render_pictformat_t root_format; xcb_render_pictformat_t argb32_format; @@ -31,7 +32,7 @@ typedef struct { xcb_xfixes_region_t paint_region; xcb_xfixes_region_t shadow_region; - double shadowalpha; + uint16_t shadowalpha; int xshadowoff; int yshadowoff; } data_t; @@ -43,11 +44,15 @@ typedef struct { } window_data_t; static void render_paint(d_screen_t *sc); -static void render_root_pixmap_changed(d_screen_t *sc); +static void render_root_pixmap_change(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, window_data_t *wd, - gboolean opaque); -static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd); + gboolean opaque, int x, int y, int width, + 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); @@ -55,12 +60,13 @@ static xcb_render_pictformat_t find_visual_format(data_t *d, xcb_visualid_t visual); 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); + uint16_t a, uint16_t r, + uint16_t g, uint16_t 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_opacity_change(d_window_t *w); void render_init(d_screen_t *sc, int id) @@ -73,17 +79,19 @@ render_init(d_screen_t *sc, int id) data_t *d = malloc(sizeof(data_t)); d->screen_paint = sc->screen_paint; - d->screen_root_pixmap_changed = sc->screen_root_pixmap_changed; + d->screen_root_pixmap_change = sc->screen_root_pixmap_change; d->window_show = sc->window_show; d->window_hide = sc->window_hide; d->window_resize = sc->window_resize; + d->window_opacity_change = sc->window_opacity_change; screen_add_plugin_data(sc, plugin_id, d); sc->screen_paint = render_paint; - sc->screen_root_pixmap_changed = render_root_pixmap_changed; + sc->screen_root_pixmap_change = render_root_pixmap_change; sc->window_show = render_window_show; sc->window_hide = render_window_hide; sc->window_resize = render_window_resize; + sc->window_opacity_change = render_window_opacity_change; ck = xcb_render_query_pict_formats_unchecked(sc->dpy->conn); d->pict_formats = xcb_render_query_pict_formats_reply(sc->dpy->conn, ck, @@ -108,7 +116,7 @@ render_init(d_screen_t *sc, int id) d->root_format, 0, 0); xcb_free_pixmap(sc->dpy->conn, px); - d->solid_bg = solid_picture(d, sc, 1.0, 0.0, 0.0, 0.0); + d->solid_bg = solid_picture(d, sc, 0xffff, 0x6060, 02020, 0x3030); d->all_region = xcb_generate_id(sc->dpy->conn); d->paint_region = xcb_generate_id(sc->dpy->conn); @@ -120,7 +128,7 @@ render_init(d_screen_t *sc, int id) 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->shadowalpha = 0x3333; /* 20% */ d->xshadowoff = 2; d->yshadowoff = 2; } @@ -171,14 +179,14 @@ render_window_show(d_window_t *w) 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); + render_update_shadow_picture(w, d, wd); + window_add_plugin_data(w, plugin_id, wd); window_ref(w); @@ -203,8 +211,8 @@ render_window_hide(d_window_t *w) } static xcb_render_picture_t -solid_picture(data_t *d, d_screen_t *sc, - double a, double r, double g, double b) +solid_picture(data_t *d, d_screen_t *sc, uint16_t a, uint16_t r, + uint16_t g, uint16_t b) { xcb_pixmap_t pixmap; xcb_render_picture_t picture; @@ -219,10 +227,10 @@ solid_picture(data_t *d, d_screen_t *sc, xcb_render_create_picture(sc->dpy->conn, picture, pixmap, d->argb32_format, XCB_RENDER_CP_REPEAT, &vals); - c.alpha = a * 0xffff; - c.red = r * 0xffff; - c.green = g * 0xffff; - c.blue = b * 0xffff; + c.alpha = a; + c.red = r; + c.green = g; + c.blue = b; xcb_render_fill_rectangles(sc->dpy->conn, XCB_RENDER_PICT_OP_SRC, picture, c, 1, &rect); @@ -290,6 +298,17 @@ render_free_picture(d_window_t *w, window_data_t *wd) } } +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) { @@ -298,9 +317,9 @@ render_update_root_picture(d_screen_t *sc, data_t *d) px = screen_get_root_pixmap(sc); if (px) { d->root_picture = xcb_generate_id(sc->dpy->conn); - xcb_render_create_picture_checked(sc->dpy->conn, - d->root_picture, px, - d->root_format, 0, NULL); + xcb_render_create_picture(sc->dpy->conn, + d->root_picture, px, + d->root_format, 0, NULL); } } @@ -346,7 +365,23 @@ render_window_resize(d_window_t *w) } static void -render_root_pixmap_changed(d_screen_t *sc) +render_window_opacity_change(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_opacity_change(w); + + assert(wd != NULL); + render_update_shadow_picture(w, d, wd); +} + +static void +render_root_pixmap_change(d_screen_t *sc) { data_t *d; @@ -357,7 +392,7 @@ render_root_pixmap_changed(d_screen_t *sc) } /* pass it on */ - d->screen_root_pixmap_changed(sc); + d->screen_root_pixmap_change(sc); } static void @@ -371,16 +406,23 @@ render_paint(d_screen_t *sc) //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; - if (!window_is_input_only(w) && window_is_mapped(w)) { - gboolean opaque = !window_is_argb(w); + window_get_area(w, &x, &y, &width, &height, &bwidth); + + if (!window_is_input_only(w) && window_is_mapped(w) && + x < sc->super.width_in_pixels && + y < sc->super.height_in_pixels && + x + width > 0 && y + height > 0) + { + gboolean opaque = !(window_is_argb(w) || + window_get_opacity(w) < 0xffff); window_data_t *wd; wd = window_find_plugin_data(w, plugin_id); if (opaque) { - - paint_window(w, d, wd, opaque); + 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 */ @@ -409,10 +451,19 @@ render_paint(d_screen_t *sc) for (it = list_bottom(sc->stacking); it; it = it->prev) { d_window_t *w = it->data; + int x, y, width, height, bwidth; - if (!window_is_input_only(w) && window_is_mapped(w)) { + window_get_area(w, &x, &y, &width, &height, &bwidth); + + if (!window_is_input_only(w) && window_is_mapped(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_data_t *wd; - gboolean opaque = !window_is_argb(w); + gboolean opaque = !(window_is_argb(w) || + window_get_opacity(w) < 0xffff); wd = window_find_plugin_data(w, plugin_id); @@ -428,7 +479,7 @@ render_paint(d_screen_t *sc) d->overlay_buffer, d->shadow_region, 0, 0); - paint_shadow(w, d, wd); + paint_shadow(w, d, wd, x, y, width, height, bwidth); if (!opaque) { /* use the clip region of the highest opaque window seen so @@ -438,7 +489,7 @@ render_paint(d_screen_t *sc) d->overlay_buffer, wd->paint_clip, 0, 0); - paint_window(w, d, wd, opaque); + paint_window(w, d, wd, opaque, x, y, width, height, bwidth); } } } @@ -480,6 +531,7 @@ paint_root(d_screen_t *sc, data_t *d) src = d->solid_bg; op = XCB_RENDER_PICT_OP_CLEAR; } + xcb_render_composite(sc->dpy->conn, op, src, @@ -492,24 +544,30 @@ paint_root(d_screen_t *sc, data_t *d) } static void -paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque) +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) { - int x, y, width, height, bwidth; int op; - window_get_area(w, &x, &y, &width, &height, &bwidth); op = !opaque ? XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC; + if (opaque) + alphamap = XCB_NONE; + else + alphamap = solid_picture(d, w->sc, window_get_opacity(w), 0, 0, 0); + xcb_render_composite(w->sc->dpy->conn, op, wd->picture, - XCB_NONE, + alphamap, d->overlay_buffer, 0, 0, 0, 0, x, y, width + bwidth*2, height + bwidth *2); @@ -517,11 +575,9 @@ paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque) } static void -paint_shadow(d_window_t *w, data_t *d, window_data_t *wd) +paint_shadow(d_window_t *w, data_t *d, window_data_t *wd, + int x, int y, int width, int height, int bwidth) { - 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, diff --git a/screen.c b/screen.c index 8b6513f..1633f6a 100644 --- a/screen.c +++ b/screen.c @@ -384,7 +384,8 @@ screen_setup_default_functions(d_screen_t *sc) sc->window_move = window_move; sc->window_resize = window_resize; sc->window_reshape = window_reshape; - sc->screen_root_pixmap_changed = screen_update_root_pixmap; + sc->window_opacity_change = window_opacity_change; + sc->screen_root_pixmap_change = screen_update_root_pixmap; } void @@ -427,6 +428,7 @@ screen_get_root_pixmap(d_screen_t *sc) if (rep->type == sc->dpy->a.pixmap && rep->length >= 1) { sc->root_pixmap = ((xcb_pixmap_t*)xcb_get_property_value(rep))[0]; + printf("got root pixmap 0x%x\n", sc->root_pixmap); } free(rep); } diff --git a/screen.h b/screen.h index 79baa98..16e0ad5 100644 --- a/screen.h +++ b/screen.h @@ -40,7 +40,8 @@ typedef struct d_screen { void (*window_move)(struct d_window *w); void (*window_resize)(struct d_window *w); void (*window_reshape)(struct d_window *w); - void (*screen_root_pixmap_changed)(struct d_screen *sc); + void (*window_opacity_change)(struct d_window *w); + void (*screen_root_pixmap_change)(struct d_screen *sc); } d_screen_t; d_screen_t* screen_new(struct d_display *dpy, int num, xcb_screen_t *xcb); diff --git a/window.c b/window.c index cecae41..56cbf7e 100644 --- a/window.c +++ b/window.c @@ -32,7 +32,8 @@ typedef struct { queries should go to this window */ xcb_window_t client; - double opacity; + /* opacity is from 0xffff to 0 */ + uint16_t opacity; gboolean mapped; gboolean zombie; @@ -68,6 +69,7 @@ window_new(xcb_window_t id, struct d_screen *sc) w->damage = XCB_NONE; w->region = XCB_NONE; w->type = DC_WINDOW_TYPE_INVALID; + w->opacity = 0xffff; screen_stacking_add(sc, (d_window_t*)w); @@ -389,6 +391,11 @@ window_reshape(d_window_t *w) window_update_region((d_window_priv_t*)w); } +void window_opacity_change(d_window_t *w) +{ + (void)w; +} + void window_add_plugin_data(d_window_t *pubw, int id, void *data) { @@ -562,3 +569,20 @@ window_get_type(d_window_t *pubw) return w->type; } +uint16_t +window_get_opacity(d_window_t *pubw) +{ + d_window_priv_t *w = (d_window_priv_t*)pubw; + + return w->opacity; +} + +void +window_set_opacity(d_window_t *pubw, uint16_t o) +{ + d_window_priv_t *w = (d_window_priv_t*)pubw; + + w->opacity = o; + if (w->mapped) + w->sc->window_opacity_change(pubw); +} diff --git a/window.h b/window.h index 3a1cf09..354e872 100644 --- a/window.h +++ b/window.h @@ -46,6 +46,7 @@ void window_configure(d_window_t *w, int x, int y, int width, int height, void window_move(d_window_t *w); void window_resize(d_window_t *w); void window_reshape(d_window_t *w); +void window_opacity_change(d_window_t *w); gboolean window_is_zombie(d_window_t *w); gboolean window_is_input_only(d_window_t *w); @@ -53,7 +54,7 @@ gboolean window_is_mapped(d_window_t *w); gboolean window_is_attr_mapped(d_window_t *w); gboolean window_is_argb(d_window_t *w); -void window_get_area(d_window_t *pubw, int *x, int *y, int *width, int *height, +void window_get_area(d_window_t *w, int *x, int *y, int *width, int *height, int *border_width); xcb_pixmap_t window_get_pixmap(d_window_t *w); @@ -68,5 +69,8 @@ void window_create_damage(d_window_t *w); void window_destroy_damage(d_window_t *w); d_window_type_t window_get_type(d_window_t *w); +uint16_t window_get_opacity(d_window_t *w); + +void window_set_opacity(d_window_t *w, uint16_t o); #endif