wvkbd

git clone https://git.tarina.org/wvkbd
Log | Files | Refs | README | LICENSE

commit 2de12a90e4989f040754c2279c1fadae6f8a48f9
parent c541c7dbd611d2dbd5bc722e495a3582c3aee9f8
Author: Zach DeCook <zachdecook@librem.one>
Date:   Thu,  2 Dec 2021 11:03:41 -0500

output: add -O flag to output overlapped keys

the use-case for this is simple 'swipe'-typing:
another program can take the output, guess the word which is being typed, and type the rest of the word

Diffstat:
MREADME.md | 8+++++++-
Mkeyboard.c | 33+++++++++++++++++++++++++++++----
Mkeyboard.h | 4++++
Mmain.c | 29++++++++++++++++++++++-------
4 files changed, 62 insertions(+), 12 deletions(-)

diff --git a/README.md b/README.md @@ -66,7 +66,12 @@ Wvkbd has an output mode `-o` that will echo its output to standard output. This audio/haptic feedback, a feature explicitly out of scope for wvkbd. To achieve this, simply pipe wvkbd's output through the external tool [clickclack](https://git.sr.ht/~proycon/clickclack): -`$ wvkbd-mobileintl -l simple,special,emoji -o | clickclack -V -f keypress.wav` +`$ wvkbd-mobintl -l simple,special,emoji -o | clickclack -V -f keypress.wav` + +Another output mode, `-O` will let the keyboard output keys which are swiped over. It can be used by an external program, such as [swipeGuess](https://git.sr.ht/~earboxer/swipeGuess) to get swipe-typing support. + +`$ wvkbd-mobintl -O | swipeGuess.sh words.txt | completelyTypeWord.sh` + ## Contribute @@ -80,6 +85,7 @@ possible. ## Related projects * [clickclack](https://git.sr.ht/~proycon/clickclack) - Audio/haptic feedback (standalone) +* [swipeGuess](https://git.sr.ht/~earboxer/swipeGuess) - Word-completion for swipe-typing * [Sxmo](https://sxmo.org) - A hackable mobile interface environment for Linux phones that adopted wvkbd as its keyboard * [svkbd](https://tools.suckless.org/x/svkbd/) - A similar project as wvkbd but for X11 rather than Wayland * [squeekboard](https://gitlab.gnome.org/World/Phosh/squeekboard) - The virtual keyboard developed for the Librem5 (used diff --git a/keyboard.c b/keyboard.c @@ -189,6 +189,31 @@ kbd_unpress_key(struct kbd *kb, uint32_t time) { } } +void kbd_release_key(struct kbd *kb, uint32_t time) { + kbd_unpress_key(kb, time); + if (kb->print_intersect && kb->last_swipe) { + printf("\n"); + // Important so autocompleted words get typed in time + fflush(stdout); + kb->last_swipe = NULL; + } +} + +void kbd_motion_key(struct kbd *kb, uint32_t time, uint32_t x, uint32_t y) { + // Output intersecting keys + // (for external 'swiping'-based accelerators). + if (kb->print_intersect) { + struct key *intersect_key; + intersect_key = kbd_get_key(kb, x, y); + if (intersect_key && + (! kb->last_swipe || intersect_key->label != kb->last_swipe->label)) { + kbd_print_key_stdout(kb, intersect_key); + kb->last_swipe = intersect_key; + } + } + kbd_unpress_key(kb, time); +} + void kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) { if ((kb->compose == 1) && (k->type != Compose) && (k->type != Mod) && @@ -212,11 +237,11 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) { } else { zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0); } - kb->last_press = k; + kb->last_swipe = kb->last_press = k; kbd_draw_key(kb, k, true); zwp_virtual_keyboard_v1_key(kb->vkbd, time, kb->last_press->code, WL_KEYBOARD_KEY_STATE_PRESSED); - if (kb->print) + if (kb->print || kb->print_intersect) kbd_print_key_stdout(kb, k); if (kb->compose) { if (kb->debug) @@ -271,7 +296,7 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) { break; case Copy: // copy code as unicode chr by setting a temporary keymap - kb->last_press = k; + kb->last_swipe = kb->last_press = k; kbd_draw_key(kb, k, true); if (kb->debug) fprintf(stderr, "pressing copy key\n"); @@ -279,7 +304,7 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) { zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0); zwp_virtual_keyboard_v1_key(kb->vkbd, time, 127, // COMP key WL_KEYBOARD_KEY_STATE_PRESSED); - if (kb->print) + if (kb->print || kb->print_intersect) kbd_print_key_stdout(kb, k); break; default: diff --git a/keyboard.h b/keyboard.h @@ -85,11 +85,13 @@ struct kbd { struct clr_scheme scheme1; bool print; + bool print_intersect; uint32_t w, h, s; bool landscape; uint8_t mods; uint8_t compose; struct key *last_press; + struct key *last_swipe; struct layout *prevlayout; size_t layer_index; @@ -108,6 +110,8 @@ void kbd_init(struct kbd *kb, struct layout *layouts, char *layer_names_list); void kbd_init_layout(struct layout *l, uint32_t width, uint32_t height); struct key *kbd_get_key(struct kbd *kb, uint32_t x, uint32_t y); void kbd_unpress_key(struct kbd *kb, uint32_t time); +void kbd_release_key(struct kbd *kb, uint32_t time); +void kbd_motion_key(struct kbd *kb, uint32_t time, uint32_t x, uint32_t y); void kbd_press_key(struct kbd *kb, struct key *k, uint32_t time); void kbd_print_key_stdout(struct kbd *kb, struct key *k); void kbd_draw_key(struct kbd *kb, struct key *k, bool pressed); diff --git a/main.c b/main.c @@ -42,6 +42,7 @@ static uint32_t anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | /* application state */ static bool run_display = true; static int cur_x = -1, cur_y = -1; +static bool cur_press = false; static struct kbd keyboard; static uint32_t height, normal_height, landscape_height; @@ -159,13 +160,18 @@ wl_touch_down(void *data, struct wl_touch *wl_touch, uint32_t serial, void wl_touch_up(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, int32_t id) { - kbd_unpress_key(&keyboard, time); + kbd_release_key(&keyboard, time); } void wl_touch_motion(void *data, struct wl_touch *wl_touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) { - kbd_unpress_key(&keyboard, time); + uint32_t touch_x, touch_y; + + touch_x = wl_fixed_to_int(x); + touch_y = wl_fixed_to_int(y); + + kbd_motion_key(&keyboard, time, touch_x, touch_y); } void @@ -199,18 +205,24 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, cur_x = wl_fixed_to_int(surface_x); cur_y = wl_fixed_to_int(surface_y); - kbd_unpress_key(&keyboard, time); + if (cur_press) { + kbd_motion_key(&keyboard, time, cur_x, cur_y); + } } void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { struct key *next_key; - bool press = state == WL_POINTER_BUTTON_STATE_PRESSED; + cur_press = state == WL_POINTER_BUTTON_STATE_PRESSED; - kbd_unpress_key(&keyboard, time); + if (cur_press) { + kbd_unpress_key(&keyboard, time); + } else { + kbd_release_key(&keyboard, time); + } - if (press && cur_x >= 0 && cur_y >= 0) { + if (cur_press && cur_x >= 0 && cur_y >= 0) { next_key = kbd_get_key(&keyboard, cur_x, cur_y); if (next_key) { kbd_press_key(&keyboard, next_key, time); @@ -335,7 +347,8 @@ usage(char *argv0) { argv0); fprintf(stderr, "Options:\n"); fprintf(stderr, " -D - Enable debug\n"); - fprintf(stderr, " -o - Print press keys to standard output\n"); + fprintf(stderr, " -o - Print pressed keys to standard output\n"); + fprintf(stderr, " -O - Print intersected keys to standard output\n"); fprintf(stderr, " -l - Comma separated list of layers\n"); fprintf(stderr, " -H [int] - Height in pixels\n"); fprintf(stderr, " -L [int] - Landscape height in pixels\n"); @@ -445,6 +458,8 @@ main(int argc, char **argv) { fc_font_pattern = estrdup(argv[++i]); } else if (!strcmp(argv[i], "-o")) { keyboard.print = true; + } else if (!strcmp(argv[i], "-O")) { + keyboard.print_intersect = true; } else if ((!strcmp(argv[i], "-hidden")) || (!strcmp(argv[i], "--hidden"))) { starthidden = true; } else {