1
0
Fork 0
mirror of https://github.com/yshui/picom.git synced 2024-11-18 13:55:36 -05:00

wm: split geometry trigger into size and position

And keep geometry as an alias for setting both size and position.

Changelog: NewFeature: Separate the "geometry" animation trigger into
"size" and "position" to allow finer-grained control. "geometry" is kept
as an alias for setting both "size" and "position".

Co-authored-by: Monsterovich <monsterovich@gmail.com>
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Monsterovich 2024-09-10 03:58:31 +02:00 committed by Yuxuan Shui
parent 82f5578088
commit df7037d82b
No known key found for this signature in database
GPG key ID: D3A4405BE6CC17F4
5 changed files with 51 additions and 14 deletions

View file

@ -509,9 +509,11 @@ animations = ({
_decrease-opacity_:: When the opacity of a window is decreased.
[[trigger-geometry]]_geometry_:: When the geometry of a window is changed. (EXPERIMENTAL)
_size_, _position_:: When the size or position of a window is changed. If both changed, the position trigger has priority. (EXPERIMENTAL)
[[trigger-geometry]]_geometry_:: Alias of size + position.
+
WARNING: The _geometry_ trigger is experimental. Using this means you accept the caveat that geometry animations will also trigger when you manually resize or move a window, like when you drag the window around with your mouse.
WARNING: The _size_ and _position_ triggers are experimental. Using this means you accept the caveat that these animations will also trigger when you manually resize or move a window, like when you drag the window around with your mouse.
_suppressions_:::
Which other animations should be suppressed when this animation is running. Normally, if another trigger is activated while an animation is already running, the animation in progress will be interrupted and the new animation will start. If you want to prevent this, you can set the `suppressions` option to a list of triggers that should be suppressed. This is optional, the default value for this is an empty list.

View file

@ -73,11 +73,18 @@ enum animation_trigger {
ANIMATION_TRIGGER_OPEN,
/// When a window is closed
ANIMATION_TRIGGER_CLOSE,
/// When a window's geometry changes
ANIMATION_TRIGGER_GEOMETRY,
/// When a window's size changes
ANIMATION_TRIGGER_SIZE,
/// When a window's position changes
ANIMATION_TRIGGER_POSITION,
ANIMATION_TRIGGER_INVALID,
ANIMATION_TRIGGER_COUNT = ANIMATION_TRIGGER_INVALID,
// Aliases are not included in the count
/// Alias of size + position
ANIMATION_TRIGGER_ALIAS_GEOMETRY,
};
static const char *animation_trigger_names[] attr_unused = {
@ -87,7 +94,9 @@ static const char *animation_trigger_names[] attr_unused = {
[ANIMATION_TRIGGER_DECREASE_OPACITY] = "decrease-opacity",
[ANIMATION_TRIGGER_OPEN] = "open",
[ANIMATION_TRIGGER_CLOSE] = "close",
[ANIMATION_TRIGGER_GEOMETRY] = "geometry",
[ANIMATION_TRIGGER_SIZE] = "size",
[ANIMATION_TRIGGER_POSITION] = "position",
[ANIMATION_TRIGGER_ALIAS_GEOMETRY] = "geometry",
};
struct script;

View file

@ -363,6 +363,17 @@ static bool parse_animation_one(struct win_script *animations,
log_error("Invalid trigger defined at line %d",
config_setting_source_line(triggers));
}
if ((trigger_types & (1 << ANIMATION_TRIGGER_ALIAS_GEOMETRY)) != 0) {
const uint64_t to_set =
(1 << ANIMATION_TRIGGER_SIZE) | (1 << ANIMATION_TRIGGER_POSITION);
if ((trigger_types & to_set) != 0) {
log_warn("Trigger \"geometry\" is an alias of \"size\" and "
"\"position\", but one or both of them are also set at "
"line %d",
config_setting_source_line(triggers));
}
trigger_types |= to_set;
}
// script parser shouldn't see this.
config_setting_remove(setting, "triggers");

View file

@ -1715,7 +1715,10 @@ bool win_process_animation_and_state_change(struct session *ps, struct win *w, d
bool will_never_render =
(!w->ever_damaged || w->win_image == NULL) && w->state != WSTATE_MAPPED;
auto win_ctx = win_script_context_prepare(ps, w);
bool geometry_changed = !win_geometry_eq(w->previous.g, w->g);
bool size_changed = win_size_changed(w->previous.g, w->g);
bool position_changed = win_position_changed(w->previous.g, w->g);
auto old_state = w->previous.state;
w->previous.state = w->state;
@ -1726,7 +1729,7 @@ bool win_process_animation_and_state_change(struct session *ps, struct win *w, d
// This window won't be rendered, so we don't need to run the animations.
bool state_changed = old_state != w->state ||
win_ctx.opacity_before != win_ctx.opacity ||
geometry_changed;
size_changed || position_changed;
return state_changed || (w->running_animation_instance != NULL);
}
@ -1741,7 +1744,7 @@ bool win_process_animation_and_state_change(struct session *ps, struct win *w, d
enum animation_trigger trigger = ANIMATION_TRIGGER_INVALID;
// Animation trigger priority:
// state > geometry > opacity
// state > position > size > opacity
if (old_state != w->state) {
// Send D-Bus signal
if (ps->o.dbus) {
@ -1786,9 +1789,12 @@ bool win_process_animation_and_state_change(struct session *ps, struct win *w, d
assert(false);
return true;
}
} else if (geometry_changed) {
} else if (position_changed) {
assert(w->state == WSTATE_MAPPED);
trigger = ANIMATION_TRIGGER_GEOMETRY;
trigger = ANIMATION_TRIGGER_POSITION;
} else if (size_changed) {
assert(w->state == WSTATE_MAPPED);
trigger = ANIMATION_TRIGGER_SIZE;
} else if (win_ctx.opacity_before != win_ctx.opacity) {
assert(w->state == WSTATE_MAPPED);
trigger = win_ctx.opacity > win_ctx.opacity_before
@ -1877,7 +1883,7 @@ bool win_process_animation_and_state_change(struct session *ps, struct win *w, d
memory[output_indices[WIN_SCRIPT_SAVED_IMAGE_BLEND]] =
1 - memory[output_indices[WIN_SCRIPT_SAVED_IMAGE_BLEND]];
}
if (geometry_changed) {
if (size_changed || position_changed) {
// If the window has moved, we need to adjust scripts
// outputs so that the window will stay in the same position and
// size after applying the animation. This way the window's size

View file

@ -353,10 +353,19 @@ win_options(const struct win *w) {
win_maybe_options_fold(w->options_override, w->options), *w->options_default);
}
/// Check if win_geometry `a` and `b` have the same sizes and positions. Border width is
/// Check if the window has changed in size. Border width is
/// not considered.
static inline bool win_geometry_eq(struct win_geometry a, struct win_geometry b) {
return a.x == b.x && a.y == b.y && a.width == b.width && a.height == b.height;
static inline bool win_size_changed(struct win_geometry a, struct win_geometry b) {
return a.width != b.width || a.height != b.height;
}
/// Check if the window position has changed.
static inline bool win_position_changed(struct win_geometry a, struct win_geometry b) {
if (win_size_changed(a, b)) {
return false;
}
return a.x != b.x || a.y != b.y;
}
/// Process pending updates/images flags on a window. Has to be called in X critical