mirror of
https://github.com/yshui/picom.git
synced 2025-04-14 17:53:25 -04:00
config_libconfig: parse animation scripts
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
da76a40407
commit
9502d7509d
5 changed files with 224 additions and 0 deletions
37
src/config.h
37
src/config.h
|
@ -81,6 +81,38 @@ enum vblank_scheduler_type {
|
|||
LAST_VBLANK_SCHEDULER,
|
||||
};
|
||||
|
||||
enum animation_trigger {
|
||||
ANIMATION_TRIGGER_INVALID = -1,
|
||||
/// When a hidden window is shown
|
||||
ANIMATION_TRIGGER_SHOW = 0,
|
||||
/// When a window is hidden
|
||||
ANIMATION_TRIGGER_HIDE,
|
||||
/// When window opacity is increased
|
||||
ANIMATION_TRIGGER_INCREASE_OPACITY,
|
||||
/// When window opacity is decreased
|
||||
ANIMATION_TRIGGER_DECREASE_OPACITY,
|
||||
/// When a new window opens
|
||||
ANIMATION_TRIGGER_OPEN,
|
||||
/// When a window is closed
|
||||
ANIMATION_TRIGGER_CLOSE,
|
||||
ANIMATION_TRIGGER_LAST = ANIMATION_TRIGGER_CLOSE,
|
||||
};
|
||||
|
||||
static const char *animation_trigger_names[] attr_unused = {
|
||||
[ANIMATION_TRIGGER_SHOW] = "show",
|
||||
[ANIMATION_TRIGGER_HIDE] = "hide",
|
||||
[ANIMATION_TRIGGER_INCREASE_OPACITY] = "increase-opacity",
|
||||
[ANIMATION_TRIGGER_DECREASE_OPACITY] = "decrease-opacity",
|
||||
[ANIMATION_TRIGGER_OPEN] = "open",
|
||||
[ANIMATION_TRIGGER_CLOSE] = "close",
|
||||
};
|
||||
|
||||
struct script;
|
||||
struct win_script {
|
||||
int output_indices[NUM_OF_WIN_SCRIPT_OUTPUTS];
|
||||
struct script *script;
|
||||
};
|
||||
|
||||
extern const char *vblank_scheduler_str[];
|
||||
|
||||
/// Internal, private options for debugging and development use.
|
||||
|
@ -292,6 +324,11 @@ typedef struct options {
|
|||
c2_lptr_t *transparent_clipping_blacklist;
|
||||
|
||||
bool dithered_present;
|
||||
// === Animation ===
|
||||
struct win_script animations[ANIMATION_TRIGGER_LAST + 1];
|
||||
/// Array of all the scripts used in `animations`.
|
||||
struct script **all_scripts;
|
||||
int number_of_scripts;
|
||||
} options_t;
|
||||
|
||||
extern const char *const BACKEND_STRS[NUM_BKEND + 1];
|
||||
|
|
|
@ -15,8 +15,10 @@
|
|||
#include "config.h"
|
||||
#include "err.h"
|
||||
#include "log.h"
|
||||
#include "script.h"
|
||||
#include "string_utils.h"
|
||||
#include "utils.h"
|
||||
#include "win.h"
|
||||
|
||||
#pragma GCC diagnostic error "-Wunused-parameter"
|
||||
|
||||
|
@ -220,6 +222,140 @@ static inline void parse_wintype_config(const config_t *cfg, const char *member_
|
|||
}
|
||||
}
|
||||
|
||||
static enum animation_trigger parse_animation_trigger(const char *trigger) {
|
||||
for (int i = 0; i <= ANIMATION_TRIGGER_LAST; i++) {
|
||||
if (strcasecmp(trigger, animation_trigger_names[i]) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return ANIMATION_TRIGGER_INVALID;
|
||||
}
|
||||
|
||||
static struct script *
|
||||
compile_win_script(config_setting_t *setting, int *output_indices, char **err) {
|
||||
struct script_output_info outputs[ARR_SIZE(win_script_outputs)];
|
||||
memcpy(outputs, win_script_outputs, sizeof(win_script_outputs));
|
||||
|
||||
struct script_parse_config parse_config = {
|
||||
.context_info = win_script_context_info,
|
||||
.output_info = outputs,
|
||||
};
|
||||
auto script = script_compile(setting, parse_config, err);
|
||||
if (script == NULL) {
|
||||
return script;
|
||||
}
|
||||
for (int i = 0; i < NUM_OF_WIN_SCRIPT_OUTPUTS; i++) {
|
||||
output_indices[i] = outputs[i].slot;
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
||||
static bool set_animation(struct win_script *animations,
|
||||
const enum animation_trigger *triggers, int number_of_triggers,
|
||||
struct script *script, const int *output_indices, unsigned line) {
|
||||
bool needed = false;
|
||||
for (int i = 0; i < number_of_triggers; i++) {
|
||||
if (triggers[i] == ANIMATION_TRIGGER_INVALID) {
|
||||
log_error("Invalid trigger defined at line %d", line);
|
||||
continue;
|
||||
}
|
||||
if (animations[triggers[i]].script != NULL) {
|
||||
log_error("Duplicate animation defined for trigger %s at line "
|
||||
"%d, it will be ignored.",
|
||||
animation_trigger_names[triggers[i]], line);
|
||||
continue;
|
||||
}
|
||||
memcpy(animations[triggers[i]].output_indices, output_indices,
|
||||
sizeof(int[NUM_OF_WIN_SCRIPT_OUTPUTS]));
|
||||
animations[triggers[i]].script = script;
|
||||
needed = true;
|
||||
}
|
||||
return needed;
|
||||
}
|
||||
|
||||
static struct script *
|
||||
parse_animation_one(struct win_script *animations, config_setting_t *setting) {
|
||||
auto triggers = config_setting_lookup(setting, "triggers");
|
||||
if (!triggers) {
|
||||
log_error("Missing triggers in animation script, at line %d",
|
||||
config_setting_source_line(setting));
|
||||
return NULL;
|
||||
}
|
||||
if (!config_setting_is_list(triggers) && !config_setting_is_array(triggers) &&
|
||||
config_setting_get_string(triggers) == NULL) {
|
||||
log_error("The \"triggers\" option must either be a string, a list, or "
|
||||
"an array, but is none of those at line %d",
|
||||
config_setting_source_line(triggers));
|
||||
return NULL;
|
||||
}
|
||||
auto number_of_triggers =
|
||||
config_setting_get_string(triggers) == NULL ? config_setting_length(triggers) : 1;
|
||||
if (number_of_triggers > ANIMATION_TRIGGER_LAST) {
|
||||
log_error("Too many triggers in animation defined at line %d",
|
||||
config_setting_source_line(triggers));
|
||||
return NULL;
|
||||
}
|
||||
if (number_of_triggers == 0) {
|
||||
log_error("Trigger list is empty in animation defined at line %d",
|
||||
config_setting_source_line(triggers));
|
||||
return NULL;
|
||||
}
|
||||
enum animation_trigger *trigger_types =
|
||||
alloca(sizeof(enum animation_trigger[number_of_triggers]));
|
||||
const char *trigger0 = config_setting_get_string(triggers);
|
||||
if (trigger0 == NULL) {
|
||||
for (int i = 0; i < number_of_triggers; i++) {
|
||||
auto trigger_i = config_setting_get_string_elem(triggers, i);
|
||||
trigger_types[i] = trigger_i == NULL
|
||||
? ANIMATION_TRIGGER_INVALID
|
||||
: parse_animation_trigger(trigger_i);
|
||||
}
|
||||
} else {
|
||||
trigger_types[0] = parse_animation_trigger(trigger0);
|
||||
}
|
||||
|
||||
// script parser shouldn't see this.
|
||||
config_setting_remove(setting, "triggers");
|
||||
|
||||
int output_indices[NUM_OF_WIN_SCRIPT_OUTPUTS];
|
||||
char *err;
|
||||
auto script = compile_win_script(setting, output_indices, &err);
|
||||
if (!script) {
|
||||
log_error("Failed to parse animation script at line %d: %s",
|
||||
config_setting_source_line(setting), err);
|
||||
free(err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool needed = set_animation(animations, trigger_types, number_of_triggers, script,
|
||||
output_indices, config_setting_source_line(setting));
|
||||
if (!needed) {
|
||||
script_free(script);
|
||||
script = NULL;
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
||||
static struct script **parse_animations(struct win_script *animations,
|
||||
config_setting_t *setting, int *number_of_scripts) {
|
||||
auto number_of_animations = config_setting_length(setting);
|
||||
auto all_scripts = ccalloc(number_of_animations + 1, struct script *);
|
||||
auto len = 0;
|
||||
for (int i = 0; i < number_of_animations; i++) {
|
||||
auto sub = config_setting_get_elem(setting, (unsigned)i);
|
||||
auto script = parse_animation_one(animations, sub);
|
||||
if (script != NULL) {
|
||||
all_scripts[len++] = script;
|
||||
}
|
||||
}
|
||||
if (len == 0) {
|
||||
free(all_scripts);
|
||||
all_scripts = NULL;
|
||||
}
|
||||
*number_of_scripts = len;
|
||||
return all_scripts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a configuration file from default location.
|
||||
*
|
||||
|
@ -607,6 +743,12 @@ char *parse_config_libconfig(options_t *opt, const char *config_file) {
|
|||
parse_wintype_config(&cfg, "notify", &opt->wintype_option[WINTYPE_NOTIFICATION],
|
||||
&opt->wintype_option_mask[WINTYPE_NOTIFICATION]);
|
||||
|
||||
config_setting_t *animations = config_lookup(&cfg, "animations");
|
||||
if (animations) {
|
||||
opt->all_scripts =
|
||||
parse_animations(opt->animations, animations, &opt->number_of_scripts);
|
||||
}
|
||||
|
||||
config_destroy(&cfg);
|
||||
return path;
|
||||
|
||||
|
|
|
@ -930,6 +930,13 @@ void options_destroy(struct options *options) {
|
|||
}
|
||||
free(options->blur_kerns);
|
||||
free(options->glx_fshader_win_str);
|
||||
|
||||
for (int i = 0; i < options->number_of_scripts; i++) {
|
||||
script_free(options->all_scripts[i]);
|
||||
options->all_scripts[i] = NULL;
|
||||
}
|
||||
free(options->all_scripts);
|
||||
memset(options->animations, 0, sizeof(options->animations));
|
||||
}
|
||||
|
||||
// vim: set noet sw=8 ts=8 :
|
||||
|
|
27
src/win.h
27
src/win.h
|
@ -16,6 +16,7 @@
|
|||
#include "list.h"
|
||||
#include "region.h"
|
||||
#include "render.h"
|
||||
#include "script.h"
|
||||
#include "transition.h"
|
||||
#include "types.h"
|
||||
#include "utils.h"
|
||||
|
@ -305,6 +306,32 @@ struct managed_win {
|
|||
region_t damaged;
|
||||
};
|
||||
|
||||
struct win_script_context {
|
||||
double x, y, width, height;
|
||||
double opacity_before, opacity;
|
||||
};
|
||||
|
||||
static const struct script_context_info win_script_context_info[] = {
|
||||
{"window-x", offsetof(struct win_script_context, x)},
|
||||
{"window-y", offsetof(struct win_script_context, y)},
|
||||
{"window-width", offsetof(struct win_script_context, width)},
|
||||
{"window-height", offsetof(struct win_script_context, height)},
|
||||
{"window-raw-opacity-before", offsetof(struct win_script_context, opacity_before)},
|
||||
{"window-raw-opacity", offsetof(struct win_script_context, opacity)},
|
||||
{NULL, 0} //
|
||||
};
|
||||
|
||||
static const struct script_output_info win_script_outputs[] = {
|
||||
[WIN_SCRIPT_OFFSET_X] = {"offset-x"},
|
||||
[WIN_SCRIPT_OFFSET_Y] = {"offset-y"},
|
||||
[WIN_SCRIPT_SHADOW_OFFSET_X] = {"shadow-offset-x"},
|
||||
[WIN_SCRIPT_SHADOW_OFFSET_Y] = {"shadow-offset-y"},
|
||||
[WIN_SCRIPT_OPACITY] = {"opacity"},
|
||||
[WIN_SCRIPT_BLUR_OPACITY] = {"blur-opacity"},
|
||||
[WIN_SCRIPT_SHADOW_OPACITY] = {"shadow-opacity"},
|
||||
[NUM_OF_WIN_SCRIPT_OUTPUTS] = {NULL},
|
||||
};
|
||||
|
||||
/// Process pending updates/images flags on a window. Has to be called in X critical
|
||||
/// section
|
||||
void win_process_update_flags(session_t *ps, struct managed_win *w);
|
||||
|
|
|
@ -65,3 +65,14 @@ enum win_flags {
|
|||
/// need better name for this, is set when some aspects of the window changed
|
||||
WIN_FLAGS_FACTOR_CHANGED = 1024,
|
||||
};
|
||||
|
||||
enum win_script_output {
|
||||
WIN_SCRIPT_OFFSET_X = 0,
|
||||
WIN_SCRIPT_OFFSET_Y,
|
||||
WIN_SCRIPT_SHADOW_OFFSET_X,
|
||||
WIN_SCRIPT_SHADOW_OFFSET_Y,
|
||||
WIN_SCRIPT_OPACITY,
|
||||
WIN_SCRIPT_BLUR_OPACITY,
|
||||
WIN_SCRIPT_SHADOW_OPACITY,
|
||||
};
|
||||
#define NUM_OF_WIN_SCRIPT_OUTPUTS (WIN_SCRIPT_SHADOW_OPACITY + 1)
|
||||
|
|
Loading…
Add table
Reference in a new issue