add support for the root pixmap properties
authorDana Jansens <danakj@orodu.net>
Thu, 6 Mar 2008 03:28:23 +0000 (22:28 -0500)
committerDana Jansens <danakj@orodu.net>
Thu, 6 Mar 2008 03:28:23 +0000 (22:28 -0500)
dcompmgr.c
display.c
display.h
render.c
screen.c
screen.h

index 0957069..c16dc5e 100644 (file)
@@ -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;
index 65adc2a..c3e6b07 100644 (file)
--- 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,
index 00bb8b1..181dd6a 100644 (file)
--- 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;
index f9b1465..c1d181a 100644 (file)
--- 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,
index b16373a..e02e4a6 100644 (file)
--- a/screen.c
+++ b/screen.c
@@ -14,7 +14,8 @@
 #include <xcb/xfixes.h>
 
 #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;
+}
index 5067a80..4c40e3b 100644 (file)
--- 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