don't fade on startup/shutdown, make fading a bit quicker
authorDana Jansens <danakj@orodu.net>
Sun, 9 Mar 2008 23:33:10 +0000 (19:33 -0400)
committerDana Jansens <danakj@orodu.net>
Sun, 9 Mar 2008 23:33:10 +0000 (19:33 -0400)
Makefile
dcompmgr.c
dcompmgr.h [new file with mode: 0644]
display.c
fade.c
render.c
screen.c
screen.h
window.c
window.h

index d3d8202..311914a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,8 +2,17 @@ sources = $(wildcard *.c)
 objs = $(sources:.c=.o)
 headers = $(wildcard *.h)
 
-CFLAGS=$(shell pkg-config --cflags xcb-composite xcb-damage glib-2.0) -ggdb -W -Wall #-DEFENCE
-LIBS=$(shell pkg-config --libs xcb-composite xcb-damage glib-2.0) #-lefence
+# for profiling
+PFLAGS=-pg -fno-inline
+PLIBS=
+
+# for electric fence
+EFLAGS=-DEFENCE
+ELIBS=-lefence
+
+CFLAGS=$(shell pkg-config --cflags xcb-composite xcb-damage glib-2.0) -ggdb -W -Wall $(PFLAGS)
+LDFLAGS=$(PFLAGS)
+LIBS=$(shell pkg-config --libs xcb-composite xcb-damage glib-2.0) $(PLIBS)
 
 dcompmgr: $(objs)
        $(CC) -o $@ $^ $(LIBS) $(LDFLAGS)
index 8fa0b28..8dcaa1f 100644 (file)
@@ -26,6 +26,7 @@ typedef struct {
 } d_options_t;
 
 static gboolean quit = FALSE;
+static gboolean running = FALSE;
 
 static void
 read_options(int argc, char **argv, d_options_t *opts)
@@ -182,7 +183,8 @@ event(d_display_t *dpy)
                 }
             }
             above = screen_find_window(sc, cev->above_sibling);
-            screen_stacking_move_above(sc, w, above);
+            if (window_is_mapped(w))
+                sc->window_restack(w, above);
             screen_refresh(w->sc);
             break;
         }
@@ -232,6 +234,7 @@ event(d_display_t *dpy)
 
                     w = screen_find_window(sc, dev->drawable);
                     if (w) {
+                        sc->window_damage(w);
                         screen_refresh(w->sc);
                         break;
                     }
@@ -251,7 +254,7 @@ event(d_display_t *dpy)
                     d_window_t *w;
 
                     w = screen_find_window(sc, sev->affected_window);
-                    if (w) {
+                    if (w && window_is_mapped(w)) {
                         sc->window_reshape(w);
                         screen_refresh(w->sc);
                         break;
@@ -298,6 +301,8 @@ run(d_display_t *dpy)
 {
     struct timeval now, next_repaint;
 
+    running = TRUE;
+
     gettimeofday(&now, NULL);
     next_repaint = now;
 
@@ -306,6 +311,7 @@ run(d_display_t *dpy)
         int            r, npaint, ntime;
         d_list_it_t   *it;
         fd_set         fds;
+        gboolean due;
 
         event(dpy);
 
@@ -338,27 +344,31 @@ run(d_display_t *dpy)
             }
         }
 
-        if (!npaint && !ntime)
+        if (!npaint && !ntime) {
             /* wait forever, there is nothing that needs drawing */
             wait = NULL;
+            due = FALSE;
+        }
         else if (time_compare(&next, &now) > 0) {
             /* wait until the next allowed redraw time */
             time_difference(&next, &now, &next);
             wait = &next;
+            due = FALSE;
         }
         else {
             /* don't wait cuz a timer is due now already */
-            next.tv_sec = 0;
-            next.tv_usec = 1;
-            wait = &next;
+            due = TRUE;
         }
 
-        FD_ZERO(&fds);
-        FD_SET(dpy->fd, &fds);
-
-        //printf("select %d\n", npaint);
+        //printf("select? %d %d\n", due, npaint);
 
-        r = select(dpy->fd+1, &fds, NULL, NULL, wait);
+        if (!due) {
+            FD_ZERO(&fds);
+            FD_SET(dpy->fd, &fds);
+            r = select(dpy->fd+1, &fds, NULL, NULL, wait);
+        }
+        else
+            r = 0;
 
         gettimeofday(&now, NULL);
         if (r == 0) {
@@ -375,6 +385,8 @@ run(d_display_t *dpy)
         if (xcb_connection_has_error(dpy->conn))
             quit = TRUE;
     }
+
+    running = FALSE;
 }
 
 static void
@@ -475,6 +487,7 @@ main(int argc, char **argv)
         }
     }
 
+    printf("running\n");
     run(dpy);
 
     {
@@ -496,3 +509,9 @@ main(int argc, char **argv)
     display_unref(dpy);
     return 0;
 }
+
+gboolean
+dcompmgr_running(void)
+{
+    return running;
+}
diff --git a/dcompmgr.h b/dcompmgr.h
new file mode 100644 (file)
index 0000000..723d4e6
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef dc_dcompmgr_h
+#define dc_dcompmgr_h
+
+#include <glib.h>
+
+gboolean dcompmgr_running(void);
+
+#endif
index e331150..8fb74e7 100644 (file)
--- a/display.c
+++ b/display.c
@@ -261,6 +261,7 @@ display_error(d_display_t *dpy, xcb_generic_error_t *ev)
     case XCB_MATCH:     name = "BadMatch";     break;
     case XCB_DRAWABLE:  name = "BadDrawable";  break;
     case XCB_G_CONTEXT: name = "BadGC";        break;
+    case XCB_ID_CHOICE: name = "BadID";        break;
     default: break;
     }
     if (!name)
@@ -376,6 +377,34 @@ display_error(d_display_t *dpy, xcb_generic_error_t *ev)
         case 8: req = "ShapeGetRectangles"; break;
         default: break;
         }
+    else if (major_opcode == dpy->xfixes.opcode)
+        switch (minor_opcode)
+        {
+        case 0: req = "XFixesQueryVersion";            break;
+        case 1: req = "XFixesChangeSaveSet";           break;
+        case 2: req = "XFixesSelectSelectionInput";    break;
+        case 3: req = "XFixesSelectCursorInput";       break;
+        case 4: req = "XFixesGetCursorImage";          break;
+        case 5: req = "XFixesCreateRegion";            break;
+        case 6: req = "XFixesCreateRegionFromBitmap";  break;
+        case 7: req = "XFixesCreateRegionFromWindow";  break;
+        case 8: req = "XFixesCreateRegionFromGC";      break;
+        case 9: req = "XFixesCreateRegionFromPicture"; break;
+        case 10: req = "XFixesDestroyRegion";          break;
+        case 11: req = "XFixesSetRegion";              break;
+        case 12: req = "XFixesCopyRegion";             break;
+        case 13: req = "XFixesUnionRegion";            break;
+        case 14: req = "XFixesIntersectRegion";        break;
+        case 15: req = "XFixesSubtractRegion";         break;
+        case 16: req = "XFixesInvertRegion";           break;
+        case 17: req = "XFixesTranslanteRegion";       break;
+        case 18: req = "XFixesRegionExtents";          break;
+        case 19: req = "XFixesFetchRegion";            break;
+        case 20: req = "XFixesGCClipRegion";           break;
+        case 21: req = "XFixesSetWindowShapeRegion";   break;
+        case 22: req = "XFixesSetPictureClipRegion";   break;
+        default: break;
+        }
 
     if (name && req)
         printf("XError: %s %s\n",
@@ -384,7 +413,7 @@ display_error(d_display_t *dpy, xcb_generic_error_t *ev)
         printf("XError: %s major opcode %d minor opcode %d\n",
                name, major_opcode, minor_opcode);
     else
-        printf("XError: code %d major opcode %d minor opcode %d\n",
+        printf("XError: error code %d major opcode %d minor opcode %d\n",
                ev->error_code, major_opcode, minor_opcode);
 
     //abort();
diff --git a/fade.c b/fade.c
index 3ce8ab3..74308e4 100644 (file)
--- a/fade.c
+++ b/fade.c
@@ -1,5 +1,6 @@
 #include "efence.h"
 
+#include "dcompmgr.h"
 #include "render.h"
 #include "screen.h"
 #include "window.h"
@@ -13,6 +14,8 @@
 
 static int plugin_id;
 
+#define WINDOW_TYPE_FADE(t) (t != DC_WINDOW_TYPE_DESKTOP)
+
 typedef struct {
     void (*window_show)(d_window_t *w);
     void (*window_hide)(d_window_t *w);
@@ -53,7 +56,7 @@ fade_init(d_screen_t *sc, int id)
     sc->window_hide = fade_window_hide;
 
     d->fades = list_new();
-    d->fade_step_time = 5000;     /* 5 milliseconds */
+    d->fade_step_time = 15000;     /* 15 milliseconds */
     d->fade_total_time = 180000;  /* 0.18 seconds */
 }
 
@@ -97,8 +100,11 @@ fade_window_show(d_window_t *w)
 
     d->window_show(w);    
 
-    if (!window_is_input_only(w))
-        start_fade(w, 0x2000, 0xffff, TRUE);
+    if (!window_is_input_only(w) && dcompmgr_running()) {
+        d_window_type_t type = window_get_type(w);
+        if (WINDOW_TYPE_FADE(type))
+            start_fade(w, 0x2000, 0xffff, TRUE);
+    }
 }
 
 static void
@@ -106,8 +112,11 @@ fade_window_hide(d_window_t *w)
 {
     data_t *d;
 
-    if (!window_is_input_only(w))
-        start_fade(w, 0xffff, 0x0002, FALSE);
+    if (!window_is_input_only(w) && dcompmgr_running()) {
+        d_window_type_t type = window_get_type(w);
+        if (WINDOW_TYPE_FADE(type))
+            start_fade(w, 0xffff, 0x0002, FALSE);
+    }
 
     d = screen_find_plugin_data(w->sc, plugin_id);
     d->window_hide(w);
index 113070e..0a2d479 100644 (file)
--- a/render.c
+++ b/render.c
@@ -17,8 +17,12 @@ typedef struct {
     void (*screen_root_pixmap_change)(d_screen_t *sc);
     void (*window_show)(d_window_t *w);
     void (*window_zombie_dead)(d_window_t *w);
+    void (*window_move)(d_window_t *w);
     void (*window_resize)(d_window_t *w);
+    void (*window_reshape)(d_window_t *w);
+    void (*window_restack)(d_window_t *w, d_window_t *above);
     void (*window_opacity_change)(d_window_t *w);
+    void (*window_damage)(d_window_t *w);
 
     xcb_render_pictformat_t root_format;
     xcb_render_pictformat_t argb32_format;
@@ -29,8 +33,9 @@ typedef struct {
     xcb_render_picture_t solid_bg;
 
     xcb_xfixes_region_t all_region;
+    xcb_xfixes_region_t damaged_region;
     xcb_xfixes_region_t paint_region;
-    xcb_xfixes_region_t shadow_region;
+    xcb_xfixes_region_t shadow_paint_region;
 
     uint16_t shadowalpha;
     int xshadowoff;
@@ -39,8 +44,11 @@ typedef struct {
 
 typedef struct {
     xcb_render_picture_t picture;
+    xcb_render_picture_t alpha_picture;
     xcb_render_picture_t shadow_picture;
     xcb_xfixes_region_t paint_clip;
+    xcb_xfixes_region_t shadow_region;
+    gboolean shadow_valid;
 } window_data_t;
 
 static void render_paint(d_screen_t *sc);
@@ -51,8 +59,6 @@ static void paint_window(d_window_t *window, data_t *d, window_data_t *wd,
                          int height, int bwidth);
 static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
                          int x, int y, int width, int height, int bwidth);
-static void render_update_shadow_picture(d_window_t *w, data_t *d,
-                                         window_data_t *wd);
 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);
@@ -62,11 +68,17 @@ static xcb_render_pictformat_t find_argb32_format(data_t *d);
 static xcb_render_picture_t solid_picture(data_t *d, d_screen_t *sc,
                                           uint16_t a, uint16_t r,
                                           uint16_t g, uint16_t b);
+static void render_update_opacity(d_window_t *w, data_t *d, window_data_t *wd);
+static void render_update_shadow(d_window_t *w, data_t *d, window_data_t *wd);
 
 static void render_window_show(d_window_t *window);
 static void render_window_zombie_dead(d_window_t *window);
+static void render_window_move(d_window_t *window);
 static void render_window_resize(d_window_t *window);
+static void render_window_reshape(d_window_t *window);
+static void render_window_restack(d_window_t *window, d_window_t *above);
 static void render_window_opacity_change(d_window_t *w);
+static void render_window_damage(d_window_t *w);
 
 void
 render_init(d_screen_t *sc, int id)
@@ -82,16 +94,24 @@ render_init(d_screen_t *sc, int id)
     d->screen_root_pixmap_change = sc->screen_root_pixmap_change;
     d->window_show = sc->window_show;
     d->window_zombie_dead = sc->window_zombie_dead;
+    d->window_move = sc->window_move;
     d->window_resize = sc->window_resize;
+    d->window_reshape = sc->window_reshape;
+    d->window_restack = sc->window_restack;
     d->window_opacity_change = sc->window_opacity_change;
+    d->window_damage = sc->window_damage;
     screen_add_plugin_data(sc, plugin_id, d);
 
     sc->screen_paint = render_paint;
     sc->screen_root_pixmap_change = render_root_pixmap_change;
     sc->window_show = render_window_show;
     sc->window_zombie_dead = render_window_zombie_dead;
+    sc->window_move = render_window_move;
     sc->window_resize = render_window_resize;
+    sc->window_reshape = render_window_reshape;
+    sc->window_restack = render_window_restack;
     sc->window_opacity_change = render_window_opacity_change;
+    sc->window_damage = render_window_damage;
 
     ck = xcb_render_query_pict_formats_unchecked(sc->dpy->conn);
     d->pict_formats = xcb_render_query_pict_formats_reply(sc->dpy->conn, ck,
@@ -119,14 +139,16 @@ render_init(d_screen_t *sc, int id)
     d->solid_bg = solid_picture(d, sc, 0xffff, 0x6060, 02020, 0x3030);
 
     d->all_region = xcb_generate_id(sc->dpy->conn);
+    d->damaged_region = xcb_generate_id(sc->dpy->conn);
     d->paint_region = xcb_generate_id(sc->dpy->conn);
-    d->shadow_region = xcb_generate_id(sc->dpy->conn);
+    d->shadow_paint_region = xcb_generate_id(sc->dpy->conn);
     rect.x = rect.y = 0;
     rect.width = sc->super.width_in_pixels;
     rect.height = sc->super.height_in_pixels;
     xcb_xfixes_create_region(sc->dpy->conn, d->all_region, 1, &rect);
+    xcb_xfixes_create_region(sc->dpy->conn, d->damaged_region, 1, &rect);
     xcb_xfixes_create_region(sc->dpy->conn, d->paint_region, 1, &rect);
-    xcb_xfixes_create_region(sc->dpy->conn, d->shadow_region, 1, &rect);
+    xcb_xfixes_create_region(sc->dpy->conn, d->shadow_paint_region, 1, &rect);
 
     d->shadowalpha = 0x3333; /* 20% */
     d->xshadowoff = 2;
@@ -144,8 +166,9 @@ render_free(d_screen_t *sc)
     xcb_render_free_picture(sc->dpy->conn, d->overlay_picture);
     xcb_render_free_picture(sc->dpy->conn, d->overlay_buffer);
     xcb_xfixes_destroy_region(sc->dpy->conn, d->all_region);
+    xcb_xfixes_destroy_region(sc->dpy->conn, d->damaged_region);
     xcb_xfixes_destroy_region(sc->dpy->conn, d->paint_region);
-    xcb_xfixes_destroy_region(sc->dpy->conn, d->shadow_region);
+    xcb_xfixes_destroy_region(sc->dpy->conn, d->shadow_paint_region);
     free(d);
     screen_remove_plugin_data(sc, plugin_id);
 }
@@ -168,10 +191,10 @@ void
 render_window_free(d_window_t *w, window_data_t *wd)
 {
     render_free_picture(w, wd);
-    if (wd->shadow_picture) {
-        xcb_render_free_picture(w->sc->dpy->conn, wd->shadow_picture);
-        wd->shadow_picture = XCB_NONE;
-    }
+    xcb_render_free_picture(w->sc->dpy->conn, wd->alpha_picture);
+    xcb_render_free_picture(w->sc->dpy->conn, wd->shadow_picture);
+    xcb_xfixes_destroy_region(w->sc->dpy->conn, wd->paint_clip);
+    xcb_xfixes_destroy_region(w->sc->dpy->conn, wd->shadow_region);
     free(wd);
 }
 
@@ -195,15 +218,46 @@ render_window_show(d_window_t *w)
     wd->picture = XCB_NONE;
 
     wd->paint_clip = xcb_generate_id(w->sc->dpy->conn);
-    rect.x = rect.y = 0;
+    wd->shadow_region = xcb_generate_id(w->sc->dpy->conn);
+    rect.x = rect.y = -1;
     rect.width = rect.height = 1;
     xcb_xfixes_create_region(w->sc->dpy->conn, wd->paint_clip, 1, &rect);
+    xcb_xfixes_create_region(w->sc->dpy->conn, wd->shadow_region, 1, &rect);
 
-    render_update_shadow_picture(w, d, wd);
+    wd->shadow_valid = FALSE;
+
+    wd->alpha_picture = solid_picture(d, w->sc, 0, 0, 0, 0);
+    wd->shadow_picture = solid_picture(d, w->sc, 0, 0, 0, 0);
+
+    render_update_opacity(w, d, wd);
 
     window_add_plugin_data(w, plugin_id, wd);
 }
 
+static void 
+render_update_opacity(d_window_t *w, data_t *d, window_data_t *wd)
+{
+    static xcb_render_color_t c = { 0, 0, 0, 0 };
+    static xcb_rectangle_t rect = {0, 0, 1, 1};
+    unsigned long a;
+
+    /* make the window's shadow and alpha-map match its current opacity */
+    c.alpha = window_get_opacity(w);
+    xcb_render_fill_rectangles(w->sc->dpy->conn,
+                               XCB_RENDER_PICT_OP_SRC,
+                               wd->alpha_picture, c, 1, &rect);
+    a = d->shadowalpha;
+    a = a * window_get_opacity(w) / 0xffff;
+    //if (w->id == 0x1811453)
+    //    printf("window opacity 0x%x\n", c.alpha);
+    c.alpha = a;
+    if (w->id == 0x1811453)
+        printf("shadow opacity 0x%04x\n", c.alpha);
+    xcb_render_fill_rectangles(w->sc->dpy->conn,
+                               XCB_RENDER_PICT_OP_SRC,
+                               wd->shadow_picture, c, 1, &rect);
+}
+
 static void
 render_window_zombie_dead(d_window_t *w)
 {
@@ -213,8 +267,16 @@ render_window_zombie_dead(d_window_t *w)
     d = screen_find_plugin_data(w->sc, plugin_id);
     wd = window_find_plugin_data(w, plugin_id);
     if (wd) {
+        /* make sure the shadow region is right */
+        render_update_shadow(w, d, wd);
+
+        /* redraw the window's area, and its shadow's as well */
+        xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
+                                window_get_region(w), d->damaged_region);
+        xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
+                                wd->shadow_region, d->damaged_region);
+
         render_window_free(w, wd);
-        xcb_xfixes_destroy_region(w->sc->dpy->conn, wd->paint_clip);
         window_remove_plugin_data(w, plugin_id);
     }
 
@@ -311,17 +373,6 @@ render_free_picture(d_window_t *w, window_data_t *wd)
 }
 
 static void
-render_update_shadow_picture(d_window_t *w, data_t *d, window_data_t *wd)
-{
-    if (wd->shadow_picture)
-        xcb_render_free_picture(w->sc->dpy->conn, wd->shadow_picture);
-    wd->shadow_picture = solid_picture(d, w->sc,
-                                       d->shadowalpha *
-                                       window_get_opacity(w) / 0xffff,
-                                       0, 0, 0);
-}
-
-static void
 render_update_root_picture(d_screen_t *sc, data_t *d)
 {
     xcb_pixmap_t px;
@@ -361,6 +412,26 @@ render_update_picture(d_window_t *w, data_t *d, window_data_t *wd)
 }
 
 static void
+render_window_move(d_window_t *w)
+{
+    data_t *d;
+    window_data_t *wd;
+
+    d = screen_find_plugin_data(w->sc, plugin_id);
+    wd = window_find_plugin_data(w, plugin_id);
+
+    /* pass it on */
+    d->window_move(w);
+
+    d = screen_find_plugin_data(w->sc, plugin_id);
+
+    /* redraw the screen */
+    xcb_xfixes_copy_region(w->sc->dpy->conn, d->all_region, d->damaged_region);
+    /* reget the shadow's shape */
+    wd->shadow_valid = FALSE;
+}
+
+static void
 render_window_resize(d_window_t *w)
 {
     data_t *d;
@@ -374,9 +445,72 @@ render_window_resize(d_window_t *w)
 
     assert(wd != NULL);
     render_free_picture(w, wd);
+
+    /* redraw the screen */
+    xcb_xfixes_copy_region(w->sc->dpy->conn, d->all_region, d->damaged_region);
+    /* reget the shadow's shape */
+    wd->shadow_valid = FALSE;
+}
+
+static void
+render_window_reshape(d_window_t *w)
+{
+    data_t *d;
+    window_data_t *wd;
+
+    d = screen_find_plugin_data(w->sc, plugin_id);
+    wd = window_find_plugin_data(w, plugin_id);
+
+    /* pass it on */
+    d->window_reshape(w);
+
+    assert(wd != NULL);
+    render_free_picture(w, wd);
+
+    /* redraw the screen */
+    xcb_xfixes_copy_region(w->sc->dpy->conn, d->all_region, d->damaged_region);
+    /* reget the shadow's shape */
+    wd->shadow_valid = FALSE;
 }
 
 static void
+render_window_restack(d_window_t *w, d_window_t *above)
+{
+    data_t *d;
+    window_data_t *wd;
+
+    d = screen_find_plugin_data(w->sc, plugin_id);
+    wd = window_find_plugin_data(w, plugin_id);
+
+    /* pass it on */
+    d->window_restack(w, above);
+
+    assert(wd != NULL);
+
+    /* make sure the shadow region is right */
+    render_update_shadow(w, d, wd);
+
+    /* redraw the window's contents, and its shadow as well */
+    xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
+                            window_get_region(w), d->damaged_region);
+    xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
+                            wd->shadow_region, d->damaged_region);
+}
+
+static void
+render_update_shadow(d_window_t *w, data_t *d, window_data_t *wd)
+{
+    if (!wd->shadow_valid) {
+        xcb_xfixes_copy_region(w->sc->dpy->conn, window_get_region(w),
+                               wd->shadow_region);
+        xcb_xfixes_translate_region(w->sc->dpy->conn, wd->shadow_region,
+                                    d->xshadowoff, d->yshadowoff);
+        wd->shadow_valid = TRUE;
+    }
+}
+
+
+static void
 render_window_opacity_change(d_window_t *w)
 {
     data_t *d;
@@ -389,7 +523,35 @@ render_window_opacity_change(d_window_t *w)
     d->window_opacity_change(w);
 
     assert(wd != NULL);
-    render_update_shadow_picture(w, d, wd);
+
+    /* update the window and its shadows opacities */
+    render_update_opacity(w, d, wd);
+
+    /* make sure the shadow region is right */
+    render_update_shadow(w, d, wd);
+
+    /* redraw the window's contents, and its shadow as well */
+    xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
+                            window_get_region(w), d->damaged_region);
+    xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
+                            wd->shadow_region, d->damaged_region);
+
+    //printf("opacity change 0x%x\n", w->id);
+}
+
+static void
+render_window_damage(d_window_t *w)
+{
+    data_t *d;
+
+    d = screen_find_plugin_data(w->sc, plugin_id);
+
+    /* pass it on */
+    d->window_damage(w);
+
+    /* redraw the window's contents */
+    xcb_xfixes_union_region(w->sc->dpy->conn, d->damaged_region,
+                            window_get_region(w), d->damaged_region);
 }
 
 static void
@@ -405,6 +567,9 @@ render_root_pixmap_change(d_screen_t *sc)
 
     /* pass it on */
     d->screen_root_pixmap_change(sc);
+
+    /* redraw the screen */
+    xcb_xfixes_copy_region(sc->dpy->conn, d->all_region, d->damaged_region);
 }
 
 static void
@@ -413,39 +578,45 @@ render_paint(d_screen_t *sc)
     data_t *d = screen_find_plugin_data(sc, plugin_id);
     d_list_it_t *it;
 
-    xcb_xfixes_copy_region(sc->dpy->conn, d->all_region, d->paint_region);
+    xcb_xfixes_copy_region(sc->dpy->conn, d->damaged_region, d->paint_region);
 
     //printf("-- painting --\n");
     for (it = list_top(sc->stacking); it; it = it->next) {
         d_window_t *w = it->data;
-        int x, y, width, height, bwidth;
-
-        window_get_area(w, &x, &y, &width, &height, &bwidth);
 
         if (!window_is_input_only(w) &&
-            (window_is_mapped(w) || window_is_zombie(w)) &&
-            x < sc->super.width_in_pixels &&
-            y < sc->super.height_in_pixels &&
-            x + width > 0 && y + height > 0)
+            (window_is_mapped(w) || window_is_zombie(w)))
         {
-            gboolean opaque = !(window_is_argb(w) ||
-                                window_get_opacity(w) < 0xffff);
+            int x, y, width, height, bwidth;
+            gboolean opaque;
             window_data_t *wd;
 
+            window_get_area(w, &x, &y, &width, &height, &bwidth);
+
+            if (!(x < sc->super.width_in_pixels &&
+                  y < sc->super.height_in_pixels &&
+                  x + width > 0 && y + height > 0))
+            {
+                continue;
+            }
+
+            opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
+
             wd = window_find_plugin_data(w, plugin_id);
 
             if (opaque) {
-                paint_window(w, d, wd, opaque, x, y, width, height, bwidth);
+                xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
+                                                   d->overlay_buffer,
+                                                   d->paint_region,
+                                                   0, 0);
+                paint_window(w, d, wd, opaque,
+                             x, y, width, height, bwidth);
 
                 /* remove this window from the paint region, as nothing is
                    above it, so nothing should draw to this space again */
                 xcb_xfixes_subtract_region(sc->dpy->conn, d->paint_region,
                                            window_get_region(w),
                                            d->paint_region);
-                xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
-                                                   d->overlay_buffer,
-                                                   d->paint_region,
-                                                   0, 0);
             }
 
             /* save the clip region, when drawing windows (and shadows)
@@ -457,41 +628,40 @@ render_paint(d_screen_t *sc)
 
     paint_root(sc, d);
 
-    xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
-                                       d->overlay_buffer,
-                                       d->paint_region,
-                                       0, 0);
-
     for (it = list_bottom(sc->stacking); it; it = it->prev) {
         d_window_t *w = it->data;
-        int x, y, width, height, bwidth;
-
-        window_get_area(w, &x, &y, &width, &height, &bwidth);
 
         if (!window_is_input_only(w) &&
-            (window_is_mapped(w) || window_is_zombie(w)) &&
-            x < sc->super.width_in_pixels &&
-            y < sc->super.height_in_pixels &&
-            (x + width > 0 || x + width + d->xshadowoff > 0) &&
-            (y + height > 0 || y + height + d->yshadowoff > 0))
+            (window_is_mapped(w) || window_is_zombie(w)))
         {
+            int x, y, width, height, bwidth;
+            gboolean opaque;
             window_data_t *wd;
-            gboolean opaque = !(window_is_argb(w) ||
-                                window_get_opacity(w) < 0xffff);
+
+            window_get_area(w, &x, &y, &width, &height, &bwidth);
+
+            if (!(x < sc->super.width_in_pixels &&
+                  y < sc->super.height_in_pixels &&
+                  (x + width > 0 || x + width + d->xshadowoff > 0) &&
+                  (y + height > 0 || y + height + d->yshadowoff > 0)))
+            {
+                continue;
+            }
+
+            opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
 
             wd = window_find_plugin_data(w, plugin_id);
 
+            if (!wd->shadow_valid)
+                render_update_shadow(w, d, wd);
+
             /* shape the shadow to the window */
-            xcb_xfixes_copy_region(sc->dpy->conn, window_get_region(w),
-                                   d->shadow_region);
-            xcb_xfixes_translate_region(sc->dpy->conn, d->shadow_region,
-                                        d->xshadowoff, d->yshadowoff);
             xcb_xfixes_intersect_region(sc->dpy->conn,
-                                        wd->paint_clip, d->shadow_region,
-                                        d->shadow_region);
+                                        wd->paint_clip, wd->shadow_region,
+                                        d->shadow_paint_region);
             xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
                                                d->overlay_buffer,
-                                               d->shadow_region,
+                                               d->shadow_paint_region,
                                                0, 0);
             paint_shadow(w, d, wd, x, y, width, height, bwidth);
 
@@ -524,6 +694,10 @@ render_paint(d_screen_t *sc)
                          sc->super.width_in_pixels,
                          sc->super.height_in_pixels);
 
+    /* empty the damaged region */
+    xcb_xfixes_subtract_region(sc->dpy->conn, d->all_region,
+                               d->all_region, d->damaged_region);
+
     /* call the function we replaced in the chain */
     d->screen_paint(sc);
 }
@@ -561,22 +735,22 @@ static void
 paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
              int x, int y, int width, int height, int bwidth)
 {
-    xcb_render_picture_t alphamap;
-
     if (!wd->picture)
         render_update_picture(w, d, wd);
 
     //printf("-- paint window 0x%x picture 0x%x --\n", w->id, wd->picture);
     if (wd->picture) {
+        xcb_render_picture_t alphamap;
         int op;
 
-        op = !opaque ?
-            XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC;
-
-        if (opaque)
+        if (opaque) {
+            op = XCB_RENDER_PICT_OP_SRC;
             alphamap = XCB_NONE;
-        else
-            alphamap = solid_picture(d, w->sc, window_get_opacity(w), 0, 0, 0);
+        }
+        else {
+            op = XCB_RENDER_PICT_OP_OVER;
+            alphamap = wd->alpha_picture;
+        }
 
         xcb_render_composite(w->sc->dpy->conn,
                              op,
index 7a68c80..8314c00 100644 (file)
--- a/screen.c
+++ b/screen.c
@@ -380,6 +380,8 @@ screen_setup_default_functions(d_screen_t *sc)
     sc->window_resize = window_resize;
     sc->window_reshape = window_reshape;
     sc->window_opacity_change = window_opacity_change;
+    sc->window_damage = window_damage;
+    sc->window_restack = window_restack;
     sc->screen_root_pixmap_change = screen_update_root_pixmap;
 }
 
index 15ef143..49d0ed2 100644 (file)
--- a/screen.h
+++ b/screen.h
@@ -42,6 +42,8 @@ typedef struct d_screen {
     void (*window_resize)(struct d_window *w);
     void (*window_reshape)(struct d_window *w);
     void (*window_opacity_change)(struct d_window *w);
+    void (*window_damage)(struct d_window *w);
+    void (*window_restack)(struct d_window *w, struct d_window *above);
     void (*screen_root_pixmap_change)(struct d_screen *sc);
 } d_screen_t;
 
index 0662acf..39685a8 100644 (file)
--- a/window.c
+++ b/window.c
@@ -434,7 +434,7 @@ window_reshape(d_window_t *w)
 
 void window_opacity_change(d_window_t *w)
 {
-    (void)w;
+    screen_refresh(w->sc);
 }
 
 void
@@ -642,10 +642,8 @@ window_set_opacity(d_window_t *pubw, uint16_t o)
     d_window_priv_t *w = (d_window_priv_t*)pubw;
 
     w->opacity = o;
-    if (w->mapped || w->zombie) {
+    if (w->mapped || w->zombie)
         w->sc->window_opacity_change(pubw);
-        screen_refresh(w->sc);
-    }
     //printf("mapped %d opacity 0x%x\n", w->mapped, w->opacity);
 }
 
@@ -663,6 +661,8 @@ window_zombie_unref(d_window_t *pubw)
     d_window_priv_t *w = (d_window_priv_t*)pubw;
 
     if (--w->zombieref == 0) {
+        w->sc->window_zombie_dead(pubw);
+
         w->zombie = FALSE;
 
         if (w->region) {
@@ -677,9 +677,19 @@ window_zombie_unref(d_window_t *pubw)
             w->pixmap = XCB_NONE;
         }
 
-        w->sc->window_zombie_dead(pubw);
-
         /* reset the opacity */
         w->opacity = 0xffff;
     }
 }
+
+void
+window_damage(d_window_t *w)
+{
+    (void)w;
+}
+
+void
+window_restack(d_window_t *w, d_window_t *above)
+{
+    screen_stacking_move_above(w->sc, w, above);
+}
index 9787f84..8d29274 100644 (file)
--- a/window.h
+++ b/window.h
@@ -48,6 +48,8 @@ void window_move(d_window_t *w);
 void window_resize(d_window_t *w);
 void window_reshape(d_window_t *w);
 void window_opacity_change(d_window_t *w);
+void window_damage(d_window_t *w);
+void window_restack(d_window_t *w, d_window_t *above);
 
 gboolean window_is_zombie(d_window_t *w);
 gboolean window_is_input_only(d_window_t *w);