diff --git a/Makefile b/Makefile index f8cb4e7..a09cef6 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ CPPFLAGS += $(shell pkg-config --cflags $(DEPS)) LDLIBS += $(shell pkg-config --libs $(DEPS)) INTERP ?= MAIN = main -OBJS = main.o events.o processing.o graph.o config.o event_code_names.o hash_table.o module_registry.o event_predicate.o nodes/getchar.o nodes/print.o nodes/evdev.o nodes/tee.o nodes/router.o +OBJS = main.o events.o processing.o graph.o config.o event_code_names.o hash_table.o module_registry.o event_predicate.o nodes/getchar.o nodes/print.o nodes/evdev.o nodes/tee.o nodes/router.o nodes/modifiers.o all: $(MAIN) diff --git a/config.cfg b/config.cfg index dff3e35..6f7ebcd 100644 --- a/config.cfg +++ b/config.cfg @@ -1,3 +1,7 @@ +constants = { + my_modifier = 9; +}; + enums = { namespaces: ["stdin", "clickpad"]; }; @@ -42,7 +46,21 @@ nodes = { select_key_events = { type = "router"; options = { - predicates = ["key_event"]; + predicates = ( + "key_event", + { + type = "or"; + inverted = 1; + args = ["key_event"]; + } + ); + }; + }; + set_modifier = { + type = "modifiers"; + options = { + operation = "set"; + modifiers = ["my_modifier"]; }; }; }; @@ -55,7 +73,13 @@ channels = ({ to: ("select_key_events", 1); }, { from: ("select_key_events", 0); + to: ("set_modifier", 0); +}, { + from: ("set_modifier", 0); to: ("print", 0); +}, { + from: ("select_key_events", 1); + to: ("print", 1); }); // vim: ft=libconfig diff --git a/nodes/modifiers.c b/nodes/modifiers.c new file mode 100644 index 0000000..fff6adc --- /dev/null +++ b/nodes/modifiers.c @@ -0,0 +1,99 @@ +#include "../graph.h" +#include "../module_registry.h" + +typedef struct { + GraphNode as_GraphNode; + ModifierSet modifiers; + ModifierOperation operation; +} ModifiersGraphNode; + +static bool +handle_event(EventPositionBase * self, EventNode * event) +{ + ModifiersGraphNode *node = DOWNCAST(ModifiersGraphNode, GraphNode, DOWNCAST(GraphNode, EventPositionBase, self)); + size_t count = node->as_GraphNode.outputs.length; + if (!count) { + event_destroy(event); + return true; + } + modifier_set_operation_from(&event->data.modifiers, node->modifiers, node->operation); + if (count > 1) { + count = event_replicate(event, count - 1) + 1; + } + for (size_t i = 0; i < count; ++i) { + event->position = &node->as_GraphNode.outputs.elements[i]->as_EventPositionBase; + event = event->next; + } + return true; +} + +static GraphNode * +create(GraphNodeSpecification * spec, GraphNodeConfig * config, InitializationEnvironment * env) +{ + (void) config; + (void) env; + ModifiersGraphNode * node = T_ALLOC(1, ModifiersGraphNode); + if (!node) { + return NULL; + } + + const char *operation_name; + config_setting_lookup_string(config->options, "operation", &operation_name); + ModifierOperation op = modifier_operation_parse(operation_name); + if (op < 0) { + free(node); + return NULL; + } + + config_setting_t *modifiers_setting = config_setting_get_member(config->options, "modifiers"); + if (!modifiers_setting) { + free(node); + return NULL; + } + + ModifierSet modifier_set = EMPTY_MODIFIER_SET; + size_t length = config_setting_length(modifiers_setting); + for (size_t i = 0; i < length; ++i) { + long long mod = env_resolve_constant_or(env, config_setting_get_elem(modifiers_setting, i), -1); + if (mod < 0 || mod > MODIFIER_MAX) { + continue; + } + modifier_set_set(&modifier_set, mod); + } + + *node = (ModifiersGraphNode) { + .as_GraphNode = { + .as_EventPositionBase = { + .handle_event = &handle_event, + .waiting_new_event = false, + }, + .specification = spec, + .inputs = EMPTY_GRAPH_CHANNEL_LIST, + .outputs = EMPTY_GRAPH_CHANNEL_LIST, + }, + .modifiers = modifier_set, + .operation = op, + }; + return &node->as_GraphNode; +} + +static void destroy +(GraphNodeSpecification * self, GraphNode * target) +{ + (void) self; + ModifiersGraphNode * node = DOWNCAST(ModifiersGraphNode, GraphNode, target); + modifier_set_destruct(&node->modifiers); + free(target); +} + +GraphNodeSpecification nodespec_modifiers = (GraphNodeSpecification) { + .create = &create, + .destroy = &destroy, + .register_io = NULL, + .name = "modifiers", +}; + +MODULE_CONSTRUCTOR(init) +{ + register_graph_node_specification(&nodespec_modifiers); +}