get the offscreen pixmaps for all windows (including their frames)
authorDana Jansens <danakj@orodu.net>
Wed, 20 Jun 2007 02:51:42 +0000 (02:51 +0000)
committerDana Jansens <danakj@orodu.net>
Wed, 20 Jun 2007 02:51:42 +0000 (02:51 +0000)
Makefile.am
openbox/extensions.c
openbox/extensions.h
openbox/frame.c
openbox/frame.h
openbox/openbox.c
openbox/screen.c

index 73a05ee..dbecc43 100644 (file)
@@ -164,6 +164,8 @@ openbox_openbox_SOURCES = \
        openbox/client_list_combined_menu.h \
        openbox/client_menu.c \
        openbox/client_menu.h \
+       openbox/composite.c \
+       openbox/composite.h \
        openbox/config.c \
        openbox/config.h \
        openbox/debug.c \
index 4f3a397..2fdc686 100644 (file)
@@ -84,11 +84,19 @@ void extensions_query_all()
 #endif
 
 #ifdef USE_XCOMPOSITE
-    extensions_comp =
-        XRRQueryExtension(ob_display, &extensions_comp_event_basep,
-                          &junk);
+    if (XCompositeQueryExtension(ob_display, &extensions_comp_event_basep,
+                                 &junk))
+    {
+        gint major = 0, minor = 2;
+        XCompositeQueryVersion(ob_display, &major, &minor);
+        /* Version 0.2 is the first version to have the
+           XCompositeNameWindowPixmap() request. */
+        if (major > 0 || minor >= 2)
+            extensions_comp = TRUE;
+    }
     if (!extensions_comp)
-        ob_debug("X Composite extension is not present on the server\n");
+        ob_debug("X Composite extension is not present on the server or is an "
+                 "incompatible version\n");
 #endif
 }
 
@@ -138,3 +146,10 @@ void extensions_xinerama_screens(Rect **xin_areas, guint *nxin)
     }
     RECT_SET((*xin_areas)[*nxin], l, t, r - l + 1, b - t + 1);
 }
+
+#ifdef USE_XCOMPOSITE
+Picture extensions_create_composite_picture(Window win, Visual *vis,
+                                            gboolean *has_alpha)
+{
+}
+#endif
index e1070e8..94bf0db 100644 (file)
@@ -80,5 +80,5 @@ extern gint extensions_comp_event_basep;
 void extensions_query_all();
 
 void extensions_xinerama_screens(Rect **areas, guint *nxin);
-  
+
 #endif
index 9ecee81..d88074c 100644 (file)
@@ -27,6 +27,7 @@
 #include "mainloop.h"
 #include "focus_cycle.h"
 #include "focus_cycle_indicator.h"
+#include "composite.h"
 #include "moveresize.h"
 #include "screen.h"
 #include "render/theme.h"
@@ -51,6 +52,8 @@ static void set_theme_statics(ObFrame *self);
 static void free_theme_statics(ObFrame *self);
 static gboolean frame_animate_iconify(gpointer self);
 static void frame_adjust_cursors(ObFrame *self);
+static void frame_get_offscreen_buffer(ObFrame *self);
+static void frame_free_offscreen_buffer(ObFrame *self);
 
 static Window createWindow(Window parent, Visual *visual,
                            gulong mask, XSetWindowAttributes *attrib)
@@ -62,58 +65,46 @@ static Window createWindow(Window parent, Visual *visual,
                        
 }
 
-static Visual *check_32bit_client(ObClient *c)
-{
-    XWindowAttributes wattrib;
-    Status ret;
-
-    /* we're already running at 32 bit depth, yay. we don't need to use their
-       visual */
-    if (RrDepth(ob_rr_inst) == 32)
-        return NULL;
-
-    ret = XGetWindowAttributes(ob_display, c->window, &wattrib);
-    g_assert(ret != BadDrawable);
-    g_assert(ret != BadWindow);
-
-    if (wattrib.depth == 32)
-        return wattrib.visual;
-    return NULL;
-}
-
 ObFrame *frame_new(ObClient *client)
 {
     XSetWindowAttributes attrib;
     gulong mask;
     ObFrame *self;
-    Visual *visual;
+    XWindowAttributes wattrib;
+    Status ret;
 
     self = g_new0(ObFrame, 1);
     self->client = client;
 
-    visual = check_32bit_client(client);
+    ret = XGetWindowAttributes(ob_display, client->window, &wattrib);
+    g_assert(ret != BadDrawable);
+    g_assert(ret != BadWindow);
+    self->has_alpha = composite_window_has_alpha(wattrib.visual);
 
     /* create the non-visible decor windows */
 
     mask = 0;
-    if (visual) {
-        /* client has a 32-bit visual */
-        mask |= CWColormap | CWBackPixel | CWBorderPixel;
+    if (self->has_alpha) {
+        /* the colormap/backpixel/borderpixel are required for supporting
+           windows with 32bit visuals */
+        mask = CWColormap | CWBackPixel | CWBorderPixel;
         /* create a colormap with the visual */
         self->colormap = attrib.colormap =
             XCreateColormap(ob_display,
                             RootWindow(ob_display, ob_screen),
-                            visual, AllocNone);
+                            wattrib.visual, AllocNone);
         attrib.background_pixel = BlackPixel(ob_display, ob_screen);
         attrib.border_pixel = BlackPixel(ob_display, ob_screen);
     }
-    self->window = createWindow(RootWindow(ob_display, ob_screen), visual,
+
+    self->window = createWindow(RootWindow(ob_display, ob_screen),
+                                (self->has_alpha ? wattrib.visual : NULL),
                                 mask, &attrib);
 
     /* create the visible decor windows */
 
     mask = 0;
-    if (visual) {
+    if (self->has_alpha) {
         /* client has a 32-bit visual */
         mask |= CWColormap | CWBackPixel | CWBorderPixel;
         attrib.colormap = RrColormap(ob_rr_inst);
@@ -240,6 +231,7 @@ void frame_free(ObFrame *self)
     XDestroyWindow(ob_display, self->window);
     if (self->colormap)
         XFreeColormap(ob_display, self->colormap);
+    frame_free_offscreen_buffer(self);
 
     g_free(self);
 }
@@ -251,6 +243,8 @@ void frame_show(ObFrame *self)
         framerender_frame(self);
         XMapWindow(ob_display, self->client->window);
         XMapWindow(ob_display, self->window);
+
+        frame_get_offscreen_buffer(self);
     }
 }
 
@@ -260,6 +254,7 @@ void frame_hide(ObFrame *self)
         self->visible = FALSE;
         if (!frame_iconify_animating(self))
             XUnmapWindow(ob_display, self->window);
+
         /* we unmap the client itself so that we can get MapRequest
            events, and because the ICCCM tells us to! */
         XUnmapWindow(ob_display, self->client->window);
@@ -317,6 +312,11 @@ void frame_adjust_shape(ObFrame *self)
                                 ShapeBounding, 0, 0, xrect, num,
                                 ShapeUnion, Unsorted);
     }
+
+    if (self->pixmap)
+        XShapeCombineShape(ob_display, self->pixmap, ShapeBounding,
+                           0, 0, self->window, ShapeBounding, ShapeSet);
+
 #endif
 }
 
@@ -788,6 +788,10 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
             self->need_render = TRUE;
             framerender_frame(self);
             frame_adjust_shape(self);
+
+            /* the offscreen buffer is invalid when the window is resized */
+            if (self->visible)
+                frame_get_offscreen_buffer(self);
         }
 
         if (!STRUT_EQUAL(self->size, oldsize)) {
@@ -1676,6 +1680,9 @@ void frame_end_iconify_animation(ObFrame *self)
         /* Send a ConfigureNotify when the animation is done, this fixes
            KDE's pager showing the window in the wrong place. */
         client_reconfigure(self->client, TRUE);
+
+        /* the offscreen buffer is invalid when the window is resized */
+        frame_get_offscreen_buffer(self);
     }
 
     /* we're not animating any more ! */
@@ -1740,3 +1747,26 @@ void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying)
             XMapWindow(ob_display, self->window);
     }
 }
+
+static void frame_get_offscreen_buffer(ObFrame *self)
+{
+    frame_free_offscreen_buffer(self);
+
+    if (self->visible || frame_iconify_animating(self)) {
+        self->pixmap = composite_get_window_pixmap(self->window);
+        /*
+          self->picture = composite_create_picture(self->window,
+          wattrib.visual,
+          &self->has_alpha);
+        */
+    }
+
+}
+
+static void frame_free_offscreen_buffer(ObFrame *self)
+{
+    if (self->pixmap) {
+        XFreePixmap(ob_display, self->pixmap);
+        self->pixmap = None;
+    }
+}
index cf840bd..c21860e 100644 (file)
@@ -78,6 +78,10 @@ struct _ObFrame
 
     Window    window;
 
+    Pixmap    pixmap;    /* Offscreen buffer of the frame window's contents
+                            when Composite is enabled */
+    gboolean  has_alpha;
+
     Strut     size;
     Rect      area;
     gboolean  visible;
index 1e1e3bf..ae1232f 100644 (file)
@@ -34,6 +34,7 @@
 #include "focus_cycle_indicator.h"
 #include "focus_cycle_popup.h"
 #include "moveresize.h"
+#include "composite.h"
 #include "frame.h"
 #include "keyboard.h"
 #include "mouse.h"
@@ -297,6 +298,7 @@ gint main(gint argc, gchar **argv)
             window_startup(reconfigure);
             sn_startup(reconfigure);
             screen_startup(reconfigure);
+            composite_startup(reconfigure);
             grab_startup(reconfigure);
             propwin_startup(reconfigure);
             group_startup(reconfigure);
@@ -362,6 +364,7 @@ gint main(gint argc, gchar **argv)
             group_shutdown(reconfigure);
             propwin_shutdown(reconfigure);
             grab_shutdown(reconfigure);
+            composite_shutdown(reconfigure);
             screen_shutdown(reconfigure);
             focus_cycle_popup_shutdown(reconfigure);
             focus_cycle_indicator_shutdown(reconfigure);
index 0f42b81..4abf5b6 100644 (file)
@@ -364,15 +364,6 @@ void screen_startup(gboolean reconfig)
         return;
     }
 
-#ifdef USE_XCOMPOSITE
-    if (extensions_comp) {
-        /* Redirect window contents to offscreen pixmaps */
-        XCompositeRedirectSubwindows(ob_display,
-                                     RootWindow(ob_display, ob_screen),
-                                     CompositeRedirectAutomatic);
-    }
-#endif
-
     /* get the initial size */
     screen_resize();
 
@@ -499,6 +490,9 @@ void screen_resize()
 
     for (it = client_list; it; it = g_list_next(it))
         client_move_onscreen(it->data, FALSE);
+
+    /* this needs to be setup whenever the root window's size changes */
+    composite_setup_root_window();
 }
 
 void screen_set_num_desktops(guint num)