blend argb windows, but just blit non-argb windows which is faster
[dana/dcompmgr.git] / window.c
index 2c55b10..794a1e4 100644 (file)
--- a/window.c
+++ b/window.c
@@ -21,13 +21,15 @@ typedef struct {
 
     /* queried things, don't read them directly from the struct */
     int              x, y, w, h, bw;
-    gboolean         mapped;
+    gboolean         attr_mapped;
     gboolean         input_only;
+    gboolean         argb;
     xcb_visualid_t   visual;
     xcb_pixmap_t     pixmap;
 
     double           opacity;
 
+    gboolean         mapped;
     gboolean         zombie;
 
     d_list_t        *plugin_data;
@@ -38,8 +40,6 @@ typedef struct {
     xcb_get_window_attributes_cookie_t ck_get_attr;
     gboolean waiting_geom;
     xcb_get_geometry_cookie_t          ck_get_geom;
-    gboolean waiting_pixmap;
-    xcb_void_cookie_t                  ck_get_pixmap;
 } d_window_priv_t;
 
 static void window_get_attributes_reply(d_window_priv_t *w);
@@ -55,6 +55,7 @@ window_new(xcb_window_t id, struct d_screen *sc)
     w->ref = 1;
     w->sc = sc;
     w->zombie = FALSE;
+    w->mapped = FALSE;
     w->pixmap = XCB_NONE;
     w->damage = XCB_NONE;
 
@@ -66,8 +67,6 @@ window_new(xcb_window_t id, struct d_screen *sc)
     w->ck_get_geom = xcb_get_geometry(sc->dpy->conn, id);
     w->waiting_geom = TRUE;
 
-    w->waiting_pixmap = FALSE;
-
     w->plugin_data = list_new();
 
     //printf("new window 0x%x\n", w->id);
@@ -89,12 +88,12 @@ window_unref(d_window_t *pubw)
     d_window_priv_t *w = (d_window_priv_t*)pubw;
 
     if (w && --w->ref == 0) {
-        xcb_pixmap_t p;
-
         screen_stacking_remove(w->sc, (d_window_t*)w);
 
-        if ((p = window_get_pixmap(pubw))) {
-            xcb_free_pixmap(w->sc->dpy->conn, p);
+        if (w->pixmap) {
+            /* this may cause an error if the pixmap was never valid, but
+               that's fine */
+            xcb_free_pixmap(w->sc->dpy->conn, w->pixmap);
             w->pixmap = XCB_NONE;
         }
 
@@ -103,26 +102,37 @@ window_unref(d_window_t *pubw)
     }
 }
 
+xcb_pixmap_t
+window_get_pixmap(d_window_t *pubw)
+{
+    d_window_priv_t *w = (d_window_priv_t*)pubw;
+
+    return w->pixmap;
+}
+
+
 static void
 window_update_pixmap(d_window_priv_t *w)
 {
-    xcb_pixmap_t p;
-
     if (window_is_zombie((d_window_t*)w)) return;
 
-    /* XXX can we save it for until we get the new pixmap? */
-    if ((p = window_get_pixmap((d_window_t*)w))) {
-        xcb_free_pixmap(w->sc->dpy->conn, p);
+    /* the pixmap may not be valid even though it is non-zero, but
+       we can free it anyways and let it fail.  we don't need to wait
+       for a response from the server */
+    if (w->pixmap) {
+        xcb_free_pixmap(w->sc->dpy->conn, w->pixmap);
         w->pixmap = XCB_NONE;
     }
 
     //printf("updating pixmap for 0x%x\n", w->id);
 
+    /* we don't check the result of this call, because it seems that sometimes
+       the X server just doesn't reply.  if we check it, we end up hanging
+       sometimes waiting for the reply */
     w->pixmap = xcb_generate_id(w->sc->dpy->conn);
-    w->ck_get_pixmap = 
-        xcb_composite_name_window_pixmap_checked(w->sc->dpy->conn,
-                                                 w->id, w->pixmap);
-    w->waiting_pixmap = TRUE;
+    xcb_composite_name_window_pixmap(w->sc->dpy->conn, w->id, w->pixmap);
+    //printf("requested pixmap sequence %u\n", w->ck_get_pixmap.sequence);
+    //fflush(stdout);
     xcb_flush(w->sc->dpy->conn);
 }
 
@@ -131,7 +141,6 @@ window_show(d_window_t *pubw)
 {
     d_window_priv_t *w = (d_window_priv_t*)pubw;
 
-    window_is_mapped(pubw); /* kill any ongoing request */
     assert(!w->mapped);
 
     //printf("show window 0x%x\n", w->id);
@@ -145,7 +154,6 @@ window_hide(d_window_t *pubw)
 {
     d_window_priv_t *w = (d_window_priv_t*)pubw;
 
-    window_is_mapped(pubw); /* kill any ongoing request */
     assert(w->mapped);
 
     //printf("hide window 0x%x\n", w->id);
@@ -213,14 +221,14 @@ 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->attr_mapped = rep->map_state != XCB_MAP_STATE_UNMAPPED;
         w->visual = rep->visual;
         //printf("0x%x attributes mapped %d\n", w->id, w->mapped);
         free(rep);
     }
     else {
         w->input_only = TRUE;
-        w->mapped = FALSE;
+        w->attr_mapped = FALSE;
         w->visual = XCB_NONE;
     }
     if (err) {
@@ -246,12 +254,14 @@ window_get_geometry_reply(d_window_priv_t *w)
         w->w = rep->width;
         w->h = rep->height;
         w->bw = rep->border_width;
+        w->argb = rep->depth == 32;
         free(rep);
     }
     else {
         w->x = w->y = -1;
         w->w = w->h = 1;
         w->bw = 0;
+        w->argb = FALSE;
     }
     if (err) {
         printf("error getting geometry for window 0x%x\n", w->id);
@@ -264,29 +274,25 @@ gboolean
 window_is_mapped(d_window_t *pubw)
 {
     d_window_priv_t *w = (d_window_priv_t*)pubw;
-    if (w->waiting_attr)
-        window_get_attributes_reply(w);
     return w->mapped;
 }
 
-xcb_pixmap_t
-window_get_pixmap(d_window_t *pubw)
+gboolean
+window_is_attr_mapped(d_window_t *pubw)
 {
     d_window_priv_t *w = (d_window_priv_t*)pubw;
+    if (w->waiting_attr)
+        window_get_attributes_reply(w);
+    return w->attr_mapped;
+}
 
-    if (w->waiting_pixmap) {
-        xcb_generic_error_t *err;
-        //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->waiting_pixmap = FALSE;
-    }
-    //printf("returning pixmap 0x%x for window 0x%x\n", w->pixmap, w->id);
-    return w->pixmap;
+gboolean
+window_is_argb(d_window_t *pubw)
+{
+    d_window_priv_t *w = (d_window_priv_t*)pubw;
+    if (w->waiting_geom)
+        window_get_geometry_reply(w);
+    return w->argb;
 }
 
 xcb_visualid_t