diff options
-rw-r--r-- | menu.c | 2 | ||||
-rw-r--r-- | menu.h | 1 | ||||
-rw-r--r-- | meson.build | 25 | ||||
-rw-r--r-- | wayland.c | 5 | ||||
-rw-r--r-- | wayland.h | 1 | ||||
-rw-r--r-- | wmenu-run.c | 70 | ||||
-rw-r--r-- | wmenu.c (renamed from main.c) | 0 |
7 files changed, 103 insertions, 1 deletions
@@ -529,6 +529,8 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state, puts(menu->input); fflush(stdout); menu->exit = true; + } else if (menu->callback) { + menu->callback(menu); } else { char *text = menu->sel ? menu->sel->text : menu->input; puts(text); @@ -68,6 +68,7 @@ struct menu { struct item *sel; // selected item struct page *pages; // list of pages + void (*callback)(struct menu *menu); bool exit; bool failure; }; diff --git a/meson.build b/meson.build index fc4a2c0..552e1f8 100644 --- a/meson.build +++ b/meson.build @@ -38,12 +38,35 @@ install_data('wmenu_run', install_dir: get_option('bindir')) executable( 'wmenu', files( - 'main.c', 'menu.c', 'pango.c', 'pool-buffer.c', 'render.c', 'wayland.c', + 'wmenu.c', + ), + dependencies: [ + cairo, + client_protos, + pango, + pangocairo, + rt, + wayland_client, + wayland_protos, + xkbcommon, + ], + install: true, +) + +executable( + 'wmenu-run', + files( + 'menu.c', + 'pango.c', + 'pool-buffer.c', + 'render.c', + 'wayland.c', + 'wmenu-run.c', ), dependencies: [ cairo, @@ -128,6 +128,11 @@ struct xkb_state *context_get_xkb_state(struct wl_context *context) { return context->keyboard->state; } +// Returns the XDG activation object for the context. +struct xdg_activation_v1 *context_get_xdg_activation(struct wl_context *context) { + return context->activation; +} + // Retrieves pasted text from a Wayland data offer. bool context_paste(struct wl_context *context) { if (!context->data_offer) { @@ -13,6 +13,7 @@ struct pool_buffer *context_get_current_buffer(struct wl_context *context); struct pool_buffer *context_get_next_buffer(struct wl_context *context, int scale); struct wl_surface *context_get_surface(struct wl_context *context); struct xkb_state *context_get_xkb_state(struct wl_context *context); +struct xdg_activation_v1 *context_get_xdg_activation(struct wl_context *context); bool context_paste(struct wl_context *context); #endif diff --git a/wmenu-run.c b/wmenu-run.c new file mode 100644 index 0000000..fe79ece --- /dev/null +++ b/wmenu-run.c @@ -0,0 +1,70 @@ +#define _POSIX_C_SOURCE 200809L +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "menu.h" +#include "wayland.h" +#include "xdg-activation-v1-client-protocol.h" + +static void read_items(struct menu *menu) { + char buf[sizeof menu->input]; + while (fgets(buf, sizeof buf, stdin)) { + char *p = strchr(buf, '\n'); + if (p) { + *p = '\0'; + } + menu_add_item(menu, strdup(buf)); + } +} + +struct executable { + struct menu *menu; + char *name; +}; + +static void activation_token_done(void *data, struct xdg_activation_token_v1 *activation_token, + const char *token) { + struct executable *exe = data; + xdg_activation_token_v1_destroy(activation_token); + menu_destroy(exe->menu); + + setenv("XDG_ACTIVATION_TOKEN", token, true); + execlp(exe->name, exe->name, NULL); + + fprintf(stderr, "Failed to execute selection: %s\n", strerror(errno)); + free(exe->name); + free(exe); + exit(EXIT_FAILURE); +} + +static const struct xdg_activation_token_v1_listener activation_token_listener = { + .done = activation_token_done, +}; + +static void exec(struct menu *menu) { + if (!menu->sel) { + return; + } + + struct executable *exe = calloc(1, sizeof(struct executable)); + exe->menu = menu; + exe->name = strdup(menu->sel->text); + + struct xdg_activation_v1 *activation = context_get_xdg_activation(menu->context); + struct xdg_activation_token_v1 *activation_token = xdg_activation_v1_get_activation_token(activation); + xdg_activation_token_v1_set_surface(activation_token, context_get_surface(menu->context)); + xdg_activation_token_v1_add_listener(activation_token, &activation_token_listener, exe); + xdg_activation_token_v1_commit(activation_token); +} + +int main(int argc, char *argv[]) { + struct menu *menu = menu_create(); + menu->callback = exec; + menu_getopts(menu, argc, argv); + read_items(menu); + int status = menu_run(menu); + menu_destroy(menu); + return status; +} |