Streamline menu callbacks - wmenu - 🔧 fork of wmenu
 (HTM) git clone git@git.drkhsh.at/wmenu.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 7d717b3696e8295f1236bb5c6c69417f14394883
 (DIR) parent a0df7959f9182a87a833d0a7f653f5ac8a2b5d0e
 (HTM) Author: adnano <me@adnano.co>
       Date:   Sun,  9 Jun 2024 20:30:58 -0400
       
       Streamline menu callbacks
       
       Diffstat:
         M menu.c                              |      15 ++++-----------
         M menu.h                              |       7 +++++--
         M wayland.c                           |       3 +--
         M wmenu-run.c                         |      42 ++++++++++++++++---------------
         M wmenu.c                             |      11 ++++++++++-
       
       5 files changed, 42 insertions(+), 36 deletions(-)
       ---
 (DIR) diff --git a/menu.c b/menu.c
       @@ -22,7 +22,7 @@
        #include "wayland.h"
        
        // Creates and returns a new menu.
       -struct menu *menu_create() {
       +struct menu *menu_create(menu_callback callback) {
                struct menu *menu = calloc(1, sizeof(struct menu));
                menu->strncmp = strncmp;
                menu->font = "monospace 10";
       @@ -32,6 +32,7 @@ struct menu *menu_create() {
                menu->promptfg = 0xeeeeeeff;
                menu->selectionbg = 0x005577ff;
                menu->selectionfg = 0xeeeeeeff;
       +        menu->callback = callback;
                return menu;
        }
        
       @@ -571,18 +572,10 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
                case XKB_KEY_Return:
                case XKB_KEY_KP_Enter:
                        if (shift) {
       -                        puts(menu->input);
       -                        fflush(stdout);
       -                        menu->exit = true;
       -                } else if (menu->callback) {
       -                        menu->callback(menu);
       +                        menu->callback(menu, menu->input, true);
                        } else {
                                char *text = menu->sel ? menu->sel->text : menu->input;
       -                        puts(text);
       -                        fflush(stdout);
       -                        if (!ctrl) {
       -                                menu->exit = true;
       -                        }
       +                        menu->callback(menu, text, !ctrl);
                        }
                        break;
                case XKB_KEY_Left:
 (DIR) diff --git a/menu.h b/menu.h
       @@ -6,6 +6,9 @@
        #include <xkbcommon/xkbcommon.h>
        #include <wayland-client.h>
        
       +struct menu;
       +typedef void (*menu_callback)(struct menu *menu, char *text, bool exit);
       +
        // A menu item.
        struct item {
                char *text;
       @@ -68,12 +71,12 @@ struct menu {
                struct item *sel;         // selected item
                struct page *pages;       // list of pages
        
       -        void (*callback)(struct menu *menu);
       +        menu_callback callback;
                bool exit;
                bool failure;
        };
        
       -struct menu *menu_create();
       +struct menu *menu_create(menu_callback callback);
        void menu_destroy(struct menu *menu);
        void menu_getopts(struct menu *menu, int argc, char *argv[]);
        void menu_add_item(struct menu *menu, char *text, bool sort);
 (DIR) diff --git a/wayland.c b/wayland.c
       @@ -494,11 +494,10 @@ int menu_run(struct menu *menu) {
                        }
                }
        
       -        bool failure = menu->failure;
                context_destroy(context);
                menu->context = NULL;
        
       -        if (failure) {
       +        if (menu->failure) {
                        return EXIT_FAILURE;
                }
                return EXIT_SUCCESS;
 (DIR) diff --git a/wmenu-run.c b/wmenu-run.c
       @@ -1,6 +1,6 @@
        #define _POSIX_C_SOURCE 200809L
        #include <dirent.h>
       -#include <errno.h>
       +#include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        #include <unistd.h>
       @@ -27,46 +27,48 @@ static void read_items(struct menu *menu) {
                free(path);
        }
        
       -struct executable {
       +struct command {
                struct menu *menu;
       -        char *name;
       +        char *text;
       +        bool exit;
        };
        
        static void activation_token_done(void *data, struct xdg_activation_token_v1 *activation_token,
                const char *token) {
       -        struct executable *exe = data;
       +        struct command *cmd = data;
                xdg_activation_token_v1_destroy(activation_token);
       -        menu_destroy(exe->menu);
        
       -        setenv("XDG_ACTIVATION_TOKEN", token, true);
       -        char* cmd[] = {"/bin/sh", "-c", exe->name, NULL};
       -        execvp(cmd[0], (char**)cmd);
       -
       -        fprintf(stderr, "Failed to execute selection: %s\n", strerror(errno));
       -        free(exe->name);
       -        free(exe);
       -        exit(EXIT_FAILURE);
       +        int pid = fork();
       +        if (pid == 0) {
       +                setenv("XDG_ACTIVATION_TOKEN", token, true);
       +                char *argv[] = {"/bin/sh", "-c", cmd->text, NULL};
       +                execvp(argv[0], (char**)argv);
       +        } else {
       +                if (cmd->exit) {
       +                        cmd->menu->exit = true;
       +                }
       +        }
        }
        
        static const struct xdg_activation_token_v1_listener activation_token_listener = {
                .done = activation_token_done,
        };
        
       -static void exec(struct menu *menu) {
       -        struct executable *exe = calloc(1, sizeof(struct executable));
       -        exe->menu = menu;
       -        exe->name = strdup(menu->input);
       +static void exec_item(struct menu *menu, char *text, bool exit) {
       +        struct command *cmd = calloc(1, sizeof(struct command));
       +        cmd->menu = menu;
       +        cmd->text = strdup(text);
       +        cmd->exit = exit;
        
                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_add_listener(activation_token, &activation_token_listener, cmd);
                xdg_activation_token_v1_commit(activation_token);
        }
        
        int main(int argc, char *argv[]) {
       -        struct menu *menu = menu_create();
       -        menu->callback = exec;
       +        struct menu *menu = menu_create(exec_item);
                menu_getopts(menu, argc, argv);
                read_items(menu);
                int status = menu_run(menu);
 (DIR) diff --git a/wmenu.c b/wmenu.c
       @@ -1,5 +1,6 @@
        #define _POSIX_C_SOURCE 200809L
        
       +#include <stdio.h>
        #include <string.h>
        
        #include "menu.h"
       @@ -16,8 +17,16 @@ static void read_items(struct menu *menu) {
                }
        }
        
       +static void print_item(struct menu *menu, char *text, bool exit) {
       +        puts(text);
       +        fflush(stdout);
       +        if (exit) {
       +                menu->exit = true;
       +        }
       +}
       +
        int main(int argc, char *argv[]) {
       -        struct menu *menu = menu_create();
       +        struct menu *menu = menu_create(print_item);
                menu_getopts(menu, argc, argv);
                read_items(menu);
                int status = menu_run(menu);