From c33ddf6bb408a08a513b9e2602f64fd85eb38a6d Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Fri, 13 Jul 2007 00:10:24 -0400 Subject: [PATCH] readding the composite stuff to the new composite branch --- Makefile.am | 8 ++++ configure.ac | 46 ++++++++++++++++++++++ openbox/client.c | 29 +++++++++++++- openbox/client.h | 4 ++ openbox/composite.c | 75 ++++++++++++++++++++++++++++++++++++ openbox/composite.h | 17 +++++++++ openbox/event.c | 2 +- openbox/extensions.c | 25 ++++++++++++ openbox/extensions.h | 10 +++++ openbox/frame.c | 90 +++++++++++++++++++++++++++++++------------- openbox/frame.h | 5 ++- openbox/openbox.c | 3 ++ openbox/screen.c | 4 ++ 13 files changed, 288 insertions(+), 30 deletions(-) create mode 100644 openbox/composite.c create mode 100644 openbox/composite.h diff --git a/Makefile.am b/Makefile.am index dd6d6835..4798f61a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/configure.ac b/configure.ac index 53e50013..b38993ec 100644 --- a/configure.ac +++ b/configure.ac @@ -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"]) diff --git a/openbox/client.c b/openbox/client.c index 712df3a5..82625f7f 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -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); + } +} diff --git a/openbox/client.h b/openbox/client.h index cba1aebb..cc26de9b 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -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 index 00000000..deedf965 --- /dev/null +++ b/openbox/composite.c @@ -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 index 00000000..d20abacb --- /dev/null +++ b/openbox/composite.h @@ -0,0 +1,17 @@ +#ifndef __composite_h +#define __composite_h + +#include +#include + +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 diff --git a/openbox/event.c b/openbox/event.c index c119573e..d2febd7e 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -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 } diff --git a/openbox/extensions.c b/openbox/extensions.c index 89a96576..8f79a46d 100644 --- a/openbox/extensions.c +++ b/openbox/extensions.c @@ -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 diff --git a/openbox/extensions.h b/openbox/extensions.h index 31558740..94bf0dbf 100644 --- a/openbox/extensions.h +++ b/openbox/extensions.h @@ -39,6 +39,11 @@ #ifdef SYNC #include #endif +#ifdef USE_XCOMPOSITE +#include +#include +#include +#endif #include @@ -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); diff --git a/openbox/frame.c b/openbox/frame.c index cefa389e..9fb7b2b8 100644 --- a/openbox/frame.c +++ b/openbox/frame.c @@ -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; + } +} diff --git a/openbox/frame.h b/openbox/frame.h index edf75b05..f7adbfd4 100644 --- a/openbox/frame.h +++ b/openbox/frame.h @@ -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); diff --git a/openbox/openbox.c b/openbox/openbox.c index 0c758cfd..1ea54fdc 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -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); diff --git a/openbox/screen.c b/openbox/screen.c index 330cb0a2..8be41a47 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -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) -- 2.34.1