Make the inactive windows less opaque. This is presently unconditional and is fixed at 2/3 opacity. This patch depends on xfwm4_prop_deny_wm_opacity_change.patch. Without that patch, this patch *will* break programs which use things such as Xv overlays. Signed-off-by: Darren Salt Index: src/compositor.c =================================================================== diff -u src/compositor.c src/compositor.c --- src/compositor.c (revision 22201) +++ src/compositor.c (working copy) @@ -38,6 +38,7 @@ #include "screen.h" #include "client.h" #include "frame.h" +#include "focus.h" #include "hints.h" #include "compositor.h" @@ -68,7 +69,7 @@ !FLAG_TEST (cw->c->flags, CLIENT_FLAG_FULLSCREEN)) #define WIN_IS_OVERRIDE(cw) (cw->c == NULL) #define WIN_IS_ARGB(cw) (cw->argb) -#define WIN_IS_OPAQUE(cw) (((cw->opacity == NET_WM_OPAQUE) && !WIN_IS_ARGB(cw)) || (cw->screen_info->overlays)) +#define WIN_IS_OPAQUE(cw) (((calculate_opacity(cw) == NET_WM_OPAQUE) && !WIN_IS_ARGB(cw)) || (cw->screen_info->overlays)) #define WIN_IS_NATIVE_OPAQUE(cw) ((cw->native_opacity) && !WIN_IS_ARGB(cw)) #define WIN_IS_FULLSCREEN(cw) ((cw->attr.x <= 0) && \ (cw->attr.y <= 0) && \ @@ -166,6 +167,44 @@ return NULL; } +static guint +calculate_opacity (CWindow *cw) +{ + if (!cw->c || cw->c->opacity_locked) + return cw->opacity; + + if (FLAG_TEST(cw->c->flags, + CLIENT_FLAG_STATE_MODAL | CLIENT_FLAG_DEMANDS_ATTENTION) + || + FLAG_TEST(cw->c->type, + WINDOW_MODAL_DIALOG | WINDOW_TYPE_DONT_PLACE | + WINDOW_TYPE_DONT_FOCUS) + ) + return cw->opacity; + +#if 1 + if (cw->c == clientGetFocus()) + return cw->opacity; +#else/* disabled: may cause incomplete redrawing of some windows */ + { + Client *focus = clientGetFocus(); + + if (cw->c == focus) + return cw->opacity; + + if ( focus && (cw->c->transient_for == focus->window) && + FLAG_TEST(cw->c->type, WINDOW_MENU | WINDOW_TOOLBAR) ) + return cw->opacity; + + if ( cw->c && focus && cw->c->transient_for && focus->transient_for && + clientGetFromWindow(cw->screen_info, cw->c->transient_for, WINDOW) == + clientGetFromWindow(cw->screen_info, focus->transient_for, WINDOW) ) + return cw->opacity; + } +#endif + return cw->opacity / 3 * 2; /* overflow here is bad :-) */ +} + static gboolean is_shaped (DisplayInfo *display_info, Window id) { @@ -1234,10 +1273,12 @@ if (cw->picture) { - if ((cw->opacity != NET_WM_OPAQUE) && !(cw->alphaPict)) + guint opacity = calculate_opacity (cw); + + if (opacity < NET_WM_OPAQUE && !(cw->alphaPict)) { cw->alphaPict = solid_picture (screen_info, FALSE, - (double) cw->opacity / NET_WM_OPAQUE, 0, 0, 0); + (double) opacity / NET_WM_OPAQUE, 0, 0, 0); } XFixesIntersectRegion (dpy, cw->borderClip, cw->borderClip, cw->borderSize); XFixesSetPictureClipRegion (dpy, screen_info->rootBuffer, 0, 0, cw->borderClip); Index: src/events.c =================================================================== diff -u src/events.c src/events.c --- src/events.c (revision 22201) +++ src/events.c (working copy) @@ -1637,6 +1637,7 @@ { TRACE ("focus set to \"%s\" (0x%lx)", c->name, c->window); screen_info = c->screen_info; + compositorWindowSetOpacity (display_info, c->frame, c->opacity); clientUpdateFocus (screen_info, c, FOCUS_SORT); last_raised = clientGetLastRaise (screen_info); if ((screen_info->params->click_to_focus) && @@ -1694,6 +1695,7 @@ { TRACE ("focus lost from \"%s\" (0x%lx)", c->name, c->window); clientPassGrabMouseButton (NULL); + compositorWindowSetOpacity (display_info, c->frame, c->opacity); clientUpdateFocus (c->screen_info, NULL, NO_FOCUS_FLAG); /* Clear timeout */ clear_timeout ();