From: Dana Jansens Date: Fri, 11 Jun 2010 18:38:56 +0000 (-0400) Subject: Make composite code more reliable and correct. X-Git-Tag: cgl~37 X-Git-Url: http://git.openbox.org/?a=commitdiff_plain;h=0ebc08168b8761bd8b3943e0a1f67bbe0058b7bb;p=dana%2Fopenbox.git Make composite code more reliable and correct. use glXDestroyPixmap not glXDestroyGLXPixmap (since we use glXCreatePixmap) send a client message after taking the composite selection. allow others to take the composite selection and disable our compositing gracefully, destroying our selection window. start composite before anything that will create an ObWindow --- diff --git a/openbox/composite.c b/openbox/composite.c index 0dba1c9e..3d79b88a 100644 --- a/openbox/composite.c +++ b/openbox/composite.c @@ -28,32 +28,33 @@ #include "window.h" #include "frame.h" #include "geom.h" +#include "debug.h" #include "gettext.h" +#include "obt/prop.h" #include #include #ifdef USE_COMPOSITING -#include -#include +# include +# include +#endif +#ifdef DEBUG +# include #endif Window composite_overlay = None; +Atom composite_cm_atom = None; -#ifndef USE_COMPOSITING -void composite_startup (gboolean boiv) {;(void)(biov);} -void composite_shutdown(gboolean boiv) {;(void)(biov);} -void composite (void) {} -void composite_redir (ObWindow *d, gboolean b) {;(void)(d);(void)(b);} -void composite_resize (void) {} -#else - +#ifdef USE_COMPOSITING #define MAX_DEPTH 32 typedef GLXPixmap (*CreatePixmapT) (Display *display, GLXFBConfig config, int attribute, int *value); +typedef void (*DestroyPixmapT) (Display *display, + GLXPixmap pixmap); typedef void (*BindTexImageT) (Display *display, GLXDrawable drawable, int buffer, @@ -74,7 +75,13 @@ typedef struct _ObCompositeFBConfig { gint tf; /* texture format */ } ObCompositeFBConfig; +/*! Turn composite redirection on for a window */ +static void composite_window_redir(struct _ObWindow *w); +/*! Turn composite redirection off for a window */ +static void composite_window_unredir(struct _ObWindow *w); + static CreatePixmapT cglXCreatePixmap = NULL; +static DestroyPixmapT cglXDestroyPixmap = NULL; static BindTexImageT cglXBindTexImage = NULL; static ReleaseTexImageT cglXReleaseTexImage = NULL; static GetFBConfigsT cglXGetFBConfigs = NULL; @@ -82,9 +89,15 @@ static GetFBConfigAttribT cglXGetFBConfigAttrib = NULL; static GLXContext composite_ctx = NULL; static ObCompositeFBConfig pixmap_config[MAX_DEPTH + 1]; /* depth is index */ +static guint composite_idle_source = 0; static gboolean need_redraw = FALSE; +static Window composite_support_win = None; +#ifdef DEBUG +static gboolean composite_started = FALSE; +#endif static gboolean composite(gpointer data); +#define composite_enabled() (!!composite_idle_source) static inline void time_fix(struct timeval *tv) { @@ -168,28 +181,43 @@ static void get_best_fbcon(GLXFBConfig *in, int count, int depth, static gboolean composite_annex(void) { gchar *astr; - Atom cm_atom; Window cm_owner; + Time timestamp; + XSetWindowAttributes attrib; + + g_assert(composite_support_win == None); + + attrib.override_redirect = TRUE; + composite_support_win = XCreateWindow(obt_display, obt_root(ob_screen), + -100, -100, 1, 1, 0, + CopyFromParent, InputOnly, + CopyFromParent, + CWOverrideRedirect, + &attrib); astr = g_strdup_printf("_NET_WM_CM_S%d", ob_screen); - cm_atom = XInternAtom(obt_display, astr, FALSE); + composite_cm_atom = XInternAtom(obt_display, astr, FALSE); g_free(astr); - cm_owner = XGetSelectionOwner(obt_display, cm_atom); + cm_owner = XGetSelectionOwner(obt_display, composite_cm_atom); if (cm_owner != None) return FALSE; - XSetSelectionOwner(obt_display, cm_atom, screen_support_win, event_time()); + timestamp = event_time(); + XSetSelectionOwner(obt_display, composite_cm_atom, composite_support_win, + timestamp); - if (XGetSelectionOwner(obt_display, cm_atom) != screen_support_win) - return FALSE; + cm_owner = XGetSelectionOwner(obt_display, composite_cm_atom); + if (cm_owner != composite_support_win) return FALSE; + + /* Send client message indicating that we are now the CM */ + obt_prop_message(ob_screen, obt_root(ob_screen), OBT_PROP_ATOM(MANAGER), + timestamp, composite_cm_atom, composite_support_win, 0, 0, + SubstructureNotifyMask); return TRUE; } -/*! This function will try enable composite if config_comp is TRUE. At the - end of this process, config_comp will be set to TRUE only if composite - is enabled, and FALSE otherwise. */ -void composite_startup(gboolean reconfig) +gboolean composite_enable(void) { int count, val, i; XWindowAttributes xa; @@ -198,32 +226,28 @@ void composite_startup(gboolean reconfig) GLXFBConfig *fbcs; const char *glstring; - if (reconfig) return; - if (!config_comp) return; - - if (ob_comp_indirect) - setenv("LIBGL_ALWAYS_INDIRECT", "1", TRUE); + if (composite_enabled()) return TRUE; - config_comp = FALSE; + g_assert(config_comp); /* Check for the required extensions in the server */ if (!obt_display_extension_composite) { g_message( _("Failed to enable composite. The %s extension is missing."), "XComposite"); - return; + return FALSE; } if (!obt_display_extension_damage) { g_message( _("Failed to enable composite. The %s extension is missing."), "XDamage"); - return; + return FALSE; } if (!obt_display_extension_fixes) { g_message( _("Failed to enable composite. The %s extension is missing."), "XFixes"); - return; + return FALSE; } /* Check for the required glX functions */ @@ -233,35 +257,42 @@ void composite_startup(gboolean reconfig) if (!cglXCreatePixmap) { g_message(_("Failed to enable composite. %s unavailable."), "glXCreatePixmap"); - return; + return FALSE; + } + cglXDestroyPixmap = (DestroyPixmapT) + glXGetProcAddress((const unsigned char*)"glXDestroyPixmap"); + if (!cglXDestroyPixmap) { + g_message(_("Failed to enable composite. %s unavailable."), + "glXDestroyPixmap"); + return FALSE; } cglXBindTexImage = (BindTexImageT) glXGetProcAddress((const unsigned char*)"glXBindTexImageEXT"); if (!cglXBindTexImage) { g_message(_("Failed to enable composite. %s unavailable."), "glXBindTexImage"); - return; + return FALSE; } cglXReleaseTexImage = (ReleaseTexImageT) glXGetProcAddress((const unsigned char*)"glXReleaseTexImageEXT"); if (!cglXReleaseTexImage) { g_message(_("Failed to enable composite. %s unavailable."), "glXReleaseTexImage"); - return; + return FALSE; } cglXGetFBConfigs = (GetFBConfigsT)glXGetProcAddress( (const unsigned char*)"glXGetFBConfigs"); if (!cglXGetFBConfigs) { g_message(_("Failed to enable composite. %s unavailable."), "glXGetFBConfigs"); - return; + return FALSE; } cglXGetFBConfigAttrib = (GetFBConfigAttribT)glXGetProcAddress( (const unsigned char*)"glXGetFBConfigAttrib"); if (!cglXGetFBConfigAttrib) { g_message(_("Failed to enable composite. %s unavailable."), "glXGetFBConfigAttrib"); - return; + return FALSE; } /* Check for required GLX extensions */ @@ -270,7 +301,7 @@ void composite_startup(gboolean reconfig) if (!strstr(glstring, "GLX_EXT_texture_from_pixmap")) { g_message(_("Failed to enable composite. %s is not present."), "GLX_EXT_texture_from_pixmap"); - return; + return FALSE; } /* Check for FBconfigs */ @@ -278,7 +309,7 @@ void composite_startup(gboolean reconfig) fbcs = cglXGetFBConfigs(obt_display, ob_screen, &count); if (!count) { g_message(_("Failed to enable composite. No valid FBConfigs.")); - return; + return FALSE; } memset(&pixmap_config, 0, sizeof(pixmap_config)); for (i = 1; i < MAX_DEPTH + 1; i++) @@ -289,16 +320,20 @@ void composite_startup(gboolean reconfig) if (!composite_annex()) { g_message(_("Failed to enable composite. Another composite manager is running.")); - return; + return FALSE; } + /* From here on, if initializing composite fails, make sure you call + composite_disable() ! */ + /* Set up the overlay window */ composite_overlay = XCompositeGetOverlayWindow(obt_display, obt_root(ob_screen)); if (!composite_overlay) { g_message(_("Failed to enable composite. Unable to get overlay window from X server")); - return; + composite_disable(); + return FALSE; } xr = XFixesCreateRegion(obt_display, NULL, 0); XFixesSetWindowShapeRegion(obt_display, composite_overlay, ShapeBounding, @@ -307,44 +342,46 @@ void composite_startup(gboolean reconfig) 0, 0, xr); XFixesDestroyRegion(obt_display, xr); - /* From here on, if initializing composite fails, make sure you call - composite_shutdown() ! */ - - /* Make sure the root window's visual is acceptable for our GLX needs and create a GLX context with it */ if (!XGetWindowAttributes(obt_display, obt_root(ob_screen), &xa)) { g_message(_("Failed to enable composite. %s failed."), "XGetWindowAttributes"); - composite_shutdown(reconfig); - return; + composite_disable(); + return FALSE; } tmp.visualid = XVisualIDFromVisual(xa.visual); vi = XGetVisualInfo(obt_display, VisualIDMask, &tmp, &count); if (!count) { g_message( _("Failed to enable composite. Failed to get visual info.")); - composite_shutdown(reconfig); - return; + composite_disable(); + return FALSE; } glXGetConfig(obt_display, vi, GLX_USE_GL, &val); if (!val) { g_message(_("Failed to enable composite. Visual is not GL capable")); XFree(vi); - composite_shutdown(reconfig); - return; + composite_disable(); + return FALSE; } glXGetConfig(obt_display, vi, GLX_DOUBLEBUFFER, &val); if (!val) { g_message( _("Failed to enable composite. Visual is not double buffered")); XFree(vi); - composite_shutdown(reconfig); - return; + composite_disable(); + return FALSE; } composite_ctx = glXCreateContext(obt_display, vi, NULL, True); XFree(vi); + if (!composite_ctx) { + g_message( + _("Failed to enable composite. Unable to create GLX context")); + composite_disable(); + return FALSE; + } printf("Best visual for 24bpp was 0x%lx\n", (gulong)pixmap_config[24].fbc); @@ -352,35 +389,35 @@ void composite_startup(gboolean reconfig) (gulong)pixmap_config[32].fbc); /* We're good to go for composite ! */ - config_comp = TRUE; - g_idle_add(composite, NULL); + /* register our screen redraw callback */ + composite_idle_source = g_idle_add(composite, NULL); glXMakeCurrent(obt_display, composite_overlay, composite_ctx); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glXSwapBuffers(obt_display, composite_overlay); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - - composite_resize(); - glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -} -void composite_shutdown(gboolean reconfig) -{ - if (reconfig) return; + composite_resize(); + window_foreach(composite_window_redir); - obt_display_ignore_errors(TRUE); - glXMakeCurrent(obt_display, None, NULL); - obt_display_ignore_errors(FALSE); + return TRUE; +} +void composite_disable(void) +{ if (composite_ctx) { + obt_display_ignore_errors(TRUE); + glXMakeCurrent(obt_display, None, NULL); + obt_display_ignore_errors(FALSE); + glXDestroyContext(obt_display, composite_ctx); composite_ctx = NULL; } @@ -389,11 +426,49 @@ void composite_shutdown(gboolean reconfig) XCompositeReleaseOverlayWindow(obt_display, composite_overlay); composite_overlay = None; } + + if (composite_support_win) + XDestroyWindow(obt_display, composite_support_win); + + window_foreach(composite_window_unredir); + + g_source_remove(composite_idle_source); + composite_idle_source = 0; +} + +/*! This function will try enable composite if config_comp is TRUE. At the + end of this process, config_comp will be set to TRUE only if composite + is enabled, and FALSE otherwise. */ +void composite_startup(gboolean reconfig) +{ +#ifdef DEBUG + composite_started = TRUE; +#endif + + if (!reconfig) { + if (ob_comp_indirect) + setenv("LIBGL_ALWAYS_INDIRECT", "1", TRUE); + } +} + +void composite_shutdown(gboolean reconfig) +{ +#ifdef DEBUG + composite_started = FALSE; +#endif + + if (reconfig) return; + + if (composite_enabled()) + composite_disable(); } void composite_resize(void) { const Rect *a; + + if (!composite_enabled()) return; + a = screen_physical_area_all_monitors(); glOrtho(a->x, a->x + a->width, a->y + a->height, a->y, -100, 100); } @@ -405,7 +480,7 @@ static gboolean composite(gpointer data) ObWindow *win; ObClient *client; - if (!config_comp) return FALSE; + if (!composite_enabled()) return FALSE; /* if (!need_redraw) return FALSE; */ @@ -430,9 +505,21 @@ static gboolean composite(gpointer data) d = window_depth(win); - if (win->pixmap == None) + if (win->pixmap == None) { + obt_display_ignore_errors(TRUE); win->pixmap = XCompositeNameWindowPixmap(obt_display, window_top(win)); + obt_display_ignore_errors(FALSE); + if (obt_display_error_occured) { + ob_debug_type(OB_DEBUG_CM, + "Error in XCompositeNameWindowPixmap for " + "window 0x%x\n", window_top(win)); + if (win->pixmap) { + XFreePixmap(obt_display, win->pixmap); + win->pixmap = None; + } + } + } if (win->pixmap == None) continue; @@ -452,13 +539,18 @@ static gboolean composite(gpointer data) continue; glBindTexture(GL_TEXTURE_2D, win->texture); -gettimeofday(&start, NULL); +#ifdef DEBUG + gettimeofday(&start, NULL); +#endif cglXBindTexImage(obt_display, win->gpixmap, GLX_FRONT_LEFT_EXT, NULL); -gettimeofday(&end, NULL); -dif.tv_sec = end.tv_sec - start.tv_sec; -dif.tv_usec = end.tv_usec - start.tv_usec; -time_fix(&dif); +#ifdef DEBUG + gettimeofday(&end, NULL); + dif.tv_sec = end.tv_sec - start.tv_sec; + dif.tv_usec = end.tv_usec - start.tv_usec; + time_fix(&dif); //printf("took %f ms\n", dif.tv_sec * 1000.0 + dif.tv_usec / 1000.0); +#endif + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -486,6 +578,9 @@ time_fix(&dif); glXSwapBuffers(obt_display, composite_overlay); glFinish(); + if (ob_comp_indirect) + g_usleep(5000); + #ifdef DEBUG { GLenum gler; @@ -499,23 +594,84 @@ time_fix(&dif); return TRUE; } -void composite_redir(ObWindow *w, gboolean on) +static void composite_window_redir(ObWindow *w) +{ + if (!composite_enabled()) return; + + if (w->redir) return; + XCompositeRedirectWindow(obt_display, window_top(w), + CompositeRedirectManual); + w->redir = TRUE; +} + +static void composite_window_unredir(ObWindow *w) +{ + if (!w->redir) return; + XCompositeUnredirectWindow(obt_display, window_top(w), + CompositeRedirectManual); + w->redir = FALSE; +} + +void composite_window_setup(ObWindow *w) +{ + if (w->type == OB_WINDOW_CLASS_PROMPT) return; + +#ifdef DEBUG + g_assert(composite_started); +#endif + + w->damage = XDamageCreate(obt_display, window_top(w), + XDamageReportNonEmpty); + + composite_window_redir(w); +} + +void composite_window_cleanup(ObWindow *w) { - if (!config_comp) return; + if (w->type == OB_WINDOW_CLASS_PROMPT) return; + +#ifdef DEBUG + g_assert(composite_started); +#endif + + composite_window_unredir(w); - if (on) { - if (w->redir) return; - XCompositeRedirectWindow(obt_display, window_top(w), - CompositeRedirectManual); - w->redir = TRUE; + composite_window_invalid(w); + if (w->damage) { + XDamageDestroy(obt_display, w->damage); + w->damage = None; } - else { - if (!w->redir) return; - XCompositeUnredirectWindow(obt_display, window_top(w), - CompositeRedirectManual); - w->redir = FALSE; + if (w->texture) { + glDeleteTextures(1, &w->texture); + w->texture = 0; + } +} + +void composite_window_invalid(ObWindow *w) +{ + if (w->gpixmap) { + cglXDestroyPixmap(obt_display, w->gpixmap); + w->gpixmap = None; + } + if (w->pixmap) { + XFreePixmap(obt_display, w->pixmap); + w->pixmap = None; } } +#else +void composite_startup (gboolean boiv) {;(void)(biov);} +void composite_shutdown (gboolean boiv) {;(void)(biov);} +void composite (void) {} +void composite_resize (void) {} +void composite_disable (void) {} +void composite_window_setup (ObWindow *w) {} +void composite_window_cleanup (ObWindow *w) {} +void composite_window_invalid (ObWindow *w) {} + +void composite_enable(void) +{ + g_message( + _("Unable to use compositing. Openbox was compiled without it.")); +} #endif - diff --git a/openbox/composite.h b/openbox/composite.h index a78fe68b..6e159828 100644 --- a/openbox/composite.h +++ b/openbox/composite.h @@ -26,16 +26,25 @@ struct _ObWindow; extern Window composite_overlay; +/*! The atom for the selection we hold on the screen to claim ourselves as the + current composite manager */ +extern Atom composite_cm_atom; void composite_startup(gboolean reconfig); void composite_shutdown(gboolean reconfig); -/*! Draw everything */ -void composite(void); +/*! Turn composite on */ +gboolean composite_enable(void); +/*! Turn composite off */ +void composite_disable(void); -/*! Turn composite redirection on or off for a window */ -void composite_redir(struct _ObWindow *w, gboolean on); /*! Called when the screen changes its size */ void composite_resize(void); +void composite_window_setup(struct _ObWindow *w); +void composite_window_cleanup(struct _ObWindow *w); + +/*! Called when a window's pixmaps become invalid and need to be destroyed */ +void composite_window_invalid(struct _ObWindow *w); + #endif diff --git a/openbox/event.c b/openbox/event.c index c1657c3c..c1b23fad 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -678,18 +678,8 @@ static void event_process(const XEvent *ec, gpointer data) obwin->mapped = TRUE; } - if (pixchange) { -#ifdef USE_COMPOSITING - if (obwin->gpixmap != None) { - glXDestroyGLXPixmap(obt_display, obwin->gpixmap); - obwin->gpixmap = None; - } - if (obwin->pixmap != None) { - XFreePixmap(obt_display, obwin->pixmap); - obwin->pixmap = None; - } -#endif - } + if (pixchange) + composite_window_invalid(obwin); } else if ((e->type == UnmapNotify) && obwin && obwin->type != OB_WINDOW_CLASS_PROMPT && e->xunmap.window == window_top(obwin)) @@ -819,8 +809,15 @@ static void event_handle_root(XEvent *e) switch(e->type) { case SelectionClear: - ob_debug("Another WM has requested to replace us. Exiting."); - ob_exit_replace(); + if (e->xselectionclear.selection == screen_wm_sn_atom) { + ob_debug("Another WM has requested to replace us. Exiting."); + ob_exit_replace(); + } + else if (e->xselectionclear.selection == composite_cm_atom) { + ob_debug("Another composite manager has requested to replace us. Disabling composite."); + composite_disable(); + config_comp = FALSE; + } break; case ClientMessage: @@ -870,7 +867,6 @@ static void event_handle_root(XEvent *e) XRRUpdateConfiguration(e); #endif screen_resize(); - composite_resize(); break; default: ; diff --git a/openbox/openbox.c b/openbox/openbox.c index 14ef7d41..dd152386 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -304,11 +304,12 @@ gint main(gint argc, gchar **argv) anything that calls stacking_add */ sn_startup(reconfigure); window_startup(reconfigure); + composite_startup(reconfigure); focus_startup(reconfigure); + screen_startup(reconfigure); focus_cycle_startup(reconfigure); focus_cycle_indicator_startup(reconfigure); focus_cycle_popup_startup(reconfigure); - screen_startup(reconfigure); grab_startup(reconfigure); group_startup(reconfigure); ping_startup(reconfigure); @@ -320,7 +321,12 @@ gint main(gint argc, gchar **argv) menu_frame_startup(reconfigure); menu_startup(reconfigure); prompt_startup(reconfigure); - composite_startup(reconfigure); + + /* turn compositing on/off */ + if (!config_comp) + composite_disable(); + else + config_comp = composite_enable(); /* do this after everything is started so no events will get missed */ @@ -389,7 +395,6 @@ gint main(gint argc, gchar **argv) if (!reconfigure) window_unmanage_all(); - composite_shutdown(reconfigure); prompt_shutdown(reconfigure); menu_shutdown(reconfigure); menu_frame_shutdown(reconfigure); @@ -401,11 +406,12 @@ gint main(gint argc, gchar **argv) ping_shutdown(reconfigure); group_shutdown(reconfigure); grab_shutdown(reconfigure); - screen_shutdown(reconfigure); focus_cycle_popup_shutdown(reconfigure); focus_cycle_indicator_shutdown(reconfigure); focus_cycle_shutdown(reconfigure); + screen_shutdown(reconfigure); focus_shutdown(reconfigure); + composite_shutdown(reconfigure); window_shutdown(reconfigure); sn_shutdown(reconfigure); event_shutdown(reconfigure); diff --git a/openbox/screen.c b/openbox/screen.c index 56a7551f..249b456a 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -67,6 +67,7 @@ ObDesktopLayout screen_desktop_layout; gchar **screen_desktop_names; Window screen_support_win; Time screen_desktop_user_time = CurrentTime; +Atom screen_wm_sn_atom = None; static Size screen_physical_size; static guint screen_old_desktop; @@ -91,15 +92,14 @@ static gboolean desktop_popup_perm; static gboolean replace_wm(void) { gchar *wm_sn; - Atom wm_sn_atom; Window current_wm_sn_owner; Time timestamp; wm_sn = g_strdup_printf("WM_S%d", ob_screen); - wm_sn_atom = XInternAtom(obt_display, wm_sn, FALSE); + screen_wm_sn_atom = XInternAtom(obt_display, wm_sn, FALSE); g_free(wm_sn); - current_wm_sn_owner = XGetSelectionOwner(obt_display, wm_sn_atom); + current_wm_sn_owner = XGetSelectionOwner(obt_display, screen_wm_sn_atom); if (current_wm_sn_owner == screen_support_win) current_wm_sn_owner = None; if (current_wm_sn_owner) { @@ -121,10 +121,12 @@ static gboolean replace_wm(void) timestamp = event_time(); - XSetSelectionOwner(obt_display, wm_sn_atom, screen_support_win, + XSetSelectionOwner(obt_display, screen_wm_sn_atom, screen_support_win, timestamp); - if (XGetSelectionOwner(obt_display, wm_sn_atom) != screen_support_win) { + if (XGetSelectionOwner(obt_display, screen_wm_sn_atom) != + screen_support_win) + { g_message(_("Could not acquire window manager selection on screen %d"), ob_screen); return FALSE; @@ -155,7 +157,7 @@ static gboolean replace_wm(void) /* Send client message indicating that we are now the WM */ obt_prop_message(ob_screen, obt_root(ob_screen), OBT_PROP_ATOM(MANAGER), - timestamp, wm_sn_atom, screen_support_win, 0, 0, + timestamp, screen_wm_sn_atom, screen_support_win, 0, 0, SubstructureNotifyMask); return TRUE; @@ -173,7 +175,7 @@ gboolean screen_annex(void) attrib.event_mask = PropertyChangeMask; screen_support_win = XCreateWindow(obt_display, obt_root(ob_screen), -100, -100, 1, 1, 0, - CopyFromParent, InputOutput, + CopyFromParent, InputOnly, CopyFromParent, CWEventMask | CWOverrideRedirect, &attrib); @@ -503,6 +505,7 @@ void screen_resize(void) screen_update_areas(); dock_configure(); + composite_resize(); for (it = client_list; it; it = g_list_next(it)) client_move_onscreen(it->data, FALSE); diff --git a/openbox/screen.h b/openbox/screen.h index d15b352c..26e272ce 100644 --- a/openbox/screen.h +++ b/openbox/screen.h @@ -40,6 +40,9 @@ extern gboolean screen_showing_desktop; extern Window screen_support_win; /*! The last time at which the user changed desktops */ extern Time screen_desktop_user_time; +/*! The atom for the selection we hold on the screen to claim ourselves as the + current window manager */ +extern Atom screen_wm_sn_atom; typedef struct ObDesktopLayout { ObOrientation orientation; diff --git a/openbox/window.c b/openbox/window.c index ad4c10d4..13ba0658 100644 --- a/openbox/window.c +++ b/openbox/window.c @@ -73,19 +73,12 @@ void window_set_abstract(ObWindow *self, /* set up any things in ObWindow that require use of the abstract pointers now */ -#ifdef USE_COMPOSITING - if (self->type != OB_WINDOW_CLASS_PROMPT) { - self->damage = XDamageCreate(obt_display, window_top(self), - XDamageReportNonEmpty); - } -#endif - - composite_redir(self, TRUE); + composite_window_setup(self); } void window_cleanup(ObWindow *self) { - composite_redir(self, FALSE); + composite_window_cleanup(self); } void window_free(ObWindow *self) @@ -93,19 +86,6 @@ void window_free(ObWindow *self) /* The abstract pointers must not be used here, they are likely invalid by now ! */ -#ifdef USE_COMPOSITING - if (self->type != OB_WINDOW_CLASS_PROMPT) { - if (self->damage) - XDamageDestroy(obt_display, self->damage); - if (self->gpixmap) - glXDestroyGLXPixmap(obt_display, self->gpixmap); - if (self->pixmap) - XFreePixmap(obt_display, self->pixmap); - if (self->texture) - glDeleteTextures(1, &self->texture); - } -#endif - g_slice_free1(self->size, self); } @@ -114,6 +94,16 @@ ObWindow* window_find(Window xwin) return g_hash_table_lookup(window_map, &xwin); } +void wfe(gpointer k, gpointer v, gpointer data) +{ + ((ObWindowForeachFunc)data)(v); +} + +void window_foreach(ObWindowForeachFunc func) +{ + g_hash_table_foreach(window_map, wfe, func); +} + void window_add(Window *xwin, ObWindow *win) { g_assert(xwin != NULL); diff --git a/openbox/window.h b/openbox/window.h index 946525c3..02de98d0 100644 --- a/openbox/window.h +++ b/openbox/window.h @@ -125,6 +125,10 @@ ObWindow* window_find (Window xwin); void window_add (Window *xwin, ObWindow *win); void window_remove(Window xwin); +typedef void (*ObWindowForeachFunc)(ObWindow *w); + +void window_foreach(ObWindowForeachFunc func); + #define window_top(w) (*((ObWindow*)w)->top) #define window_layer(w) (*((ObWindow*)w)->layer) #define window_area(w) (*((ObWindow*)w)->area)