diff --git a/src/animation.c b/src/animation.c index 1a1cf3f..7457c32 100644 --- a/src/animation.c +++ b/src/animation.c @@ -17,6 +17,10 @@ static void animation_destroy(struct animation* animation) { if (animation) free(animation); } +static void animation_lock(struct animation* animation) { + animation->locked = true; +} + void animation_setup(struct animation* animation, void* target, animator_function* update_function, int initial_value, int final_value, uint32_t duration, char interp_function) { animation->counter = 1; animation->duration = duration; @@ -100,6 +104,12 @@ void animator_init(struct animator* animator) { animator->duration = 0; } +void animator_lock(struct animator* animator) { + for (int i = 0; i < animator->animation_count; i++) { + animation_lock(animator->animations[i]); + } +} + static void animator_calculate_offset_for_animation(struct animator* animator, struct animation* animation) { if (animator->animation_count < 1) return; @@ -171,30 +181,64 @@ static void animator_remove(struct animator* animator, struct animation* animati } } +void animator_cancel_locked(struct animator* animator, void* target, animator_function* function) { + struct animation* remove[animator->animation_count]; + memset(remove, 0, animator->animation_count); + uint32_t remove_count = 0; + + for (int i = 0; i < animator->animation_count; i++) { + struct animation* animation = animator->animations[i]; + if (animation->locked + && animation->target == target + && animation->update_function == function) { + remove[remove_count++] = animation; + } + } + + for (uint32_t i = 0; i < remove_count; i++) { + animator_remove(animator, remove[i]); + } +} + bool animator_cancel(struct animator* animator, void* target, animator_function* function) { bool needs_update = false; + + struct animation* remove[animator->animation_count]; + memset(remove, 0, animator->animation_count); + uint32_t remove_count = 0; + for (int i = 0; i < animator->animation_count; i++) { struct animation* animation = animator->animations[i]; if (animation->target == target && animation->update_function == function) { needs_update |= function(animation->target, animation->final_value); - animator_remove(animator, animation); + remove[remove_count++] = animation; } } + + for (uint32_t i = 0; i < remove_count; i++) { + animator_remove(animator, remove[i]); + } + return needs_update; } bool animator_update(struct animator* animator) { - bool removed = false; bool needs_refresh = false; + struct animation* remove[animator->animation_count]; + memset(remove, 0, animator->animation_count); + uint32_t remove_count = 0; + for (uint32_t i = 0; i < animator->animation_count; i++) { - if (removed) i--; - removed = false; needs_refresh |= animation_update(animator->animations[i]); if (animator->animations[i]->counter > animator->animations[i]->duration) { - animator_remove(animator, animator->animations[i]); - removed = true; + remove[remove_count++] = animator->animations[i]; } } + + for (uint32_t i = 0; i < remove_count; i++) { + animator_remove(animator, remove[i]); + } + return needs_refresh; } diff --git a/src/animation.h b/src/animation.h index cfd6a5c..6a44913 100644 --- a/src/animation.h +++ b/src/animation.h @@ -6,6 +6,7 @@ extern struct bar_manager g_bar_manager; #define ANIMATE(f, o, p, t) \ {\ if (g_bar_manager.animator.duration > 0) { \ + animator_cancel_locked(&g_bar_manager.animator, (void*)o, (bool (*)(void*, int))&f); \ struct animation* animation = animation_create(); \ animation_setup(animation, \ (void*)o, \ @@ -24,6 +25,7 @@ extern struct bar_manager g_bar_manager; #define ANIMATE_BYTES(f, o, p, t) \ {\ if (g_bar_manager.animator.duration > 0) { \ + animator_cancel_locked(&g_bar_manager.animator, (void*)o, (bool (*)(void*, int))&f); \ struct animation* animation = animation_create(); \ animation_setup(animation, \ (void*)o, \ @@ -35,7 +37,8 @@ extern struct bar_manager g_bar_manager; animation->seperate_bytes = true; \ animator_add(&g_bar_manager.animator, animation); \ } else { \ - needs_refresh = f(o, t); \ + needs_refresh = animator_cancel(&g_bar_manager.animator, (void*)o, (bool (*)(void*, int))&f); \ + needs_refresh |= f(o, t); \ } \ } @@ -56,6 +59,7 @@ typedef ANIMATION_FUNCTION(animation_function); struct animation { bool seperate_bytes; + bool locked; uint32_t duration; uint32_t counter; @@ -89,4 +93,6 @@ struct animator { void animator_init(struct animator* animator); void animator_add(struct animator* animator, struct animation* animation); bool animator_cancel(struct animator* animator, void* target, animator_function* function); +void animator_cancel_locked(struct animator* animator, void* target, animator_function* function); bool animator_update(struct animator* animator); +void animator_lock(struct animator* animator); diff --git a/src/message.c b/src/message.c index 041a932..6792831 100644 --- a/src/message.c +++ b/src/message.c @@ -670,6 +670,7 @@ void handle_message_mach(struct mach_buffer* buffer) { g_bar_manager.bar_needs_update = true; } + animator_lock(&g_bar_manager.animator); g_bar_manager.frozen = false; bar_manager_refresh(&g_bar_manager, false); bar_manager_unfreeze(&g_bar_manager);