add support for shaped windows, and the circulatenotify event
[dana/dcompmgr.git] / window.c
index 794a1e4..265e515 100644 (file)
--- a/window.c
+++ b/window.c
@@ -20,12 +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;
-    gboolean         argb;
-    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;
 
@@ -44,6 +45,8 @@ typedef struct {
 
 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)
@@ -58,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);
 
@@ -90,6 +94,11 @@ window_unref(d_window_t *pubw)
     if (w && --w->ref == 0) {
         screen_stacking_remove(w->sc, (d_window_t*)w);
 
+        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 */
@@ -110,6 +119,24 @@ window_get_pixmap(d_window_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, bw, bw);
+}
 
 static void
 window_update_pixmap(d_window_priv_t *w)
@@ -145,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;
 }
 
@@ -157,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;
 }
@@ -304,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)
@@ -321,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;
+    (void)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
@@ -367,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;