1
0
mirror of https://github.com/Cloudef/bemenu synced 2024-11-23 01:12:01 +01:00

Add relative width option

It works on Wayland and X11 and acts as a complement to margin. Exact
behavior is as follows:
- If width factor is 0, width minus margin is used.
- If width multiplied by factor is greater than width minus margin,
  width minus is used. (so margin may be used to make sure that bemenu
  is at least N pixels away from the view border)
- Otherwise width multiplied by factor is used.

I think it's fine to disable warnings about floating point numbers
comparision. We don't do any arithmetics on them anyway, so we can't
suffer from inaccuracy.
This commit is contained in:
Maxim Karasev 2021-12-26 19:38:11 +03:00 committed by Jari Vetoniemi
parent 192736c554
commit 43255bbbe8
12 changed files with 102 additions and 62 deletions

@ -10,7 +10,7 @@ GIT_TAG = $(shell git tag --points-at HEAD 2>/dev/null || cat VERSION)
MAKEFLAGS += --no-builtin-rules
WARNINGS = -Wall -Wextra -Wpedantic -Wformat=2 -Wstrict-aliasing=3 -Wstrict-overflow=5 -Wstack-usage=12500 \
-Wfloat-equal -Wcast-align -Wpointer-arith -Wchar-subscripts -Warray-bounds=2 -Wno-unknown-warning-option
-Wcast-align -Wpointer-arith -Wchar-subscripts -Warray-bounds=2 -Wno-unknown-warning-option
override CFLAGS ?= -g -O2 $(WARNINGS) $(EXTRA_WARNINGS)
override CFLAGS += -std=c99

@ -201,6 +201,7 @@ usage(FILE *out, const char *name)
" -m, --monitor index of monitor where menu will appear. (wx)\n"
" -H, --line-height defines the height to make each menu line (0 = default height). (wx)\n"
" -M, --margin defines the empty space on either side of the menu. (wx)\n"
" -W, --width-factor defines the relative width factor of the menu (from 0 to 1). (wx)\n"
" --ch defines the height of the cursor (0 = scales with line height). (wx)\n"
" --fn defines the font to be used ('name [size]'). (wx)\n"
" --tb defines the title background color. (wx)\n"
@ -243,44 +244,45 @@ do_getopt(struct client *client, int *argc, char **argv[])
assert(client && argc && argv);
static const struct option opts[] = {
{ "help", no_argument, 0, 'h' },
{ "version", no_argument, 0, 'v' },
{ "help", no_argument, 0, 'h' },
{ "version", no_argument, 0, 'v' },
{ "ignorecase", no_argument, 0, 'i' },
{ "filter", required_argument, 0, 'F' },
{ "wrap", no_argument, 0, 'w' },
{ "list", required_argument, 0, 'l' },
{ "center", no_argument, 0, 'c' },
{ "prompt", required_argument, 0, 'p' },
{ "index", required_argument, 0, 'I' },
{ "prefix", required_argument, 0, 'P' },
{ "password", no_argument, 0, 'x' },
{ "scrollbar", required_argument, 0, 0x100 },
{ "ifne", no_argument, 0, 0x115 },
{ "fork", no_argument, 0, 0x116 },
{ "no-exec", no_argument, 0, 0x117 },
{ "ignorecase", no_argument, 0, 'i' },
{ "filter", required_argument, 0, 'F' },
{ "wrap", no_argument, 0, 'w' },
{ "list", required_argument, 0, 'l' },
{ "center", no_argument, 0, 'c' },
{ "prompt", required_argument, 0, 'p' },
{ "index", required_argument, 0, 'I' },
{ "prefix", required_argument, 0, 'P' },
{ "password", no_argument, 0, 'x' },
{ "scrollbar", required_argument, 0, 0x100 },
{ "ifne", no_argument, 0, 0x115 },
{ "fork", no_argument, 0, 0x116 },
{ "no-exec", no_argument, 0, 0x117 },
{ "bottom", no_argument, 0, 'b' },
{ "grab", no_argument, 0, 'f' },
{ "no-overlap", no_argument, 0, 'n' },
{ "no-spacing", no_argument, 0, 's' },
{ "monitor", required_argument, 0, 'm' },
{ "line-height", required_argument, 0, 'H' },
{ "margin", required_argument, 0, 'M' },
{ "ch", required_argument, 0, 0x118 },
{ "fn", required_argument, 0, 0x101 },
{ "tb", required_argument, 0, 0x102 },
{ "tf", required_argument, 0, 0x103 },
{ "fb", required_argument, 0, 0x104 },
{ "ff", required_argument, 0, 0x105 },
{ "nb", required_argument, 0, 0x106 },
{ "nf", required_argument, 0, 0x107 },
{ "hb", required_argument, 0, 0x108 },
{ "hf", required_argument, 0, 0x109 },
{ "sb", required_argument, 0, 0x110 },
{ "sf", required_argument, 0, 0x111 },
{ "scb", required_argument, 0, 0x112 },
{ "scf", required_argument, 0, 0x113 },
{ "bottom", no_argument, 0, 'b' },
{ "grab", no_argument, 0, 'f' },
{ "no-overlap", no_argument, 0, 'n' },
{ "no-spacing", no_argument, 0, 's' },
{ "monitor", required_argument, 0, 'm' },
{ "line-height", required_argument, 0, 'H' },
{ "margin", required_argument, 0, 'M' },
{ "width-factor", required_argument, 0, 'W' },
{ "ch", required_argument, 0, 0x118 },
{ "fn", required_argument, 0, 0x101 },
{ "tb", required_argument, 0, 0x102 },
{ "tf", required_argument, 0, 0x103 },
{ "fb", required_argument, 0, 0x104 },
{ "ff", required_argument, 0, 0x105 },
{ "nb", required_argument, 0, 0x106 },
{ "nf", required_argument, 0, 0x107 },
{ "hb", required_argument, 0, 0x108 },
{ "hf", required_argument, 0, 0x109 },
{ "sb", required_argument, 0, 0x110 },
{ "sf", required_argument, 0, 0x111 },
{ "scb", required_argument, 0, 0x112 },
{ "scf", required_argument, 0, 0x113 },
{ "disco", no_argument, 0, 0x114 },
{ 0, 0, 0, 0 }
@ -296,7 +298,7 @@ do_getopt(struct client *client, int *argc, char **argv[])
for (optind = 0;;) {
int32_t opt;
if ((opt = getopt_long(*argc, *argv, "hviwxcl:I:p:P:I:bfm:H:M:ns", opts, NULL)) < 0)
if ((opt = getopt_long(*argc, *argv, "hviwxcl:I:p:P:I:bfm:H:M:W:ns", opts, NULL)) < 0)
break;
switch (opt) {
@ -369,6 +371,9 @@ do_getopt(struct client *client, int *argc, char **argv[])
case 'M':
client->hmargin_size = strtol(optarg, NULL, 10);
break;
case 'W':
client->width_factor = strtof(optarg, NULL);
break;
case 0x118:
client->cursor_height = strtol(optarg, NULL, 10);
break;
@ -462,7 +467,7 @@ menu_with_options(struct client *client)
bm_menu_set_panel_overlap(menu, !client->no_overlap);
bm_menu_set_spacing(menu, !client->no_spacing);
bm_menu_set_password(menu, client->password);
bm_menu_set_hmargin_size(menu, client->hmargin_size);
bm_menu_set_width(menu, client->hmargin_size, client->width_factor);
if (client->center) {
bm_menu_set_align(menu, BM_ALIGN_CENTER);

@ -18,6 +18,7 @@ struct client {
uint32_t selected;
uint32_t monitor;
uint32_t hmargin_size;
float width_factor;
bool bottom;
bool center;
bool grab;

@ -539,13 +539,14 @@ BM_PUBLIC void bm_menu_set_align(struct bm_menu *menu, enum bm_align align);
BM_PUBLIC enum bm_align bm_menu_get_align(struct bm_menu *menu);
/**
* Set the horizontal margin of the bar.
* Set the horizontal margin and the relative width factor of the bar.
*
* @param menu bm_menu to set horizontal margin for.
* @param margin margin to set.
* @param factor factor to set.
*/
BM_PUBLIC void bm_menu_set_hmargin_size(struct bm_menu *menu, uint32_t margin);
BM_PUBLIC void bm_menu_set_width(struct bm_menu *menu, uint32_t margin, float factor);
/**
* Get the horizontal margin of the bar.
@ -556,6 +557,15 @@ BM_PUBLIC void bm_menu_set_hmargin_size(struct bm_menu *menu, uint32_t margin);
BM_PUBLIC uint32_t bm_menu_get_hmargin_size(struct bm_menu *menu);
/**
* Get the relative width factor of the bar.
*
* @param menu bm_menu to get relative width factor from.
* @return relative width factor of the menu.
*/
BM_PUBLIC float bm_menu_get_width_factor(struct bm_menu *menu);
/**
* Display menu at monitor index.
* Indices start at 0, a value of -1 can be passed for the active monitor (default).

@ -83,9 +83,9 @@ struct render_api {
void (*set_align)(const struct bm_menu *menu, enum bm_align align);
/**
* Set horizontal margin.
* Set horizontal margin and relative width factor.
*/
void (*set_hmargin_size)(const struct bm_menu *menu, uint32_t margin);
void (*set_width)(const struct bm_menu *menu, uint32_t margin, float factor);
/**
* Set monitor indeax where menu will appear
@ -334,6 +334,11 @@ struct bm_menu {
*/
uint32_t hmargin_size;
/**
* Relative width factor.
*/
float width_factor;
/**
* Is menu grabbed?
*/

@ -376,17 +376,18 @@ bm_menu_get_align(struct bm_menu *menu)
}
void
bm_menu_set_hmargin_size(struct bm_menu *menu, uint32_t margin)
bm_menu_set_width(struct bm_menu *menu, uint32_t margin, float factor)
{
assert(menu);
if(menu->hmargin_size == margin)
if(menu->hmargin_size == margin && menu->width_factor == factor)
return;
menu->hmargin_size = margin;
menu->width_factor = factor;
if(menu->renderer->api.set_hmargin_size)
menu->renderer->api.set_hmargin_size(menu, margin);
if(menu->renderer->api.set_width)
menu->renderer->api.set_width(menu, margin, factor);
}
uint32_t
@ -396,6 +397,13 @@ bm_menu_get_hmargin_size(struct bm_menu *menu)
return menu->hmargin_size;
}
float
bm_menu_get_width_factor(struct bm_menu *menu)
{
assert(menu);
return menu->width_factor;
}
void
bm_menu_set_monitor(struct bm_menu *menu, int32_t monitor)
{

@ -73,7 +73,7 @@ poll_key(const struct bm_menu *menu, unsigned int *unicode)
wayland->input.code = 0;
if (!wayland->input.key_pending)
return BM_KEY_UNICODE;
return BM_KEY_UNICODE;
wayland->input.key_pending = false;
switch (sym) {
@ -232,14 +232,14 @@ get_displayed_count(const struct bm_menu *menu)
}
static void
set_hmargin_size(const struct bm_menu *menu, uint32_t margin)
set_width(const struct bm_menu *menu, uint32_t margin, float factor)
{
struct wayland *wayland = menu->renderer->internal;
assert(wayland);
struct window *window;
wl_list_for_each(window, &wayland->windows, link) {
bm_wl_window_set_hmargin_size(window, wayland->display, margin);
bm_wl_window_set_width(window, wayland->display, margin, factor);
}
}
@ -322,6 +322,7 @@ recreate_windows(const struct bm_menu *menu, struct wayland *wayland)
struct window *window = calloc(1, sizeof(struct window));
window->align = menu->align;
window->hmargin_size = menu->hmargin_size;
window->width_factor = menu->width_factor;
const char *scale = getenv("BEMENU_SCALE");
if (scale) {
@ -449,7 +450,7 @@ register_renderer(struct render_api *api)
api->poll_key = poll_key;
api->render = render;
api->set_align = set_align;
api->set_hmargin_size = set_hmargin_size;
api->set_width = set_width;
api->grab_keyboard = grab_keyboard;
api->set_overlap = set_overlap;
api->set_monitor = set_monitor;

@ -87,6 +87,7 @@ struct window {
struct buffer buffers[2];
uint32_t width, height, max_height;
uint32_t hmargin_size;
float width_factor;
int32_t scale;
uint32_t displayed;
struct wl_list link;
@ -132,7 +133,7 @@ bool bm_wl_registry_register(struct wayland *wayland);
void bm_wl_registry_destroy(struct wayland *wayland);
void bm_wl_window_schedule_render(struct window *window);
void bm_wl_window_render(struct window *window, struct wl_display *display, const struct bm_menu *menu);
void bm_wl_window_set_hmargin_size(struct window *window, struct wl_display *display, uint32_t margin);
void bm_wl_window_set_width(struct window *window, struct wl_display *display, uint32_t margin, float factor);
void bm_wl_window_set_align(struct window *window, struct wl_display *display, enum bm_align align);
void bm_wl_window_grab_keyboard(struct window *window, struct wl_display *display, bool grab);
void bm_wl_window_set_overlap(struct window *window, struct wl_display *display, bool overlap);

@ -305,7 +305,10 @@ layer_surface_closed(void *data, struct zwlr_layer_surface_v1 *layer_surface)
static uint32_t
get_window_width(struct window *window)
{
uint32_t width = window->width - 2 * window->hmargin_size;
uint32_t width = window->width * ((window->width_factor != 0) ? window->width_factor : 1);
if(width > window->width - 2 * window->hmargin_size)
width = window->width - 2 * window->hmargin_size;
if(width < WINDOW_MIN_WIDTH || 2 * window->hmargin_size > window->width)
width = WINDOW_MIN_WIDTH;
@ -319,12 +322,13 @@ static const struct zwlr_layer_surface_v1_listener layer_surface_listener = {
};
void
bm_wl_window_set_hmargin_size(struct window *window, struct wl_display *display, uint32_t margin)
bm_wl_window_set_width(struct window *window, struct wl_display *display, uint32_t margin, float factor)
{
if(window->hmargin_size == margin)
if(window->hmargin_size == margin && window->width_factor == factor)
return;
window->hmargin_size = margin;
window->width_factor = factor;
zwlr_layer_surface_v1_set_anchor(window->layer_surface, window->align_anchor);
zwlr_layer_surface_v1_set_size(window->layer_surface, get_window_width(window), window->height);

@ -66,7 +66,10 @@ next_buffer(struct window *window)
static uint32_t
get_window_width(struct window *window)
{
uint32_t width = window->width - 2 * window->hmargin_size;
uint32_t width = window->width * ((window->width_factor != 0) ? window->width_factor : 1);
if(width > window->width - 2 * window->hmargin_size)
width = window->width - 2 * window->hmargin_size;
if(width < WINDOW_MIN_WIDTH || 2 * window->hmargin_size > window->width)
width = WINDOW_MIN_WIDTH;
@ -242,12 +245,13 @@ bm_x11_window_set_align(struct window *window, enum bm_align align)
}
void
bm_x11_window_set_hmargin_size(struct window *window, uint32_t margin)
bm_x11_window_set_width(struct window *window, uint32_t margin, float factor)
{
if(window->hmargin_size == margin)
if(window->hmargin_size == margin && window->width_factor == factor)
return;
window->hmargin_size = margin;
window->width_factor = factor;
window->width = window->orig_width;
window->x = window->orig_x;
window->width = get_window_width(window);

@ -210,11 +210,11 @@ set_align(const struct bm_menu *menu, enum bm_align align)
}
static void
set_hmargin_size(const struct bm_menu *menu, uint32_t margin)
set_width(const struct bm_menu *menu, uint32_t margin, float factor)
{
struct x11 *x11 = menu->renderer->internal;
assert(x11);
bm_x11_window_set_hmargin_size(&x11->window, margin);
bm_x11_window_set_width(&x11->window, margin, factor);
}
static void
@ -299,7 +299,7 @@ register_renderer(struct render_api *api)
api->poll_key = poll_key;
api->render = render;
api->set_align = set_align;
api->set_hmargin_size = set_hmargin_size;
api->set_width = set_width;
api->set_monitor = set_monitor;
api->grab_keyboard = grab_keyboard;
api->priorty = BM_PRIO_GUI;

@ -35,6 +35,7 @@ struct window {
uint32_t x, y, width, height, max_height;
uint32_t orig_width, orig_x;
uint32_t hmargin_size;
float width_factor;
uint32_t displayed;
int32_t monitor;
@ -54,7 +55,7 @@ void bm_x11_window_render(struct window *window, const struct bm_menu *menu);
void bm_x11_window_key_press(struct window *window, XKeyEvent *ev);
void bm_x11_window_set_monitor(struct window *window, int32_t monitor);
void bm_x11_window_set_align(struct window *window, enum bm_align align);
void bm_x11_window_set_hmargin_size(struct window *window, uint32_t margin);
void bm_x11_window_set_width(struct window *window, uint32_t margin, float factor);
bool bm_x11_window_create(struct window *window, Display *display);
void bm_x11_window_destroy(struct window *window);