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
This commit is contained in:
Zach DeCook 2021-12-02 11:03:41 -05:00 committed by John Sullivan
parent c541c7dbd6
commit 2de12a90e4
4 changed files with 62 additions and 12 deletions

View File

@ -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

View File

@ -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:

View File

@ -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);

29
main.c
View File

@ -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 {