diff --git a/src/config_libconfig.c b/src/config_libconfig.c index ca169c16..339d86e2 100644 --- a/src/config_libconfig.c +++ b/src/config_libconfig.c @@ -407,15 +407,15 @@ static struct script **parse_animations(struct win_script *animations, #define FADING_TEMPLATE_1 \ "opacity = { " \ - " timing = \"%fms linear\"; " \ + " timing = \"%sms linear\"; " \ " start = \"window-raw-opacity-before\"; " \ " end = \"window-raw-opacity\"; " \ "};" \ "shadow-opacity = \"opacity\";" #define FADING_TEMPLATE_2 \ "blur-opacity = { " \ - " timing = \"%fms linear\"; " \ - " start = %f; end = %f; " \ + " timing = \"%sms linear\"; " \ + " start = %d; end = %d; " \ "};" static struct script *compile_win_script_from_string(const char *input, int *output_indices) { @@ -438,7 +438,7 @@ static struct script *compile_win_script_from_string(const char *input, int *out void generate_fading_config(struct options *opt) { // We create stand-in animations for fade-in/fade-out if they haven't be // overwritten - char *str = NULL; + scoped_charp str = NULL; size_t len = 0; enum animation_trigger trigger[2]; struct script *scripts[4]; @@ -447,72 +447,88 @@ void generate_fading_config(struct options *opt) { int output_indices[NUM_OF_WIN_SCRIPT_OUTPUTS]; double duration = 1.0 / opt->fade_in_step * opt->fade_delta; - // Fading in from nothing, i.e. `open` and `show` - asnprintf(&str, &len, FADING_TEMPLATE_1 FADING_TEMPLATE_2, duration, duration, - 0.F, 1.F); + if (!safe_isinf(duration) && !safe_isnan(duration) && duration > 0) { + scoped_charp duration_str = NULL; + dtostr(duration, &duration_str); - auto fade_in1 = compile_win_script_from_string(str, output_indices); - if (opt->animations[ANIMATION_TRIGGER_OPEN].script == NULL && !opt->no_fading_openclose) { - trigger[number_of_triggers++] = ANIMATION_TRIGGER_OPEN; - } - if (opt->animations[ANIMATION_TRIGGER_SHOW].script == NULL) { - trigger[number_of_triggers++] = ANIMATION_TRIGGER_SHOW; - } - if (set_animation(opt->animations, trigger, number_of_triggers, fade_in1, - output_indices, 0, 0)) { - scripts[number_of_scripts++] = fade_in1; - } else { - script_free(fade_in1); - } + // Fading in from nothing, i.e. `open` and `show` + asnprintf(&str, &len, FADING_TEMPLATE_1 FADING_TEMPLATE_2, duration_str, + duration_str, 0, 1); - // Fading for opacity change, for these, the blur opacity doesn't change. - asnprintf(&str, &len, FADING_TEMPLATE_1, duration); - auto fade_in2 = compile_win_script_from_string(str, output_indices); - number_of_triggers = 0; - if (opt->animations[ANIMATION_TRIGGER_INCREASE_OPACITY].script == NULL) { - trigger[number_of_triggers++] = ANIMATION_TRIGGER_INCREASE_OPACITY; - } - if (set_animation(opt->animations, trigger, number_of_triggers, fade_in2, - output_indices, 0, 0)) { - scripts[number_of_scripts++] = fade_in2; + auto fade_in1 = compile_win_script_from_string(str, output_indices); + if (opt->animations[ANIMATION_TRIGGER_OPEN].script == NULL && + !opt->no_fading_openclose) { + trigger[number_of_triggers++] = ANIMATION_TRIGGER_OPEN; + } + if (opt->animations[ANIMATION_TRIGGER_SHOW].script == NULL) { + trigger[number_of_triggers++] = ANIMATION_TRIGGER_SHOW; + } + if (set_animation(opt->animations, trigger, number_of_triggers, fade_in1, + output_indices, 0, 0)) { + scripts[number_of_scripts++] = fade_in1; + } else { + script_free(fade_in1); + } + + // Fading for opacity change, for these, the blur opacity doesn't change. + asnprintf(&str, &len, FADING_TEMPLATE_1, duration_str); + auto fade_in2 = compile_win_script_from_string(str, output_indices); + number_of_triggers = 0; + if (opt->animations[ANIMATION_TRIGGER_INCREASE_OPACITY].script == NULL) { + trigger[number_of_triggers++] = ANIMATION_TRIGGER_INCREASE_OPACITY; + } + if (set_animation(opt->animations, trigger, number_of_triggers, fade_in2, + output_indices, 0, 0)) { + scripts[number_of_scripts++] = fade_in2; + } else { + script_free(fade_in2); + } } else { - script_free(fade_in2); + log_error("Invalid fade-in setting (step: %f, delta: %d), ignoring.", + opt->fade_in_step, opt->fade_delta); } duration = 1.0 / opt->fade_out_step * opt->fade_delta; - // Fading out to nothing, i.e. `hide` and `close` - asnprintf(&str, &len, FADING_TEMPLATE_1 FADING_TEMPLATE_2, duration, duration, - 1.F, 0.F); - auto fade_out1 = compile_win_script_from_string(str, output_indices); - number_of_triggers = 0; - if (opt->animations[ANIMATION_TRIGGER_CLOSE].script == NULL && - !opt->no_fading_openclose) { - trigger[number_of_triggers++] = ANIMATION_TRIGGER_CLOSE; - } - if (opt->animations[ANIMATION_TRIGGER_HIDE].script == NULL) { - trigger[number_of_triggers++] = ANIMATION_TRIGGER_HIDE; - } - if (set_animation(opt->animations, trigger, number_of_triggers, fade_out1, - output_indices, 0, 0)) { - scripts[number_of_scripts++] = fade_out1; - } else { - script_free(fade_out1); - } + if (!safe_isinf(duration) && !safe_isnan(duration) && duration > 0) { + scoped_charp duration_str = NULL; + dtostr(duration, &duration_str); - // Fading for opacity change - asnprintf(&str, &len, FADING_TEMPLATE_1, duration); - auto fade_out2 = compile_win_script_from_string(str, output_indices); - number_of_triggers = 0; - if (opt->animations[ANIMATION_TRIGGER_DECREASE_OPACITY].script == NULL) { - trigger[number_of_triggers++] = ANIMATION_TRIGGER_DECREASE_OPACITY; - } - if (set_animation(opt->animations, trigger, number_of_triggers, fade_out2, - output_indices, 0, 0)) { - scripts[number_of_scripts++] = fade_out2; + // Fading out to nothing, i.e. `hide` and `close` + asnprintf(&str, &len, FADING_TEMPLATE_1 FADING_TEMPLATE_2, duration_str, + duration_str, 1, 0); + auto fade_out1 = compile_win_script_from_string(str, output_indices); + number_of_triggers = 0; + if (opt->animations[ANIMATION_TRIGGER_CLOSE].script == NULL && + !opt->no_fading_openclose) { + trigger[number_of_triggers++] = ANIMATION_TRIGGER_CLOSE; + } + if (opt->animations[ANIMATION_TRIGGER_HIDE].script == NULL) { + trigger[number_of_triggers++] = ANIMATION_TRIGGER_HIDE; + } + if (set_animation(opt->animations, trigger, number_of_triggers, fade_out1, + output_indices, 0, 0)) { + scripts[number_of_scripts++] = fade_out1; + } else { + script_free(fade_out1); + } + + // Fading for opacity change + asnprintf(&str, &len, FADING_TEMPLATE_1, duration_str); + auto fade_out2 = compile_win_script_from_string(str, output_indices); + number_of_triggers = 0; + if (opt->animations[ANIMATION_TRIGGER_DECREASE_OPACITY].script == NULL) { + trigger[number_of_triggers++] = ANIMATION_TRIGGER_DECREASE_OPACITY; + } + if (set_animation(opt->animations, trigger, number_of_triggers, fade_out2, + output_indices, 0, 0)) { + scripts[number_of_scripts++] = fade_out2; + } else { + script_free(fade_out2); + } } else { - script_free(fade_out2); + log_error("Invalid fade-out setting (step: %f, delta: %d), ignoring.", + opt->fade_out_step, opt->fade_delta); } - free(str); log_debug("Generated %d scripts for fading.", number_of_scripts); if (number_of_scripts) { diff --git a/src/string_utils.h b/src/string_utils.h index 970f227e..88f7d477 100644 --- a/src/string_utils.h +++ b/src/string_utils.h @@ -2,11 +2,12 @@ // Copyright (c) Yuxuan Shui #pragma once #include +#include #include #include #include -#include "compiler.h" +#include "utils.h" #define mstrncmp(s1, s2) strncmp((s1), (s2), strlen(s1)) @@ -38,6 +39,24 @@ static inline int uitostr(unsigned int n, char *buf) { return ret; } +/// Convert a double into a string. Avoid using *printf functions to print floating points +/// directly because they are locale dependent. +static inline void dtostr(double n, char **buf) { + BUG_ON(safe_isnan(n)); + BUG_ON(safe_isinf(n)); + if (fabs(n) > 1e9) { + // The number is so big that it's not meaningful to keep decimal places. + asprintf(buf, "%.0f", n); + return; + } + + if (n > 0) { + asprintf(buf, "%.0f.%03d", floor(n), (int)(fmod(n, 1) * 1000)); + } else { + asprintf(buf, "-%.0f.%03d", floor(-n), (int)(fmod(-n, 1) * 1000)); + } +} + static inline const char *skip_space_const(const char *src) { if (!src) { return NULL; @@ -70,4 +89,5 @@ static inline bool starts_with(const char *str, const char *needle, bool ignore_ /// Similar to `asprintf`, but it reuses the allocated memory pointed to by `*strp`, and /// reallocates it if it's not big enough. -int asnprintf(char **strp, size_t *capacity, const char *fmt, ...); +int asnprintf(char **strp, size_t *capacity, const char *fmt, ...) + __attribute__((format(printf, 3, 4)));