wmenu-run.c - wmenu - [fork] efficient dynamic menu for wayland
 (HTM) git clone https://git.drkhsh.at/wmenu.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       wmenu-run.c (2116B)
       ---
            1 #define _POSIX_C_SOURCE 200809L
            2 #include <dirent.h>
            3 #include <stdio.h>
            4 #include <stdlib.h>
            5 #include <string.h>
            6 #include <unistd.h>
            7 
            8 #include "menu.h"
            9 #include "wayland.h"
           10 #include "xdg-activation-v1-client-protocol.h"
           11 
           12 static void read_items(struct menu *menu) {
           13         char *path = strdup(getenv("PATH"));
           14         for (char *p = strtok(path, ":"); p != NULL; p = strtok(NULL, ":")) {
           15                 DIR *dir = opendir(p);
           16                 if (dir == NULL) {
           17                         continue;
           18                 }
           19                 for (struct dirent *ent = readdir(dir); ent != NULL; ent = readdir(dir)) {
           20                         if (ent->d_name[0] == '.') {
           21                                 continue;
           22                         }
           23                         menu_add_item(menu, strdup(ent->d_name));
           24                 }
           25                 closedir(dir);
           26         }
           27         menu_sort_and_deduplicate(menu);
           28         free(path);
           29 }
           30 
           31 struct command {
           32         struct menu *menu;
           33         char *text;
           34         bool exit;
           35 };
           36 
           37 static void activation_token_done(void *data, struct xdg_activation_token_v1 *activation_token,
           38         const char *token) {
           39         struct command *cmd = data;
           40         xdg_activation_token_v1_destroy(activation_token);
           41 
           42         int pid = fork();
           43         if (pid == 0) {
           44                 setenv("XDG_ACTIVATION_TOKEN", token, true);
           45                 char *argv[] = {"/bin/sh", "-c", cmd->text, NULL};
           46                 execvp(argv[0], (char**)argv);
           47         } else {
           48                 if (cmd->exit) {
           49                         cmd->menu->exit = true;
           50                 }
           51         }
           52 }
           53 
           54 static const struct xdg_activation_token_v1_listener activation_token_listener = {
           55         .done = activation_token_done,
           56 };
           57 
           58 static void exec_item(struct menu *menu, char *text, bool exit) {
           59         struct command *cmd = calloc(1, sizeof(struct command));
           60         cmd->menu = menu;
           61         cmd->text = strdup(text);
           62         cmd->exit = exit;
           63 
           64         struct xdg_activation_v1 *activation = context_get_xdg_activation(menu->context);
           65         struct xdg_activation_token_v1 *activation_token = xdg_activation_v1_get_activation_token(activation);
           66         xdg_activation_token_v1_set_surface(activation_token, context_get_surface(menu->context));
           67         xdg_activation_token_v1_add_listener(activation_token, &activation_token_listener, cmd);
           68         xdg_activation_token_v1_commit(activation_token);
           69 }
           70 
           71 int main(int argc, char *argv[]) {
           72         struct menu *menu = menu_create(exec_item);
           73         menu_getopts(menu, argc, argv);
           74         read_items(menu);
           75         int status = menu_run(menu);
           76         menu_destroy(menu);
           77         return status;
           78 }