diff options
| -rw-r--r-- | src/animate.c | 24 | ||||
| -rw-r--r-- | src/animate.h | 13 | ||||
| -rw-r--r-- | src/button.c | 31 | ||||
| -rw-r--r-- | src/button.h | 2 | ||||
| -rw-r--r-- | src/comet.c | 14 | ||||
| -rw-r--r-- | src/connect.c | 11 | ||||
| -rw-r--r-- | src/draw.c | 5 | ||||
| -rw-r--r-- | src/dwm.c | 4 | ||||
| -rw-r--r-- | src/state.c | 63 | ||||
| -rw-r--r-- | src/state.h | 7 |
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, ¤t); @@ -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; } @@ -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); @@ -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); |
