suggestion picker: a persistent layer to complement virtual keyboards like wvkbd
Diffstat (limited to 'main.c')
-rw-r--r--main.c113
1 files changed, 68 insertions, 45 deletions
diff --git a/main.c b/main.c
index 2193713..bf8a81a 100644
--- a/main.c
+++ b/main.c
@@ -4,6 +4,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
+#include <sys/signalfd.h>
#include <unistd.h>
#include <wayland-client.h>
#include <wchar.h>
@@ -246,7 +247,8 @@ display_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
physical_height = tmp;
}
bool landscape = physical_width > physical_height;
- if (landscape == keyboard.landscape) return;
+ if (landscape == keyboard.landscape)
+ return;
keyboard.landscape = landscape;
if (keyboard.landscape) {
height = landscape_height;
@@ -296,7 +298,6 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name,
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
layer_shell =
wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 1);
-
}
}
@@ -340,25 +341,26 @@ usage(char *argv0) {
void
hide(int sigint) {
- if(keyboard.debug) fprintf(stderr, "hiding keyboard\n");
- signal(SIGUSR1, hide);
+ if (keyboard.debug)
+ fprintf(stderr, "hiding keyboard\n");
if (!layer_surface) {
+ if (keyboard.debug)
+ fprintf(stderr, "can't hide nothing\n");
return;
}
-
zwlr_layer_surface_v1_destroy(layer_surface);
wl_surface_destroy(draw_surf.surf);
layer_surface = NULL;
hidden = true;
- // dispatch to make it disappear
- wl_display_dispatch(display);
}
void
show(int sigint) {
- if(keyboard.debug) fprintf(stderr, "showing keyboard\n");
- signal(SIGUSR2, show);
+ if (keyboard.debug)
+ fprintf(stderr, "showing keyboard\n");
if (layer_surface) {
+ if (keyboard.debug)
+ fprintf(stderr, "already shown\n");
return;
}
@@ -376,16 +378,12 @@ show(int sigint) {
zwlr_layer_surface_v1_add_listener(layer_surface, &layer_surface_listener,
NULL);
wl_surface_commit(draw_surf.surf);
-
- wl_display_roundtrip(display);
- drwsurf_flip(&draw_surf);
- // Dispatch so that bar appears (and can take events).
- wl_display_dispatch(display);
}
-void toggle_visibility(int sigint) {
- if(keyboard.debug) fprintf(stderr, "toggling visibility\n");
- signal(SIGRTMIN, toggle_visibility);
+void
+toggle_visibility(int sigint) {
+ if (keyboard.debug)
+ fprintf(stderr, "toggling visibility\n");
if (hidden) {
show(sigint);
} else {
@@ -402,19 +400,19 @@ handle_input(FILE *fd, struct key *sugg, struct kbd *kb) {
int i;
struct key *key = sugg;
char *l = line;
- for (i = 0; l[i+1]; i++) {
+ for (i = 0; l[i + 1]; i++) {
if (l[i] == '\t') {
free(key->label);
- key->label = strndup(l,i);
+ key->label = strndup(l, i);
l += i + 1;
i = 0;
key++;
} else if (l[i] == '\n') {
break;
}
- }
+ }
free(key->label);
- key->label = strndup(l,i);
+ key->label = strndup(l, i);
key++;
free(key->label);
key->label = NULL;
@@ -508,36 +506,61 @@ main(int argc, char **argv) {
if (!hidden) {
show(0);
- } else {
- signal(SIGUSR2, show);
}
- signal(SIGUSR1, hide);
- signal(SIGPIPE, pipewarn);
- signal(SIGRTMIN, toggle_visibility);
-
// We need a more complicated event loop than wayland's default.
- struct pollfd fds[2];
- fds[0].fd = STDIN_FILENO;
- fds[0].events = POLLIN;
- fds[1].fd = wl_display_get_fd(display);
- fds[1].events = POLLIN;
+ struct pollfd fds[3];
+ int WAYLAND_FD = 0;
+ int SIGNAL_FD = 1;
+ int STDIN_FD = 2;
+ fds[WAYLAND_FD].events = POLLIN;
+ fds[SIGNAL_FD].events = POLLIN;
+ fds[STDIN_FD].events = POLLIN;
+
+ fds[WAYLAND_FD].fd = wl_display_get_fd(display);
+ if (fds[WAYLAND_FD].fd == -1) {
+ die("Failed to get wayland_fd: %d\n", errno);
+ }
+
+ sigset_t signal_mask;
+ sigemptyset(&signal_mask);
+ sigaddset(&signal_mask, SIGUSR1);
+ sigaddset(&signal_mask, SIGUSR2);
+ sigaddset(&signal_mask, SIGRTMIN);
+ sigaddset(&signal_mask, SIGPIPE);
+ if (sigprocmask(SIG_BLOCK, &signal_mask, NULL) == -1) {
+ die("Failed to disable handled signals: %d\n", errno);
+ }
+ fds[SIGNAL_FD].fd = signalfd(-1, &signal_mask, 0);
+ if (fds[SIGNAL_FD].fd == -1) {
+ die("Failed to get signalfd: %d\n", errno);
+ }
+
+ fds[STDIN_FD].fd = STDIN_FILENO;
+
while (run_display) {
- while(layer_surface && poll(fds, 2, -1) != -1) {
- if (fds[0].revents & POLLIN) {
- handle_input(stdin, keyboard.suggs, &keyboard);
- } else if(fds[1].revents & POLLIN) {
- //error check?
- wl_display_dispatch(display);
- }
- wl_display_flush(display);
+ wl_display_flush(display);
+ poll(fds, 3, -1);
+ if (fds[STDIN_FD].revents & POLLIN) {
+ handle_input(stdin, keyboard.suggs, &keyboard);
}
- if (layer_surface){
- wl_display_roundtrip(display);
+ if (fds[WAYLAND_FD].revents & POLLIN) {
+ wl_display_dispatch(display);
}
- while (run_display && !layer_surface) {
- // Hidden
- sleep(1);
+
+ if (fds[SIGNAL_FD].revents & POLLIN) {
+ struct signalfd_siginfo si;
+
+ if (read(fds[SIGNAL_FD].fd, &si, sizeof(si)) != sizeof(si))
+ fprintf(stderr, "Signal read error: %d", errno);
+ else if (si.ssi_signo == SIGUSR1)
+ hide(0);
+ else if (si.ssi_signo == SIGUSR2)
+ show(0);
+ else if (si.ssi_signo == SIGRTMIN)
+ toggle_visibility(0);
+ else if (si.ssi_signo == SIGPIPE)
+ pipewarn(0);
}
}