diff options
author | Phil Jones <philj56@gmail.com> | 2023-07-16 15:18:46 +0100 |
---|---|---|
committer | Phil Jones <philj56@gmail.com> | 2023-07-16 15:18:46 +0100 |
commit | 47a7f68cd03948035617b83b31349330ae8e55dc (patch) | |
tree | 2eac35d6fbce7d19782389f92180def6a80cb062 | |
parent | 0f1b2a8cf196f4661fbf7bdd54f818fbba8cf8c9 (diff) |
Add --physical-keybindings option.
-rw-r--r-- | completions/tofi | 1 | ||||
-rw-r--r-- | doc/config | 4 | ||||
-rw-r--r-- | doc/tofi.5.md | 7 | ||||
-rw-r--r-- | doc/tofi.5.scd | 6 | ||||
-rw-r--r-- | src/config.c | 5 | ||||
-rw-r--r-- | src/input.c | 113 | ||||
-rw-r--r-- | src/main.c | 2 | ||||
-rw-r--r-- | src/tofi.h | 1 |
8 files changed, 115 insertions, 24 deletions
diff --git a/completions/tofi b/completions/tofi index 38ef388..55c5707 100644 --- a/completions/tofi +++ b/completions/tofi @@ -83,6 +83,7 @@ _tofi() --print-index --hide-input --hidden-character + --physical-keybindings --drun-launch --terminal --hint-font @@ -277,6 +277,10 @@ # This option only has an effect when hide-input is set to true. hidden-character = "*" + # If true, use physical keys for shortcuts, regardless of the current + # keyboard layout. If false, use the current layout's keys. + physical-keybindings = true + # Instead of printing the selected entry, print the 1-based index of # the selection. This option has no effect in run or drun mode. If # require-match is set to false, non-matching input will still result diff --git a/doc/tofi.5.md b/doc/tofi.5.md index 3656143..5065752 100644 --- a/doc/tofi.5.md +++ b/doc/tofi.5.md @@ -117,6 +117,13 @@ options. > > Default: \* +**physical-keybindings**=*true\|false* + +> If true, use physical keys for shortcuts, regardless of the current +> keyboard layout. If false, use the current layout's keys. +> +> Default: true + **print-index**=*true\|false* > Instead of printing the selected entry, print the 1-based index of the diff --git a/doc/tofi.5.scd b/doc/tofi.5.scd index de564c5..59f5779 100644 --- a/doc/tofi.5.scd +++ b/doc/tofi.5.scd @@ -109,6 +109,12 @@ options. Default: \* +*physical-keybindings*=_true|false_ + If true, use physical keys for shortcuts, regardless of the current + keyboard layout. If false, use the current layout's keys. + + Default: true + *print-index*=_true|false_ Instead of printing the selected entry, print the 1-based index of the selection. This option has no effect in run or drun mode. If diff --git a/src/config.c b/src/config.c index c0ede7a..52e14d8 100644 --- a/src/config.c +++ b/src/config.c @@ -724,6 +724,11 @@ bool parse_option(struct tofi *tofi, const char *filename, size_t lineno, const tofi->window.entry.hidden_character_utf8_length = utf32_to_utf8(ch, tofi->window.entry.hidden_character_utf8); } + } else if (strcasecmp(option, "physical-keybindings") == 0) { + bool val = parse_bool(filename, lineno, value, &err); + if (!err) { + tofi->physical_keybindings = val; + } } else if (strcasecmp(option, "drun-launch") == 0) { bool val = parse_bool(filename, lineno, value, &err); if (!err) { diff --git a/src/input.c b/src/input.c index fe777f6..58154a7 100644 --- a/src/input.c +++ b/src/input.c @@ -9,6 +9,7 @@ #include "unicode.h" +static uint32_t keysym_to_key(xkb_keysym_t sym); static void add_character(struct tofi *tofi, xkb_keycode_t keycode); static void delete_character(struct tofi *tofi); static void delete_word(struct tofi *tofi); @@ -28,13 +29,6 @@ void input_handle_keypress(struct tofi *tofi, xkb_keycode_t keycode) return; } - /* - * Use physical key code for shortcuts, ignoring layout changes. - * Linux keycodes are 8 less than XKB keycodes. - */ - const uint32_t key = keycode - 8; - - xkb_keysym_t sym = xkb_state_key_get_one_sym(tofi->xkb_state, keycode); bool ctrl = xkb_state_mod_name_is_active( tofi->xkb_state, XKB_MOD_NAME_CTRL, @@ -43,49 +37,64 @@ void input_handle_keypress(struct tofi *tofi, xkb_keycode_t keycode) tofi->xkb_state, XKB_MOD_NAME_ALT, XKB_STATE_MODS_EFFECTIVE); + bool shift = xkb_state_mod_name_is_active( + tofi->xkb_state, + XKB_MOD_NAME_SHIFT, + XKB_STATE_MODS_EFFECTIVE); uint32_t ch = xkb_state_key_get_utf32(tofi->xkb_state, keycode); + + /* + * Use physical key code for shortcuts by default, ignoring layout + * changes. Linux keycodes are 8 less than XKB keycodes. + */ + uint32_t key = keycode - 8; + if (!tofi->physical_keybindings) { + xkb_keysym_t sym = xkb_state_key_get_one_sym(tofi->xkb_state, keycode); + key = keysym_to_key(sym); + } + /* * Alt does not affect which character is selected, so we have to check * for it explicitly. */ - if (utf32_isprint(ch) && !alt) { + if (utf32_isprint(ch) && !ctrl && !alt) { add_character(tofi, keycode); - } else if ((sym == XKB_KEY_BackSpace || key == KEY_W) && ctrl) { + } else if ((key == KEY_BACKSPACE || key == KEY_W) && ctrl) { delete_word(tofi); - } else if (sym == XKB_KEY_BackSpace) { + } else if (key == KEY_BACKSPACE) { delete_character(tofi); } else if (key == KEY_U && ctrl) { clear_input(tofi); } else if (key == KEY_V && ctrl) { paste(tofi); - } else if (sym == XKB_KEY_Left) { + } else if (key == KEY_LEFT) { previous_cursor_or_result(tofi); - } else if (sym == XKB_KEY_Right) { + } else if (key == KEY_RIGHT) { next_cursor_or_result(tofi); - } else if (sym == XKB_KEY_Up - || sym == XKB_KEY_Left - || sym == XKB_KEY_ISO_Left_Tab + } else if (key == KEY_UP + || key == KEY_LEFT + || (key == KEY_TAB && shift) || (key == KEY_H && alt) || ((key == KEY_K || key == KEY_P) && (ctrl || alt))) { select_previous_result(tofi); - } else if (sym == XKB_KEY_Down - || sym == XKB_KEY_Right - || sym == XKB_KEY_Tab + } else if (key == KEY_DOWN + || key == KEY_RIGHT + || key == KEY_TAB || (key == KEY_L && alt) || ((key == KEY_J || key == KEY_N) && (ctrl || alt))) { select_next_result(tofi); - } else if (sym == XKB_KEY_Home) { + } else if (key == KEY_HOME) { reset_selection(tofi); - } else if (sym == XKB_KEY_Page_Up) { + } else if (key == KEY_PAGEUP) { select_previous_page(tofi); - } else if (sym == XKB_KEY_Page_Down) { + } else if (key == KEY_PAGEDOWN) { select_next_page(tofi); - } else if (sym == XKB_KEY_Escape + } else if (key == KEY_ESC || ((key == KEY_C || key == KEY_LEFTBRACE) && ctrl)) { tofi->closed = true; return; - } else if (sym == XKB_KEY_Return || sym == XKB_KEY_KP_Enter) { + } else if (key == KEY_ENTER || key == KEY_KPENTER) { tofi->submit = true; return; } @@ -97,7 +106,63 @@ void input_handle_keypress(struct tofi *tofi, xkb_keycode_t keycode) tofi->window.surface.redraw = true; } -void reset_selection(struct tofi *tofi) { +static uint32_t keysym_to_key(xkb_keysym_t sym) +{ + switch (sym) { + case XKB_KEY_BackSpace: + return KEY_BACKSPACE; + case XKB_KEY_w: + return KEY_W; + case XKB_KEY_u: + return KEY_U; + case XKB_KEY_v: + return KEY_V; + case XKB_KEY_Left: + return KEY_LEFT; + case XKB_KEY_Right: + return KEY_RIGHT; + case XKB_KEY_Up: + return KEY_UP; + case XKB_KEY_ISO_Left_Tab: + return KEY_TAB; + case XKB_KEY_h: + return KEY_H; + case XKB_KEY_k: + return KEY_K; + case XKB_KEY_p: + return KEY_P; + case XKB_KEY_Down: + return KEY_DOWN; + case XKB_KEY_Tab: + return KEY_TAB; + case XKB_KEY_l: + return KEY_L; + case XKB_KEY_j: + return KEY_J; + case XKB_KEY_n: + return KEY_N; + case XKB_KEY_Home: + return KEY_HOME; + case XKB_KEY_Page_Up: + return KEY_PAGEUP; + case XKB_KEY_Page_Down: + return KEY_PAGEDOWN; + case XKB_KEY_Escape: + return KEY_ESC; + case XKB_KEY_c: + return KEY_C; + case XKB_KEY_bracketleft: + return KEY_LEFTBRACE; + case XKB_KEY_Return: + return KEY_ENTER; + case XKB_KEY_KP_Enter: + return KEY_KPENTER; + } + return (uint32_t)-1; +} + +void reset_selection(struct tofi *tofi) +{ struct entry *entry = &tofi->window.entry; entry->selection = 0; entry->first_result = 0; @@ -917,6 +917,7 @@ const struct option long_options[] = { {"print-index", required_argument, NULL, 0}, {"hide-input", required_argument, NULL, 0}, {"hidden-character", required_argument, NULL, 0}, + {"physical-keybindings", required_argument, NULL, 0}, {"drun-launch", required_argument, NULL, 0}, {"drun-print-exec", required_argument, NULL, 0}, {"terminal", required_argument, NULL, 0}, @@ -1198,6 +1199,7 @@ int main(int argc, char *argv[]) .use_history = true, .require_match = true, .use_scale = true, + .physical_keybindings = true, }; wl_list_init(&tofi.output_list); if (getenv("TERMINAL") != NULL) { @@ -103,6 +103,7 @@ struct tofi { bool auto_accept_single; bool print_index; bool multiple_instance; + bool physical_keybindings; char target_output_name[MAX_OUTPUT_NAME_LEN]; char default_terminal[MAX_TERMINAL_NAME_LEN]; char history_file[MAX_HISTORY_FILE_NAME_LEN]; |