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:
parent
82f5578088
commit
df7037d82b
5 changed files with 51 additions and 14 deletions
|
@ -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.
|
||||
|
|
15
src/config.h
15
src/config.h
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
18
src/wm/win.c
18
src/wm/win.c
|
@ -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
|
||||
|
|
15
src/wm/win.h
15
src/wm/win.h
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue