readding the composite stuff to the new composite branch
authorDana Jansens <danakj@orodu.net>
Fri, 13 Jul 2007 04:10:24 +0000 (00:10 -0400)
committerDana Jansens <danakj@orodu.net>
Thu, 26 Jul 2007 13:57:19 +0000 (09:57 -0400)
13 files changed:
Makefile.am
configure.ac
openbox/client.c
openbox/client.h
openbox/composite.c [new file with mode: 0644]
openbox/composite.h [new file with mode: 0644]
openbox/event.c
openbox/extensions.c
openbox/extensions.h
openbox/frame.c
openbox/frame.h
openbox/openbox.c
openbox/screen.c

index dd6d68354a65251f12af08635c9f9a45ca48eda2..4798f61a98671a7e698475f80e944de2e67b05e6 100644 (file)
@@ -118,6 +118,9 @@ openbox_openbox_CPPFLAGS = \
        $(XRANDR_CFLAGS) \
        $(XSHAPE_CFLAGS) \
        $(XSYNC_CFLAGS) \
+       $(XRENDER_CFLAGS) \
+       $(XDAMAGE_CFLAGS) \
+       $(XCOMPOSITE_CFLAGS) \
        $(X_CFLAGS) \
        $(XCURSOR_CFLAGS) \
        $(SM_CFLAGS) \
@@ -137,6 +140,9 @@ openbox_openbox_LDADD = \
        $(XSHAPE_LIBS) \
        $(XSYNC_LIBS) \
        $(GLIB_LIBS) \
+       $(XRENDER_LIBS) \
+       $(XDAMAGE_LIBS) \
+       $(XCOMPOSITE_LIBS) \
        $(X_LIBS) \
        $(XCURSOR_LIBS) \
        $(LIBSN_LIBS) \
@@ -196,6 +202,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 53e50013683365eb030912601724f9605f47087b..b38993ec0ac7a311167dc1db1b94ec8034a26245 100644 (file)
@@ -136,6 +136,51 @@ else
   xcursor_found=no
 fi
 
+AC_ARG_ENABLE(xcomposite,
+  AC_HELP_STRING(
+    [--disable-xcomposite],
+    [disable use of the X Composite library. [[default=enabled]]]
+  ),
+  [enable_xcomposite=$enableval],
+  [enable_xcomposite=yes]
+)
+
+if test "$enable_xcomposite" = yes; then
+PKG_CHECK_MODULES(XRENDER, [xrender],
+  [
+    AC_DEFINE(USE_XRENDER, [1], [Use X Render library])
+    AC_SUBST(XRENDER_CFLAGS)
+    AC_SUBST(XRENDER_LIBS)
+    PKG_CHECK_MODULES(XDAMAGE, [xdamage],
+      [
+        AC_DEFINE(USE_XDAMAGE, [1], [Use X Damage library])
+        AC_SUBST(XDAMAGE_CFLAGS)
+        AC_SUBST(XDAMAGE_LIBS)
+        PKG_CHECK_MODULES(XCOMPOSITE, [xcomposite],
+          [
+            AC_DEFINE(USE_XCOMPOSITE, [1], [Use X Composite library])
+            AC_SUBST(XCOMPOSITE_CFLAGS)
+            AC_SUBST(XCOMPOSITE_LIBS)
+            xcomposite_found=yes
+          ],
+          [
+            xcomposite_found=no
+          ]
+        )
+      ],
+      [
+        xcomposite_found=no
+      ]
+    )
+  ],
+  [
+    xcomposite_found=no
+  ]
+)
+else
+  xcomposite_found=no
+fi
+
 dnl Check for session management
 X11_SM
 
@@ -170,6 +215,7 @@ AC_MSG_RESULT
 AC_MSG_RESULT([Compiling with these options:
                Startup Notification... $sn_found
                X Cursor Library... $xcursor_found
+               X Composite Library... $xcomposite_found
                Session Management... $SM
                ])
 AC_MSG_RESULT([configure complete, now type "make"])
index 712df3a579768f8a0664fc727717e7097094cbe7..82625f7f090231bd5bb63c10d5fb063d98f6d0fd 100644 (file)
@@ -1359,7 +1359,7 @@ static void client_update_transient_tree(ObClient *self,
        C is transient for B
        A can't be transient for C or we have a cycle
     */
-    if (!newgtran && newgroup &&
+    if (!newgtran &&
         (!newparent ||
          !client_search_top_direct_parent(newparent)->transient_for_group) &&
         client_normal(self))
@@ -4211,3 +4211,30 @@ gboolean client_has_group_siblings(ObClient *self)
 {
     return self->group && self->group->members->next;
 }
+
+ObClientIcon *client_thumbnail(ObClient *self, gint wantw, gint wanth)
+{
+    ObClientIcon *ret;
+    RrPixel32 *data;
+    gint w, h;
+
+    if (!self->frame->pixmap) return NULL;
+    if (!RrPixmapToRGBA(ob_rr_inst, self->frame->pixmap, None, &w, &h, &data))
+        return NULL;
+
+    /* resize the thumbnail (within aspect ratio) to the given sizes */
+
+    ret = g_new(ObClientIcon, 1);
+    ret->data = data;
+    ret->width = w;
+    ret->height = h;
+    return ret;
+}
+
+void clienticon_free(ObClientIcon *ci)
+{
+    if (ci) {
+        g_free(ci->data);
+        g_free(ci);
+    }
+}
index cba1aebbd901ee4fb12ab15e5bf8aa818b86d80c..cc26de9b2c33c1a9f03c3724e7183f3985ae5c18 100644 (file)
@@ -626,6 +626,8 @@ void client_get_type_and_transientness(ObClient *self);
 
 const ObClientIcon *client_icon(ObClient *self, gint w, gint h);
 
+ObClientIcon *client_thumbnail(ObClient *self, gint w, gint h);
+
 /*! Return TRUE if the client is transient for some other window. Return
   FALSE if it's not transient or there is no window for it to be
   transient for */
@@ -707,4 +709,6 @@ ObClient* client_under_pointer();
 
 gboolean client_has_group_siblings(ObClient *self);
 
+void clienticon_free(ObClientIcon *ci);
+
 #endif
diff --git a/openbox/composite.c b/openbox/composite.c
new file mode 100644 (file)
index 0000000..deedf96
--- /dev/null
@@ -0,0 +1,75 @@
+#include "composite.h"
+#include "openbox.h"
+#include "extensions.h"
+
+#ifndef USE_XCOMPOSITE
+void composite_startup(gboolean reconfig) {}
+void composite_shutdown(gboolean reconfig) {}
+gboolean composite_window_has_alpha(Visual *vis) { return FALSE; }
+XID composite_get_window_picture(Window win, Visual *vis) { return None; }
+Pixmap composite_get_window_pixmap(Window win) { return None; }
+void composite_setup_root_window() {}
+void composite_enable_for_window(Window win) {}
+#else
+
+static Picture root_picture = None;
+
+void composite_startup(gboolean reconfig)
+{
+    if (reconfig) return;
+    if (!extensions_comp) return;
+}
+
+void composite_shutdown(gboolean reconfig)
+{
+    if (reconfig) return;
+    if (!extensions_comp) return;
+}
+
+void composite_setup_root_window()
+{
+    if (root_picture)
+        XRenderFreePicture(ob_display, root_picture);
+
+    root_picture =
+        composite_get_window_picture(RootWindow(ob_display, ob_screen),
+                                     RrVisual(ob_rr_inst));
+}
+
+gboolean composite_window_has_alpha(Visual *vis)
+{
+    XRenderPictFormat *format;
+
+    if (!extensions_comp) return FALSE;
+
+    format = XRenderFindVisualFormat(ob_display, vis);
+    return format->type == PictTypeDirect && format->direct.alphaMask;
+}
+
+XID composite_get_window_picture(Window win, Visual *vis)
+{
+    XRenderPictureAttributes pa;
+    XRenderPictFormat *format;
+
+    if (!extensions_comp) return None;
+
+    format = XRenderFindVisualFormat(ob_display, vis);
+
+    pa.subwindow_mode = IncludeInferiors;
+    return XRenderCreatePicture(ob_display, win, format, CPSubwindowMode, &pa);
+}
+
+Pixmap composite_get_window_pixmap(Window win)
+{
+    if (!extensions_comp) return None;
+
+    return XCompositeNameWindowPixmap(ob_display, win);
+}
+
+void composite_enable_for_window(Window win)
+{
+    /* Redirect window contents to offscreen pixmaps */
+    XCompositeRedirectWindow(ob_display, win, CompositeRedirectAutomatic);
+}
+
+#endif
diff --git a/openbox/composite.h b/openbox/composite.h
new file mode 100644 (file)
index 0000000..d20abac
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __composite_h
+#define __composite_h
+
+#include <glib.h>
+#include <X11/Xlib.h>
+
+void composite_startup(gboolean reconfig);
+void composite_shutdown(gboolean reconfig);
+
+void composite_setup_root_window();
+void composite_enable_for_window(Window win);
+
+gboolean composite_window_has_alpha(Visual *vis);
+XID composite_get_window_picture(Window win, Visual *vis);
+Pixmap composite_get_window_pixmap(Window win);
+
+#endif
index c119573e3b975ff65e399764f16a07e603f88425..d2febd7e4349cfef206c6660980667dedb605086 100644 (file)
@@ -1529,7 +1529,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
 #ifdef SHAPE
         if (extensions_shape && e->type == extensions_shape_event_basep) {
             client->shaped = ((XShapeEvent*)e)->shaped;
-            frame_adjust_shape(client->frame);
+            frame_adjust_area(client->frame, FALSE, TRUE, FALSE);
         }
 #endif
     }
index 89a965769970e8224d01029cf8c9a3f934b665cd..8f79a46d1011b64eb663bd093136bedaddce6179 100644 (file)
@@ -33,6 +33,8 @@ gboolean extensions_randr     = FALSE;
 gint     extensions_randr_event_basep;
 gboolean extensions_sync      = FALSE;
 gint     extensions_sync_event_basep;
+gboolean extensions_comp      = FALSE;
+gint     extensions_comp_event_basep;
 
 void extensions_query_all()
 {
@@ -80,6 +82,22 @@ void extensions_query_all()
         ob_debug("X Sync extension is not present on the server or is an "
                  "incompatible version\n");
 #endif
+
+#ifdef USE_XCOMPOSITE
+    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 or is an "
+                 "incompatible version\n");
+#endif
 }
 
 void extensions_xinerama_screens(Rect **xin_areas, guint *nxin)
@@ -128,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 3155874035227092482fec95812a0f9b4efee867..94bf0dbf1c692dea33be475b1ac659e9e9fcb12d 100644 (file)
 #ifdef    SYNC
 #include <X11/extensions/sync.h>
 #endif
+#ifdef    USE_XCOMPOSITE
+#include <X11/extensions/Xcomposite.h>
+#include <X11/extensions/Xdamage.h>
+#include <X11/extensions/Xrender.h>
+#endif
 
 #include <glib.h>
 
@@ -67,6 +72,11 @@ extern gboolean extensions_sync;
 /*! Base for events for the Sync extension */
 extern gint extensions_sync_event_basep;
 
+/*! Does the display have the Composite extension? */
+extern gboolean extensions_comp;
+/*! Base for events for the Composite extension */
+extern gint extensions_comp_event_basep;
+
 void extensions_query_all();
 
 void extensions_xinerama_screens(Rect **areas, guint *nxin);
index cefa389e50b58d6362ccfb78020313d5cc88b929..9fb7b2b8a48de0f9e963fc45d6f43cd8540b3f3f 100644 (file)
@@ -28,6 +28,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,7 +52,10 @@ static void layout_title(ObFrame *self);
 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_shape(ObFrame *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)
@@ -63,58 +67,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);
@@ -241,6 +233,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);
 }
@@ -257,6 +250,8 @@ void frame_show(ObFrame *self)
         XMapWindow(ob_display, self->client->window);
         XMapWindow(ob_display, self->window);
         grab_server(FALSE);
+
+        frame_get_offscreen_buffer(self);
     }
 }
 
@@ -266,6 +261,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);
@@ -799,6 +795,9 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
             self->need_render = TRUE;
             framerender_frame(self);
             frame_adjust_shape(self);
+
+            /* the offscreen buffer's shape needs to match */
+            frame_get_offscreen_buffer(self);
         }
 
         if (!STRUT_EQUAL(self->size, oldsize)) {
@@ -929,6 +928,9 @@ void frame_grab_client(ObFrame *self)
     /* reparent the client to the frame */
     XReparentWindow(ob_display, self->client->window, self->window, 0, 0);
 
+    /* enable the offscreen composite buffer for the client window */
+    composite_enable_for_window(self->client->window);
+
     /*
       When reparenting the client window, it is usually not mapped yet, since
       this occurs from a MapRequest. However, in the case where Openbox is
@@ -1690,6 +1692,9 @@ void frame_end_iconify_animation(ObFrame *self)
            need to send the synthetic configurenotify, since apps may have
            read the position when the client mapped, apparently. */
         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 ! */
@@ -1754,3 +1759,34 @@ 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->client->window);
+
+#ifdef SHAPE
+        /* shape the offscreen buffer to match the window */
+        XShapeCombineShape(ob_display, self->pixmap, ShapeBounding,
+                           0, 0, self->client->window,
+                           ShapeBounding, ShapeSet);
+#endif
+
+        /*
+          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 edf75b059ffee51033d385505b1e4f88253945e4..f7adbfd40b25317afe7cb7a4b4fbf116b3033abc 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;
@@ -205,7 +209,6 @@ void frame_free(ObFrame *self);
 void frame_show(ObFrame *self);
 void frame_hide(ObFrame *self);
 void frame_adjust_theme(ObFrame *self);
-void frame_adjust_shape(ObFrame *self);
 void frame_adjust_area(ObFrame *self, gboolean moved,
                        gboolean resized, gboolean fake);
 void frame_adjust_client_area(ObFrame *self);
index 0c758cfdf4bd4c762833522c5c12c89dfb7003ed..1ea54fdcf04ec4347010ab1a1391df17a7f95a6b 100644 (file)
@@ -35,6 +35,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"
@@ -300,6 +301,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);
@@ -365,6 +367,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 330cb0a2e9c804917bc6b9477761f9c50355fc2a..8be41a476f5c492c082b72a7d54bc57a08f6923b 100644 (file)
@@ -27,6 +27,7 @@
 #include "moveresize.h"
 #include "config.h"
 #include "screen.h"
+#include "composite.h"
 #include "client.h"
 #include "session.h"
 #include "frame.h"
@@ -490,6 +491,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)