suggestion picker: a persistent layer to complement virtual keyboards like wvkbd
-rw-r--r--.gitignore1
-rw-r--r--Makefile11
-rw-r--r--README.md6
-rw-r--r--config.mk2
-rw-r--r--drw.c18
-rw-r--r--drw.h1
-rw-r--r--keyboard.c36
-rw-r--r--main.c202
-rw-r--r--os-compatibility.c201
-rw-r--r--os-compatibility.h52
-rw-r--r--suggpicker.1.scd21
11 files changed, 176 insertions, 375 deletions
diff --git a/.gitignore b/.gitignore
index f2595a2..ef21f4e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@
.gdb_history
*.log
suggpicker
+suggpicker.1
diff --git a/Makefile b/Makefile
index ac9250b..4c9f28b 100644
--- a/Makefile
+++ b/Makefile
@@ -2,10 +2,12 @@ include config.mk
NAME=suggpicker
BIN=${NAME}
+MAN=${NAME}.1
SRC=.
-PKGS = wayland-client xkbcommon pangocairo
+PKGS = wayland-client pangocairo
+PREFIX?=/usr/local
MY_SOURCES += $(wildcard $(SRC)/*.c)
MY_HEADERS += $(wildcard $(SRC)/*.h)
@@ -21,7 +23,7 @@ SOURCES = $(MY_SOURCES) $(WAYLAND_SRC)
OBJECTS = $(SOURCES:.c=.o)
-all: ${BIN}
+all: ${BIN} ${MAN}
proto/%-client-protocol.c: proto/%.xml
wayland-scanner code < $? > $@
@@ -34,6 +36,9 @@ $(OBJECTS): $(HDRS) $(MY_HEADERS)
${BIN}: config.h $(OBJECTS)
$(CC) -o ${BIN} $(OBJECTS) $(LDFLAGS)
+${MAN}: ${MAN}.scd
+ scdoc < $? > $@
+
clean:
rm -f $(OBJECTS) $(HDRS) $(WAYLAND_SRC) ${BIN}
@@ -44,3 +49,5 @@ install: all
mkdir -p ${DESTDIR}${PREFIX}/bin
cp -f ${BIN} ${DESTDIR}${PREFIX}/bin
chmod 755 ${DESTDIR}${PREFIX}/bin/${BIN}
+ mkdir -p ${DESTDIR}${PREFIX}/share/man/man1
+ cp -f ${MAN} ${DESTDIR}${PREFIX}/share/man/man1
diff --git a/README.md b/README.md
index ea2dca5..4d938e4 100644
--- a/README.md
+++ b/README.md
@@ -13,15 +13,15 @@ Each line of input is treated as TSV.
You'll need the following developer packages
- - pangocairo
+ - cairo
+ - pango
- wayland-client
- - xkbcommon
Make any customizations you would like in `config.h` and run `make`
## Usage
-The keyboard can be hidden by sending it a `SIGUSR1` signal and shown again by sending it `SIGUSR2`. This saves some
+The keyboard can be hidden by sending it a `SIGUSR1` signal, shown again by sending it `SIGUSR2`, or toggled by sending it `SIGRTMIN`. This saves some
start up time and may be appropriate in some low-resource environments.
## Contribute
diff --git a/config.mk b/config.mk
index ab39d6d..fd9f467 100644
--- a/config.mk
+++ b/config.mk
@@ -1,2 +1,2 @@
-VERSION = 0.0.1
+VERSION = 0.1.4
CFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=700
diff --git a/drw.c b/drw.c
index a7cfd20..6ea904e 100644
--- a/drw.c
+++ b/drw.c
@@ -20,31 +20,13 @@ drwsurf_resize(struct drwsurf *ds, uint32_t w, uint32_t h, uint32_t s) {
setup_buffer(ds);
}
-static void surface_frame_callback(void *data, struct wl_callback *cb,
- uint32_t time);
-
-static struct wl_callback_listener frame_listener = {.done =
- surface_frame_callback};
-
void
drwsurf_flip(struct drwsurf *ds) {
- ds->cb = wl_surface_frame(ds->surf);
- wl_callback_add_listener(ds->cb, &frame_listener, (void *)ds);
-
wl_surface_attach(ds->surf, ds->buf, 0, 0);
wl_surface_commit(ds->surf);
}
void
-surface_frame_callback(void *data, struct wl_callback *cb, uint32_t time) {
- struct drwsurf *ds = (struct drwsurf *)data;
- wl_callback_destroy(cb);
- ds->cb = NULL;
-
- drwsurf_flip(ds);
-}
-
-void
drw_draw_text(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
uint32_t w, uint32_t h, const char *label) {
diff --git a/drw.h b/drw.h
index fb3df1c..c1139f4 100644
--- a/drw.h
+++ b/drw.h
@@ -15,7 +15,6 @@ struct drwsurf {
struct wl_surface *surf;
struct wl_buffer *buf;
struct wl_shm *shm;
- struct wl_callback *cb;
unsigned char *pool_data;
cairo_t *cairo;
diff --git a/keyboard.c b/keyboard.c
index 5de8d6b..293a2f6 100644
--- a/keyboard.c
+++ b/keyboard.c
@@ -2,7 +2,6 @@
#include <sys/mman.h>
#include "keyboard.h"
#include "drw.h"
-#include "os-compatibility.h"
#define KBD_KEY_BORDER 1
@@ -15,9 +14,9 @@ void
kbd_init(struct kbd *kb) {
fprintf(stderr, "Initializing keyboard\n");
- kb->suggs[0].label = strdup("Hello");
- kb->suggs[1].label = strdup("Sugar");
- kb->suggs[2].label = strdup("Pie");
+ kb->suggs[0].label = strdup("Hey");
+ kb->suggs[1].label = strdup("Honey");
+ kb->suggs[2].label = strdup("Bunches");
kb->suggs[3].label = NULL;
}
@@ -30,11 +29,16 @@ kbd_init_suggs(struct key *suggs, uint32_t width, uint32_t height) {
struct key *k = suggs;
double rowlength = kbd_get_row_length(k);
+ uint8_t i = 0;
while (k->label != NULL) {
k->x = x;
k->y = y;
k->w = width / rowlength;
x += k->w;
+ i++;
+ if (x < (width * i) / rowlength) {
+ k->w++; x++;
+ }
k->h = keyheight;
k++;
}
@@ -69,21 +73,30 @@ kbd_unpress_key(struct kbd *kb) {
if (kb->last_press) {
kbd_draw_key(kb, kb->last_press, Unpress);
kb->last_press = NULL;
+ drwsurf_flip(kb->surf);
}
}
void
kbd_release_key(struct kbd *kb) {
- kbd_unpress_key(kb);
- printf("\n");
- // Important so autocompleted words get typed in time
- fflush(stdout);
- kbd_draw_layout(kb);
+ if (kb->last_press) {
+ printf("%s\n", kb->last_press->label);
+ // Important so autocompleted words get typed in time
+ fflush(stdout);
+ kbd_unpress_key(kb);
+ }
}
void
kbd_motion_key(struct kbd *kb, uint32_t x, uint32_t y) {
-
+ struct key *next_key;
+ next_key = kbd_get_key(kb, x, y);
+ if (next_key != kb->last_press) {
+ kbd_unpress_key(kb);
+ if (next_key) {
+ kbd_press_key(kb, next_key);
+ }
+ }
}
void
@@ -91,8 +104,7 @@ kbd_press_key(struct kbd *kb, struct key *k) {
if (k->label) {
kb->last_press = k;
kbd_draw_key(kb, k, Press);
- printf("%s", k->label);
- fflush(stdout);
+ drwsurf_flip(kb->surf);
}
}
diff --git a/main.c b/main.c
index b05dd08..848041b 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>
@@ -17,7 +18,7 @@
exit(1)
/* client state */
-static const char *namespace = "wlroots";
+static const char *namespace = "suggpicker";
static struct wl_display *display;
static struct wl_compositor *compositor;
static struct wl_seat *seat;
@@ -43,6 +44,7 @@ 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;
+static bool hidden = false;
/* event handler prototypes */
static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer,
@@ -141,18 +143,12 @@ void
wl_touch_down(void *data, struct wl_touch *wl_touch, uint32_t serial,
uint32_t time, struct wl_surface *surface, int32_t id,
wl_fixed_t x, wl_fixed_t y) {
- struct key *next_key;
uint32_t touch_x, touch_y;
touch_x = wl_fixed_to_int(x);
touch_y = wl_fixed_to_int(y);
- kbd_unpress_key(&keyboard);
-
- next_key = kbd_get_key(&keyboard, touch_x, touch_y);
- if (next_key) {
- kbd_press_key(&keyboard, next_key);
- }
+ kbd_motion_key(&keyboard, touch_x, touch_y);
}
void
@@ -211,7 +207,6 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time,
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;
cur_press = state == WL_POINTER_BUTTON_STATE_PRESSED;
if (cur_press) {
@@ -221,10 +216,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial,
}
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);
- }
+ kbd_motion_key(&keyboard, cur_x, cur_y);
}
}
@@ -248,19 +240,27 @@ static void
display_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
int physical_width, int physical_height, int subpixel,
const char *make, const char *model, int transform) {
- if (transform % 2 == 0 && keyboard.landscape) {
- keyboard.landscape = false;
- height = normal_height;
- } else if (transform % 2 != 0 && !keyboard.landscape) {
- keyboard.landscape = true;
+ // Swap width and height on rotated displays
+ if (transform % 2 != 0) {
+ int tmp = physical_width;
+ physical_width = physical_height;
+ physical_height = tmp;
+ }
+ bool landscape = physical_width > physical_height;
+ if (landscape == keyboard.landscape)
+ return;
+ keyboard.landscape = landscape;
+ if (keyboard.landscape) {
height = landscape_height;
} else {
- return; // no changes
+ height = normal_height;
}
- zwlr_layer_surface_v1_set_size(layer_surface, 0, height);
- zwlr_layer_surface_v1_set_exclusive_zone(layer_surface, height);
- wl_surface_commit(draw_surf.surf);
+ if (layer_surface) {
+ zwlr_layer_surface_v1_set_size(layer_surface, 0, height);
+ zwlr_layer_surface_v1_set_exclusive_zone(layer_surface, height);
+ wl_surface_commit(draw_surf.surf);
+ }
}
static void
@@ -300,7 +300,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);
-
}
}
@@ -310,11 +309,16 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {}
void
layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface,
uint32_t serial, uint32_t w, uint32_t h) {
- keyboard.w = w;
- keyboard.h = h;
- kbd_resize(&keyboard);
+ if (w != keyboard.w || h != keyboard.h || hidden) {
+ keyboard.w = w;
+ keyboard.h = h;
+ kbd_resize(&keyboard);
+ hidden = false;
+ }
zwlr_layer_surface_v1_ack_configure(surface, serial);
+
+ drwsurf_flip(&draw_surf);
}
void
@@ -339,24 +343,26 @@ usage(char *argv0) {
void
hide(int sigint) {
- 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;
- if (draw_surf.cb) {
- wl_callback_destroy(draw_surf.cb);
- draw_surf.cb = NULL;
- }
+ hidden = true;
}
void
show(int sigint) {
- signal(SIGUSR2, show);
+ if (keyboard.debug)
+ fprintf(stderr, "showing keyboard\n");
if (layer_surface) {
+ if (keyboard.debug)
+ fprintf(stderr, "already shown\n");
return;
}
@@ -374,12 +380,19 @@ 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);
}
void
+toggle_visibility(int sigint) {
+ if (keyboard.debug)
+ fprintf(stderr, "toggling visibility\n");
+ if (hidden) {
+ show(sigint);
+ } else {
+ hide(sigint);
+ }
+}
+void
handle_input(FILE *fd, struct key *sugg, struct kbd *kb) {
char *line;
line = malloc(1024);
@@ -389,29 +402,35 @@ 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;
kbd_init_suggs(sugg, kb->w, kb->h);
kbd_draw_layout(kb);
+ drwsurf_flip(kb->surf);
}
free(line);
}
+void
+pipewarn(int sigint) {
+ fprintf(stderr, "suggpicker: cannot pipe data out.\n");
+}
+
int
main(int argc, char **argv) {
/* parse command line arguments */
@@ -422,21 +441,14 @@ main(int argc, char **argv) {
/* keyboard settings */
keyboard.scheme = scheme;
- bool starthidden = false;
-
int i;
for (i = 1; argv[i]; i++) {
if ((!strcmp(argv[i], "-v")) || (!strcmp(argv[i], "--version"))) {
- printf("suggpicker-%s", VERSION);
+ printf("suggpicker-%s\n", VERSION);
exit(0);
} else if ((!strcmp(argv[i], "-h")) || (!strcmp(argv[i], "--help"))) {
usage(argv[0]);
exit(0);
- } else if (!strcmp(argv[i], "-l")) {
- if (i >= argc - 1) {
- usage(argv[0]);
- exit(1);
- }
} else if (!strcmp(argv[i], "-H")) {
if (i >= argc - 1) {
usage(argv[0]);
@@ -455,7 +467,7 @@ main(int argc, char **argv) {
fc_font_pattern = estrdup(argv[++i]);
} else if ((!strcmp(argv[i], "-hidden")) ||
(!strcmp(argv[i], "--hidden"))) {
- starthidden = true;
+ hidden = true;
} else {
fprintf(stderr, "Invalid argument: %s\n", argv[i]);
usage(argv[0]);
@@ -494,49 +506,69 @@ main(int argc, char **argv) {
draw_ctx.font_description =
pango_font_description_from_string(fc_font_pattern);
- if (!starthidden) {
- draw_surf.surf = wl_compositor_create_surface(compositor);
-
- layer_surface = zwlr_layer_shell_v1_get_layer_surface(
- layer_shell, draw_surf.surf, wl_output, layer, namespace);
+ if (!hidden) {
+ show(0);
+ }
- zwlr_layer_surface_v1_set_size(layer_surface, 0, height);
- zwlr_layer_surface_v1_set_anchor(layer_surface, anchor);
- zwlr_layer_surface_v1_set_exclusive_zone(layer_surface, height);
- zwlr_layer_surface_v1_set_keyboard_interactivity(layer_surface, false);
- zwlr_layer_surface_v1_add_listener(layer_surface, &layer_surface_listener,
- NULL);
- wl_surface_commit(draw_surf.surf);
+ // We need a more complicated event loop than wayland's default.
+ 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);
+ }
- wl_display_roundtrip(display);
- drwsurf_flip(&draw_surf);
+ 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);
}
- signal(SIGUSR1, hide);
- signal(SIGUSR2, show);
+ fds[STDIN_FD].fd = STDIN_FILENO;
- // 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;
- // Initial dispatch so that bar appears (and can take events).
- wl_display_dispatch(display);
while (run_display) {
- while(layer_surface && poll(fds, 2, -1) != -1) {
- if (fds[0].revents & POLLIN) {
- handle_input(stdin, keyboard.suggs, &keyboard);
- }
- if (wl_display_dispatch(display) == -1) {
- break;
- }
- 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 (fds[WAYLAND_FD].revents & POLLIN) {
+ wl_display_dispatch(display);
}
- wl_display_roundtrip(display);
- while (run_display && !layer_surface) {
- // Hidden
- sleep(1);
+ if (fds[WAYLAND_FD].revents & POLLERR) {
+ die("Exceptional condition on wayland socket.\n");
+ }
+ if (fds[WAYLAND_FD].revents & POLLHUP) {
+ die("Wayland socket has been disconnected.\n");
+ }
+
+ 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);
}
}
diff --git a/os-compatibility.c b/os-compatibility.c
deleted file mode 100644
index 93f744b..0000000
--- a/os-compatibility.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright © 2012 Collabora, Ltd.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/epoll.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "os-compatibility.h"
-
-int
-os_fd_set_cloexec(int fd) {
- long flags;
-
- if (fd == -1)
- return -1;
-
- flags = fcntl(fd, F_GETFD);
- if (flags == -1)
- return -1;
-
- if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
- return -1;
-
- return 0;
-}
-
-static int
-set_cloexec_or_close(int fd) {
- if (os_fd_set_cloexec(fd) != 0) {
- close(fd);
- return -1;
- }
- return fd;
-}
-
-int
-os_socketpair_cloexec(int domain, int type, int protocol, int *sv) {
- int ret;
-
-#ifdef SOCK_CLOEXEC
- ret = socketpair(domain, type | SOCK_CLOEXEC, protocol, sv);
- if (ret == 0 || errno != EINVAL)
- return ret;
-#endif
-
- ret = socketpair(domain, type, protocol, sv);
- if (ret < 0)
- return ret;
-
- sv[0] = set_cloexec_or_close(sv[0]);
- sv[1] = set_cloexec_or_close(sv[1]);
-
- if (sv[0] != -1 && sv[1] != -1)
- return 0;
-
- close(sv[0]);
- close(sv[1]);
- return -1;
-}
-
-int
-os_epoll_create_cloexec(void) {
- int fd;
-
-#ifdef EPOLL_CLOEXEC
- fd = epoll_create1(EPOLL_CLOEXEC);
- if (fd >= 0)
- return fd;
- if (errno != EINVAL)
- return -1;
-#endif
-
- fd = epoll_create(1);
- return set_cloexec_or_close(fd);
-}
-
-static int
-create_tmpfile_cloexec(char *tmpname) {
- int fd;
-
-#ifdef HAVE_MKOSTEMP
- fd = mkostemp(tmpname, O_CLOEXEC);
- if (fd >= 0)
- unlink(tmpname);
-#else
- fd = mkstemp(tmpname);
- if (fd >= 0) {
- fd = set_cloexec_or_close(fd);
- unlink(tmpname);
- }
-#endif
-
- return fd;
-}
-
-/*
- * Create a new, unique, anonymous file of the given size, and
- * return the file descriptor for it. The file descriptor is set
- * CLOEXEC. The file is immediately suitable for mmap()'ing
- * the given size at offset zero.
- *
- * The file should not have a permanent backing store like a disk,
- * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
- *
- * The file name is deleted from the file system.
- *
- * The file is suitable for buffer sharing between processes by
- * transmitting the file descriptor over Unix sockets using the
- * SCM_RIGHTS methods.
- *
- * If the C library implements posix_fallocate(), it is used to
- * guarantee that disk space is available for the file at the
- * given size. If disk space is insufficient, errno is set to ENOSPC.
- * If posix_fallocate() is not supported, program may receive
- * SIGBUS on accessing mmap()'ed file contents instead.
- */
-int
-os_create_anonymous_file(off_t size) {
- static const char template[] = "/weston-shared-XXXXXX";
- const char *path;
- char *name;
- int fd;
- int ret;
-
- path = getenv("XDG_RUNTIME_DIR");
- if (!path) {
- errno = ENOENT;
- return -1;
- }
-
- name = malloc(strlen(path) + sizeof(template));
- if (!name)
- return -1;
-
- strcpy(name, path);
- strcat(name, template);
-
- fd = create_tmpfile_cloexec(name);
-
- free(name);
-
- if (fd < 0)
- return -1;
-
-#ifdef HAVE_POSIX_FALLOCATE
- do {
- ret = posix_fallocate(fd, 0, size);
- } while (ret == EINTR);
- if (ret != 0) {
- close(fd);
- errno = ret;
- return -1;
- }
-#else
- do {
- ret = ftruncate(fd, size);
- } while (ret < 0 && errno == EINTR);
- if (ret < 0) {
- close(fd);
- return -1;
- }
-#endif
-
- return fd;
-}
-
-#ifndef MISSING_STRCHRNUL
-char *
-strchrnul(const char *s, int c) {
- while (*s && *s != c)
- s++;
- return (char *)s;
-}
-#endif
diff --git a/os-compatibility.h b/os-compatibility.h
deleted file mode 100644
index 80e7627..0000000
--- a/os-compatibility.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright © 2012 Collabora, Ltd.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef OS_COMPATIBILITY_H
-#define OS_COMPATIBILITY_H
-
-#include <sys/types.h>
-
-#ifdef HAVE_EXECINFO_H
-#include <execinfo.h>
-#else
-static inline int
-backtrace(void **buffer, int size) {
- return 0;
-}
-#endif
-
-int os_fd_set_cloexec(int fd);
-
-int os_socketpair_cloexec(int domain, int type, int protocol, int *sv);
-
-int os_epoll_create_cloexec(void);
-
-int os_create_anonymous_file(off_t size);
-
-#ifdef MISSING_STRCHRNUL
-char *strchrnul(const char *s, int c);
-#endif
-
-#endif /* OS_COMPATIBILITY_H */
diff --git a/suggpicker.1.scd b/suggpicker.1.scd
new file mode 100644
index 0000000..9800255
--- /dev/null
+++ b/suggpicker.1.scd
@@ -0,0 +1,21 @@
+suggpicker(1)
+
+# NAME
+suggpicker - floating bar for making decisions
+
+# SYNOPSIS
+
+suggpicker < choices.sock > selection.sock
+
+wvkbd -O | swipeGuess words.txt 5 | *suggpicker* | completelyTypeWord.sh
+
+# DESCRIPTION
+
+*suggpicker* is a persistent dynamic menu for Wayland.
+
+Each line of tab-separated choices it reads changes the choices on the bar. Choices which are clicked or tapped will be outputted into stdout, so it can be processed by another program.
+
+It's made to be used in conjunction with a virtual keyboard, which it will float above or below.
+
+# SEE ALSO
+*bemenu*(1) *swipeGuess*(1) *wvkbd*(1) *SwipeBehavior*(7)