New backends: smoothly fade blur-texture on fade-in/-out
* Add new field `opacity_target_old` to `struct managed_win` for tracking relevant `opacity_target` changes. * Smoothly fade blur-texture opacity on window opacity changes (based on window opacity), when the window was or will be fully transparent (`w->opacity ~< 0.004`). * Fixed alpha-clipping of the blur-texture when using `inactive-opacity` or repeatedly setting window opacity with large fade intervals (should fix #314).
This commit is contained in:
parent
32754b0262
commit
ad8632b017
|
@ -204,16 +204,34 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
|||
// itself is not opaque, only the frame is.
|
||||
|
||||
double blur_opacity = 1;
|
||||
if (w->state == WSTATE_MAPPING) {
|
||||
if (w->opacity < (1.0 / MAX_ALPHA)) {
|
||||
// Hide blur for fully transparent windows.
|
||||
blur_opacity = 0;
|
||||
} else if (w->state == WSTATE_MAPPING) {
|
||||
// Gradually increase the blur intensity during
|
||||
// fading in.
|
||||
assert(w->opacity <= w->opacity_target);
|
||||
blur_opacity = w->opacity / w->opacity_target;
|
||||
} else if (w->state == WSTATE_UNMAPPING ||
|
||||
w->state == WSTATE_DESTROYING) {
|
||||
// Gradually decrease the blur intensity during
|
||||
// fading out.
|
||||
blur_opacity =
|
||||
w->opacity / win_calc_opacity_target(ps, w, true);
|
||||
assert(w->opacity <= w->opacity_target_old);
|
||||
blur_opacity = w->opacity / w->opacity_target_old;
|
||||
} else if (w->state == WSTATE_FADING) {
|
||||
if (w->opacity < w->opacity_target &&
|
||||
w->opacity_target_old < (1.0 / MAX_ALPHA)) {
|
||||
// Gradually increase the blur intensity during
|
||||
// fading in.
|
||||
assert(w->opacity <= w->opacity_target);
|
||||
blur_opacity = w->opacity / w->opacity_target;
|
||||
} else if (w->opacity > w->opacity_target &&
|
||||
w->opacity_target < (1.0 / MAX_ALPHA)) {
|
||||
// Gradually decrease the blur intensity during
|
||||
// fading out.
|
||||
assert(w->opacity <= w->opacity_target_old);
|
||||
blur_opacity = w->opacity / w->opacity_target_old;
|
||||
}
|
||||
}
|
||||
assert(blur_opacity >= 0 && blur_opacity <= 1);
|
||||
|
||||
|
|
|
@ -482,14 +482,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
|
|||
win_update_opacity_prop(ps, w);
|
||||
// we cannot receive OPACITY change when window is destroyed
|
||||
assert(w->state != WSTATE_DESTROYING);
|
||||
w->opacity_target = win_calc_opacity_target(ps, w, false);
|
||||
if (w->state == WSTATE_MAPPED) {
|
||||
// See the winstate_t transition table
|
||||
w->state = WSTATE_FADING;
|
||||
}
|
||||
if (!ps->redirected) {
|
||||
CHECK(!win_skip_fading(ps, w));
|
||||
}
|
||||
win_update_opacity_target(ps, w);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
69
src/win.c
69
src/win.c
|
@ -912,18 +912,7 @@ void win_on_factor_change(session_t *ps, struct managed_win *w) {
|
|||
w->unredir_if_possible_excluded =
|
||||
c2_match(ps, w, ps->o.unredir_if_possible_blacklist, NULL);
|
||||
|
||||
auto opacity_target_old = w->opacity_target;
|
||||
w->opacity_target = win_calc_opacity_target(ps, w, false);
|
||||
if (opacity_target_old != w->opacity_target && w->state == WSTATE_MAPPED) {
|
||||
// Only MAPPED can transition to FADING
|
||||
assert(w->opacity == opacity_target_old);
|
||||
w->state = WSTATE_FADING;
|
||||
log_debug("Window %#010x (%s) opactiy %f, opacity target %f", w->base.id,
|
||||
w->name, w->opacity, w->opacity_target);
|
||||
if (!ps->redirected) {
|
||||
CHECK(!win_skip_fading(ps, w));
|
||||
}
|
||||
}
|
||||
win_update_opacity_target(ps, w);
|
||||
|
||||
w->reg_ignore_valid = false;
|
||||
}
|
||||
|
@ -1939,6 +1928,7 @@ void unmap_win_start(session_t *ps, struct managed_win *w) {
|
|||
|
||||
w->a.map_state = XCB_MAP_STATE_UNMAPPED;
|
||||
w->state = WSTATE_UNMAPPING;
|
||||
w->opacity_target_old = fmax(w->opacity_target, w->opacity_target_old);
|
||||
w->opacity_target = win_calc_opacity_target(ps, w, false);
|
||||
|
||||
// Clear PIXMAP_STALE flag, since the window is unmapped there is no pixmap
|
||||
|
@ -2123,6 +2113,7 @@ void map_win_start(session_t *ps, struct managed_win *w) {
|
|||
// XXX We need to make sure that win_data is available
|
||||
// iff `state` is MAPPED
|
||||
w->state = WSTATE_MAPPING;
|
||||
w->opacity_target_old = 0;
|
||||
w->opacity_target = win_calc_opacity_target(ps, w, false);
|
||||
|
||||
log_debug("Window %#010x has opacity %f, opacity target is %f", w->base.id,
|
||||
|
@ -2158,6 +2149,60 @@ void map_win_start(session_t *ps, struct managed_win *w) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update target window opacity depending on the current state.
|
||||
*/
|
||||
void win_update_opacity_target(session_t *ps, struct managed_win *w) {
|
||||
auto opacity_target_old = w->opacity_target;
|
||||
w->opacity_target = win_calc_opacity_target(ps, w, false);
|
||||
|
||||
if (opacity_target_old == w->opacity_target) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (w->state == WSTATE_MAPPED) {
|
||||
// Opacity target changed while MAPPED. Transition to FADING.
|
||||
assert(w->opacity == opacity_target_old);
|
||||
w->opacity_target_old = opacity_target_old;
|
||||
w->state = WSTATE_FADING;
|
||||
log_debug("Window %#010x (%s) opacity %f, opacity target %f, set "
|
||||
"old target %f",
|
||||
w->base.id, w->name, w->opacity, w->opacity_target,
|
||||
w->opacity_target_old);
|
||||
} else if (w->state == WSTATE_MAPPING) {
|
||||
// Opacity target changed while fading in.
|
||||
if (w->opacity >= w->opacity_target) {
|
||||
// Already reached new target opacity. Transition to
|
||||
// FADING.
|
||||
map_win_finish(w);
|
||||
w->opacity_target_old = fmax(opacity_target_old, w->opacity);
|
||||
w->state = WSTATE_FADING;
|
||||
log_debug("Window %#010x (%s) opacity %f already reached "
|
||||
"new opacity target %f while mapping, set old "
|
||||
"target %f",
|
||||
w->base.id, w->name, w->opacity, w->opacity_target,
|
||||
w->opacity_target_old);
|
||||
}
|
||||
} else if (w->state == WSTATE_FADING) {
|
||||
// Opacity target changed while FADING.
|
||||
if ((w->opacity < opacity_target_old && w->opacity > w->opacity_target) ||
|
||||
(w->opacity > opacity_target_old && w->opacity < w->opacity_target)) {
|
||||
// Changed while fading in and will fade out or while
|
||||
// fading out and will fade in.
|
||||
w->opacity_target_old = opacity_target_old;
|
||||
log_debug("Window %#010x (%s) opacity %f already reached "
|
||||
"new opacity target %f while fading, set "
|
||||
"old target %f",
|
||||
w->base.id, w->name, w->opacity, w->opacity_target,
|
||||
w->opacity_target_old);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ps->redirected) {
|
||||
CHECK(!win_skip_fading(ps, w));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a managed window from window id in window linked list of the session.
|
||||
*/
|
||||
|
|
|
@ -192,6 +192,8 @@ struct managed_win {
|
|||
double opacity;
|
||||
/// Target window opacity.
|
||||
double opacity_target;
|
||||
/// Previous window opacity.
|
||||
double opacity_target_old;
|
||||
/// true if window (or client window, for broken window managers
|
||||
/// not transferring client window's _NET_WM_OPACITY value) has opacity prop
|
||||
bool has_opacity_prop;
|
||||
|
@ -287,6 +289,7 @@ void win_set_focused(session_t *ps, struct managed_win *w);
|
|||
bool attr_pure win_should_fade(session_t *ps, const struct managed_win *w);
|
||||
void win_update_prop_shadow_raw(session_t *ps, struct managed_win *w);
|
||||
void win_update_prop_shadow(session_t *ps, struct managed_win *w);
|
||||
void win_update_opacity_target(session_t *ps, struct managed_win *w);
|
||||
void win_on_factor_change(session_t *ps, struct managed_win *w);
|
||||
/**
|
||||
* Update cache data in struct _win that depends on window size.
|
||||
|
|
|
@ -40,8 +40,8 @@ typedef enum {
|
|||
/// | DESTROYING | - | o | - | - | - | - | Fading |
|
||||
/// | | | | | | | |finished |
|
||||
/// +-------------+---------+----------+-------+-------+--------+--------+---------+
|
||||
/// | MAPPING | Window | Window | o | - | - | Fading | - |
|
||||
/// | |unmapped |destroyed | | | |finished| |
|
||||
/// | MAPPING | Window | Window | o |Opacity| - | Fading | - |
|
||||
/// | |unmapped |destroyed | |change | |finished| |
|
||||
/// +-------------+---------+----------+-------+-------+--------+--------+---------+
|
||||
/// | FADING | Window | Window | - | o | - | Fading | - |
|
||||
/// | |unmapped |destroyed | | | |finished| |
|
||||
|
|
Loading…
Reference in New Issue