Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/sway/desktop/animation.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ bool animation_animating();
// Are we in the middle of an animation for output?
bool animation_animating_output(struct wlr_output *output);

// Manual stepping control for testing
void animation_set_manual_stepping(bool enabled);
void animation_step(uint32_t ms);
uint32_t animation_get_duration();
uint32_t animation_get_elapsed_time();

// Get the current parameters for the active animation
void animation_get_values(double *t, double *x, double *y);

Expand Down
2 changes: 2 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[pytest]
addopts = -n 4
48 changes: 48 additions & 0 deletions scroll.lua
Original file line number Diff line number Diff line change
Expand Up @@ -643,4 +643,52 @@ function scroll.add_callback(event, cb_func, cb_data) end
--- @return integer
function scroll.remove_callback(id) end

---
--- Enables or disables manual stepping for animations.
--- When enabled, animations do not progress automatically with real time.
--- Instead, they stay at the current frame until scroll.animation_step is called.
---
--- @param enabled boolean
---
function scroll.animation_set_manual_stepping(enabled) end

---
--- Steps the current animation forward by the given amount of milliseconds.
--- Only has an effect if manual stepping is enabled.
---
--- @param ms integer
---
function scroll.animation_step(ms) end

---
--- Returns true if there is an active animation running.
---
--- @return boolean
---
function scroll.animating() end

---
--- Returns true if there are pending transactions that haven't been applied yet.
---
--- @return boolean
---
function scroll.pending_transactions() end

---
--- Returns the total duration of the current animation in milliseconds.
--- Returns 0 if there is no active animation.
---
--- @return integer
---
function scroll.animation_get_duration() end

---
--- Returns the elapsed time of the current animation in milliseconds.
--- Accounts for manual stepping if enabled.
--- Returns 0 if there is no active animation.
---
--- @return integer
---
function scroll.animation_get_elapsed_time() end

return scroll
94 changes: 91 additions & 3 deletions sway/desktop/animation.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ struct sway_animation {
struct sway_animation_callbacks default_callbacks;

struct sway_animation_config config;

bool manual_stepping;
uint32_t manual_time_ms;
};

static struct sway_animation *animation = NULL;
Expand Down Expand Up @@ -619,7 +622,11 @@ void animation_begin() {
if (path) {
animation_reset_path(path);
animation->animating = true;
clock_gettime(CLOCK_MONOTONIC, &animation->start);
if (animation->manual_stepping) {
animation->manual_time_ms = 0;
} else {
clock_gettime(CLOCK_MONOTONIC, &animation->start);
}
if (animation->current.callbacks.callback_begin) {
animation->current.callbacks.callback_begin(animation->current.callbacks.callback_begin_data);
}
Expand Down Expand Up @@ -650,7 +657,12 @@ static bool animation_set_time(struct timespec *time) {
if (!curve) {
goto last;
}
uint32_t diff = difftime_ms(&animation->start, time);
uint32_t diff;
if (animation->manual_stepping) {
diff = animation->manual_time_ms;
} else {
diff = difftime_ms(&animation->start, time);
}
uint32_t duration = curve->duration_ms;
animation->time = (double) diff / duration;
if (animation->time <= 1.0) {
Expand All @@ -661,7 +673,11 @@ static bool animation_set_time(struct timespec *time) {
path->idx = path->curves->length - 1;
goto last;
} else {
addtime_ms(&animation->start, duration);
if (animation->manual_stepping) {
animation->manual_time_ms -= duration;
} else {
addtime_ms(&animation->start, duration);
}
}
}
return false;
Expand Down Expand Up @@ -883,3 +899,75 @@ void destroy_animation_curve(struct sway_animation_curve *curve) {
}
free(curve);
}

void animation_set_manual_stepping(bool enabled) {
if (animation) {
animation->manual_stepping = enabled;
if (enabled) {
animation->manual_time_ms = 0;
}
}
}

void animation_step(uint32_t ms) {
if (animation && animation->manual_stepping && animation->animating) {
animation->manual_time_ms += ms;
for (int i = 0; i < root->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i];
if (animation_animating_output(output->wlr_output)) {
animation_animate(output->wlr_output);
}
}
}
}

uint32_t animation_get_duration() {
if (!animation || !animation->animating) {
return 0;
}
struct sway_animation_path *path = get_path();
if (!path) {
return 0;
}
uint32_t duration = 0;
for (int i = 0; i < path->curves->length; ++i) {
struct sway_animation_curve *curve = path->curves->items[i];
if (curve) {
duration += curve->duration_ms;
}
}
return duration;
}

uint32_t animation_get_elapsed_time() {
if (!animation || !animation->animating) {
return 0;
}
struct sway_animation_path *path = get_path();
if (!path) {
return 0;
}
if (animation->manual_stepping) {
uint32_t elapsed = 0;
for (int i = 0; i < path->idx; ++i) {
struct sway_animation_curve *curve = path->curves->items[i];
if (curve) {
elapsed += curve->duration_ms;
}
}
elapsed += animation->manual_time_ms;
return elapsed;
} else {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
uint32_t elapsed = 0;
for (int i = 0; i < path->idx; ++i) {
struct sway_animation_curve *curve = path->curves->items[i];
if (curve) {
elapsed += curve->duration_ms;
}
}
elapsed += difftime_ms(&animation->start, &now);
return elapsed;
}
}
54 changes: 54 additions & 0 deletions sway/lua.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "sway/output.h"
#include "sway/desktop/animation.h"
#include "sway/ipc-server.h"
#include "sway/server.h"

#if 0
static void print_table(lua_State *L, int index);
Expand Down Expand Up @@ -1613,7 +1614,53 @@ static int scroll_remove_callback(lua_State *L) {
return 0;
}

static int scroll_animation_set_manual_stepping(lua_State *L) {
int argc = lua_gettop(L);
if (argc < 1) {
return 0;
}
bool enabled = lua_toboolean(L, 1);
animation_set_manual_stepping(enabled);
return 0;
}

static int scroll_animation_step(lua_State *L) {
int argc = lua_gettop(L);
if (argc < 1) {
return 0;
}
int ms = luaL_checkinteger(L, 1);
if (ms < 0) {
return 0;
}
animation_step(ms);
return 0;
}

static int scroll_animating(lua_State *L) {
lua_pushboolean(L, animation_animating());
return 1;
}

static int scroll_pending_transactions(lua_State *L) {
bool pending = server.queued_transaction != NULL || server.pending_transaction != NULL ||
server.dirty_nodes->length > 0;
lua_pushboolean(L, pending);
return 1;
}

static int scroll_animation_get_duration(lua_State *L) {
lua_pushinteger(L, animation_get_duration());
return 1;
}

static int scroll_animation_get_elapsed_time(lua_State *L) {
lua_pushinteger(L, animation_get_elapsed_time());
return 1;
}

// Module functions
/* clang-format off */
static luaL_Reg const scroll_lib[] = {
{ "log", scroll_log },
{ "state_set_value", scroll_state_set_value },
Expand Down Expand Up @@ -1682,8 +1729,15 @@ static luaL_Reg const scroll_lib[] = {
{ "scratchpad_hide", scroll_scratchpad_hide },
{ "add_callback", scroll_add_callback },
{ "remove_callback", scroll_remove_callback },
{ "animation_set_manual_stepping", scroll_animation_set_manual_stepping },
{ "animation_step", scroll_animation_step },
{ "animating", scroll_animating },
{ "pending_transactions", scroll_pending_transactions },
{ "animation_get_duration", scroll_animation_get_duration },
{ "animation_get_elapsed_time", scroll_animation_get_elapsed_time },
{ NULL, NULL }
};
/* clang-format on */

// Module Loader
int luaopen_scroll(lua_State *L) {
Expand Down
25 changes: 25 additions & 0 deletions sway/scroll.5.scd
Original file line number Diff line number Diff line change
Expand Up @@ -2390,6 +2390,31 @@ scroll.command(nil, "set_size v 0.33333333; move left nomode")
Removes a callback set earlier using *add_callback*. _id_ is the unique
identifier returned by *add_callback*.

*animation_set_manual_stepping(enabled)*
Enables or disables manual stepping for animations. When enabled,
animations do not progress automatically with real time. Instead, they
stay at the current frame until *animation_step* is called.

*animation_step(ms)*
Steps the current animation forward by the given amount of _ms_
(milliseconds). Only has an effect if manual stepping is enabled.

*animating()*
Returns _true_ if there is an active animation running.

*pending_transactions()*
Returns _true_ if there are pending transactions that haven't been applied
yet.

*animation_get_duration()*
Returns the total duration of the current animation in milliseconds, or
0 if there is no active animation.

*animation_get_elapsed_time()*
Returns the elapsed time of the current animation in milliseconds.
Accounts for manual stepping if enabled. Returns 0 if there is no active
animation.

Examples:

Calling this script from the configuration file, you will get focus on every
Expand Down
Loading