From fd3a65e1eec2abaa8d6d7edadec545c8029868f8 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 5 Mar 2008 22:28:23 -0500 Subject: [PATCH] add support for the root pixmap properties --- dcompmgr.c | 16 +++++++ display.c | 6 +++ display.h | 3 ++ render.c | 130 +++++++++++++++++++++++++++++++---------------------- screen.c | 62 ++++++++++++++++++++++++- screen.h | 9 ++++ 6 files changed, 172 insertions(+), 54 deletions(-) diff --git a/dcompmgr.c b/dcompmgr.c index 0957069..c16dc5e 100644 --- a/dcompmgr.c +++ b/dcompmgr.c @@ -161,6 +161,22 @@ event(d_display_t *dpy) screen_refresh(w->sc); break; } + case XCB_PROPERTY_NOTIFY: + { + xcb_property_notify_event_t *pev; + d_screen_t *sc; + + pev = (xcb_property_notify_event_t*)ev; + sc = display_screen_from_root(dpy, pev->window); + if (!sc) break; + if (pev->atom == dpy->a.xrootpmap_id || + pev->atom == dpy->a.esetroot_pmap_id || + pev->atom == dpy->a.xsetroot_id) + { + sc->screen_root_pixmap_changed(sc); + } + break; + } default: if (ev->response_type - dpy->damage.event == XCB_DAMAGE_NOTIFY) { xcb_damage_notify_event_t *dev; diff --git a/display.c b/display.c index 65adc2a..c3e6b07 100644 --- a/display.c +++ b/display.c @@ -103,6 +103,12 @@ query_statics(d_display_t *dpy) d_atom_query_t atoms[] = { { .atom = &dpy->a.utf8_string, .name = "UTF8_STRING" }, + { .atom = &dpy->a.esetroot_pmap_id, + .name = "ESETROOT_PMAP_ID" }, + { .atom = &dpy->a.xrootpmap_id, + .name = "_XROOTPMAP_ID" }, + { .atom = &dpy->a.xsetroot_id, + .name = "_XSETROOT_ID" }, { .atom = &dpy->a.net_wm_window_type, .name = "_NET_WM_WINDOW_TYPE" }, { .atom = &dpy->a.net_wm_window_type_desktop, diff --git a/display.h b/display.h index 00bb8b1..181dd6a 100644 --- a/display.h +++ b/display.h @@ -35,6 +35,9 @@ typedef struct d_display { xcb_atom_t string; xcb_atom_t pixmap; /* properties */ + xcb_atom_t esetroot_pmap_id; + xcb_atom_t xrootpmap_id; + xcb_atom_t xsetroot_id; xcb_atom_t net_wm_window_type; xcb_atom_t net_wm_window_type_desktop; xcb_atom_t net_wm_window_type_dock; diff --git a/render.c b/render.c index f9b1465..c1d181a 100644 --- a/render.c +++ b/render.c @@ -14,27 +14,29 @@ static int plugin_id; typedef struct { void (*screen_paint)(d_screen_t *sc); + void (*screen_root_pixmap_changed)(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); + xcb_render_pictformat_t root_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; } data_t; typedef struct { xcb_render_picture_t picture; - gboolean waiting_picture; - xcb_void_cookie_t ck_picture; } window_data_t; -static void render_screen_paint(d_screen_t *sc); +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 render_update_picture(d_window_t *w, data_t *d, window_data_t *wd, - gboolean children); +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); @@ -50,19 +52,20 @@ void render_init(d_screen_t *sc, int id) { xcb_render_query_pict_formats_cookie_t ck; - xcb_render_pictformat_t format; xcb_pixmap_t px; plugin_id = 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->window_show = sc->window_show; d->window_hide = sc->window_hide; d->window_resize = sc->window_resize; screen_add_plugin_data(sc, plugin_id, d); - sc->screen_paint = render_screen_paint; + sc->screen_paint = render_paint; + sc->screen_root_pixmap_changed = render_root_pixmap_changed; sc->window_show = render_window_show; sc->window_hide = render_window_hide; sc->window_resize = render_window_resize; @@ -71,11 +74,12 @@ render_init(d_screen_t *sc, int id) d->pict_formats = xcb_render_query_pict_formats_reply(sc->dpy->conn, ck, NULL); - format = find_visual_format(d, sc->super.root_visual); + d->root_format = find_visual_format(d, sc->super.root_visual); + d->root_picture = XCB_NONE; d->overlay_picture = xcb_generate_id(sc->dpy->conn); xcb_render_create_picture(sc->dpy->conn, - d->overlay_picture, sc->overlay, format, + d->overlay_picture, sc->overlay, d->root_format, 0, NULL); /* make the double buffer */ @@ -85,7 +89,7 @@ render_init(d_screen_t *sc, int id) sc->super.height_in_pixels); d->overlay_buffer = xcb_generate_id(sc->dpy->conn); xcb_render_create_picture(sc->dpy->conn, d->overlay_buffer, px, - format, 0, 0); + 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); @@ -97,6 +101,8 @@ render_free(d_screen_t *sc) data_t *d = screen_find_plugin_data(sc, plugin_id); free(d->pict_formats); xcb_render_free_picture(sc->dpy->conn, d->solid_bg); + if (d->root_picture) + 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); free(d); @@ -127,7 +133,6 @@ render_window_show(d_window_t *w) wd = malloc(sizeof(window_data_t)); wd->picture = XCB_NONE; - wd->waiting_picture = FALSE; window_add_plugin_data(w, plugin_id, wd); window_ref(w); @@ -150,10 +155,8 @@ render_window_hide(d_window_t *w) d->window_hide(w); } -static -xcb_render_picture_t solid_picture(d_screen_t *sc, - double a, double r, - double g, double b) +static xcb_render_picture_t +solid_picture(d_screen_t *sc, double a, double r, double g, double b) { xcb_render_picture_t picture; xcb_render_color_t c; @@ -193,37 +196,32 @@ find_visual_format(data_t *d, xcb_visualid_t visual) return XCB_NONE; } -static xcb_render_picture_t -render_get_picture(d_window_t *w, window_data_t *wd) +static void +render_free_picture(d_window_t *w, window_data_t *wd) { - if (wd->waiting_picture) { - xcb_generic_error_t *err; - //printf("** checking create picture 0x%x\n", w->id); - err = xcb_request_check(w->sc->dpy->conn, wd->ck_picture); - if (err) { - wd->picture = XCB_NONE; - printf("error creating picture for window 0x%x\n", w->id); - free(err); - } - wd->waiting_picture = FALSE; + /* this might cause an error, oh well */ + if (wd->picture) { + xcb_render_free_picture(w->sc->dpy->conn, wd->picture); + wd->picture = XCB_NONE; } - //printf("returning picture 0x%x for window 0x%x\n", wd->picture, w->id); - return wd->picture; } static void -render_free_picture(d_window_t *w, window_data_t *wd) +render_update_root_picture(d_screen_t *sc, data_t *d) { - xcb_render_picture_t pict; + xcb_pixmap_t px; - pict = render_get_picture(w, wd); - if (pict) xcb_render_free_picture(w->sc->dpy->conn, pict); - wd->picture = XCB_NONE; + 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); + } } static void -render_update_picture(d_window_t *w, data_t *d, window_data_t *wd, - gboolean children) +render_update_picture(d_window_t *w, data_t *d, window_data_t *wd) { xcb_pixmap_t px; @@ -231,20 +229,19 @@ render_update_picture(d_window_t *w, data_t *d, window_data_t *wd, //printf("got pixmap 0x%x\n", px); if (px) { xcb_render_pictformat_t format; - const uint32_t vals = (children ? - XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS : - XCB_SUBWINDOW_MODE_CLIP_BY_CHILDREN); + const uint32_t vals = XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS; render_free_picture(w, wd); wd->picture = xcb_generate_id(w->sc->dpy->conn); format = find_visual_format(d, window_get_visual(w)); - wd->ck_picture = - xcb_render_create_picture_checked(w->sc->dpy->conn, - wd->picture, px, format, - XCB_RENDER_CP_SUBWINDOW_MODE, - &vals); - wd->waiting_picture = TRUE; + /* we don't need to check this. if it fails, we'll just be drawing + an invalid picture and creating some X errors but that's no big + deal really */ + xcb_render_create_picture(w->sc->dpy->conn, + wd->picture, px, format, + XCB_RENDER_CP_SUBWINDOW_MODE, + &vals); } } @@ -264,7 +261,22 @@ render_window_resize(d_window_t *w) } static void -render_screen_paint(d_screen_t *sc) +render_root_pixmap_changed(d_screen_t *sc) +{ + data_t *d; + + d = screen_find_plugin_data(sc, plugin_id); + if (d->root_picture) { + xcb_render_free_picture(sc->dpy->conn, d->root_picture); + d->root_picture = XCB_NONE; + } + + /* pass it on */ + d->screen_root_pixmap_changed(sc); +} + +static void +render_paint(d_screen_t *sc) { data_t *d = screen_find_plugin_data(sc, plugin_id); d_list_it_t *it; @@ -297,9 +309,23 @@ render_screen_paint(d_screen_t *sc) static void paint_root(d_screen_t *sc, data_t *d) { + xcb_render_picture_t src; + int op; + + if (!d->root_picture) + render_update_root_picture(sc, d); + + if (d->root_picture) { + src = d->root_picture; + op = XCB_RENDER_PICT_OP_SRC; + } + else { + src = d->solid_bg; + op = XCB_RENDER_PICT_OP_CLEAR; + } xcb_render_composite(sc->dpy->conn, - XCB_RENDER_PICT_OP_CLEAR, - d->solid_bg, + op, + src, XCB_NONE, d->overlay_buffer, 0, 0, 0, 0, @@ -312,22 +338,20 @@ static void paint_window(d_window_t *w, data_t *d) { window_data_t *wd; - xcb_render_picture_t pict; int x, y, width, height, bwidth; wd = window_find_plugin_data(w, plugin_id); if (!wd->picture) - render_update_picture(w, d, wd, TRUE); - pict = render_get_picture(w, wd); + render_update_picture(w, d, wd); //printf("-- paint window 0x%x picture 0x%x --\n", w->id, wd->picture); - if (pict) { + if (wd->picture) { window_get_area(w, &x, &y, &width, &height, &bwidth); xcb_render_composite(w->sc->dpy->conn, //XCB_RENDER_PICT_OP_SRC, /* - for solid */ XCB_RENDER_PICT_OP_OVER, /* - for argb */ - pict, + wd->picture, XCB_NONE, d->overlay_buffer, 0, 0, 0, 0, diff --git a/screen.c b/screen.c index b16373a..e02e4a6 100644 --- a/screen.c +++ b/screen.c @@ -14,7 +14,8 @@ #include #define ROOT_MASK (XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \ - XCB_EVENT_MASK_STRUCTURE_NOTIFY) + XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_PROPERTY_CHANGE) #define SELECTION_MASK (XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ XCB_EVENT_MASK_PROPERTY_CHANGE) @@ -65,6 +66,9 @@ screen_unref(d_screen_t *sc) if (sc && --sc->ref == 0) { d_list_it_t *it, *next; + /* clean up pending requests */ + screen_get_root_pixmap(sc); + g_hash_table_unref(sc->winhash); for (it = list_top(sc->stacking); it; it = next) { next = it->next; @@ -205,9 +209,41 @@ screen_init(d_screen_t *sc) xcb_change_window_attributes(sc->dpy->conn, sc->super.root, XCB_CW_EVENT_MASK, &mask); + screen_update_root_pixmap(sc); + return TRUE; } +void +screen_update_root_pixmap(d_screen_t *sc) +{ + if (sc->root_pixmap_waiting) { + xcb_get_property_reply_t *rep; + rep = xcb_get_property_reply(sc->dpy->conn, sc->root_pixmap_ck[0], + NULL); + if (rep) free(rep); + rep = xcb_get_property_reply(sc->dpy->conn, sc->root_pixmap_ck[1], + NULL); + if (rep) free(rep); + rep = xcb_get_property_reply(sc->dpy->conn, sc->root_pixmap_ck[2], + NULL); + if (rep) free(rep); + } + sc->root_pixmap_ck[0] = + xcb_get_property_unchecked(sc->dpy->conn, FALSE, + sc->super.root, sc->dpy->a.xrootpmap_id, + sc->dpy->a.pixmap, 0, 1); + sc->root_pixmap_ck[1] = + xcb_get_property_unchecked(sc->dpy->conn, FALSE, + sc->super.root, sc->dpy->a.esetroot_pmap_id, + sc->dpy->a.pixmap, 0, 1); + sc->root_pixmap_ck[2] = + xcb_get_property_unchecked(sc->dpy->conn, FALSE, + sc->super.root, sc->dpy->a.xsetroot_id, + sc->dpy->a.pixmap, 0, 1); + sc->root_pixmap_waiting = TRUE; +} + d_window_t* screen_add_window(d_screen_t *sc, xcb_window_t wid) { @@ -334,6 +370,7 @@ screen_setup_default_functions(d_screen_t *sc) sc->window_become_zombie = window_become_zombie; sc->window_move = window_move; sc->window_resize = window_resize; + sc->screen_root_pixmap_changed = screen_update_root_pixmap; } void @@ -360,3 +397,26 @@ screen_refresh(d_screen_t *sc) sc->need_repaint = TRUE; //printf("*** need repaint! ***\n"); } + +xcb_pixmap_t +screen_get_root_pixmap(d_screen_t *sc) +{ + if (sc->root_pixmap_waiting) { + xcb_get_property_reply_t *rep; + int i; + + sc->root_pixmap = XCB_NONE; + for (i = 2; i >= 0; --i) { + rep = xcb_get_property_reply(sc->dpy->conn, sc->root_pixmap_ck[i], + NULL); + if (rep) { + if (rep->type == sc->dpy->a.pixmap && rep->length >= 1) { + sc->root_pixmap = + ((xcb_pixmap_t*)xcb_get_property_value(rep))[0]; + } + free(rep); + } + } + } + return sc->root_pixmap; +} diff --git a/screen.h b/screen.h index 5067a80..4c40e3b 100644 --- a/screen.h +++ b/screen.h @@ -28,12 +28,18 @@ typedef struct d_screen { struct d_list *stacking; struct d_list *plugin_data; + /* don't read this directly, use screen_get_root_pixmap() */ + xcb_pixmap_t root_pixmap; + gboolean root_pixmap_waiting; + xcb_get_property_cookie_t root_pixmap_ck[3]; + void (*screen_paint)(struct d_screen *sc); void (*window_show)(struct d_window *w); void (*window_hide)(struct d_window *w); void (*window_become_zombie)(struct d_window *w); void (*window_move)(struct d_window *w); void (*window_resize)(struct d_window *w); + void (*screen_root_pixmap_changed)(struct d_screen *sc); } d_screen_t; d_screen_t* screen_new(struct d_display *dpy, int num, xcb_screen_t *xcb); @@ -64,4 +70,7 @@ void screen_remove_plugin_data(d_screen_t *sc, int id); void screen_refresh(d_screen_t *sc); +void screen_update_root_pixmap(d_screen_t *sc); +xcb_pixmap_t screen_get_root_pixmap(d_screen_t *sc); + #endif -- 2.34.1