mirror of
https://codeberg.org/adnano/wmenu.git
synced 2025-10-29 05:40:20 -04:00
Main commit; add features, remove wmenu-run.c, create wmenu-run script and update all docs and build system files.
This commit is contained in:
parent
fc69aa6e2b
commit
65f3093bb3
9 changed files with 47 additions and 118 deletions
|
|
@ -9,6 +9,8 @@ wmenu - dynamic menu for Wayland
|
|||
*wmenu* [-biPv] \
|
||||
[-f _font_] \
|
||||
[-l _lines_] \
|
||||
[-g _height_] \
|
||||
[-w _width_] \
|
||||
[-o _output_] \
|
||||
[-p _prompt_] \
|
||||
[-N _color_] [-n _color_] \
|
||||
|
|
@ -24,8 +26,8 @@ items from stdin. When the user selects an item and presses Return, their choice
|
|||
is printed to stdout and wmenu terminates. Entering text will narrow the items
|
||||
to those matching the tokens in the input.
|
||||
|
||||
*wmenu-run* is a special invocation of wmenu which lists programs in the user's
|
||||
$PATH and runs the result.
|
||||
*wmenu-run* is a special script which lists programs in the user's
|
||||
$PATH and runs the result with the main *wmenu* executable.
|
||||
|
||||
# OPTIONS
|
||||
|
||||
|
|
@ -49,6 +51,12 @@ $PATH and runs the result.
|
|||
*-l* _lines_
|
||||
wmenu lists items vertically, with the given number of lines.
|
||||
|
||||
*-g* _height_
|
||||
this value will be added to the height of each line.
|
||||
|
||||
*-w* _width_
|
||||
the width of the window will be constrained to this value.
|
||||
|
||||
*-o* _output_
|
||||
wmenu is displayed on the output with the given name.
|
||||
|
||||
|
|
|
|||
3
install-wmenu-run.sh
Executable file
3
install-wmenu-run.sh
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
cp ../wmenu-run /usr/local/bin/
|
||||
21
menu.c
21
menu.c
|
|
@ -27,6 +27,7 @@ struct menu *menu_create(menu_callback callback) {
|
|||
struct menu *menu = calloc(1, sizeof(struct menu));
|
||||
menu->strncmp = strncmp;
|
||||
menu->font = "monospace 10";
|
||||
menu->line_height = get_font_height(menu->font) + 2;
|
||||
menu->normalbg = 0x222222ff;
|
||||
menu->normalfg = 0xbbbbbbff;
|
||||
menu->promptbg = 0x005577ff;
|
||||
|
|
@ -85,11 +86,14 @@ 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"
|
||||
"\t[-N color] [-n color] [-M color] [-m color] [-S color] [-s color]\n";
|
||||
"Usage: wmenu [-biPv] [-f font] [-l lines] [-g height] [-w width] [-o output]\n"
|
||||
"\t[-p prompt] [-N color] [-n color] [-M color] [-m color] [-S color] [-s color]\n";
|
||||
|
||||
menu->customwidth = 0;
|
||||
menu->customheight = 0;
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "bhiPvf:l:o:p:N:n:M:m:S:s:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "bhiPvf:l:g:w:o:p:N:n:M:m:S:s:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'b':
|
||||
menu->bottom = true;
|
||||
|
|
@ -109,6 +113,13 @@ void menu_getopts(struct menu *menu, int argc, char *argv[]) {
|
|||
case 'l':
|
||||
menu->lines = atoi(optarg);
|
||||
break;
|
||||
case 'g':
|
||||
menu->customheight = atoi(optarg);
|
||||
menu->line_height = get_font_height(menu->font) + menu->customheight;
|
||||
break;
|
||||
case 'w':
|
||||
menu->customwidth = atoi(optarg);
|
||||
break;
|
||||
case 'o':
|
||||
menu->output_name = optarg;
|
||||
break;
|
||||
|
|
@ -156,13 +167,11 @@ void menu_getopts(struct menu *menu, int argc, char *argv[]) {
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int height = get_font_height(menu->font);
|
||||
menu->line_height = height + 2;
|
||||
menu->height = menu->line_height;
|
||||
if (menu->lines > 0) {
|
||||
menu->height += menu->height * menu->lines;
|
||||
}
|
||||
menu->padding = height / 2;
|
||||
menu->padding = get_font_height(menu->font) / 2;
|
||||
}
|
||||
|
||||
// Add an item to the menu.
|
||||
|
|
|
|||
2
menu.h
2
menu.h
|
|
@ -59,6 +59,8 @@ struct menu {
|
|||
int width;
|
||||
int height;
|
||||
int line_height;
|
||||
int customwidth;
|
||||
int customheight;
|
||||
int padding;
|
||||
int inputw;
|
||||
int promptw;
|
||||
|
|
|
|||
23
meson.build
23
meson.build
|
|
@ -56,25 +56,4 @@ executable(
|
|||
install: true,
|
||||
)
|
||||
|
||||
executable(
|
||||
'wmenu-run',
|
||||
files(
|
||||
'menu.c',
|
||||
'pango.c',
|
||||
'pool-buffer.c',
|
||||
'render.c',
|
||||
'wayland.c',
|
||||
'wmenu-run.c',
|
||||
),
|
||||
dependencies: [
|
||||
cairo,
|
||||
client_protos,
|
||||
pango,
|
||||
pangocairo,
|
||||
rt,
|
||||
wayland_client,
|
||||
wayland_protos,
|
||||
xkbcommon,
|
||||
],
|
||||
install: true,
|
||||
)
|
||||
meson.add_install_script('install-wmenu-run.sh')
|
||||
|
|
|
|||
6
render.c
6
render.c
|
|
@ -106,7 +106,7 @@ static void render_input(struct menu *menu, cairo_t *cairo) {
|
|||
// Renders a cursor for the input field.
|
||||
static void render_cursor(struct menu *menu, cairo_t *cairo) {
|
||||
const int cursor_width = 2;
|
||||
const int cursor_margin = 2;
|
||||
const int cursor_margin = menu->line_height / 5;
|
||||
int cursor_pos = menu->promptw + menu->padding
|
||||
+ text_width(cairo, menu->font, menu->input)
|
||||
- text_width(cairo, menu->font, &menu->input[menu->cursor])
|
||||
|
|
@ -144,11 +144,11 @@ static void render_horizontal_page(struct menu *menu, cairo_t *cairo, struct pag
|
|||
|
||||
// Draw left and right scroll indicators if necessary
|
||||
if (page->prev) {
|
||||
cairo_move_to(cairo, menu->promptw + menu->inputw + menu->padding, 0);
|
||||
cairo_move_to(cairo, menu->promptw + menu->inputw + menu->padding, menu->customheight / 2);
|
||||
pango_printf(cairo, menu->font, 1, "<");
|
||||
}
|
||||
if (page->next) {
|
||||
cairo_move_to(cairo, menu->width - menu->right_arrow + menu->padding, 0);
|
||||
cairo_move_to(cairo, menu->width - menu->right_arrow + menu->padding, menu->customheight / 2);
|
||||
pango_printf(cairo, menu->font, 1, ">");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,7 +220,11 @@ static void layer_surface_configure(void *data,
|
|||
struct zwlr_layer_surface_v1 *surface,
|
||||
uint32_t serial, uint32_t width, uint32_t height) {
|
||||
struct wl_context *context = data;
|
||||
if (context->menu->customwidth > 0) {
|
||||
context->menu->width = context->menu->customwidth;
|
||||
} else {
|
||||
context->menu->width = width;
|
||||
}
|
||||
context->menu->height = height;
|
||||
zwlr_layer_surface_v1_ack_configure(surface, serial);
|
||||
}
|
||||
|
|
|
|||
2
wmenu-run
Executable file
2
wmenu-run
Executable file
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
compgen -c | sort | wmenu "$@" | sh
|
||||
78
wmenu-run.c
78
wmenu-run.c
|
|
@ -1,78 +0,0 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <dirent.h>
|
||||
#include <stdio.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 *path = strdup(getenv("PATH"));
|
||||
for (char *p = strtok(path, ":"); p != NULL; p = strtok(NULL, ":")) {
|
||||
DIR *dir = opendir(p);
|
||||
if (dir == NULL) {
|
||||
continue;
|
||||
}
|
||||
for (struct dirent *ent = readdir(dir); ent != NULL; ent = readdir(dir)) {
|
||||
if (ent->d_name[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
menu_add_item(menu, strdup(ent->d_name));
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
menu_sort_and_deduplicate(menu);
|
||||
free(path);
|
||||
}
|
||||
|
||||
struct command {
|
||||
struct menu *menu;
|
||||
char *text;
|
||||
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);
|
||||
|
||||
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_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, 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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue