Allow windows to be locked against WM-initiated opacity changes. This uses a new non-standard hint, _NET_WM_WINDOW_OPACITY_LOCKED. If the hint is present for the current window, then the window manager SHOULD NOT alter its opacity from the current value of _NET_WM_WINDOW_OPACITY (if it uses that hint), and opacity-setting tools SHOULD NOT alter _NET_WM_WINDOW_OPACITY. If the hint is absent, then the behaviour of xfwm4 without this patch is maintained. (Reason: opacity of windows which (contain sub-windows which) are used for Xv overlays.) Signed-off-by: Darren Salt Index: src/display.c =================================================================== --- src/display.c (revision 22201) +++ src/display.c (working copy) @@ -106,6 +106,7 @@ "_NET_WM_MOVERESIZE", "_NET_WM_NAME", "_NET_WM_WINDOW_OPACITY", + "_NET_WM_WINDOW_OPACITY_LOCKED", "_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_BELOW", Index: src/display.h =================================================================== --- src/display.h (revision 22201) +++ src/display.h (working copy) @@ -117,6 +117,7 @@ NET_WM_MOVERESIZE, NET_WM_NAME, NET_WM_WINDOW_OPACITY, + NET_WM_WINDOW_OPACITY_LOCKED, NET_WM_STATE, NET_WM_STATE_ABOVE, NET_WM_STATE_BELOW, Index: src/events.c =================================================================== --- src/events.c (revision 22201) +++ src/events.c (working copy) @@ -1823,6 +1823,11 @@ } compositorWindowSetOpacity (display_info, c->frame, c->opacity); } + else if (ev->atom == display_info->atoms[NET_WM_WINDOW_OPACITY_LOCKED]) + { + TRACE ("client \"%s\" (0x%lx) has received a net_wm_opacity_locked notify", c->name, c->window); + c->opacity_locked = getOpacityLock (display_info, c->window); + } else if ((screen_info->params->show_app_icon) && ((ev->atom == display_info->atoms[NET_WM_ICON]) || (ev->atom == display_info->atoms[KWM_WIN_ICON]))) Index: src/compositor.c =================================================================== --- src/compositor.c (revision 22201) +++ src/compositor.c (working copy) @@ -99,6 +99,7 @@ gboolean argb; gboolean skipped; gboolean native_opacity; + gboolean opacity_locked; Damage damage; #if HAVE_NAME_WINDOW_PIXMAP @@ -1769,17 +1770,20 @@ cw->native_opacity = FALSE; if (c) { + cw->opacity_locked = c->opacity_locked; cw->opacity = c->opacity; cw->native_opacity = WIN_IS_OPAQUE(cw); } else if (getOpacity (display_info, cw->id, &cw->opacity)) { cw->native_opacity = WIN_IS_OPAQUE(cw); + cw->opacity_locked = getOpacityLock (display_info, cw->id); } else { cw->opacity = (double) (screen_info->params->popup_opacity / 100.0) * NET_WM_OPAQUE; cw->native_opacity = TRUE; + cw->opacity_locked = getOpacityLock (display_info, cw->id); } } @@ -2146,6 +2150,20 @@ } } } + else if (ev->atom == display_info->atoms[NET_WM_WINDOW_OPACITY_LOCKED]) + { + CWindow *cw = find_cwindow_in_display (display_info, ev->window); + TRACE ("Opacity locking property changed for id 0x%lx", ev->window); + + if (cw) + { + cw->opacity_locked = getOpacityLock (display_info, cw->id); + if (cw->c) + { + cw->c->opacity_locked = cw->opacity_locked; + } + } + } else { TRACE ("No compositor property changed for id 0x%lx", ev->window); Index: src/client.c =================================================================== --- src/client.c (revision 22201) +++ src/client.c (working copy) @@ -1629,6 +1629,8 @@ c->opacity = NET_WM_OPAQUE; getOpacity (display_info, c->window, &c->opacity); + c->opacity_locked = getOpacityLock (display_info, c->window); + /* Timeout for blinking on urgency */ c->blink_timeout_id = 0; @@ -2865,7 +2867,7 @@ screen_info = c->screen_info; display_info = screen_info->display_info; - if ( c->opacity > OPACITY_SET_MIN ) + if ( c->opacity > OPACITY_SET_MIN && !c->opacity_locked ) { c->opacity -= OPACITY_SET_STEP; compositorWindowSetOpacity (display_info, c->frame, c->opacity); @@ -2881,7 +2883,7 @@ screen_info = c->screen_info; display_info = screen_info->display_info; - if ( c->opacity < NET_WM_OPAQUE ) + if ( c->opacity < NET_WM_OPAQUE && !c->opacity_locked ) { c->opacity += OPACITY_SET_STEP; @@ -3534,7 +3536,7 @@ #endif /* SHOW_POSITION */ /* Set window translucent while moving, looks nice */ - if ((screen_info->params->move_opacity < 100) && !(screen_info->params->box_move)) + if ((screen_info->params->move_opacity < 100) && !(screen_info->params->box_move) && !c->opacity_locked) { compositorWindowSetOpacity (display_info, c->frame, (guint) (c->opacity * (double) (screen_info->params->move_opacity / 100.0))); @@ -4014,7 +4016,7 @@ #endif /* SHOW_POSITION */ /* Set window translucent while resizing, doesn't looks too nice :( */ - if ((screen_info->params->resize_opacity < 100) && !(screen_info->params->box_resize)) + if ((screen_info->params->resize_opacity < 100) && !(screen_info->params->box_resize) && !c->opacity_locked) { compositorWindowSetOpacity (display_info, c->frame, (guint) (c->opacity * (double) (screen_info->params->resize_opacity / 100.0))); Index: src/client.h =================================================================== --- src/client.h (revision 22201) +++ src/client.h (working copy) @@ -269,6 +269,7 @@ ClientPixmapCache pm_cache; /* Opacity for the compositor */ guint opacity; + gboolean opacity_locked; #ifdef HAVE_LIBSTARTUP_NOTIFICATION /* Startup notification */ Index: src/hints.c =================================================================== --- src/hints.c (revision 22201) +++ src/hints.c (working copy) @@ -1103,6 +1103,18 @@ } gboolean +getOpacityLock (DisplayInfo *display_info, Window window) +{ + long val; + + g_return_val_if_fail (window != None, FALSE); + TRACE ("entering getOpacityLock"); + + /* only presence/absence matters */ + return !!getHint (display_info, window, NET_WM_WINDOW_OPACITY_LOCKED, &val); +} + +gboolean setCompositingManagerOwner (DisplayInfo *display_info, Window root, Window w) { XClientMessageEvent ev; Index: src/hints.h =================================================================== --- src/hints.h (revision 22201) +++ src/hints.h (working copy) @@ -176,6 +176,7 @@ gboolean getKDEIcon (DisplayInfo *, Window, Pixmap *, Pixmap *); gboolean getRGBIconData (DisplayInfo *, Window, unsigned long **, unsigned long *); gboolean getOpacity (DisplayInfo *, Window, guint *); +gboolean getOpacityLock (DisplayInfo *, Window); gboolean setCompositingManagerOwner (DisplayInfo *, Window , Window); #ifdef ENABLE_KDE_SYSTRAY_PROXY