aboutsummaryrefslogtreecommitdiff
path: root/src/win.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/win.c')
-rw-r--r--src/win.c412
1 files changed, 260 insertions, 152 deletions
diff --git a/src/win.c b/src/win.c
index 767efc1..116b2a2 100644
--- a/src/win.c
+++ b/src/win.c
@@ -322,6 +322,13 @@ static inline void win_release_shadow(backend_t *base, struct managed_win *w) {
}
}
+static inline void win_release_mask(backend_t *base, struct managed_win *w) {
+ if (w->mask_image) {
+ base->ops->release_image(base, w->mask_image);
+ w->mask_image = NULL;
+ }
+}
+
static inline bool win_bind_pixmap(struct backend_base *b, struct managed_win *w) {
assert(!w->win_image);
auto pixmap = x_new_id(b->c);
@@ -346,14 +353,36 @@ static inline bool win_bind_pixmap(struct backend_base *b, struct managed_win *w
return true;
}
+bool win_bind_mask(struct backend_base *b, struct managed_win *w) {
+ assert(!w->mask_image);
+ auto reg_bound_local = win_get_bounding_shape_global_by_val(w);
+ pixman_region32_translate(&reg_bound_local, -w->g.x, -w->g.y);
+ w->mask_image = b->ops->make_mask(
+ b, (geometry_t){.width = w->widthb, .height = w->heightb}, &reg_bound_local);
+ pixman_region32_fini(&reg_bound_local);
+
+ if (!w->mask_image) {
+ return false;
+ }
+ b->ops->set_image_property(b, IMAGE_PROPERTY_CORNER_RADIUS, w->mask_image,
+ (double[]){w->corner_radius});
+ return true;
+}
+
bool win_bind_shadow(struct backend_base *b, struct managed_win *w, struct color c,
- struct conv *kernel) {
+ struct backend_shadow_context *sctx) {
assert(!w->shadow_image);
assert(w->shadow);
- w->shadow_image = b->ops->render_shadow(b, w->widthb, w->heightb, kernel, c.red,
- c.green, c.blue, c.alpha);
+ if ((w->corner_radius == 0 && w->bounding_shaped == false) ||
+ b->ops->shadow_from_mask == NULL) {
+ w->shadow_image = b->ops->render_shadow(b, w->widthb, w->heightb, sctx, c);
+ } else {
+ win_bind_mask(b, w);
+ w->shadow_image = b->ops->shadow_from_mask(b, w->mask_image, sctx, c);
+ }
if (!w->shadow_image) {
- log_error("Failed to bind shadow image, shadow will be disabled for "
+ log_error("Failed to bind shadow image, shadow will be disabled "
+ "for "
"%#010x (%s)",
w->base.id, w->name);
win_set_flags(w, WIN_FLAGS_SHADOW_NONE);
@@ -367,10 +396,9 @@ bool win_bind_shadow(struct backend_base *b, struct managed_win *w, struct color
}
void win_release_images(struct backend_base *backend, struct managed_win *w) {
- // We don't want to decide what we should do if the image we want to release is
- // stale (do we clear the stale flags or not?)
- // But if we are not releasing any images anyway, we don't care about the stale
- // flags.
+ // We don't want to decide what we should do if the image we want to
+ // release is stale (do we clear the stale flags or not?) But if we are
+ // not releasing any images anyway, we don't care about the stale flags.
if (!win_check_flags_all(w, WIN_FLAGS_PIXMAP_NONE)) {
assert(!win_check_flags_all(w, WIN_FLAGS_PIXMAP_STALE));
@@ -382,15 +410,19 @@ void win_release_images(struct backend_base *backend, struct managed_win *w) {
assert(!win_check_flags_all(w, WIN_FLAGS_SHADOW_STALE));
win_release_shadow(backend, w);
}
+
+ win_release_mask(backend, w);
}
-/// Returns true if the `prop` property is stale, as well as clears the stale flag.
+/// Returns true if the `prop` property is stale, as well as clears the stale
+/// flag.
static bool win_fetch_and_unset_property_stale(struct managed_win *w, xcb_atom_t prop);
-/// Returns true if any of the properties are stale, as well as clear all the stale flags.
+/// Returns true if any of the properties are stale, as well as clear all the
+/// stale flags.
static void win_clear_all_properties_stale(struct managed_win *w);
-/// Fetch new window properties from the X server, and run appropriate updates. Might set
-/// WIN_FLAGS_FACTOR_CHANGED
+/// Fetch new window properties from the X server, and run appropriate updates.
+/// Might set WIN_FLAGS_FACTOR_CHANGED
static void win_update_properties(session_t *ps, struct managed_win *w) {
if (win_fetch_and_unset_property_stale(w, ps->atoms->a_NET_WM_WINDOW_TYPE)) {
win_update_wintype(ps, w);
@@ -576,10 +608,6 @@ static void init_animation_unmap(session_t *ps, struct managed_win *w) {
animation = ps->o.wintype_option[w->window_type].animation_unmap;
}
- if (c2_match(ps, w, ps->o.animation_unmap_blacklist, NULL)) {
- animation = OPEN_WINDOW_ANIMATION_NONE;
- }
-
if (ps->root_desktop_switch_direction != 0) {
if (ps->o.animation_for_workspace_switch_out == OPEN_WINDOW_ANIMATION_AUTO)
animation = OPEN_WINDOW_ANIMATION_SLIDE_OUT;
@@ -587,6 +615,10 @@ static void init_animation_unmap(session_t *ps, struct managed_win *w) {
animation = ps->o.animation_for_workspace_switch_out;
}
+ if (c2_match(ps, w, ps->o.animation_unmap_blacklist, NULL)) {
+ animation = OPEN_WINDOW_ANIMATION_NONE;
+ }
+
switch (animation) {
case OPEN_WINDOW_ANIMATION_AUTO:
case OPEN_WINDOW_ANIMATION_NONE: { // No animation
@@ -672,8 +704,8 @@ static void init_animation_unmap(session_t *ps, struct managed_win *w) {
/// Handle non-image flags. This phase might set IMAGES_STALE flags
void win_process_update_flags(session_t *ps, struct managed_win *w) {
- // Whether the window was visible before we process the mapped flag. i.e. is the
- // window just mapped.
+ // Whether the window was visible before we process the mapped flag. i.e.
+ // is the window just mapped.
bool was_visible = win_is_real_visible(w);
log_trace("Processing flags for window %#010x (%s), was visible: %d", w->base.id,
w->name, was_visible);
@@ -688,8 +720,8 @@ void win_process_update_flags(session_t *ps, struct managed_win *w) {
return;
}
- // Check client first, because later property updates need accurate client window
- // information
+ // Check client first, because later property updates need accurate client
+ // window information
if (win_check_flags_all(w, WIN_FLAGS_CLIENT_STALE)) {
win_recheck_client(ps, w);
win_clear_flags(w, WIN_FLAGS_CLIENT_STALE);
@@ -698,15 +730,15 @@ void win_process_update_flags(session_t *ps, struct managed_win *w) {
bool damaged = false;
if (win_check_flags_any(w, WIN_FLAGS_SIZE_STALE | WIN_FLAGS_POSITION_STALE)) {
if (was_visible) {
- // Mark the old extents of this window as damaged. The new extents
- // will be marked damaged below, after the window extents are
- // updated.
+ // Mark the old extents of this window as damaged. The new
+ // extents will be marked damaged below, after the window
+ // extents are updated.
//
- // If the window is just mapped, we don't need to mark the old
- // extent as damaged. (It's possible that the window was in fading
- // and is interrupted by being mapped. In that case, the fading
- // window will be added to damage by map_win_start, so we don't
- // need to do it here)
+ // If the window is just mapped, we don't need to mark the
+ // old extent as damaged. (It's possible that the window
+ // was in fading and is interrupted by being mapped. In
+ // that case, the fading window will be added to damage by
+ // map_win_start, so we don't need to do it here)
add_damage_from_win(ps, w);
}
@@ -800,7 +832,8 @@ void win_process_update_flags(session_t *ps, struct managed_win *w) {
win_clear_flags(w, WIN_FLAGS_PROPERTY_STALE);
}
- // Factor change flags could be set by previous stages, so must be handled last
+ // Factor change flags could be set by previous stages, so must be handled
+ // last
if (win_check_flags_all(w, WIN_FLAGS_FACTOR_CHANGED)) {
win_on_factor_change(ps, w);
win_clear_flags(w, WIN_FLAGS_FACTOR_CHANGED);
@@ -832,9 +865,10 @@ void win_process_image_flags(session_t *ps, struct managed_win *w) {
}
if (win_check_flags_all(w, WIN_FLAGS_PIXMAP_STALE)) {
- // Check to make sure the window is still mapped, otherwise we
- // won't be able to rebind pixmap after releasing it, yet we might
- // still need the pixmap for rendering.
+ // Check to make sure the window is still mapped,
+ // otherwise we won't be able to rebind pixmap after
+ // releasing it, yet we might still need the pixmap for
+ // rendering.
assert(w->state != WSTATE_UNMAPPING && w->state != WSTATE_DESTROYING);
if (!win_check_flags_all(w, WIN_FLAGS_PIXMAP_NONE)) {
// Must release images first, otherwise breaks
@@ -854,7 +888,7 @@ void win_process_image_flags(session_t *ps, struct managed_win *w) {
.green = ps->o.shadow_green,
.blue = ps->o.shadow_blue,
.alpha = ps->o.shadow_opacity},
- ps->gaussian_map);
+ ps->shadow_context);
}
}
@@ -914,7 +948,8 @@ int win_update_name(session_t *ps, struct managed_win *w) {
}
if (!(wid_get_text_prop(ps, w->client_win, ps->atoms->a_NET_WM_NAME, &strlst, &nstr))) {
- log_debug("(%#010x): _NET_WM_NAME unset, falling back to WM_NAME.",
+ log_debug("(%#010x): _NET_WM_NAME unset, falling back to "
+ "WM_NAME.",
w->client_win);
if (!wid_get_text_prop(ps, w->client_win, ps->atoms->aWM_NAME, &strlst, &nstr)) {
@@ -1036,8 +1071,8 @@ winmode_t win_calc_mode(const struct managed_win *w) {
if (win_has_alpha(w)) {
if (w->client_win == XCB_NONE) {
- // This is a window not managed by the WM, and it has alpha,
- // so it's transparent. No need to check WM frame.
+ // This is a window not managed by the WM, and it has
+ // alpha, so it's transparent. No need to check WM frame.
return WMODE_TRANS;
}
// The WM window has alpha
@@ -1047,12 +1082,12 @@ winmode_t win_calc_mode(const struct managed_win *w) {
return WMODE_TRANS;
}
if (win_has_frame(w)) {
- // The client window doesn't have alpha, but we have a WM frame
- // window, which has alpha.
+ // The client window doesn't have alpha, but we have a WM
+ // frame window, which has alpha.
return WMODE_FRAME_TRANS;
}
- // Although the WM window has alpha, the frame window has 0 size, so
- // consider the window solid
+ // Although the WM window has alpha, the frame window has 0 size,
+ // so consider the window solid
}
if (w->frame_opacity != 1.0 && win_has_frame(w)) {
@@ -1068,8 +1103,9 @@ winmode_t win_calc_mode(const struct managed_win *w) {
*
* The priority of opacity settings are:
*
- * inactive_opacity_override (if set, and unfocused) > _NET_WM_WINDOW_OPACITY (if set) >
- * opacity-rules (if matched) > window type default opacity > active/inactive opacity
+ * inactive_opacity_override (if set, and unfocused) > _NET_WM_WINDOW_OPACITY (if
+ * set) > opacity-rules (if matched) > window type default opacity >
+ * active/inactive opacity
*
* @param ps current session
* @param w struct _win object representing the window
@@ -1097,7 +1133,8 @@ double win_calc_opacity_target(session_t *ps, const struct managed_win *w) {
} else if (!safe_isnan(ps->o.wintype_option[w->window_type].opacity)) {
opacity = ps->o.wintype_option[w->window_type].opacity;
} else {
- // Respect active_opacity only when the window is physically focused
+ // Respect active_opacity only when the window is physically
+ // focused
if (win_is_focused_raw(ps, w))
opacity = ps->o.active_opacity;
else if (!w->focused)
@@ -1133,7 +1170,8 @@ bool win_should_dim(session_t *ps, const struct managed_win *w) {
* Determine if a window should fade on opacity change.
*/
bool win_should_fade(session_t *ps, const struct managed_win *w) {
- // To prevent it from being overwritten by last-paint value if the window is
+ // To prevent it from being overwritten by last-paint value if the window
+ // is
if (w->fade_force != UNSET) {
return w->fade_force;
}
@@ -1177,7 +1215,8 @@ static void win_set_shadow(session_t *ps, struct managed_win *w, bool shadow_new
log_debug("Updating shadow property of window %#010x (%s) to %d", w->base.id,
w->name, shadow_new);
- // We don't handle property updates of non-visible windows until they are mapped.
+ // We don't handle property updates of non-visible windows until they are
+ // mapped.
assert(w->state != WSTATE_UNMAPPED && w->state != WSTATE_DESTROYING &&
w->state != WSTATE_UNMAPPING);
@@ -1199,33 +1238,35 @@ static void win_set_shadow(session_t *ps, struct managed_win *w, bool shadow_new
// Note: because the release and creation of the shadow images are
// delayed. When multiple shadow changes happen in a row, without
- // rendering phase between them, there could be a stale shadow image
- // attached to the window even if w->shadow was previously false. And vice
- // versa. So we check the STALE flag before asserting the existence of the
- // shadow image.
+ // rendering phase between them, there could be a stale shadow
+ // image attached to the window even if w->shadow was previously
+ // false. And vice versa. So we check the STALE flag before
+ // asserting the existence of the shadow image.
if (w->shadow) {
// Mark the new extents as damaged if the shadow is added
assert(!w->shadow_image ||
win_check_flags_all(w, WIN_FLAGS_SHADOW_STALE) ||
- !ps->o.experimental_backends);
+ ps->o.legacy_backends);
pixman_region32_clear(&extents);
win_extents(w, &extents);
add_damage_from_win(ps, w);
} else {
- // Mark the old extents as damaged if the shadow is removed
+ // Mark the old extents as damaged if the shadow is
+ // removed
assert(w->shadow_image ||
win_check_flags_all(w, WIN_FLAGS_SHADOW_STALE) ||
- !ps->o.experimental_backends);
+ ps->o.legacy_backends);
add_damage(ps, &extents);
}
// Delayed update of shadow image
// By setting WIN_FLAGS_SHADOW_STALE, we ask win_process_flags to
- // re-create or release the shaodw in based on whether w->shadow is set.
+ // re-create or release the shaodw in based on whether w->shadow
+ // is set.
win_set_flags(w, WIN_FLAGS_SHADOW_STALE);
- // Only set pending_updates if we are redirected. Otherwise change of a
- // shadow won't have influence on whether we should redirect.
+ // Only set pending_updates if we are redirected. Otherwise change
+ // of a shadow won't have influence on whether we should redirect.
ps->pending_updates = true;
}
@@ -1268,7 +1309,7 @@ static void win_determine_shadow(session_t *ps, struct managed_win *w) {
* things.
*/
void win_update_prop_shadow(session_t *ps, struct managed_win *w) {
- long attr_shadow_old = w->prop_shadow;
+ long long attr_shadow_old = w->prop_shadow;
win_update_prop_shadow_raw(ps, w);
@@ -1357,8 +1398,22 @@ win_set_blur_background(session_t *ps, struct managed_win *w, bool blur_backgrou
w->blur_background = blur_background_new;
- // This damage might not be absolutely necessary (e.g. when the window is opaque),
- // but blur_background changes should be rare, so this should be fine.
+ // This damage might not be absolutely necessary (e.g. when the window is
+ // opaque), but blur_background changes should be rare, so this should be
+ // fine.
+ add_damage_from_win(ps, w);
+}
+
+static void
+win_set_fg_shader(session_t *ps, struct managed_win *w, struct shader_info *shader_new) {
+ if (w->fg_shader == shader_new) {
+ return;
+ }
+
+ w->fg_shader = shader_new;
+
+ // A different shader might change how the window is drawn, these changes
+ // should be rare however, so this should be fine.
add_damage_from_win(ps, w);
}
@@ -1377,7 +1432,12 @@ static void win_determine_blur_background(session_t *ps, struct managed_win *w)
log_debug("Blur background disabled by wintypes");
blur_background_new = false;
} else if (c2_match(ps, w, ps->o.blur_background_blacklist, NULL)) {
- log_debug("Blur background disabled by blur-background-exclude");
+ log_debug("Blur background disabled by "
+ "blur-background-exclude");
+ blur_background_new = false;
+ } else if (c2_match(ps, w, ps->o.blur_rules, NULL)) {
+ blur_background_new = true;
+ } else {
blur_background_new = false;
}
}
@@ -1393,7 +1453,7 @@ static void win_determine_rounded_corners(session_t *ps, struct managed_win *w)
w->corner_radius = 0;
return;
}
-
+
void *val = NULL;
// Don't round full screen windows & excluded windows
@@ -1413,6 +1473,28 @@ static void win_determine_rounded_corners(session_t *ps, struct managed_win *w)
}
/**
+ * Determine custom window shader to use for a window.
+ */
+static void win_determine_fg_shader(session_t *ps, struct managed_win *w) {
+ if (w->a.map_state != XCB_MAP_STATE_VIEWABLE) {
+ return;
+ }
+
+ auto shader_new = ps->o.window_shader_fg;
+ void *val = NULL;
+ if (c2_match(ps, w, ps->o.window_shader_fg_rules, &val)) {
+ shader_new = val;
+ }
+
+ struct shader_info *shader = NULL;
+ if (shader_new) {
+ HASH_FIND_STR(ps->shaders, shader_new, shader);
+ }
+
+ win_set_fg_shader(ps, w, shader);
+}
+
+/**
* Update window opacity according to opacity rules.
*/
void win_update_opacity_rule(session_t *ps, struct managed_win *w) {
@@ -1439,8 +1521,8 @@ void win_update_opacity_rule(session_t *ps, struct managed_win *w) {
*/
void win_on_factor_change(session_t *ps, struct managed_win *w) {
log_debug("Window %#010x (%s) factor change", w->base.id, w->name);
- // Focus needs to be updated first, as other rules might depend on the focused
- // state of the window
+ // Focus needs to be updated first, as other rules might depend on the
+ // focused state of the window
win_update_focused(ps, w);
win_determine_shadow(ps, w);
@@ -1448,6 +1530,7 @@ void win_on_factor_change(session_t *ps, struct managed_win *w) {
win_determine_invert_color(ps, w);
win_determine_blur_background(ps, w);
win_determine_rounded_corners(ps, w);
+ win_determine_fg_shader(ps, w);
w->mode = win_calc_mode(w);
log_debug("Window mode changed to %d", w->mode);
win_update_opacity_rule(ps, w);
@@ -1461,6 +1544,9 @@ void win_on_factor_change(session_t *ps, struct managed_win *w) {
w->fade_excluded = c2_match(ps, w, ps->o.fade_blacklist, NULL);
+ w->transparent_clipping_excluded =
+ c2_match(ps, w, ps->o.transparent_clipping_blacklist, NULL);
+
win_update_opacity_target(ps, w);
w->reg_ignore_valid = false;
@@ -1477,14 +1563,14 @@ void win_on_win_size_change(session_t *ps, struct managed_win *w) {
w->shadow_width = w->widthb + ps->o.shadow_radius * 2;
w->shadow_height = w->heightb + ps->o.shadow_radius * 2;
- // We don't handle property updates of non-visible windows until they are mapped.
+ // We don't handle property updates of non-visible windows until they are
+ // mapped.
assert(w->state != WSTATE_UNMAPPED && w->state != WSTATE_DESTROYING &&
w->state != WSTATE_UNMAPPING);
// Invalidate the shadow we built
- if (w->state != WSTATE_DESTROYING)
- win_set_flags(w, WIN_FLAGS_IMAGES_STALE);
-
+ win_set_flags(w, WIN_FLAGS_IMAGES_STALE);
+ win_release_mask(ps->backend_data, w);
ps->pending_updates = true;
free_paint(ps, &w->shadow_paint);
}
@@ -1707,21 +1793,21 @@ struct win *add_win_top(session_t *ps, xcb_window_t id) {
return add_win(ps, id, &ps->window_stack);
}
-/// Insert a new window above window with id `below`, if there is no window, add to top
-/// New window will be in unmapped state
+/// Insert a new window above window with id `below`, if there is no window, add
+/// to top New window will be in unmapped state
struct win *add_win_above(session_t *ps, xcb_window_t id, xcb_window_t below) {
struct win *w = NULL;
HASH_FIND_INT(ps->windows, &below, w);
if (!w) {
if (!list_is_empty(&ps->window_stack)) {
- // `below` window is not found even if the window stack is not
- // empty
+ // `below` window is not found even if the window stack is
+ // not empty
return NULL;
}
return add_win_top(ps, id);
} else {
- // we found something from the hash table, so if the stack is empty,
- // we are in an inconsistent state.
+ // we found something from the hash table, so if the stack is
+ // empty, we are in an inconsistent state.
assert(!list_is_empty(&ps->window_stack));
return add_win(ps, id, w->stack_neighbour.prev);
}
@@ -1743,19 +1829,20 @@ struct win *fill_win(session_t *ps, struct win *w) {
.blur_background = false,
.reg_ignore = NULL,
// The following ones are updated for other reasons
- .pixmap_damaged = false, // updated by damage events
- .state = WSTATE_UNMAPPED, // updated by window state changes
- .in_openclose = true, // set to false after first map is done,
- // true here because window is just created
+ .pixmap_damaged = false, // updated by damage events
+ .state = WSTATE_UNMAPPED, // updated by window state changes
+ .in_openclose = true, // set to false after first map is done,
+ // true here because window is just created
.animation_velocity_x = 0.0, // updated by window geometry changes
.animation_velocity_y = 0.0, // updated by window geometry changes
.animation_velocity_w = 0.0, // updated by window geometry changes
.animation_velocity_h = 0.0, // updated by window geometry changes
.animation_progress = 1.0, // updated by window geometry changes
.animation_inv_og_distance = NAN, // updated by window geometry changes
- .reg_ignore_valid = false, // set to true when damaged
- .flags = WIN_FLAGS_IMAGES_NONE, // updated by property/attributes/etc
- // change
+ .reg_ignore_valid = false, // set to true when damaged
+ .flags = WIN_FLAGS_IMAGES_NONE, // updated by
+ // property/attributes/etc
+ // change
.stale_props = NULL,
.stale_props_capacity = 0,
@@ -1783,9 +1870,11 @@ struct win *fill_win(session_t *ps, struct win *w) {
.win_image = NULL,
.old_win_image = NULL,
.shadow_image = NULL,
+ .mask_image = NULL,
.prev_trans = NULL,
.shadow = false,
.clip_shadow_above = false,
+ .fg_shader = NULL,
.xinerama_scr = -1,
.mode = WMODE_TRANS,
.ever_damaged = false,
@@ -1807,6 +1896,7 @@ struct win *fill_win(session_t *ps, struct win *w) {
.rounded_corners = false,
.paint_excluded = false,
.fade_excluded = false,
+ .transparent_clipping_excluded = false,
.unredir_if_possible_excluded = false,
.prop_shadow = -1,
// following 4 are set in win_mark_client
@@ -1834,8 +1924,9 @@ struct win *fill_win(session_t *ps, struct win *w) {
auto duplicated_win = find_managed_win(ps, w->id);
if (duplicated_win) {
- log_debug("Window %#010x (recorded name: %s) added multiple times", w->id,
- duplicated_win->name);
+ log_debug("Window %#010x (recorded name: %s) added multiple "
+ "times",
+ w->id, duplicated_win->name);
return &duplicated_win->base;
}
@@ -1847,14 +1938,15 @@ struct win *fill_win(session_t *ps, struct win *w) {
// Failed to get window attributes or geometry probably means
// the window is gone already. Unviewable means the window is
// already reparented elsewhere.
- // BTW, we don't care about Input Only windows, except for stacking
- // proposes, so we need to keep track of them still.
+ // BTW, we don't care about Input Only windows, except for
+ // stacking proposes, so we need to keep track of them still.
free(a);
return w;
}
if (a->_class == XCB_WINDOW_CLASS_INPUT_ONLY) {
- // No need to manage this window, but we still keep it on the window stack
+ // No need to manage this window, but we still keep it on the
+ // window stack
w->managed = false;
free(a);
return w;
@@ -1924,8 +2016,8 @@ struct win *fill_win(session_t *ps, struct win *w) {
assert(replaced == w);
free(w);
- // Set all the stale flags on this new window, so it's properties will get updated
- // when it's mapped
+ // Set all the stale flags on this new window, so it's properties will get
+ // updated when it's mapped
win_set_flags(new, WIN_FLAGS_CLIENT_STALE | WIN_FLAGS_SIZE_STALE |
WIN_FLAGS_POSITION_STALE | WIN_FLAGS_PROPERTY_STALE |
WIN_FLAGS_FACTOR_CHANGED);
@@ -1961,8 +2053,8 @@ static inline void win_set_leader(session_t *ps, struct managed_win *w, xcb_wind
// gets mapped before parent, or when the window is a waypoint
clear_cache_win_leaders(ps);
- // Update the old and new window group and active_leader if the window
- // could affect their state.
+ // Update the old and new window group and active_leader if the
+ // window could affect their state.
xcb_window_t cache_leader = win_get_leader(ps, w);
if (win_is_focused_raw(ps, w) && cache_leader_old != cache_leader) {
ps->active_leader = cache_leader;
@@ -2009,7 +2101,8 @@ static xcb_window_t win_get_leader_raw(session_t *ps, struct managed_win *w, int
if (!(w->cache_leader = w->leader))
w->cache_leader = w->client_win;
- // If the leader of this window isn't itself, look for its ancestors
+ // If the leader of this window isn't itself, look for its
+ // ancestors
if (w->cache_leader && w->cache_leader != w->client_win) {
auto wp = find_toplevel(ps, w->cache_leader);
if (wp) {
@@ -2157,7 +2250,8 @@ void win_update_bounding_shape(session_t *ps, struct managed_win *w) {
w->bounding_shaped = win_bounding_shaped(ps, w->base.id);
}
- // We don't handle property updates of non-visible windows until they are mapped.
+ // We don't handle property updates of non-visible windows until they are
+ // mapped.
assert(w->state != WSTATE_UNMAPPED && w->state != WSTATE_DESTROYING &&
w->state != WSTATE_UNMAPPING);
@@ -2198,8 +2292,8 @@ void win_update_bounding_shape(session_t *ps, struct managed_win *w) {
// We think the top left of the border is the origin
pixman_region32_translate(&br, w->g.border_width, w->g.border_width);
- // Intersect the bounding region we got with the window rectangle, to
- // make sure the bounding region is not bigger than the window
+ // Intersect the bounding region we got with the window rectangle,
+ // to make sure the bounding region is not bigger than the window
// rectangle
pixman_region32_intersect(&w->bounding_shape, &w->bounding_shape, &br);
pixman_region32_fini(&br);
@@ -2213,6 +2307,7 @@ void win_update_bounding_shape(session_t *ps, struct managed_win *w) {
// Window shape changed, we should free old wpaint and shadow pict
// log_trace("free out dated pict");
win_set_flags(w, WIN_FLAGS_IMAGES_STALE);
+ win_release_mask(ps->backend_data, w);
ps->pending_updates = true;
free_paint(ps, &w->paint);
@@ -2255,7 +2350,8 @@ void win_update_frame_extents(session_t *ps, struct managed_win *w, xcb_window_t
for (int i = 0; i < 4; i++) {
if (prop.c32[i] > (uint32_t)INT_MAX) {
log_warn("Your window manager sets a absurd "
- "_NET_FRAME_EXTENTS value (%u), ignoring it.",
+ "_NET_FRAME_EXTENTS value (%u), "
+ "ignoring it.",
prop.c32[i]);
memset(extents, 0, sizeof(extents));
break;
@@ -2369,11 +2465,12 @@ static void destroy_win_finish(session_t *ps, struct win *w) {
auto mw = (struct managed_win *)w;
if (mw->state != WSTATE_UNMAPPED) {
- // Only UNMAPPED state has window resources freed, otherwise
- // we need to call unmap_win_finish to free them.
- // XXX actually we unmap_win_finish only frees the rendering
- // resources, we still need to call free_win_res. will fix
- // later.
+ // Only UNMAPPED state has window resources freed,
+ // otherwise we need to call unmap_win_finish to free
+ // them.
+ // XXX actually we unmap_win_finish only frees the
+ // rendering resources, we still need to call free_win_res.
+ // will fix later.
unmap_win_finish(ps, mw);
}
@@ -2382,6 +2479,7 @@ static void destroy_win_finish(session_t *ps, struct win *w) {
assert(mw->shadow_image != NULL);
win_release_shadow(ps->backend_data, mw);
}
+ win_release_mask(ps->backend_data, mw);
// Invalidate reg_ignore of windows below this one
// TODO(yshui) what if next_w is not mapped??
@@ -2396,11 +2494,12 @@ static void destroy_win_finish(session_t *ps, struct win *w) {
}
if (mw == ps->active_win) {
- // Usually, the window cannot be the focused at destruction.
- // FocusOut should be generated before the window is destroyed. We
- // do this check just to be completely sure we don't have dangling
- // references.
- log_debug("window %#010x (%s) is destroyed while being focused",
+ // Usually, the window cannot be the focused at
+ // destruction. FocusOut should be generated before the
+ // window is destroyed. We do this check just to be
+ // completely sure we don't have dangling references.
+ log_debug("window %#010x (%s) is destroyed while being "
+ "focused",
w->id, mw->name);
ps->active_win = NULL;
}
@@ -2433,11 +2532,13 @@ static inline void restack_win(session_t *ps, struct win *w, struct list_node *n
}
if (mw) {
- // This invalidates all reg_ignore below the new stack position of `w`
+ // This invalidates all reg_ignore below the new stack position of
+ // `w`
mw->reg_ignore_valid = false;
rc_region_unref(&mw->reg_ignore);
- // This invalidates all reg_ignore below the old stack position of `w`
+ // This invalidates all reg_ignore below the old stack position of
+ // `w`
auto next_w = win_stack_find_next_managed(ps, &w->stack_neighbour);
if (next_w) {
next_w->reg_ignore_valid = false;
@@ -2519,39 +2620,42 @@ bool destroy_win_start(session_t *ps, struct win *w) {
log_debug("Destroying %#010x \"%s\", managed = %d", w->id,
(w->managed ? mw->name : NULL), w->managed);
- // Delete destroyed window from the hash table, even though the window might still
- // be rendered for a while. We need to make sure future window with the same
- // window id won't confuse us. Keep the window in the window stack if it's managed
- // and mapped, since we might still need to render it (e.g. fading out). Window
- // will be removed from the stack when it finishes destroying.
+ // Delete destroyed window from the hash table, even though the window
+ // might still be rendered for a while. We need to make sure future window
+ // with the same window id won't confuse us. Keep the window in the window
+ // stack if it's managed and mapped, since we might still need to render
+ // it (e.g. fading out). Window will be removed from the stack when it
+ // finishes destroying.
HASH_DEL(ps->windows, w);
if (!w->managed || mw->state == WSTATE_UNMAPPED) {
- // Window is already unmapped, or is an unmanged window, just destroy it
+ // Window is already unmapped, or is an unmanged window, just
+ // destroy it
destroy_win_finish(ps, w);
return true;
}
if (w->managed) {
// Clear IMAGES_STALE flags since the window is destroyed: Clear
- // PIXMAP_STALE as there is no pixmap available anymore, so STALE doesn't
- // make sense.
- // XXX Clear SHADOW_STALE as setting/clearing flags on a destroyed window
- // doesn't work leading to an inconsistent state where the shadow is
- // refreshed but the flags are stuck in STALE.
- // Do this before changing the window state to destroying
+ // PIXMAP_STALE as there is no pixmap available anymore, so STALE
+ // doesn't make sense.
+ // XXX Clear SHADOW_STALE as setting/clearing flags on a destroyed
+ // window doesn't work leading to an inconsistent state where the
+ // shadow is refreshed but the flags are stuck in STALE. Do this
+ // before changing the window state to destroying
win_clear_flags(mw, WIN_FLAGS_IMAGES_STALE);
- // If size/shape/position information is stale, win_process_update_flags
- // will update them and add the new window extents to damage. Since the
- // window has been destroyed, we cannot get the complete information at
- // this point, so we just add what we currently have to the damage.
+ // If size/shape/position information is stale,
+ // win_process_update_flags will update them and add the new
+ // window extents to damage. Since the window has been destroyed,
+ // we cannot get the complete information at this point, so we
+ // just add what we currently have to the damage.
if (win_check_flags_any(mw, WIN_FLAGS_SIZE_STALE | WIN_FLAGS_POSITION_STALE)) {
add_damage_from_win(ps, mw);
}
- // Clear some flags about stale window information. Because now the window
- // is destroyed, we can't update them anyway.
+ // Clear some flags about stale window information. Because now
+ // the window is destroyed, we can't update them anyway.
win_clear_flags(mw, WIN_FLAGS_SIZE_STALE | WIN_FLAGS_POSITION_STALE |
WIN_FLAGS_PROPERTY_STALE |
WIN_FLAGS_FACTOR_CHANGED | WIN_FLAGS_CLIENT_STALE);
@@ -2598,7 +2702,8 @@ void unmap_win_start(session_t *ps, struct managed_win *w) {
// Clear the pending map as this window is now unmapped
win_clear_flags(w, WIN_FLAGS_MAPPED);
} else {
- log_warn("Trying to unmapping an already unmapped window %#010x "
+ log_warn("Trying to unmapping an already unmapped window "
+ "%#010x "
"\"%s\"",
w->base.id, w->name);
assert(false);
@@ -2648,10 +2753,10 @@ void unmap_win_start(session_t *ps, struct managed_win *w) {
#endif
if (!ps->redirected || !was_damaged) {
- // If we are not redirected, we skip fading because we aren't rendering
- // anything anyway.
- // If the window wasn't ever damaged, it shouldn't be painted either. But
- // a fading out window is always painted, so we have to skip fading here.
+ // If we are not redirected, we skip fading because we aren't
+ // rendering anything anyway. If the window wasn't ever damaged,
+ // it shouldn't be painted either. But a fading out window is
+ // always painted, so we have to skip fading here.
CHECK(!win_skip_fading(ps, w));
}
}
@@ -2667,7 +2772,6 @@ bool win_check_fade_finished(session_t *ps, struct managed_win *w) {
assert(w->opacity_target == w->opacity);
return false;
}
-
if (w->opacity == w->opacity_target) {
switch (w->state) {
case WSTATE_UNMAPPING: unmap_win_finish(ps, w); return false;
@@ -2720,14 +2824,16 @@ void win_update_screen(int nscreens, region_t *screens, struct managed_win *w) {
if (e->x1 <= w->g.x && e->y1 <= w->g.y && e->x2 >= w->g.x + w->widthb &&
e->y2 >= w->g.y + w->heightb) {
w->xinerama_scr = i;
- log_debug("Window %#010x (%s), %dx%d+%dx%d, is on screen %d "
+ log_debug("Window %#010x (%s), %dx%d+%dx%d, is on screen "
+ "%d "
"(%dx%d+%dx%d)",
w->base.id, w->name, w->g.x, w->g.y, w->widthb, w->heightb,
i, e->x1, e->y1, e->x2 - e->x1, e->y2 - e->y1);
return;
}
}
- log_debug("Window %#010x (%s), %dx%d+%dx%d, is not contained by any screen",
+ log_debug("Window %#010x (%s), %dx%d+%dx%d, is not contained by any "
+ "screen",
w->base.id, w->name, w->g.x, w->g.y, w->g.width, w->g.height);
}
@@ -2752,23 +2858,24 @@ void map_win_start(session_t *ps, struct managed_win *w) {
if (w->state == WSTATE_UNMAPPING) {
CHECK(!win_skip_fading(ps, w));
- // We skipped the unmapping process, the window was rendered, now it is
- // not anymore. So we need to mark the then unmapping window as damaged.
+ // We skipped the unmapping process, the window was rendered, now
+ // it is not anymore. So we need to mark the then unmapping window
+ // as damaged.
//
- // Solves problem when, for example, a window is unmapped then mapped in a
- // different location
+ // Solves problem when, for example, a window is unmapped then
+ // mapped in a different location
add_damage_from_win(ps, w);
assert(w);
}
assert(w->state == WSTATE_UNMAPPED);
- // Rant: window size could change after we queried its geometry here and before
- // we get its pixmap. Later, when we get back to the event processing loop, we
- // will get the notification about size change from Xserver and try to refresh the
- // pixmap, while the pixmap is actually already up-to-date (i.e. the notification
- // is stale). There is basically no real way to prevent this, aside from grabbing
- // the server.
+ // Rant: window size could change after we queried its geometry here and
+ // before we get its pixmap. Later, when we get back to the event
+ // processing loop, we will get the notification about size change from
+ // Xserver and try to refresh the pixmap, while the pixmap is actually
+ // already up-to-date (i.e. the notification is stale). There is basically
+ // no real way to prevent this, aside from grabbing the server.
// XXX Can we assume map_state is always viewable?
w->a.map_state = XCB_MAP_STATE_VIEWABLE;
@@ -2788,9 +2895,9 @@ void map_win_start(session_t *ps, struct managed_win *w) {
w->opacity, w->opacity_target);
// Cannot set w->ever_damaged = false here, since window mapping could be
- // delayed, so a damage event might have already arrived before this function
- // is called. But this should be unnecessary in the first place, since
- // ever_damaged is set to false in unmap_win_finish anyway.
+ // delayed, so a damage event might have already arrived before this
+ // function is called. But this should be unnecessary in the first place,
+ // since ever_damaged is set to false in unmap_win_finish anyway.
// Sets the WIN_FLAGS_IMAGES_STALE flag so later in the critical section
// the window's image will be bound
@@ -2925,17 +3032,17 @@ struct managed_win *find_toplevel(session_t *ps, xcb_window_t id) {
* @return struct _win object of the found window, NULL if not found
*/
struct managed_win *find_managed_window_or_parent(session_t *ps, xcb_window_t wid) {
- // TODO(yshui) this should probably be an "update tree", then find_toplevel.
- // current approach is a bit more "racy", as the server state might be ahead of
- // our state
+ // TODO(yshui) this should probably be an "update tree", then
+ // find_toplevel. current approach is a bit more "racy", as the server
+ // state might be ahead of our state
struct win *w = NULL;
// We traverse through its ancestors to find out the frame
- // Using find_win here because if we found a unmanaged window we know about, we
- // can stop early.
+ // Using find_win here because if we found a unmanaged window we know
+ // about, we can stop early.
while (wid && wid != ps->root && !(w = find_win(ps, wid))) {
- // xcb_query_tree probably fails if you run picom when X is somehow
- // initializing (like add it in .xinitrc). In this case
+ // xcb_query_tree probably fails if you run picom when X is
+ // somehow initializing (like add it in .xinitrc). In this case
// just leave it alone.
auto reply = xcb_query_tree_reply(ps->c, xcb_query_tree(ps->c, wid), NULL);
if (reply == NULL) {
@@ -3101,7 +3208,8 @@ bool win_is_bypassing_compositor(const session_t *ps, const struct managed_win *
}
/**
- * Check if a window is focused, without using any focus rules or forced focus settings
+ * Check if a window is focused, without using any focus rules or forced focus
+ * settings
*/
bool win_is_focused_raw(const session_t *ps, const struct managed_win *w) {
return w->a.map_state == XCB_MAP_STATE_VIEWABLE && ps->active_win == w;