aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Angelilli <code@fedang.net>2024-03-14 15:44:41 +0100
committerFederico Angelilli <code@fedang.net>2024-03-14 15:44:41 +0100
commitc7a8b75933b3bd963e19f1a9d85f3b610a08e669 (patch)
tree91de053f1caaf655eaeb1bbd3458c49362b22e2a
parent93c4dc6893e733f563e70c315537922d55adfab2 (diff)
Change animation code and refactor state
-rw-r--r--src/animate.c24
-rw-r--r--src/animate.h13
-rw-r--r--src/button.c31
-rw-r--r--src/button.h2
-rw-r--r--src/comet.c14
-rw-r--r--src/connect.c11
-rw-r--r--src/draw.c5
-rw-r--r--src/dwm.c4
-rw-r--r--src/state.c63
-rw-r--r--src/state.h7
10 files changed, 92 insertions, 82 deletions
diff --git a/src/animate.c b/src/animate.c
index 33b4e8f..874dece 100644
--- a/src/animate.c
+++ b/src/animate.c
@@ -30,37 +30,35 @@ double cubic_bezier(double x, double a, double b, double c, double d)
typedef struct {
Animation anim;
- State *state;
gint64 start;
gint64 duration;
double x;
} AnimationShine;
-static gboolean shine_handler(AnimationShine *anim)
+bool shine_paint(AnimationShine *anim, cairo_t *cr, const Layout *layout)
{
gint64 now = g_get_monotonic_time();
if (anim->start == 0)
anim->start = now;
gint64 end = anim->start + anim->duration;
- if (now > end) {
- anim->x = 1.0;
- state_redraw(anim->state, false);
- return G_SOURCE_REMOVE;
+ anim->x = 1.0;
+
+ if (now <= end) {
+ double t = (double)(now - anim->start) / (end - anim->start);
+ anim->x = cubic_bezier(t, 0.19, 1.0, 0.22, 1.0);
}
- double t = (double)(now - anim->start) / (end - anim->start);
- anim->x = cubic_bezier(t, 0.19, 1.0, 0.22, 1.0);
- state_redraw(anim->state, false);
- return G_SOURCE_CONTINUE;
+ // Draw at x on the surface...
+ return false;
}
-Animation *animation_shine_create(State *state, gint64 duration)
+Animation *animation_shine_create(gint64 duration)
{
+ // Note the 0 initialization
AnimationShine *anim = g_malloc0(sizeof(AnimationShine));
anim->anim.type = ANIM_SHINE;
- anim->anim.handler = G_SOURCE_FUNC(shine_handler);
- anim->state = state;
+ anim->anim.paint = (DrawFunc)shine_paint;
anim->duration = duration;
return (gpointer)anim;
}
diff --git a/src/animate.h b/src/animate.h
index 3bfa87f..c243287 100644
--- a/src/animate.h
+++ b/src/animate.h
@@ -5,24 +5,23 @@
#include "draw.h"
-// TODO: Custom drawing for animations
-typedef void (* DrawFunc)(cairo_t *cr, const Layout *layout);
-
+typedef struct Animation Animation;
typedef struct State State;
-typedef struct {
+typedef bool (* DrawFunc)(Animation *anim, cairo_t *cr, const Layout *layout);
+
+struct Animation {
enum {
ANIM_SHINE,
} type;
- GSourceFunc handler;
DrawFunc paint;
-} Animation;
+};
double quadratic_bezier(double x, double a, double b, double c);
double cubic_bezier(double x, double a, double b, double c, double d);
-Animation *animation_shine_create(State *state, gint64 duration);
+Animation *animation_shine_create(gint64 duration);
void animation_destroy(Animation *anim);
diff --git a/src/button.c b/src/button.c
index b313f8a..9a7df67 100644
--- a/src/button.c
+++ b/src/button.c
@@ -66,38 +66,13 @@ void button_set_padding(Button *btn, int padding)
bool button_set_animation(Button *btn, Animation *anim)
{
- if (btn->anim) return false;
+ if (btn->anim != NULL)
+ return false;
+
btn->anim = anim;
return true;
}
-// Wrapper for animation sources
-static gboolean anim_handler(gpointer data)
-{
- Button *btn = data;
- if (btn->anim->handler(btn->anim))
- return G_SOURCE_CONTINUE;
-
- g_free(btn->anim);
- btn->anim = NULL;
- return G_SOURCE_REMOVE;
-}
-
-void button_start_animation(Button *btn)
-{
- // Maybe error out
- if (btn->anim == NULL) {
- log_warning("Button animation was not set");
- return;
- }
-
- const int fps = 60;
- if (btn->anim->handler(btn->anim))
- g_timeout_add(1000 / 60, anim_handler, btn);
-
- log_debug("Started animation [type=%d, button=%p]", btn->anim->type, btn);
-}
-
void button_destroy(Button *btn)
{
if (btn->simple) g_free(CAST(btn, ButtonSimple)->text);
diff --git a/src/button.h b/src/button.h
index 5492599..0a9b2ce 100644
--- a/src/button.h
+++ b/src/button.h
@@ -59,8 +59,6 @@ void button_set_padding(Button *btn, int padding);
bool button_set_animation(Button *btn, Animation *anim);
-void button_start_animation(Button *btn);
-
void button_destroy(Button *btn);
#endif
diff --git a/src/comet.c b/src/comet.c
index 7f8b2d1..ea574cc 100644
--- a/src/comet.c
+++ b/src/comet.c
@@ -53,7 +53,7 @@ static gboolean disk_update(gpointer data)
size_t len2 = g_utf8_strlen(btn->text, -1);
log_debug("Updated disk percentage");
- state_redraw(btn->action_data, len1 != len2);
+ state_request_redraw(btn->action_data, len1 != len2);
return G_SOURCE_CONTINUE;
}
@@ -76,7 +76,7 @@ static gboolean temp_update(gpointer data)
size_t len2 = g_utf8_strlen(btn->text, -1);
log_debug("Updated temperature");
- state_redraw(btn->action_data, len1 != len2);
+ state_request_redraw(btn->action_data, len1 != len2);
return G_SOURCE_CONTINUE;
}
@@ -119,7 +119,7 @@ static gboolean cpu_update(gpointer data)
button_simple_set_text((gpointer)btn, perc, btn->text_color);
size_t len2 = g_utf8_strlen(btn->text, -1);
- state_redraw(btn->action_data, len1 != len2);
+ state_request_redraw(btn->action_data, len1 != len2);
}
log_debug("%s cpu percentage", perc != NULL ? "Updated" : "Unchanged");
@@ -150,7 +150,7 @@ static gboolean ram_update(gpointer data)
size_t len2 = g_utf8_strlen(btn->text, -1);
log_debug("Updated ram percentage");
- state_redraw(btn->action_data, len1 != len2);
+ state_request_redraw(btn->action_data, len1 != len2);
return G_SOURCE_CONTINUE;
}
@@ -173,7 +173,7 @@ static gboolean date_update(gpointer data)
} *date_ctx = btn->action_data;
log_debug("Updated date and time");
- state_redraw(date_ctx->state, len1 != len2);
+ state_request_redraw(date_ctx->state, len1 != len2);
struct timespec current;
clock_gettime(CLOCK_REALTIME, &current);
@@ -217,7 +217,7 @@ static void menu_action(Button *btn)
button_simple_set_text(btn, g_strdup(menu_ctx->strings[!closed]), sbtn->text_color);
log_debug("%s menu", closed ? "Closed" : "Opened");
- state_redraw(menu_ctx->state, true);
+ state_request_redraw(menu_ctx->state, true);
}
static void register_buttons(State *state, Color color, Color line_color, Color text_color)
@@ -369,7 +369,7 @@ int main(int argc, char **argv)
guint source_term = g_unix_signal_add(SIGTERM, mainloop_quit, mainloop);
guint source_int = g_unix_signal_add(SIGINT, mainloop_quit, mainloop);
- state_redraw(state, true);
+ state_request_redraw(state, true);
log_debug("Starting main loop");
g_main_loop_run(mainloop);
diff --git a/src/connect.c b/src/connect.c
index d5d4f12..1a21be3 100644
--- a/src/connect.c
+++ b/src/connect.c
@@ -97,13 +97,14 @@ static void button_action(State *state, const char *event, int x, int y)
ButtonAction action = button_simple_get_action(layout->btn);
if (action != NULL) {
- action(layout->btn);
+ Animation *shine = animation_shine_create(500 * G_TIME_SPAN_MILLISECOND);
- Animation *shine = animation_shine_create(state, 500 * G_TIME_SPAN_MILLISECOND);
if (button_set_animation(layout->btn, shine))
- button_start_animation(layout->btn);
+ state_request_animation(state);
else
animation_destroy(shine);
+
+ action(layout->btn);
}
return;
@@ -169,7 +170,7 @@ static gboolean source_dispatch(GSource *source, GSourceFunc callback, gpointer
xcb_expose_event_t *expose = (xcb_expose_event_t *)xsource->event;
log_debug("Processing event 'Expose' [type=%d]", XCB_EXPOSE);
- state_redraw(xsource->con->state, true);
+ state_request_redraw(xsource->con->state, true);
break;
}
@@ -217,7 +218,7 @@ static gboolean source_dispatch(GSource *source, GSourceFunc callback, gpointer
update_xrm(xsource->con);
update_scale(xsource->con);
- state_redraw(xsource->con->state, true);
+ state_request_redraw(xsource->con->state, true);
}
break;
}
diff --git a/src/draw.c b/src/draw.c
index 814c310..549c360 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -99,6 +99,11 @@ void draw_paint(Drawer *draw, Window *win)
pango_cairo_update_layout(cr, layout->pl);
pango_cairo_show_layout(cr, layout->pl);
}
+
+ if (layout->btn->anim != NULL && !layout->btn->anim->paint(layout->btn->anim, cr, layout)) {
+ animation_destroy(layout->btn->anim);
+ layout->btn->anim = NULL;
+ }
}
cairo_destroy(cr);
diff --git a/src/dwm.c b/src/dwm.c
index 66756a7..a2bf764 100644
--- a/src/dwm.c
+++ b/src/dwm.c
@@ -184,7 +184,7 @@ static void ipc_handle(DwmIpc *dwm, DwmIpcMessage type, char *reply, uint32_t re
for (int i = 0; i < 9; i++)
dwm->tags[i]->color = selected & (1 << i) ? dwm->selected : dwm->color;
- state_redraw(dwm->state, false);
+ state_request_redraw(dwm->state, false);
}
} else if (JSON_FIELD(reader, IPC_EVENT_CLIENT_FOCUS_CHANGE)) {
log_debug("Handling dwm ipc event [event=%s]", IPC_EVENT_CLIENT_FOCUS_CHANGE);
@@ -246,7 +246,7 @@ static void ipc_handle(DwmIpc *dwm, DwmIpcMessage type, char *reply, uint32_t re
}
dwm->change_title = false;
- state_redraw(dwm->state, true);
+ state_request_redraw(dwm->state, true);
json_reader_end_member(reader);
}
break;
diff --git a/src/state.c b/src/state.c
index 134e644..0f17695 100644
--- a/src/state.c
+++ b/src/state.c
@@ -1,17 +1,14 @@
#include <glib.h>
#include "state.h"
+#include "log.h"
State *state_create(Window *win, Drawer *draw)
{
- State *state = g_malloc(sizeof(State));
+ State *state = g_malloc0(sizeof(State));
g_assert_nonnull(state);
-
state->win = win;
state->draw = draw;
- state->btns = NULL;
- state->id = 0;
-
return state;
}
@@ -40,9 +37,9 @@ void state_order_button(State *state)
state->btns = g_list_sort(state->btns, align_compare);
}
-static gboolean redraw_handler(gpointer data)
+static gboolean redraw_handler(State *state)
{
- State *state = data;
+ log_debug("Redrawing once [relayout=%d]", state->relayout);
if (state->relayout) {
draw_compute_layout(state->draw, state->win, state->btns);
@@ -51,22 +48,56 @@ static gboolean redraw_handler(gpointer data)
draw_paint(state->draw, state->win);
- state->id = 0;
+ state->idle_id = 0;
return G_SOURCE_REMOVE;
}
-void state_redraw(State *state, bool changed_layout)
+void state_request_redraw(State *state, bool relayout)
{
- if (state->id != 0) {
- if (!changed_layout || state->relayout)
- return;
+ // Override old redraw
+ if (state->idle_id != 0)
+ g_source_remove(state->idle_id);
+
+ state->relayout = relayout;
+
+ if (state->anim_id != 0) return;
+
+ state->idle_id = g_idle_add(G_SOURCE_FUNC(redraw_handler), state);
+}
+
+static gboolean anim_handler(State *state)
+{
+ //log_debug("Animating [relayout=%d]", state->relayout);
+
+ if (state->relayout) {
+ draw_compute_layout(state->draw, state->win, state->btns);
+ state->relayout = false;
+ }
+
+ draw_paint(state->draw, state->win);
- // If we should relayout override old redraw
- g_source_remove(state->id);
+ for (GList *it = state->btns; it != NULL; it = it->next) {
+ Button *btn = it->data;
+ if (btn->anim != NULL)
+ return G_SOURCE_CONTINUE;
}
- state->relayout = changed_layout;
- state->id = g_idle_add_full(G_PRIORITY_HIGH_IDLE, redraw_handler, state, NULL);
+ state->anim_id = 0;
+ return G_SOURCE_REMOVE;
+}
+
+void state_request_animation(State *state)
+{
+ if (state->idle_id != 0) {
+ g_source_remove(state->idle_id);
+ state->idle_id = 0;
+ }
+
+ if (state->anim_id != 0) return;
+ if (!anim_handler(state)) return;
+
+ const int fps = 60;
+ state->anim_id = g_timeout_add(1000 / fps, G_SOURCE_FUNC(anim_handler), state);
}
void state_destroy(State *state)
diff --git a/src/state.h b/src/state.h
index 14f7d4d..ef621f4 100644
--- a/src/state.h
+++ b/src/state.h
@@ -13,7 +13,8 @@ struct State {
Window *win;
Drawer *draw;
GList *btns;
- gint id;
+ gint idle_id;
+ gint anim_id;
bool relayout;
};
@@ -25,7 +26,9 @@ void state_remove_button(State *state, Button *btn);
void state_order_button(State *state);
-void state_redraw(State *state, bool changed_layout);
+void state_request_redraw(State *state, bool relayout);
+
+void state_request_animation(State *state);
void state_destroy(State *state);