$(XRANDR_CFLAGS) \
$(XSHAPE_CFLAGS) \
$(XSYNC_CFLAGS) \
+ $(XRENDER_CFLAGS) \
+ $(XDAMAGE_CFLAGS) \
+ $(XCOMPOSITE_CFLAGS) \
$(X_CFLAGS) \
$(XCURSOR_CFLAGS) \
$(SM_CFLAGS) \
$(XSHAPE_LIBS) \
$(XSYNC_LIBS) \
$(GLIB_LIBS) \
+ $(XRENDER_LIBS) \
+ $(XDAMAGE_LIBS) \
+ $(XCOMPOSITE_LIBS) \
$(X_LIBS) \
$(XCURSOR_LIBS) \
$(LIBSN_LIBS) \
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 \
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
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"])
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))
{
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);
+ }
+}
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 */
gboolean client_has_group_siblings(ObClient *self);
+void clienticon_free(ObClientIcon *ci);
+
#endif
--- /dev/null
+#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
--- /dev/null
+#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
#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
}
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()
{
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)
}
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
#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>
/*! 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);
#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"
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)
}
-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);
XDestroyWindow(ob_display, self->window);
if (self->colormap)
XFreeColormap(ob_display, self->colormap);
+ frame_free_offscreen_buffer(self);
g_free(self);
}
XMapWindow(ob_display, self->client->window);
XMapWindow(ob_display, self->window);
grab_server(FALSE);
+
+ frame_get_offscreen_buffer(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);
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)) {
/* 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
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 ! */
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;
+ }
+}
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;
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);
#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"
window_startup(reconfigure);
sn_startup(reconfigure);
screen_startup(reconfigure);
+ composite_startup(reconfigure);
grab_startup(reconfigure);
propwin_startup(reconfigure);
group_startup(reconfigure);
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);
#include "moveresize.h"
#include "config.h"
#include "screen.h"
+#include "composite.h"
#include "client.h"
#include "session.h"
#include "frame.h"
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)