diff --git a/data/keyd-application-mapper.1.gz b/data/keyd-application-mapper.1.gz index 9a5d913..2ad7980 100644 Binary files a/data/keyd-application-mapper.1.gz and b/data/keyd-application-mapper.1.gz differ diff --git a/data/keyd.1.gz b/data/keyd.1.gz index bf8032c..ef7b68d 100644 Binary files a/data/keyd.1.gz and b/data/keyd.1.gz differ diff --git a/docs/keyd.scdoc b/docs/keyd.scdoc index 7f907d6..59b6f6c 100644 --- a/docs/keyd.scdoc +++ b/docs/keyd.scdoc @@ -364,6 +364,15 @@ arguments. b = S-insert ``` +*macro2(, , )* + Creates a macro with the given timeout and repeat timeout. If a timeout value of 0 is used, + macro repeat is disabled. + + E.G + + macro2(400, 50, macro(Hello space World)) + + *noop* Do nothing. diff --git a/src/descriptor.c b/src/descriptor.c index 3f3455c..8f7a6b0 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -153,7 +153,7 @@ static int parse_sequence(const char *s, uint8_t *codep, uint8_t *modsp) return -1; } -/* +/* * Returns the character size in bytes, or 0 in the case of the empty string. */ static int utf8_read_char(const char *_s, uint32_t *code) @@ -514,25 +514,34 @@ int create_layer(struct layer *layer, const char *desc, const struct layer_table return 0; } -/* +/* * Returns: * * > 0 if exp is a valid macro but the macro table is full * < 0 in the case of an invalid macro * 0 on success */ -int set_macro_arg(struct descriptor *d, int idx, struct layer_table *lt, const char *exp) +int set_macro_arg(struct descriptor *d, + int idx, + struct layer_table *lt, const char *exp, + int32_t timeout, + int32_t repeat_timeout) { + struct macro *macro = <->macros[lt->nr_macros]; + if (lt->nr_macros >= MAX_MACROS) { err("max macros (%d), exceeded", MAX_MACROS); return 1; } - if (parse_macro(exp, <->macros[lt->nr_macros]) < 0) { + if (parse_macro(exp, macro) < 0) { err("\"%s\" is not a valid macro", exp); return -1; } + macro->timeout = timeout; + macro->repeat_timeout = repeat_timeout; + d->args[idx].idx = lt->nr_macros; lt->nr_macros++; @@ -573,7 +582,7 @@ int parse_descriptor(const char *descstr, if (keycode_to_mod(code)) fprintf(stderr, "WARNING: mapping modifier keycodes directly may produce unintended results, you probably want layer() instead\n"); - } else if ((ret=set_macro_arg(d, 0, lt, descstr)) >= 0) { + } else if ((ret=set_macro_arg(d, 0, lt, descstr, -1, -1)) >= 0) { if (ret > 0) return -1; else @@ -589,6 +598,8 @@ int parse_descriptor(const char *descstr, d->op = OP_OVERLOAD; else if (!strcmp(fn, "swap")) { d->op = OP_SWAP; + } else if (!strcmp(fn, "macro2")) { + d->op = OP_MACRO; } else if (!strcmp(fn, "timeout")) { d->op = OP_TIMEOUT; } else { @@ -601,6 +612,25 @@ int parse_descriptor(const char *descstr, return -1; } + if (d->op == OP_MACRO) { + int32_t timeout; + int32_t repeat_timeout; + + if (nargs != 3) { + err("macro2 requires 3 arguments."); + return -1; + } + + timeout = atoi(args[0]); + repeat_timeout = atoi(args[1]); + + if (set_macro_arg(d, 0, lt, args[2], timeout, repeat_timeout) < 0) + return -1; + + + return 0; + } + if (d->op == OP_TIMEOUT) { struct timeout *timeout; @@ -642,13 +672,13 @@ int parse_descriptor(const char *descstr, d->args[1].idx = -1; if (nargs > 1) - return set_macro_arg(d, 1, lt, args[1]); + return set_macro_arg(d, 1, lt, args[1], -1, -1); } else if (utf8_strlen(descstr) == 1) { char buf[32]; sprintf(buf, "macro(%s)", descstr); d->op = OP_MACRO; - if (set_macro_arg(d, 0, lt, buf)) + if (set_macro_arg(d, 0, lt, buf, -1, -1)) return -1; } else { err("invalid key or action"); diff --git a/src/keyboard.c b/src/keyboard.c index ef365c7..f5baf79 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -447,7 +447,9 @@ static long process_descriptor(struct keyboard *kbd, uint8_t code, kbd->active_macro = macro; kbd->active_macro_layer = dl; - timeout = kbd->config.macro_timeout; + timeout = macro->timeout == -1 ? + kbd->config.macro_timeout : + macro->timeout; } break; @@ -498,9 +500,11 @@ static long process_descriptor(struct keyboard *kbd, uint8_t code, } } else { deactivate_layer(kbd, layer); - update_mods(kbd, layer, mods); + update_mods(kbd, layer, 0); } + break; + case OP_UNDEFINED: break; } @@ -523,14 +527,16 @@ static long process_descriptor(struct keyboard *kbd, uint8_t code, long kbd_process_key_event(struct keyboard *kbd, uint8_t code, int pressed) { - struct layer *dl; + struct layer *dl = NULL; struct descriptor d; /* timeout */ if (!code) { if (kbd->active_macro) { execute_macro(kbd, kbd->active_macro_layer, kbd->active_macro); - return kbd->config.macro_repeat_timeout; + return kbd->active_macro->repeat_timeout == -1 ? + kbd->config.macro_repeat_timeout : + kbd->active_macro->repeat_timeout; } if (kbd->pending_timeout.active) { diff --git a/src/layer.h b/src/layer.h index 9b6ab49..53cd369 100644 --- a/src/layer.h +++ b/src/layer.h @@ -72,7 +72,10 @@ struct macro_entry { */ struct macro { struct macro_entry entries[MAX_MACRO_SIZE]; - size_t sz; + + int32_t timeout; + int32_t repeat_timeout; + uint32_t sz; }; struct layer_table {