From 8530e85b5b8ed34f5f0f2f8e00ac38e553b23750 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 5 Mar 2008 00:29:12 -0500 Subject: [PATCH] the compmgr works.. hooray! --- dcompmgr.c | 48 +++++++--- display.c | 69 +++++++++++++-- render.c | 295 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- screen.c | 42 ++++++--- screen.h | 4 +- window.c | 126 +++++++++++++++++++++----- window.h | 15 +++- 7 files changed, 528 insertions(+), 71 deletions(-) diff --git a/dcompmgr.c b/dcompmgr.c index f9d1ebb..b8124fb 100644 --- a/dcompmgr.c +++ b/dcompmgr.c @@ -12,6 +12,7 @@ #include #include #include +#include typedef struct { int foo; @@ -118,22 +119,50 @@ event(d_display_t *dpy) xcb_configure_notify_event_t *cev; d_screen_t *sc; d_window_t *w, *above; + int x, y, width, height, bwidth; cev = (xcb_configure_notify_event_t*)ev; sc = display_screen_from_root(dpy, cev->event); if (!sc) break; w = screen_find_window(sc, cev->window); - sc->window_configure(w, cev->x, cev->y, - cev->width, cev->height, cev->border_width); + window_get_area(w, &x, &y, &width, &height, &bwidth); + if (x != cev->x || y != cev->y || width != cev->width || + height != cev->height || bwidth != cev->border_width) + { + window_configure(w, cev->x, cev->y, + cev->width, cev->height, + cev->border_width); + if (window_is_mapped(w)) + sc->window_reconfigure(w); + } above = screen_find_window(sc, cev->above_sibling); screen_stacking_move_above(sc, w, above); screen_refresh(w->sc); break; } default: + if (ev->response_type - dpy->damage.event == XCB_DAMAGE_NOTIFY) { + xcb_damage_notify_event_t *dev; + d_list_it_t *it; + + dev = (xcb_damage_notify_event_t*)ev; + for (it = list_top(dpy->screens); it; it = it->next) { + d_screen_t *sc = it->data; + d_window_t *w; + + w = screen_find_window(sc, dev->drawable); + if (w) { + screen_refresh(w->sc); + break; + } + } + xcb_damage_subtract(dpy->conn, dev->damage, + XCB_NONE, XCB_NONE); + } break; } free(ev); + xcb_flush(dpy->conn); } } @@ -158,8 +187,6 @@ run(d_display_t *dpy) { gboolean quit; - paint(dpy); - quit = FALSE; while (!quit) { struct timeval next, now, *wait; @@ -167,6 +194,8 @@ run(d_display_t *dpy) d_list_it_t *it; fd_set fds; + event(dpy); + npaint = 0; for (it = list_top(dpy->screens); it; it = it->next) { d_screen_t *sc = it->data; @@ -198,24 +227,19 @@ run(d_display_t *dpy) FD_ZERO(&fds); FD_SET(dpy->fd, &fds); + //printf("select %d\n", npaint); + r = select(dpy->fd+1, &fds, NULL, NULL, wait); if (r < 0) printf("select error\n"); else if (r == 0) { //printf("select timeout\n"); paint(dpy); - } - else { - //printf("select data\n"); - /*if (FD_ISSET(dpy->fd, &fds))*/ { - event(dpy); - } + xcb_flush(dpy->conn); } if (xcb_connection_has_error(dpy->conn)) quit = TRUE; - else - xcb_flush(dpy->conn); } } diff --git a/display.c b/display.c index 99d154c..1beee21 100644 --- a/display.c +++ b/display.c @@ -44,10 +44,10 @@ typedef struct { rep = xcb_get_extension_data(dpy->conn, &xcb_##name##_id); \ \ ext = find_extension_##name(dpy) \ - ext->present = rep && rep->present; \ - ext->error = rep && rep->first_error; \ - ext->event = rep && rep->first_event; \ - ext->opcode = rep && rep->major_opcode; \ + ext->present = rep && rep->present; \ + ext->error = rep ? rep->first_error : 0; \ + ext->event = rep ? rep->first_event : 0; \ + ext->opcode = rep ? rep->major_opcode : 0; \ \ if (ext->present) \ ck_##name = xcb_##name##_query_version(dpy->conn, \ @@ -266,6 +266,65 @@ display_error(d_display_t *dpy, xcb_generic_error_t *ev) case 72: req = "PutImage"; break; default: break; } + else if (major_opcode == dpy->damage.opcode) + switch (minor_opcode) + { + case 0: req = "DamageQueryVersion"; break; + case 1: req = "DamageCreate"; break; + case 2: req = "DamageDestroy"; break; + case 3: req = "DamageSubtract"; break; + default: break; + } + else if (major_opcode == dpy->render.opcode) + switch (minor_opcode) + { + case 0: req = "RenderQueryVersion"; break; + case 1: req = "RenderQueryPictFormats"; break; + case 2: req = "RenderQueryPictIndexValues"; break; + case 4: req = "RenderCreatePicture"; break; + case 5: req = "RenderChangePicture"; break; + case 6: req = "RenderSetPictureClipRectangles"; break; + case 7: req = "RenderFreePicture"; break; + case 8: req = "RenderComposite"; break; + case 10: req = "RenderCompositeTrapezoids"; break; + case 11: req = "RenderCompositeTriangles"; break; + case 12: req = "RenderCompositeTriStrip"; break; + case 13: req = "RenderCompositeTriFan"; break; + case 17: req = "RenderCreateGlyphSet"; break; + case 18: req = "RenderReferenceGlyphSet"; break; + case 19: req = "RenderFreeGlyphSet"; break; + case 20: req = "RenderAddGlyphs"; break; + case 22: req = "RenderFreeGlyphs"; break; + case 23: req = "RenderCompositeGlyphs8"; break; + case 24: req = "RenderCompositeGlyphs16"; break; + case 25: req = "RenderCompositeGlyphs32"; break; + case 26: req = "RenderFillRectangles"; break; + case 27: req = "RenderCreateCursor"; break; + case 28: req = "RenderSetPictureTransform"; break; + case 29: req = "RenderQueryFilters"; break; + case 30: req = "RenderSetPictureFilter"; break; + case 31: req = "RenderCreateAnimCursor"; break; + case 32: req = "RenderAddTraps"; break; + case 33: req = "RenderCreateSolidFill"; break; + case 34: req = "RenderLinearGradient"; break; + case 35: req = "RenderRadialGradient"; break; + case 36: req = "RenderConicalGradient"; break; + default: break; + } + else if (major_opcode == dpy->composite.opcode) + switch (minor_opcode) + { + case 0: req = "CompositeQueryVersion"; break; + case 1: req = "CompositeRedirectWindow"; break; + case 2: req = "CompositeRedirectSubwindows"; break; + case 3: req = "CompositeUnredirectWindow"; break; + case 4: req = "CompositeUnredirectSubwindows"; break; + case 5: req = "CompositeCreateRegionFromBorderClip"; break; + case 6: req = "CompositeNameWindowPixmap"; break; + case 7: req = "CompositeGetOverlayWindow"; break; + case 8: req = "CompositeReleaseOverlayWindow"; break; + default: break; + } if (name && req) printf("XError: %s %s!\n", @@ -277,7 +336,7 @@ display_error(d_display_t *dpy, xcb_generic_error_t *ev) printf("XError: code %d major opcode %d minor opcode %d!\n", ev->error_code, major_opcode, minor_opcode); - abort(); + //abort(); } int diff --git a/render.c b/render.c index 5aafc6e..222a642 100644 --- a/render.c +++ b/render.c @@ -1,6 +1,7 @@ #include "render.h" #include "screen.h" #include "window.h" +#include "display.h" #include "list.h" #include #include @@ -10,57 +11,319 @@ typedef struct { void (*screen_paint)(d_screen_t *sc); + void (*window_show)(d_window_t *w); + void (*window_hide)(d_window_t *w); + void (*window_reconfigure)(d_window_t *w); + + 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 solid_bg; } data_t; -static void render_paint_screen(d_screen_t *sc); -static void paint_root(d_screen_t *sc); +typedef struct { + xcb_render_picture_t picture; + xcb_void_cookie_t ck_picture; +} window_data_t; + +static void render_screen_paint(d_screen_t *sc); +static void paint_root(d_screen_t *sc, data_t *d); static void paint_window(d_window_t *window); +static void render_update_picture(d_window_t *w, data_t *d, window_data_t *wd, + gboolean children); +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, + 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_reconfigure(d_window_t *window); void render_init(d_screen_t *sc) { + xcb_render_query_pict_formats_cookie_t ck; + xcb_render_pictformat_t format; + xcb_pixmap_t px; + data_t *d = malloc(sizeof(data_t)); d->screen_paint = sc->screen_paint; + d->window_show = sc->window_show; + d->window_hide = sc->window_hide; + d->window_reconfigure = sc->window_reconfigure; screen_add_plugin_data(sc, PLUGIN_NAME, d); - sc->screen_paint = render_paint_screen; + sc->screen_paint = render_screen_paint; + sc->window_show = render_window_show; + sc->window_hide = render_window_hide; + sc->window_reconfigure = render_window_reconfigure; + + ck = xcb_render_query_pict_formats_unchecked(sc->dpy->conn); + d->pict_formats = xcb_render_query_pict_formats_reply(sc->dpy->conn, ck, + NULL); + + format = find_visual_format(d, sc->super.root_visual); + + d->overlay_picture = xcb_generate_id(sc->dpy->conn); + xcb_render_create_picture(sc->dpy->conn, + d->overlay_picture, sc->overlay, format, + 0, NULL); + + /* make the double buffer */ + px = xcb_generate_id(sc->dpy->conn); + xcb_create_pixmap(sc->dpy->conn, sc->super.root_depth, px, + sc->super.root, sc->super.width_in_pixels, + 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); + xcb_free_pixmap(sc->dpy->conn, px); + + d->solid_bg = solid_picture(sc, 1.0, 0.0, 0.0, 0.0); } void render_free(d_screen_t *sc) { data_t *d = screen_find_plugin_data(sc, PLUGIN_NAME); + free(d->pict_formats); + xcb_render_free_picture(sc->dpy->conn, d->solid_bg); + xcb_render_free_picture(sc->dpy->conn, d->overlay_picture); + xcb_render_free_picture(sc->dpy->conn, d->overlay_buffer); free(d); } +void +render_window_free(d_window_t *w, window_data_t *wd) +{ + render_free_picture(w, wd); + free(wd); +} + +static void +render_window_show(d_window_t *w) +{ + data_t *d; + window_data_t *wd; + + d = screen_find_plugin_data(w->sc, PLUGIN_NAME); + + /* pass it on */ + d->window_show(w); + + wd = window_find_plugin_data(w, PLUGIN_NAME); + if (wd) + render_window_free(w, wd); + + wd = malloc(sizeof(window_data_t)); + wd->picture = XCB_NONE; + wd->ck_picture.sequence = 0; + window_add_plugin_data(w, PLUGIN_NAME, wd); + + window_ref(w); +} + static void -render_paint_screen(d_screen_t *sc) +render_window_hide(d_window_t *w) +{ + data_t *d; + window_data_t *wd; + + d = screen_find_plugin_data(w->sc, PLUGIN_NAME); + wd = window_find_plugin_data(w, PLUGIN_NAME); + if (wd) { + render_window_free(w, wd); + window_remove_plugin_data(w, PLUGIN_NAME); + } + + window_unref(w); + + /* pass it on */ + d->window_hide(w); +} + +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; + + picture = xcb_generate_id (sc->dpy->conn); + + c.alpha = a * 0xffff; + c.red = a * r * 0xffff; + c.green = a * g * 0xffff; + c.blue = a * b * 0xffff; + + xcb_render_create_solid_fill (sc->dpy->conn, picture, c); + return picture; +} + +static xcb_render_pictformat_t +find_visual_format(data_t *d, xcb_visualid_t visual) +{ + xcb_render_pictscreen_iterator_t si; + xcb_render_pictdepth_iterator_t di; + xcb_render_pictvisual_iterator_t vi; + + if (!visual) return XCB_NONE; + + /* go through all the screens */ + si = xcb_render_query_pict_formats_screens_iterator(d->pict_formats); + for (; si.rem; xcb_render_pictscreen_next(&si)) { + di = xcb_render_pictscreen_depths_iterator(si.data); + for (; di.rem; xcb_render_pictdepth_next(&di)) { + vi = xcb_render_pictdepth_visuals_iterator(di.data); + for (; vi.rem; xcb_render_pictvisual_next(&vi)) { + if (vi.data->visual == visual) + return vi.data->format; + } + } + } + return XCB_NONE; +} + +static xcb_render_picture_t +render_get_picture(d_window_t *w, window_data_t *wd) +{ + if (wd->ck_picture.sequence) { + 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->ck_picture.sequence = 0; + } + //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) +{ + xcb_render_picture_t pict; + + pict = render_get_picture(w, wd); + if (pict) xcb_render_free_picture(w->sc->dpy->conn, pict); + wd->picture = XCB_NONE; +} + +static void +render_update_picture(d_window_t *w, data_t *d, window_data_t *wd, + gboolean children) +{ + xcb_pixmap_t px; + + px = window_get_pixmap(w); + //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); + + 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); + } +} + +static void +render_window_reconfigure(d_window_t *w) +{ + data_t *d; + window_data_t *wd; + + d = screen_find_plugin_data(w->sc, PLUGIN_NAME); + wd = window_find_plugin_data(w, PLUGIN_NAME); + render_free_picture(w, wd); + + /* pass it on */ + d->window_hide(w); +} + +static void +render_screen_paint(d_screen_t *sc) { data_t *d = screen_find_plugin_data(sc, PLUGIN_NAME); d_list_it_t *it; - printf("-- painting --\n"); - paint_root(sc); - for (it = list_bottom(sc->stacking); it; it = it->prev) - paint_window(it->data); + //printf("-- painting --\n"); + paint_root(sc, d); +#if 1 + 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); + } +#endif + + /* copy the double buffer to the overlay window */ + xcb_render_composite(sc->dpy->conn, + XCB_RENDER_PICT_OP_SRC, + d->overlay_buffer, + XCB_NONE, + d->overlay_picture, + 0, 0, 0, 0, + 0, 0, + sc->super.width_in_pixels, + sc->super.height_in_pixels); /* call the function we replaced in the chain */ d->screen_paint(sc); } static void -paint_root(d_screen_t *sc) +paint_root(d_screen_t *sc, data_t *d) { - int w, h; - - w = sc->super.width_in_pixels; - h = sc->super.height_in_pixels; - - //printf("-- paint root 0x%x --\n", sc->super.root); + xcb_render_composite(sc->dpy->conn, + XCB_RENDER_PICT_OP_CLEAR, + d->solid_bg, + XCB_NONE, + d->overlay_buffer, + 0, 0, 0, 0, + 0, 0, + sc->super.width_in_pixels, + sc->super.height_in_pixels); } static void paint_window(d_window_t *w) { - //printf("-- paint window 0x%x --\n", w->id); + data_t *d; + window_data_t *wd; + xcb_render_picture_t pict; + int x, y, width, height, bwidth; + + d = screen_find_plugin_data(w->sc, PLUGIN_NAME); + wd = window_find_plugin_data(w, PLUGIN_NAME); + + if (!wd->picture) + render_update_picture(w, d, wd, TRUE); + pict = render_get_picture(w, wd); + + //printf("-- paint window 0x%x picture 0x%x --\n", w->id, wd->picture); + window_get_area(w, &x, &y, &width, &height, &bwidth); + xcb_render_composite(w->sc->dpy->conn, + XCB_RENDER_PICT_OP_SRC, + /*XCB_RENDER_PICT_OP_OVER, - for argb */ + wd->picture, + XCB_NONE, + d->overlay_buffer, + 0, 0, 0, 0, + x, y, width + bwidth*2, height + bwidth *2); } diff --git a/screen.c b/screen.c index ada1b4f..8c0ea58 100644 --- a/screen.c +++ b/screen.c @@ -8,6 +8,7 @@ #include #include #include +#include #define ROOT_MASK (XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \ XCB_EVENT_MASK_STRUCTURE_NOTIFY) @@ -37,7 +38,6 @@ screen_new(struct d_display *dpy, int num, xcb_screen_t *xcb) sc->ref = 1; sc->dpy = dpy; sc->num = num; - sc->root = NULL; gettimeofday(&sc->next_repaint, NULL); sc->need_repaint = TRUE; @@ -62,9 +62,6 @@ void screen_unref(d_screen_t *sc) { if (sc && --sc->ref == 0) { - if (sc->root) - screen_remove_window(sc, sc->root); - g_hash_table_unref(sc->winhash); list_unref(sc->stacking); g_hash_table_unref(sc->plugin_data); @@ -138,7 +135,6 @@ static gboolean screen_init(d_screen_t *sc) { uint32_t mask; -#if DO_COMP xcb_generic_error_t *err; xcb_void_cookie_t redir_ck; xcb_composite_get_overlay_window_cookie_t overlay_ck; @@ -146,6 +142,11 @@ screen_init(d_screen_t *sc) redir_ck = xcb_composite_redirect_subwindows(sc->dpy->conn, sc->super.root, + XCB_COMPOSITE_REDIRECT_AUTOMATIC); + +#if 1 + redir_ck = + xcb_composite_redirect_subwindows(sc->dpy->conn, sc->super.root, XCB_COMPOSITE_REDIRECT_MANUAL); overlay_ck = xcb_composite_get_overlay_window(sc->dpy->conn, @@ -169,6 +170,23 @@ screen_init(d_screen_t *sc) } sc->overlay = overlay_rep->overlay_win; free(overlay_rep); + + /* make the overlay window click-through */ + if (sc->overlay) { + xcb_xfixes_region_t region; + + region = xcb_generate_id(sc->dpy->conn); + xcb_xfixes_create_region(sc->dpy->conn, region, 0, NULL); + xcb_xfixes_set_window_shape_region(sc->dpy->conn, + sc->overlay, + XCB_SHAPE_SK_BOUNDING, + 0, 0, XCB_NONE); + xcb_xfixes_set_window_shape_region(sc->dpy->conn, + sc->overlay, + XCB_SHAPE_SK_INPUT, + 0, 0, region); + xcb_xfixes_destroy_region(sc->dpy->conn, region); + } #endif mask = SELECTION_MASK; @@ -189,7 +207,9 @@ screen_add_window(d_screen_t *sc, xcb_window_t wid) w = window_new(wid, sc); g_hash_table_insert(sc->winhash, &w->id, w); - printf("screen added window 0x%x\n", w->id); + window_create_damage(w); + + //printf("screen added window 0x%x\n", w->id); return w; } @@ -199,8 +219,6 @@ screen_add_existing_windows(d_screen_t *sc) xcb_query_tree_cookie_t ck; xcb_query_tree_reply_t *rep; - sc->root = screen_add_window(sc, sc->super.root); - ck = xcb_query_tree(sc->dpy->conn, sc->super.root); rep = xcb_query_tree_reply(sc->dpy->conn, ck, NULL); if (rep) { @@ -217,8 +235,9 @@ screen_add_existing_windows(d_screen_t *sc) void screen_remove_window(d_screen_t *sc, struct d_window *w) { - printf("screen removed window 0x%x\n", w->id); + //printf("screen removed window 0x%x\n", w->id); + window_destroy_damage(w); g_hash_table_remove(sc->winhash, &w->id); sc->window_become_zombie(w); window_unref(w); @@ -304,14 +323,14 @@ screen_setup_default_functions(d_screen_t *sc) sc->window_show = window_show; sc->window_hide = window_hide; sc->window_become_zombie = window_become_zombie; - sc->window_configure = window_configure; + sc->window_reconfigure = window_reconfigure; } void screen_add_plugin_data(d_screen_t *sc, const char *key, void *data) { char *skey = g_strdup(key); - g_hash_table_insert(sc->plugin_data, skey, data); + g_hash_table_replace(sc->plugin_data, skey, data); } void* @@ -329,4 +348,5 @@ screen_remove_plugin_data(d_screen_t *sc, const char *key) void screen_refresh(d_screen_t *sc) { sc->need_repaint = TRUE; + //printf("*** need repaint! ***\n"); } diff --git a/screen.h b/screen.h index 5d46555..2060c19 100644 --- a/screen.h +++ b/screen.h @@ -20,7 +20,6 @@ typedef struct d_screen { xcb_atom_t selatom; /* ditto.. */ xcb_window_t overlay; - struct d_window *root; struct timeval next_repaint; gboolean need_repaint; @@ -33,8 +32,7 @@ typedef struct d_screen { void (*window_show)(struct d_window *w); void (*window_hide)(struct d_window *w); void (*window_become_zombie)(struct d_window *w); - void (*window_configure)(struct d_window *w, int x, int y, - int width, int height, int border_width); + void (*window_reconfigure)(struct d_window *w); } 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 9c7847e..e88ec9b 100644 --- a/window.c +++ b/window.c @@ -2,8 +2,10 @@ #include "screen.h" #include "display.h" #include +#include #include #include +#include typedef struct { /* public stuff */ @@ -14,15 +16,17 @@ typedef struct { int ref; /* queried things, don't read them directly from the struct */ - int x, y, w, h; + int x, y, w, h, bw; gboolean mapped; gboolean input_only; + xcb_visualid_t visual; + xcb_pixmap_t pixmap; gboolean zombie; - int opacity; + GHashTable *plugin_data; - xcb_pixmap_t pixmap; + xcb_damage_damage_t damage; xcb_get_window_attributes_cookie_t ck_get_attr; xcb_get_geometry_cookie_t ck_get_geom; @@ -42,8 +46,8 @@ window_new(xcb_window_t id, struct d_screen *sc) w->ref = 1; w->sc = sc; w->zombie = FALSE; - w->opacity = WINDOW_OPACITY_MAX; w->pixmap = XCB_NONE; + w->damage = XCB_NONE; screen_stacking_add(sc, (d_window_t*)w); @@ -52,6 +56,10 @@ window_new(xcb_window_t id, struct d_screen *sc) w->ck_get_pixmap.sequence = 0; + w->plugin_data = g_hash_table_new_full((GHashFunc)g_str_hash, + (GEqualFunc)g_str_equal, + g_free, NULL); + //printf("new window 0x%x\n", w->id); return (d_window_t*)w; @@ -80,27 +88,24 @@ window_unref(d_window_t *pubw) w->pixmap = XCB_NONE; } + g_hash_table_unref(w->plugin_data); free(w); } } -void -window_show(d_window_t *pubw) +static void +window_update_pixmap(d_window_priv_t *w) { - d_window_priv_t *w = (d_window_priv_t*)pubw; xcb_pixmap_t p; - if (window_is_mapped(pubw)) return; - - printf("show window 0x%x\n", w->id); - /* XXX can we save it for until we get the new pixmap? */ - if ((p = window_get_pixmap(pubw))) { + if ((p = window_get_pixmap((d_window_t*)w))) { xcb_free_pixmap(w->sc->dpy->conn, p); w->pixmap = XCB_NONE; } - w->mapped = TRUE; + //printf("updating pixmap for 0x%x\n", w->id); + w->pixmap = xcb_generate_id(w->sc->dpy->conn); w->ck_get_pixmap = xcb_composite_name_window_pixmap_checked(w->sc->dpy->conn, @@ -109,11 +114,24 @@ window_show(d_window_t *pubw) } void +window_show(d_window_t *pubw) +{ + d_window_priv_t *w = (d_window_priv_t*)pubw; + + window_is_mapped(pubw); /* kill any ongoing request */ + + printf("show window 0x%x\n", w->id); + + window_update_pixmap(w); + w->mapped = TRUE; +} + +void window_hide(d_window_t *pubw) { d_window_priv_t *w = (d_window_priv_t*)pubw; - if (!window_is_mapped(pubw)) return; + window_is_mapped(pubw); /* kill any ongoing request */ printf("hide window 0x%x\n", w->id); @@ -147,7 +165,8 @@ window_is_input_only(d_window_t *pubw) } void -window_get_area(d_window_t *pubw, int *x, int *y, int *width, int *height) +window_get_area(d_window_t *pubw, int *x, int *y, int *width, int *height, + int *border_width) { d_window_priv_t *w = (d_window_priv_t*)pubw; if (w->ck_get_geom.sequence) @@ -156,6 +175,7 @@ window_get_area(d_window_t *pubw, int *x, int *y, int *width, int *height) *y = w->y; *width = w->w; *height = w->h; + *border_width = w->bw; } static void @@ -171,11 +191,13 @@ window_get_attributes_reply(d_window_priv_t *w) if (rep) { w->input_only = rep->_class == XCB_WINDOW_CLASS_INPUT_ONLY; w->mapped = rep->map_state != XCB_MAP_STATE_UNMAPPED; + w->visual = rep->visual; free(rep); } else { w->input_only = TRUE; w->mapped = FALSE; + w->visual = XCB_NONE; } if (err) { printf("error getting attributes for window 0x%x\n", w->id); @@ -197,13 +219,15 @@ window_get_geometry_reply(d_window_priv_t *w) if (rep) { w->x = rep->x; w->y = rep->y; - w->w = rep->width + rep->border_width * 2; - w->h = rep->height + rep->border_width * 2; + w->w = rep->width; + w->h = rep->height; + w->bw = rep->border_width; free(rep); } else { w->x = w->y = -1; w->w = w->h = 1; + w->bw = 0; } if (err) { printf("error getting geometry for window 0x%x\n", w->id); @@ -231,15 +255,25 @@ window_get_pixmap(d_window_t *pubw) //printf("** checking get pixmap 0x%x\n", w->id); err = xcb_request_check(w->sc->dpy->conn, w->ck_get_pixmap); if (err) { + w->pixmap = XCB_NONE; printf("error getting named pixmap for window 0x%x\n", w->id); free(err); } - w->pixmap = XCB_NONE; + w->ck_get_pixmap.sequence = 0; } //printf("returning pixmap 0x%x for window 0x%x\n", w->pixmap, w->id); return w->pixmap; } +xcb_visualid_t +window_get_visual(d_window_t *pubw) +{ + d_window_priv_t *w = (d_window_priv_t*)pubw; + if (w->ck_get_attr.sequence) + window_get_attributes_reply(w); + return w->visual; +} + void window_configure(d_window_t *pubw, int x, int y, int width, int height, int border_width) @@ -251,6 +285,58 @@ window_configure(d_window_t *pubw, int x, int y, int width, int height, w->ck_get_geom.sequence = 0; w->x = x; w->y = y; - w->w = width + border_width * 2; - w->h = height + border_width * 2; + w->w = width; + w->h = height; + w->bw = border_width; +} + +void +window_reconfigure(d_window_t *w) +{ + window_update_pixmap((d_window_priv_t*)w); +} + +void +window_add_plugin_data(d_window_t *pubw, const char *key, void *data) +{ + d_window_priv_t *w = (d_window_priv_t*)pubw; + char *skey = g_strdup(key); + g_hash_table_replace(w->plugin_data, skey, data); +} + +void* +window_find_plugin_data(d_window_t *pubw, const char *key) +{ + d_window_priv_t *w = (d_window_priv_t*)pubw; + return g_hash_table_lookup(w->plugin_data, key); +} + +void +window_remove_plugin_data(d_window_t *pubw, const char *key) +{ + d_window_priv_t *w = (d_window_priv_t*)pubw; + g_hash_table_remove(w->plugin_data, key); +} + +void +window_create_damage(d_window_t *pubw) +{ + d_window_priv_t *w = (d_window_priv_t*)pubw; + + if (!window_is_input_only(pubw)) { + assert(w->damage == XCB_NONE); + w->damage = xcb_generate_id(w->sc->dpy->conn); + xcb_damage_create(w->sc->dpy->conn, w->damage, w->id, + XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY); + } +} + +void window_destroy_damage(d_window_t *pubw) +{ + d_window_priv_t *w = (d_window_priv_t*)pubw; + + if (w->damage) { + xcb_damage_destroy(w->sc->dpy->conn, w->damage); + w->damage = XCB_NONE; + } } diff --git a/window.h b/window.h index b86f587..6015b99 100644 --- a/window.h +++ b/window.h @@ -6,9 +6,6 @@ struct d_screen; -#define WINDOW_OPACITY_MAX 100 -#define WINDOW_OPACITY_MIN 0 - typedef struct d_window { xcb_window_t id; struct d_screen *sc; @@ -26,13 +23,23 @@ void window_become_zombie(d_window_t *w); void window_configure(d_window_t *w, int x, int y, int width, int height, int border_width); +void window_reconfigure(d_window_t *w); gboolean window_is_zombie(d_window_t *w); gboolean window_is_input_only(d_window_t *w); gboolean window_is_mapped(d_window_t *w); -void window_get_area(d_window_t *w, int *x, int *y, int *width, int *height); +void window_get_area(d_window_t *pubw, int *x, int *y, int *width, int *height, + int *border_width); xcb_pixmap_t window_get_pixmap(d_window_t *w); +xcb_visualid_t window_get_visual(d_window_t *w); + +void window_add_plugin_data(d_window_t *w, const char *key, void *data); +void* window_find_plugin_data(d_window_t *w, const char *key); +void window_remove_plugin_data(d_window_t *w, const char *key); + +void window_create_damage(d_window_t *w); +void window_destroy_damage(d_window_t *w); #endif -- 1.9.1