diff --git a/Makefile b/Makefile index 1502f34..025f914 100644 --- a/Makefile +++ b/Makefile @@ -98,7 +98,7 @@ test-io: src/string.c \ src/macro.c \ src/config.c \ - src/error.c \ + src/log.c \ src/ini.c \ src/keys.c \ src/unicode.c && \ diff --git a/src/config.c b/src/config.c index 20e59f9..3cad9bd 100644 --- a/src/config.c +++ b/src/config.c @@ -390,50 +390,6 @@ static int config_add_layer(struct config *config, const char *s) return 0; } -static void config_init(struct config *config) -{ - size_t i; - - memset(config, 0, sizeof *config); - - config_add_layer(config, "main"); - - config_add_layer(config, "control:C"); - config_add_layer(config, "meta:M"); - config_add_layer(config, "shift:S"); - config_add_layer(config, "altgr:G"); - config_add_layer(config, "alt:A"); - - /* Add default modifier bindings to the main layer. */ - for (i = 0; i < MAX_MOD; i++) { - const struct modifier_table_ent *mod = &modifier_table[i]; - - struct descriptor *d1 = &config->layers[0].keymap[mod->code1]; - struct descriptor *d2 = &config->layers[0].keymap[mod->code2]; - - int idx = config_get_layer_index(config, mod->name); - - assert(idx != -1); - - d1->op = OP_LAYER; - d1->args[0].idx = idx; - - d2->op = OP_LAYER; - d2->args[0].idx = idx; - - strcpy(config->aliases[mod->code1], mod->name); - strcpy(config->aliases[mod->code2], mod->name); - } - - /* In ms */ - config->chord_interkey_timeout = 50; - config->chord_hold_timeout = 0; - config->oneshot_timeout = 0; - - config->macro_timeout = 600; - config->macro_repeat_timeout = 50; -} - /* Modifies the input string */ static int parse_fn(char *s, char **name, @@ -598,7 +554,7 @@ static int parse_descriptor(char *s, /* TODO: fixme. */ if (keycode_to_mod(code)) - warn("y{NOTE:} mapping modifier keycodes directly may produce unintended results.\n"); + warn("y{NOTE:} mapping modifier keycodes directly may produce unintended results."); return 0; } else if ((ret=parse_command(s, &cmd)) >= 0) { @@ -803,7 +759,7 @@ static void parse_id_section(struct config *config, struct ini_section *section) config->ids[config->nr_ids].flags = ID_KEYBOARD | ID_MOUSE; config->nr_ids++; - } + } else { warn("%s is not a valid device id", s); } @@ -844,27 +800,18 @@ static void parse_alias_section(struct config *config, struct ini_section *secti } } -int config_parse(struct config *config, const char *path) + +static int config_parse_string(struct config *config, char *content) { size_t i; - - char *content; struct ini *ini; - struct ini_section *section; - - config_init(config); - - if (!(content = read_file(path))) - return -1; if (!(ini = ini_parse_string(content, NULL))) return -1; - snprintf(config->path, sizeof(config->path), "%s", path); - /* First pass: create all layers based on section headers. */ for (i = 0; i < ini->nr_sections; i++) { - section = &ini->sections[i]; + struct ini_section *section = &ini->sections[i]; if (!strcmp(section->name, "ids")) { parse_id_section(config, section); @@ -882,7 +829,7 @@ int config_parse(struct config *config, const char *path) for (i = 0; i < ini->nr_sections; i++) { size_t j; char *layername; - section = &ini->sections[i]; + struct ini_section *section = &ini->sections[i]; if (!strcmp(section->name, "ids") || !strcmp(section->name, "aliases") || @@ -910,6 +857,64 @@ int config_parse(struct config *config, const char *path) return 0; } +static void config_init(struct config *config) +{ + size_t i; + + memset(config, 0, sizeof *config); + + char default_config[] = + "[aliases]\n" + + "leftshift = shift\n" + "rightshift = shift\n" + + "leftalt = alt\n" + "rightalt = altgr\n" + + "leftmeta = meta\n" + "rightmeta = meta\n" + + "leftcontrol = control\n" + "rightcontrol = control\n" + + "[main]\n" + + "shift = layer(shift)\n" + "alt = layer(alt)\n" + "altgr = layer(altgr)\n" + "meta = layer(meta)\n" + "control = layer(control)\n" + + "[control:C]\n" + "[shift:S]\n" + "[meta:M]\n" + "[alt:A]\n" + "[altgr:G]\n"; + + config_parse_string(config, default_config); + + /* In ms */ + config->chord_interkey_timeout = 50; + config->chord_hold_timeout = 0; + config->oneshot_timeout = 0; + + config->macro_timeout = 600; + config->macro_repeat_timeout = 50; +} + +int config_parse(struct config *config, const char *path) +{ + char *content; + + if (!(content = read_file(path))) + return -1; + + config_init(config); + snprintf(config->path, sizeof(config->path), "%s", path); + return config_parse_string(config, content); +} + int config_check_match(struct config *config, uint16_t vendor, uint16_t product, uint8_t flags) { size_t i; @@ -941,7 +946,7 @@ int config_get_layer_index(const struct config *config, const char *name) return -1; } -/* +/* * Adds a binding of the form [.] = * to the given config. */ diff --git a/src/keyboard.c b/src/keyboard.c index 1a1a582..9168c7b 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -83,40 +83,45 @@ static void send_key(struct keyboard *kbd, uint8_t code, uint8_t pressed) } } +static void clear_mod(struct keyboard *kbd, uint8_t code) +{ + /* + * Some modifiers have a special meaning when used in + * isolation (e.g meta in Gnome, alt in Firefox). + * In order to prevent spurious key presses we + * avoid adjacent down/up pairs by interposing + * additional control sequences. + */ + int guard = (((kbd->last_pressed_output_code == code) && + (code == KEYD_LEFTMETA || + code == KEYD_LEFTALT || + code == KEYD_RIGHTALT)) && + !kbd->inhibit_modifier_guard && + !kbd->config.disable_modifier_guard); + + if (guard && !kbd->keystate[KEYD_LEFTCTRL]) { + send_key(kbd, KEYD_LEFTCTRL, 1); + send_key(kbd, code, 0); + send_key(kbd, KEYD_LEFTCTRL, 0); + } else { + send_key(kbd, code, 0); + } +} + static void set_mods(struct keyboard *kbd, uint8_t mods) { size_t i; - for (i = 0; i < ARRAY_SIZE(modifier_table); i++) { - uint8_t code = modifier_table[i].code1; - uint8_t mask = modifier_table[i].mask; + for (i = 0; i < ARRAY_SIZE(modifiers); i++) { + uint8_t mask = modifiers[i].mask; + uint8_t code = modifiers[i].key; if (mask & mods) { if (!kbd->keystate[code]) send_key(kbd, code, 1); } else { - /* - * Some modifiers have a special meaning when used in - * isolation (e.g meta in Gnome, alt in Firefox). - * In order to prevent spurious key presses we - * avoid adjacent down/up pairs by interposing - * additional control sequences. - */ - int guard = ((((kbd->last_pressed_output_code == KEYD_LEFTMETA) && mask == MOD_SUPER) || - ((kbd->last_pressed_output_code == KEYD_LEFTALT) && mask == MOD_ALT) || - ((kbd->last_pressed_output_code == KEYD_RIGHTALT) && mask == MOD_ALT_GR)) && - !kbd->inhibit_modifier_guard && - !kbd->config.disable_modifier_guard); - - if (kbd->keystate[code]) { - if (guard && !kbd->keystate[KEYD_LEFTCTRL]) { - send_key(kbd, KEYD_LEFTCTRL, 1); - send_key(kbd, code, 0); - send_key(kbd, KEYD_LEFTCTRL, 0); - } else { - send_key(kbd, code, 0); - } - } + if (kbd->keystate[code]) + clear_mod(kbd, code); } } } @@ -778,8 +783,7 @@ struct keyboard *new_keyboard(struct config *config, } if (!found) - fprintf(stderr, - "\tWARNING: could not find default layout %s.\n", + keyd_log("\tWARNING: could not find default layout %s.\n", kbd->config.default_layout); } diff --git a/src/keys.c b/src/keys.c index a6579c0..f854ade 100644 --- a/src/keys.c +++ b/src/keys.c @@ -7,13 +7,12 @@ #include #include "keys.h" -const struct modifier_table_ent modifier_table[MAX_MOD] = { - {"alt", MOD_ALT, KEYD_LEFTALT, 0}, - {"altgr", MOD_ALT_GR, KEYD_RIGHTALT, 0}, - {"shift", MOD_SHIFT, KEYD_LEFTSHIFT, KEYD_RIGHTSHIFT}, - {"meta", MOD_SUPER, KEYD_LEFTMETA, KEYD_RIGHTMETA}, - - {"control", MOD_CTRL, KEYD_LEFTCTRL, KEYD_RIGHTCTRL}, +const struct modifier modifiers[MAX_MOD] = { + {MOD_ALT, KEYD_LEFTALT}, + {MOD_ALT_GR, KEYD_RIGHTALT}, + {MOD_SHIFT, KEYD_LEFTSHIFT}, + {MOD_SUPER, KEYD_LEFTMETA}, + {MOD_CTRL, KEYD_LEFTCTRL}, }; const struct keycode_table_ent keycode_table[256] = { diff --git a/src/keys.h b/src/keys.h index 9ac9ee2..8495065 100644 --- a/src/keys.h +++ b/src/keys.h @@ -24,12 +24,9 @@ struct keycode_table_ent { const char *shifted_name; }; -struct modifier_table_ent { - const char *name; +struct modifier { uint8_t mask; - - uint8_t code1; - uint8_t code2; /* May be 0. */ + uint8_t key; }; #define KEYD_ESC 1 @@ -295,7 +292,7 @@ uint8_t keycode_to_mod(uint8_t code); int parse_modset(const char *s, uint8_t *mods); int parse_key_sequence(const char *s, uint8_t *code, uint8_t *mods); -extern const struct modifier_table_ent modifier_table[MAX_MOD]; +extern const struct modifier modifiers[MAX_MOD]; extern const struct keycode_table_ent keycode_table[256]; #endif diff --git a/src/macro.c b/src/macro.c index 6a6faea..b262fbf 100644 --- a/src/macro.c +++ b/src/macro.c @@ -131,9 +131,9 @@ void macro_execute(void (*output)(uint8_t, uint8_t), code = ent->data; mods = ent->data >> 8; - for (j = 0; j < ARRAY_SIZE(modifier_table); j++) { - uint8_t code = modifier_table[j].code1; - uint8_t mask = modifier_table[j].mask; + for (j = 0; j < ARRAY_SIZE(modifiers); j++) { + uint8_t code = modifiers[j].key; + uint8_t mask = modifiers[j].mask; if (mods & mask) output(code, 1); @@ -142,14 +142,15 @@ void macro_execute(void (*output)(uint8_t, uint8_t), output(code, 1); output(code, 0); - for (j = 0; j < ARRAY_SIZE(modifier_table); j++) { - uint8_t code = modifier_table[j].code1; - uint8_t mask = modifier_table[j].mask; + for (j = 0; j < ARRAY_SIZE(modifiers); j++) { + uint8_t code = modifiers[j].key; + uint8_t mask = modifiers[j].mask; if (mods & mask) output(code, 0); } + break; case MACRO_TIMEOUT: usleep(ent->data * 1E3);