the compmgr works.. hooray!
authorDana Jansens <danakj@orodu.net>
Wed, 5 Mar 2008 05:29:12 +0000 (00:29 -0500)
committerDana Jansens <danakj@orodu.net>
Wed, 5 Mar 2008 05:29:12 +0000 (00:29 -0500)
dcompmgr.c
display.c
render.c
screen.c
screen.h
window.c
window.h

index f9d1ebb..b8124fb 100644 (file)
@@ -12,6 +12,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <xcb/xcb.h>
+#include <xcb/damage.h>
 
 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);
     }
 }
 
index 99d154c..1beee21 100644 (file)
--- 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
index 5aafc6e..222a642 100644 (file)
--- 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 <stdio.h>
 #include <stdlib.h>
 
 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);
 }
index ada1b4f..8c0ea58 100644 (file)
--- a/screen.c
+++ b/screen.c
@@ -8,6 +8,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <xcb/composite.h>
+#include <xcb/xfixes.h>
 
 #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");
 }
index 5d46555..2060c19 100644 (file)
--- 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);
index 9c7847e..e88ec9b 100644 (file)
--- a/window.c
+++ b/window.c
@@ -2,8 +2,10 @@
 #include "screen.h"
 #include "display.h"
 #include <stdlib.h>
+#include <assert.h>
 #include <stdio.h>
 #include <xcb/composite.h>
+#include <xcb/damage.h>
 
 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;
+    }
 }
index b86f587..6015b99 100644 (file)
--- 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