~adnano/wmenu

ec1ef577d5f96821fade10e66ab04ccb04324695 — Adnan Maolood a month ago 6f15fd8
Support xdg_activation_v1 protocol
7 files changed, 71 insertions(+), 5 deletions(-)

M README.md
M docs/wmenu.1.scd
M main.c
M menu.c
M menu.h
M protocols/meson.build
M wmenu_run
M README.md => README.md +1 -1
@@ 27,7 27,7 @@ See wmenu(1)
To use wmenu with Sway, you can add the following to your configuration file:

```
set $menu dmenu_path | wmenu | xargs swaymsg exec --
set $menu wmenu_run
bindsym $mod+d exec $menu
```


M docs/wmenu.1.scd => docs/wmenu.1.scd +4 -1
@@ 6,7 6,7 @@ wmenu - dynamic menu for Wayland

# SYNOPSIS

*wmenu* [-biPv] \
*wmenu* [-biPvx] \
  [-f _font_] \
  [-l _lines_] \
  [-o _output_] \


@@ 37,6 37,9 @@ to those matching the tokens in the input.
*-v*
	prints version information to stdout, then exits.

*-x*
	wmenu will execute the selected item.

*-f* _font_
	defines the font used. For more information, see
	https://docs.gtk.org/Pango/type_func.FontDescription.from_string.html

M main.c => main.c +4 -0
@@ 18,6 18,7 @@

#include "menu.h"
#include "render.h"
#include "xdg-activation-v1-client-protocol.h"
#include "wlr-layer-shell-unstable-v1-client-protocol.h"

static void noop() {


@@ 203,6 204,8 @@ static void handle_global(void *data, struct wl_registry *registry,
		wl_output_set_user_data(wl_output, output);
		wl_output_add_listener(wl_output, &output_listener, output);
		menu_add_output(menu, output);
	} else if (strcmp(interface, xdg_activation_v1_interface.name) == 0) {
		menu->activation = wl_registry_bind(registry, name, &xdg_activation_v1_interface, 1);
	}
}



@@ 227,6 230,7 @@ static void menu_connect(struct menu *menu) {
	assert(menu->seat != NULL);
	assert(menu->data_device_manager != NULL);
	assert(menu->layer_shell != NULL);
	assert(menu->activation != NULL);
	menu->registry = registry;

	// Get data device for seat

M menu.c => menu.c +56 -2
@@ 21,6 21,7 @@
#include "pango.h"
#include "pool-buffer.h"
#include "render.h"
#include "xdg-activation-v1-client-protocol.h"
#include "wlr-layer-shell-unstable-v1-client-protocol.h"

// Creates and returns a new menu.


@@ 89,11 90,11 @@ static bool parse_color(const char *color, uint32_t *result) {
// Parse menu options from command line arguments.
void menu_getopts(struct menu *menu, int argc, char *argv[]) {
	const char *usage =
		"Usage: wmenu [-biPv] [-f font] [-l lines] [-o output] [-p prompt]\n"
		"Usage: wmenu [-biPvx] [-f font] [-l lines] [-o output] [-p prompt]\n"
		"\t[-N color] [-n color] [-M color] [-m color] [-S color] [-s color]\n";

	int opt;
	while ((opt = getopt(argc, argv, "bhiPvf:l:o:p:N:n:M:m:S:s:")) != -1) {
	while ((opt = getopt(argc, argv, "bhiPvxf:l:o:p:N:n:M:m:S:s:")) != -1) {
		switch (opt) {
		case 'b':
			menu->bottom = true;


@@ 107,6 108,9 @@ void menu_getopts(struct menu *menu, int argc, char *argv[]) {
		case 'v':
			puts("wmenu " VERSION);
			exit(EXIT_SUCCESS);
		case 'x':
			menu->exec = true;
			break;
		case 'f':
			menu->font = optarg;
			break;


@@ 409,6 413,53 @@ static void movewordedge(struct menu *menu, int dir) {
	}
}

// Information needed to execute an item.
struct executable {
	struct menu *menu;
	char *name;
};

// Executes an item with an activation token.
static void execute(struct executable *exe, const char *token) {
	menu_destroy(exe->menu);

	setenv("XDG_ACTIVATION_TOKEN", token, true);
	execlp(exe->name, exe->name, NULL);

	// Handle execution failure
	fprintf(stderr, "Failed to execute selection: %s\n", strerror(errno));
	free(exe->name);
	free(exe);
	exit(EXIT_FAILURE);
}

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);
	execute(exe, token);
}

static const struct xdg_activation_token_v1_listener activation_token_listener = {
	.done = activation_token_done,
};

// Executes the selected item.
static void menu_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_token_v1 *activation_token = xdg_activation_v1_get_activation_token(menu->activation);
	xdg_activation_token_v1_set_surface(activation_token, menu->surface);
	xdg_activation_token_v1_add_listener(activation_token, &activation_token_listener, exe);
	xdg_activation_token_v1_commit(activation_token);
}

// Handle a keypress.
void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
		xkb_keysym_t sym) {


@@ 588,6 639,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->exec) {
			menu_exec(menu);
		} else {
			char *text = menu->sel ? menu->sel->text : menu->input;
			puts(text);


@@ 750,6 803,7 @@ void menu_destroy(struct menu *menu) {
	wl_data_device_destroy(menu->data_device);
	wl_surface_destroy(menu->surface);
	zwlr_layer_surface_v1_destroy(menu->layer_surface);
	xdg_activation_v1_destroy(menu->activation);

	free_pages(menu);
	free_items(menu);

M menu.h => menu.h +4 -0
@@ 4,6 4,7 @@
#include <xkbcommon/xkbcommon.h>

#include "pool-buffer.h"
#include "xdg-activation-v1-client-protocol.h"

// A menu item.
struct item {


@@ 55,6 56,8 @@ struct menu {
	int (*strncmp)(const char *, const char *, size_t);
	// Whether the input is a password
	bool passwd;
	// Whether to execute the selected item
	bool exec;
	// The font used to display the menu
	char *font;
	// The number of lines to list items vertically


@@ 78,6 81,7 @@ struct menu {
	struct wl_data_device_manager *data_device_manager;
	struct zwlr_layer_shell_v1 *layer_shell;
	struct output *output_list;
	struct xdg_activation_v1 *activation;

	struct keyboard *keyboard;
	struct wl_data_device *data_device;

M protocols/meson.build => protocols/meson.build +1 -0
@@ 12,6 12,7 @@ endif

protocols = [
	[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
	[wl_protocol_dir, 'staging/xdg-activation/xdg-activation-v1.xml'],
	['wlr-layer-shell-unstable-v1.xml'],
]


M wmenu_run => wmenu_run +1 -1
@@ 32,4 32,4 @@ path() {
	fi
}

path | wmenu "$@" | ${SHELL:-"/bin/sh"} &
path | wmenu -x "$@"