add shadows. they even take the same shape as the window. hee!
[dana/dcompmgr.git] / window.c
index a56899a..70c8861 100644 (file)
--- a/window.c
+++ b/window.c
@@ -20,11 +20,13 @@ typedef struct {
     int              ref;
 
     /* queried things, don't read them directly from the struct */
-    int              x, y, w, h, bw;
-    gboolean         attr_mapped;
-    gboolean         input_only;
-    xcb_visualid_t   visual;
-    xcb_pixmap_t     pixmap;
+    int                 x, y, w, h, bw;
+    gboolean            attr_mapped;
+    gboolean            input_only;
+    gboolean            argb;
+    xcb_visualid_t      visual;
+    xcb_pixmap_t        pixmap;
+    xcb_xfixes_region_t region;
 
     double           opacity;
 
@@ -39,12 +41,12 @@ 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);
 static void window_get_geometry_reply(d_window_priv_t *w);
+static void window_update_pixmap(d_window_priv_t *w);
+static void window_update_region(d_window_priv_t *w);
 
 d_window_t*
 window_new(xcb_window_t id, struct d_screen *sc)
@@ -59,6 +61,7 @@ window_new(xcb_window_t id, struct d_screen *sc)
     w->mapped = FALSE;
     w->pixmap = XCB_NONE;
     w->damage = XCB_NONE;
+    w->region = XCB_NONE;
 
     screen_stacking_add(sc, (d_window_t*)w);
 
@@ -68,8 +71,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);
@@ -91,12 +92,17 @@ 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->region) {
+            xcb_xfixes_destroy_region(w->sc->dpy->conn, w->region);
+            w->region = XCB_NONE;
+        }
+
+        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;
         }
 
@@ -105,6 +111,33 @@ 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_region(d_window_priv_t *w)
+{
+    int x, y, wi, hei, bw;
+
+    if (window_is_zombie((d_window_t*)w)) return;
+
+    if (w->region) {
+        xcb_xfixes_destroy_region(w->sc->dpy->conn, w->region);
+        w->region = XCB_NONE;
+    }
+
+    w->region = xcb_generate_id(w->sc->dpy->conn);
+    xcb_xfixes_create_region_from_window(w->sc->dpy->conn, w->region,
+                                         w->id, XCB_SHAPE_SK_BOUNDING);
+    window_get_area((d_window_t*)w, &x, &y, &wi, &hei, &bw);
+    xcb_xfixes_translate_region(w->sc->dpy->conn, w->region, x+bw, y+bw);
+}
+
 static void
 window_update_pixmap(d_window_priv_t *w)
 {
@@ -120,11 +153,13 @@ window_update_pixmap(d_window_priv_t *w)
 
     //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);
 }
 
@@ -137,7 +172,12 @@ window_show(d_window_t *pubw)
 
     //printf("show window 0x%x\n", w->id);
 
+    /* make sure this is before we update the window's region */
+    if (w->sc->dpy->shape.present)
+        xcb_shape_select_input(w->sc->dpy->conn, w->id, TRUE);
+
     window_update_pixmap(w);
+    window_update_region(w);
     w->mapped = TRUE;
 }
 
@@ -149,6 +189,8 @@ window_hide(d_window_t *pubw)
     assert(w->mapped);
 
     //printf("hide window 0x%x\n", w->id);
+    if (w->sc->dpy->shape.present)
+        xcb_shape_select_input(w->sc->dpy->conn, w->id, FALSE);
 
     w->mapped = FALSE;
 }
@@ -246,12 +288,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);
@@ -276,24 +320,13 @@ window_is_attr_mapped(d_window_t *pubw)
     return w->attr_mapped;
 }
 
-xcb_pixmap_t
-window_get_pixmap(d_window_t *pubw)
+gboolean
+window_is_argb(d_window_t *pubw)
 {
     d_window_priv_t *w = (d_window_priv_t*)pubw;
-
-    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;
+    if (w->waiting_geom)
+        window_get_geometry_reply(w);
+    return w->argb;
 }
 
 xcb_visualid_t
@@ -305,6 +338,14 @@ window_get_visual(d_window_t *pubw)
     return w->visual;
 }
 
+xcb_xfixes_region_t
+window_get_region(d_window_t *pubw)
+{
+    d_window_priv_t *w = (d_window_priv_t*)pubw;
+
+    return w->region;
+}
+
 void
 window_configure(d_window_t *pubw, int x, int y, int width, int height,
                  int border_width)
@@ -322,15 +363,23 @@ window_configure(d_window_t *pubw, int x, int y, int width, int height,
 }
 
 void
-window_move(d_window_t *w)
+window_move(d_window_t *pubw)
 {
-    (void)w;
+    //d_window_priv_t *w = (d_window_priv_t*)pubw;
+    window_update_region((d_window_priv_t*)pubw);
 }
 
 void
 window_resize(d_window_t *w)
 {
     window_update_pixmap((d_window_priv_t*)w);
+    window_update_region((d_window_priv_t*)w);
+}
+
+void
+window_reshape(d_window_t *w)
+{
+    window_update_region((d_window_priv_t*)w);
 }
 
 void
@@ -368,7 +417,8 @@ window_create_damage(d_window_t *pubw)
     }
 }
 
-void window_destroy_damage(d_window_t *pubw)
+void
+window_destroy_damage(d_window_t *pubw)
 {
     d_window_priv_t *w = (d_window_priv_t*)pubw;