File wmenu/.git is a directory while file wmenud/.git is a regular file diff -Nur wmenu/menu.c wmenud/menu.c --- wmenu/menu.c 2026-03-31 04:31:08.735754566 +0200 +++ wmenud/menu.c 2026-03-31 04:31:00.976768869 +0200 @@ -172,7 +172,7 @@ } // Add an item to the menu. -void menu_add_item(struct menu *menu, char *text) { +void menu_add_item(struct menu *menu, char *text, void *app_info) { if ((menu->item_count & (menu->item_count - 1)) == 0) { size_t alloc_size = menu->item_count ? 2 * menu->item_count : 1; void *new_array = realloc(menu->items, sizeof(struct item) * alloc_size); @@ -185,6 +185,7 @@ struct item *new = &menu->items[menu->item_count]; new->text = text; + new->app_info = app_info; menu->item_count++; } @@ -593,10 +594,10 @@ case XKB_KEY_Return: case XKB_KEY_KP_Enter: if (shift) { - menu->callback(menu, menu->input, true); + menu->callback(menu, menu->input, menu->sel->app_info, true); } else { char *text = menu->sel ? menu->sel->text : menu->input; - menu->callback(menu, text, !ctrl); + menu->callback(menu, text, menu->sel->app_info, !ctrl); } break; case XKB_KEY_Left: diff -Nur wmenu/menu.h wmenud/menu.h --- wmenu/menu.h 2026-03-31 04:31:08.735754566 +0200 +++ wmenud/menu.h 2026-03-31 04:31:00.976768869 +0200 @@ -6,13 +6,15 @@ #include #include #include +#include struct menu; -typedef void (*menu_callback)(struct menu *menu, char *text, bool exit); +typedef void (*menu_callback)(struct menu *menu, char *text, GAppInfo *app_info, bool exit); // A menu item. struct item { char *text; + GAppInfo *app_info; int width; struct item *prev_match; // previous matching item struct item *next_match; // next matching item @@ -84,7 +86,7 @@ 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); +void menu_add_item(struct menu *menu, char *text, void *app_info); void menu_sort_and_deduplicate(struct menu *menu); void menu_calc_height(struct menu *menu); void menu_invalidate(struct menu *menu); diff -Nur wmenu/meson.build wmenud/meson.build --- wmenu/meson.build 2026-03-31 04:31:08.735754566 +0200 +++ wmenud/meson.build 2026-03-31 04:31:00.976768869 +0200 @@ -7,6 +7,7 @@ 'c_std=c11', 'warning_level=2', 'werror=true', + 'optimization=3', ] ) @@ -19,6 +20,7 @@ '-Wno-unused-parameter', '-Wundef', '-Wvla', + '-Wno-discarded-qualifiers', ]), language : 'c') cairo = dependency('cairo') @@ -27,6 +29,8 @@ wayland_client = dependency('wayland-client') wayland_protos = dependency('wayland-protocols') xkbcommon = dependency('xkbcommon') +glib = dependency('glib-2.0') +gio_unix = dependency('gio-unix-2.0') rt = cc.find_library('rt') @@ -78,3 +82,28 @@ ], install: true, ) + +executable( + 'wmenu-drun', + files( + 'menu.c', + 'pango.c', + 'pool-buffer.c', + 'render.c', + 'wayland.c', + 'wmenu-drun.c', + ), + dependencies: [ + cairo, + client_protos, + pango, + pangocairo, + rt, + wayland_client, + wayland_protos, + xkbcommon, + glib, + gio_unix, + ], + install: true, +) diff -Nur wmenu/wmenu.c wmenud/wmenu.c --- wmenu/wmenu.c 2026-03-31 04:31:08.736754564 +0200 +++ wmenud/wmenu.c 2026-03-31 04:31:00.979768864 +0200 @@ -2,6 +2,7 @@ #include #include +#include #include "menu.h" #include "wayland.h" @@ -13,11 +14,11 @@ if (p) { *p = '\0'; } - menu_add_item(menu, strdup(buf)); + menu_add_item(menu, strdup(buf), NULL); } } -static void print_item(struct menu *menu, char *text, bool exit) { +static void print_item(struct menu *menu, char *text, GAppInfo *app_info, bool exit) { puts(text); fflush(stdout); if (exit) { diff -Nur wmenu/wmenu-drun.c wmenud/wmenu-drun.c --- wmenu/wmenu-drun.c 1970-01-01 01:00:00.000000000 +0100 +++ wmenud/wmenu-drun.c 2026-03-31 21:24:43.667365628 +0200 @@ -0,0 +1,73 @@ +#define _POSIX_C_SOURCE 200809L +#include +#include +#include +#include +#include +#include + +#include "menu.h" +#include "wayland.h" +#include "xdg-activation-v1-client-protocol.h" + +static void read_items(struct menu *menu) { + GList* list = g_app_info_get_all(); + GList* item; + for(item = list; item; item = item->next) { + if (g_app_info_should_show(item->data) == FALSE) { + continue; + } + const char *name = g_app_info_get_name(item->data); + menu_add_item(menu, name, item->data); + } + menu_sort_and_deduplicate(menu); +} + +struct command { + struct menu *menu; + char *text; + GAppInfo *app_info; + bool exit; +}; + +static void activation_token_done(void *data, struct xdg_activation_token_v1 *activation_token, + const char *token) { + struct command *cmd = data; + xdg_activation_token_v1_destroy(activation_token); + + GAppLaunchContext *context = g_app_launch_context_new(); // Not strictly necessary. + g_app_info_launch(cmd->app_info, NULL, context, NULL); + setenv("XDG_ACTIVATION_TOKEN", token, true); + xdg_activation_token_v1_destroy(activation_token); + cmd->menu->exit = true; +} + +static const struct xdg_activation_token_v1_listener activation_token_listener = { + .done = activation_token_done, +}; + +static void exec_item(struct menu *menu, char *text, GAppInfo *app_info, bool exit) { + struct command *cmd = calloc(1, sizeof(struct command)); + cmd->menu = menu; + cmd->text = strdup(text); + cmd->app_info = app_info; + if (cmd->app_info == NULL) { + printf("app info is nil\n"); + } + 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, cmd); + xdg_activation_token_v1_commit(activation_token); +} + +int main(int argc, char *argv[]) { + struct menu *menu = menu_create(exec_item); + menu_getopts(menu, argc, argv); + read_items(menu); + int status = menu_run(menu); + menu_destroy(menu); + return status; +} diff -Nur wmenu/wmenu-run.c wmenud/wmenu-run.c --- wmenu/wmenu-run.c 2026-03-31 04:31:08.735754566 +0200 +++ wmenud/wmenu-run.c 2026-03-31 04:31:00.979768864 +0200 @@ -4,6 +4,7 @@ #include #include #include +#include #include "menu.h" #include "wayland.h" @@ -20,7 +21,7 @@ if (ent->d_name[0] == '.') { continue; } - menu_add_item(menu, strdup(ent->d_name)); + menu_add_item(menu, strdup(ent->d_name), NULL); } closedir(dir); } @@ -55,7 +56,7 @@ .done = activation_token_done, }; -static void exec_item(struct menu *menu, char *text, bool exit) { +static void exec_item(struct menu *menu, char *text, GAppInfo *app_info, bool exit) { struct command *cmd = calloc(1, sizeof(struct command)); cmd->menu = menu; cmd->text = strdup(text);