aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFederico Angelilli <code@fedang.net>2024-03-16 16:03:21 +0100
committerFederico Angelilli <code@fedang.net>2024-03-16 16:03:21 +0100
commit115a2b5d2fb0b8b4950c6daa897fbe012b9204b2 (patch)
tree2d9c7bb94dd006b750805fe742365e20a271016b /src
parent40ca9598d269c9b6f162e80b5293f83ec37bb75d (diff)
Split animation paint_func
Diffstat (limited to 'src')
-rw-r--r--src/animate.c9
-rw-r--r--src/animate.h8
-rw-r--r--src/draw.c41
-rw-r--r--src/state.c13
4 files changed, 38 insertions, 33 deletions
diff --git a/src/animate.c b/src/animate.c
index 7241104..8bd09b5 100644
--- a/src/animate.c
+++ b/src/animate.c
@@ -47,8 +47,7 @@ typedef struct {
cairo_pattern_t *gradient;
} AnimationShine;
-// FIXME: Not working for button group
-static bool shine_paint(AnimationShine *shine, cairo_t *cr, const Layout *layout)
+static bool shine_func(AnimationShine *shine, Layout *layout, cairo_t *cr)
{
gint64 end = shine->anim.start + shine->anim.duration;
gint64 now = g_get_monotonic_time();
@@ -88,7 +87,7 @@ Animation *animation_shine_create(gint64 duration)
// Note the 0 initialization
AnimationShine *shine = g_malloc0(sizeof(AnimationShine));
shine->anim.type = ANIM_SHINE;
- shine->anim.paint_func = (DrawFunc)shine_paint;
+ shine->anim.after_func = (DrawFunc)shine_func;
shine->anim.duration = duration;
// TODO: Change it depending on container size
@@ -102,7 +101,7 @@ Animation *animation_shine_create(gint64 duration)
return (gpointer)shine;
}
-static bool pulse_layout(Animation *pulse, Layout *layout)
+static bool pulse_func(Animation *pulse, Layout *layout, cairo_t *cr)
{
gint64 end = pulse->start + pulse->duration;
gint64 now = g_get_monotonic_time();
@@ -128,7 +127,7 @@ Animation *animation_pulse_create(gint64 duration)
// Note the 0 initialization
Animation *pulse = g_malloc0(sizeof(Animation));
pulse->type = ANIM_PULSE;
- pulse->layout_func = (LayoutFunc)pulse_layout;
+ pulse->before_func = (DrawFunc)pulse_func;
pulse->duration = duration;
return (gpointer)pulse;
diff --git a/src/animate.h b/src/animate.h
index a4ded33..b296723 100644
--- a/src/animate.h
+++ b/src/animate.h
@@ -8,18 +8,20 @@
typedef struct Animation Animation;
typedef struct State State;
-typedef bool (* DrawFunc)(Animation *anim, cairo_t *cr, const Layout *layout);
typedef bool (* LayoutFunc)(Animation *anim, Layout *layout);
+typedef bool (* DrawFunc)(Animation *anim, Layout *layout, cairo_t *cr);
struct Animation {
enum {
ANIM_SHINE,
ANIM_PULSE,
} type;
- DrawFunc paint_func;
- LayoutFunc layout_func;
gint64 start;
gint64 duration;
+ LayoutFunc layout_func;
+ // NOTE: These should not change the layout width
+ DrawFunc before_func;
+ DrawFunc after_func;
};
double clamp(double x, double min, double max);
diff --git a/src/draw.c b/src/draw.c
index 244a472..c6c18a2 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -8,6 +8,19 @@
#include "button.h"
#include "log.h"
+#define ANIMATION(btn, which, ...) \
+ do { \
+ if ((btn)->anim != NULL && (btn)->anim->which##_func != NULL) { \
+ if ((btn)->anim->start == 0) { \
+ (btn)->anim->start = g_get_monotonic_time(); \
+ log_debug("Starting animation [type=%d, func=%s, start=%ld, duration=%ld, button=%p]", \
+ (btn)->anim->type, #which, (btn)->anim->start, (btn)->anim->duration, (btn)); \
+ } \
+ if (!(btn)->anim->which##_func((btn)->anim, __VA_ARGS__)) \
+ (btn)->anim->which##_func = NULL; \
+ } \
+ } while (false)
+
Drawer *draw_create(const char *font, int height, int left_pad, int right_pad, int top_pad)
{
Drawer *draw = g_malloc0(sizeof(Drawer));
@@ -99,6 +112,10 @@ static void paint_button_list(cairo_t *cr, GList *layouts)
Button *btn = layout->btn;
cairo_push_group(cr);
+
+ // Apply before_func on the layout and cairo context
+ ANIMATION(btn, before, layout, cr);
+
paint_button(cr, layout);
if (btn->simple) {
@@ -109,16 +126,8 @@ static void paint_button_list(cairo_t *cr, GList *layouts)
paint_button_list(cr, layout->children);
}
- if (btn->anim != NULL && btn->anim->paint_func != NULL) {
- if (btn->anim->start == 0) {
- btn->anim->start = g_get_monotonic_time();
- log_debug("Starting animation [type=%d, start=%ld, duration=%ld, button=%p]",
- btn->anim->type, btn->anim->start, btn->anim->duration, btn);
- }
-
- if (!btn->anim->paint_func(btn->anim, cr, layout))
- btn->anim->paint_func = NULL;
- }
+ // Apply after_func on the layout and cairo context
+ ANIMATION(btn, after, layout, cr);
cairo_pop_group_to_source(cr);
cairo_paint(cr);
@@ -240,16 +249,8 @@ retry:
// NOTE: We add half a line width on both sides
layout->width += layout->line_w;
- if (btn->anim != NULL && btn->anim->layout_func != NULL) {
- if (btn->anim->start == 0) {
- btn->anim->start = g_get_monotonic_time();
- log_debug("Starting animation [type=%d, start=%ld, duration=%ld, button=%p]",
- btn->anim->type, btn->anim->start, btn->anim->duration, btn);
- }
-
- if (!btn->anim->layout_func(btn->anim, layout))
- btn->anim->layout_func = NULL;
- }
+ // Apply layout_func on the layout
+ ANIMATION(btn, layout, layout);
bx += layout->width;
if (root) {
diff --git a/src/state.c b/src/state.c
index 880c8ff..7748e58 100644
--- a/src/state.c
+++ b/src/state.c
@@ -72,16 +72,16 @@ static bool anim_check_more(State *state, GList *btns)
Button *btn = it->data;
if (btn->anim != NULL) {
- bool draw = btn->anim->paint_func != NULL;
bool layout = btn->anim->layout_func != NULL;
+ bool before = btn->anim->before_func != NULL;
+ bool after = btn->anim->after_func != NULL;
- // Remove animation if both paint_func and layout_func finished
- if (!draw && !layout) {
+ // Remove animation if all functions finished
+ if (!layout && !before && !after) {
log_debug("Removing animation [type=%d, end=%ld, button=%p]",
btn->anim->type, btn->anim->start + btn->anim->duration, btn);
- animation_destroy(btn->anim);
- btn->anim = NULL;
+ g_clear_pointer(&btn->anim, animation_destroy);
} else {
more = true;
state->relayout |= layout;
@@ -110,6 +110,9 @@ static gboolean anim_handler(State *state)
return more;
}
+// FIXME: When spamming animations there seem to be occasional
+// race condition that block animations from playing
+// (the animation timeout eagerly quits)
void state_request_animation(State *state)
{
if (state->idle_id != 0) {