summary refs log tree commit diff
path: root/main.c
diff options
context:
space:
mode:
authorZach DeCook <zachdecook@librem.one>2024-01-14 15:50:05 -0500
committerZach DeCook <zachdecook@librem.one>2024-01-14 15:50:05 -0500
commit926b67f1e30771d47510a91cf19a0243e2ac0eb5 (patch)
treea694752a7314652cc4dd0d851922f79934c90157 /main.c
parentc8e912cff4b548a134f72661ef6bb62290acc4a7 (diff)
downloadsuggpicker-926b67f1e30771d47510a91cf19a0243e2ac0eb5.tar.gz
Fix toggling hide/show by copying wvkbd's example event loop
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);
 		}
 	}