From a96ed87472254cca54df0b8881a014d292bda385 Mon Sep 17 00:00:00 2001 From: lunacb Date: Sun, 17 Oct 2021 12:33:37 -0400 Subject: [PATCH] redesigned vertical alignment single enum determines if the menu is at the top, in the center, or at the bottom. implemented in wayland and x11 renderers. --- client/common/common.c | 10 ++++--- lib/bemenu.h | 45 ++++++++++++++++++++------------ lib/internal.h | 18 +++---------- lib/menu.c | 36 ++++++++------------------ lib/renderers/wayland/wayland.c | 21 +++------------ lib/renderers/wayland/wayland.h | 9 ++++--- lib/renderers/wayland/window.c | 46 +++++++++++++++++++-------------- lib/renderers/x11/window.c | 34 +++++++++++++++++------- lib/renderers/x11/x11.c | 8 +++--- lib/renderers/x11/x11.h | 6 +++-- 10 files changed, 118 insertions(+), 115 deletions(-) diff --git a/client/common/common.c b/client/common/common.c index ef5c4c5..6e31cbc 100644 --- a/client/common/common.c +++ b/client/common/common.c @@ -1,3 +1,5 @@ +#include "internal.h" + #include "common.h" #include #include @@ -193,7 +195,7 @@ usage(FILE *out, const char *name) " (...) At end of help indicates the backend support for option.\n\n" " -b, --bottom appears at the bottom of the screen. (wx)\n" - " -c, --center appears at the center of the screen. (w)\n" + " -c, --center appears at the center of the screen. (wx)\n" " -f, --grab show the menu before reading stdin. (wx)\n" " -n, --no-overlap adjust geometry to not overlap with panels. (w)\n" " -m, --monitor index of monitor where menu will appear. (wx)\n" @@ -463,9 +465,11 @@ menu_with_options(struct client *client) bm_menu_set_hmargin_size(menu, client->hmargin_size); if (client->center) { - bm_menu_set_center(menu, client->center); + bm_menu_set_align(menu, BM_ALIGN_CENTER); } else if (client->bottom) { - bm_menu_set_bottom(menu, client->bottom); + bm_menu_set_align(menu, BM_ALIGN_BOTTOM); + } else { + bm_menu_set_align(menu, BM_ALIGN_TOP); } for (uint32_t i = 0; i < BM_COLOR_LAST; ++i) diff --git a/lib/bemenu.h b/lib/bemenu.h index dfea4d5..02ad517 100644 --- a/lib/bemenu.h +++ b/lib/bemenu.h @@ -115,6 +115,26 @@ enum bm_priorty { BM_PRIO_GUI, }; +/** + * Vertical position of the menu. + */ +enum bm_align { + /** + * Menu is at the top of the screen. + */ + BM_ALIGN_TOP, + + /** + * Menu is at the bottom of the screen. + */ + BM_ALIGN_BOTTOM, + + /** + * Menu is in the center of the screen. + */ + BM_ALIGN_CENTER, +}; + /** * Get name of the renderer. * @@ -501,30 +521,21 @@ BM_PUBLIC void bm_menu_set_scrollbar(struct bm_menu *menu, enum bm_scrollbar_mod BM_PUBLIC enum bm_scrollbar_mode bm_menu_get_scrollbar(struct bm_menu *menu); /** - * Display menu at center of the screen. - * This may be no-op on some renderers (curses, wayland) + * Set the vertical alignment of the bar. * - * @param menu bm_menu instance to set center mode for. - * @param center true for center mode, false for top mode. + * @param menu bm_menu to set alignment for. + * @param align alignment to set */ -BM_PUBLIC void bm_menu_set_center(struct bm_menu *menu, bool center); +BM_PUBLIC void bm_menu_set_align(struct bm_menu *menu, enum bm_align align); /** - * Display menu at bottom of the screen. - * This may be no-op on some renderers (curses, wayland) + * Get the vertical alignment of the bar. * - * @param menu bm_menu instance to set bottom mode for. - * @param bottom true for bottom mode, false for top mode. + * @param menu bm_menu to get alignment for. + * @return alignment for the menu */ -BM_PUBLIC void bm_menu_set_bottom(struct bm_menu *menu, bool bottom); -/** - * Is menu being displayed at bottom of the screen? - * - * @param menu bm_menu instance where to get bottom mode from. - * @return true if bottom mode, false otherwise. - */ -BM_PUBLIC bool bm_menu_get_bottom(struct bm_menu *menu); +BM_PUBLIC enum bm_align bm_menu_get_align(struct bm_menu *menu); /** * Set the horizontal margin of the bar. diff --git a/lib/internal.h b/lib/internal.h index 555aaa9..f4e5810 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -78,20 +78,15 @@ struct render_api { void (*render)(const struct bm_menu *menu); /** - * Set menu to appear from bottom of the screen. + * Set vertical alignment of the bar. */ - void (*set_bottom)(const struct bm_menu *menu, bool bottom); + void (*set_align)(const struct bm_menu *menu, enum bm_align align); /** * Set horizontal margin. */ void (*set_hmargin_size)(const struct bm_menu *menu, uint32_t margin); - /** - * Set menu to appear from center of the screen. - */ - void (*set_center)(const struct bm_menu *menu, bool center); - /** * Set monitor indeax where menu will appear */ @@ -330,14 +325,9 @@ struct bm_menu { bool wrap; /** - * Is menu shown from center? + * Vertical alignment. */ - bool center; - - /** - * Is menu shown from bottom? - */ - bool bottom; + enum bm_align align; /** * Horizontal margin. diff --git a/lib/menu.c b/lib/menu.c index 4b0b4d4..94387ac 100644 --- a/lib/menu.c +++ b/lib/menu.c @@ -355,38 +355,24 @@ bm_menu_get_scrollbar(struct bm_menu *menu) } void -bm_menu_set_center(struct bm_menu *menu, bool center) +bm_menu_set_align(struct bm_menu *menu, enum bm_align align) { - assert(menu); + assert(menu); - if (menu->center == center) - return; + if(menu->align == align) + return; - menu->center = center; + menu->align = align; - if (menu->renderer->api.set_center) - menu->renderer->api.set_center(menu, center); + if (menu->renderer->api.set_align) + menu->renderer->api.set_align(menu, align); } -void -bm_menu_set_bottom(struct bm_menu *menu, bool bottom) +enum bm_align +bm_menu_get_align(struct bm_menu *menu) { - assert(menu); - - if (menu->bottom == bottom) - return; - - menu->bottom = bottom; - - if (menu->renderer->api.set_bottom) - menu->renderer->api.set_bottom(menu, bottom); -} - -bool -bm_menu_get_bottom(struct bm_menu *menu) -{ - assert(menu); - return menu->bottom; + assert(menu); + return menu->align; } void diff --git a/lib/renderers/wayland/wayland.c b/lib/renderers/wayland/wayland.c index eb8ecc0..2be820a 100644 --- a/lib/renderers/wayland/wayland.c +++ b/lib/renderers/wayland/wayland.c @@ -228,18 +228,6 @@ get_displayed_count(const struct bm_menu *menu) return max; } -static void -set_bottom(const struct bm_menu *menu, bool bottom) -{ - struct wayland *wayland = menu->renderer->internal; - assert(wayland); - - struct window *window; - wl_list_for_each(window, &wayland->windows, link) { - bm_wl_window_set_bottom(window, wayland->display, bottom); - } -} - static void set_hmargin_size(const struct bm_menu *menu, uint32_t margin) { @@ -253,14 +241,14 @@ set_hmargin_size(const struct bm_menu *menu, uint32_t margin) } static void -set_center(const struct bm_menu *menu, bool center) +set_align(const struct bm_menu *menu, enum bm_align align) { struct wayland *wayland = menu->renderer->internal; assert(wayland); struct window *window; wl_list_for_each(window, &wayland->windows, link) { - bm_wl_window_set_center(window, wayland->display, center); + bm_wl_window_set_align(window, wayland->display, align); } } @@ -329,7 +317,7 @@ recreate_windows(const struct bm_menu *menu, struct wayland *wayland) wl_surface_set_buffer_scale(surface, output->scale); struct window *window = calloc(1, sizeof(struct window)); - window->bottom = menu->bottom; + window->align = menu->align; window->hmargin_size = menu->hmargin_size; const char *scale = getenv("BEMENU_SCALE"); @@ -457,8 +445,7 @@ register_renderer(struct render_api *api) api->get_displayed_count = get_displayed_count; api->poll_key = poll_key; api->render = render; - api->set_center = set_center; - api->set_bottom = set_bottom; + api->set_align = set_align; api->set_hmargin_size = set_hmargin_size; api->grab_keyboard = grab_keyboard; api->set_overlap = set_overlap; diff --git a/lib/renderers/wayland/wayland.h b/lib/renderers/wayland/wayland.h index 31b7599..cc6708e 100644 --- a/lib/renderers/wayland/wayland.h +++ b/lib/renderers/wayland/wayland.h @@ -1,6 +1,8 @@ #ifndef _BM_WAYLAND_H_ #define _BM_WAYLAND_H_ +#include "internal.h" + #include #include @@ -88,8 +90,8 @@ struct window { int32_t scale; uint32_t displayed; struct wl_list link; - bool bottom; - bool center; + enum bm_align align; + uint32_t align_anchor; bool render_pending; struct { @@ -130,9 +132,8 @@ 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_bottom(struct window *window, struct wl_display *display, bool bottom); void bm_wl_window_set_hmargin_size(struct window *window, struct wl_display *display, uint32_t margin); -void bm_wl_window_set_center(struct window *window, struct wl_display *display, bool center); +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); bool bm_wl_window_create(struct window *window, struct wl_display *display, struct wl_shm *shm, struct wl_output *output, struct zwlr_layer_shell_v1 *layer_shell, struct wl_surface *surface); diff --git a/lib/renderers/wayland/window.c b/lib/renderers/wayland/window.c index 9011140..55ae849 100644 --- a/lib/renderers/wayland/window.c +++ b/lib/renderers/wayland/window.c @@ -206,6 +206,22 @@ static const struct wl_callback_listener listener = { frame_callback }; +static uint32_t +get_align_anchor(enum bm_align align) +{ + uint32_t anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + + if(align == BM_ALIGN_TOP) { + anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP; + } else if(align == BM_ALIGN_CENTER) { + anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; + } else { + anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; + } + + return anchor; +} + void bm_wl_window_schedule_render(struct window *window) { @@ -302,19 +318,6 @@ static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { .closed = layer_surface_closed, }; -void -bm_wl_window_set_bottom(struct window *window, struct wl_display *display, bool bottom) -{ - if (window->bottom == bottom) - return; - - window->bottom = bottom; - - zwlr_layer_surface_v1_set_anchor(window->layer_surface, (window->bottom ? ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM : ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP) | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT); - wl_surface_commit(window->surface); - wl_display_roundtrip(display); -} - void bm_wl_window_set_hmargin_size(struct window *window, struct wl_display *display, uint32_t margin) { @@ -323,7 +326,7 @@ bm_wl_window_set_hmargin_size(struct window *window, struct wl_display *display, window->hmargin_size = margin; - zwlr_layer_surface_v1_set_anchor(window->layer_surface, (window->bottom ? ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM : ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP) | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT); + 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); wl_surface_commit(window->surface); @@ -331,14 +334,16 @@ bm_wl_window_set_hmargin_size(struct window *window, struct wl_display *display, } void -bm_wl_window_set_center(struct window *window, struct wl_display *display, bool center) +bm_wl_window_set_align(struct window *window, struct wl_display *display, enum bm_align align) { - if (window->center == center) - return; + if(window->align == align) + return; - window->center = center; + window->align = align; - zwlr_layer_surface_v1_set_anchor(window->layer_surface, ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT); + window->align_anchor = get_align_anchor(window->align); + + zwlr_layer_surface_v1_set_anchor(window->layer_surface, window->align_anchor); wl_surface_commit(window->surface); wl_display_roundtrip(display); } @@ -366,7 +371,8 @@ bm_wl_window_create(struct window *window, struct wl_display *display, struct wl if (layer_shell && (window->layer_surface = zwlr_layer_shell_v1_get_layer_surface(layer_shell, surface, output, ZWLR_LAYER_SHELL_V1_LAYER_TOP, "menu"))) { zwlr_layer_surface_v1_add_listener(window->layer_surface, &layer_surface_listener, window); - zwlr_layer_surface_v1_set_anchor(window->layer_surface, (window->bottom ? ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM : ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP) | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT); + window->align_anchor = get_align_anchor(window->align); + zwlr_layer_surface_v1_set_anchor(window->layer_surface, window->align_anchor); zwlr_layer_surface_v1_set_size(window->layer_surface, 0, 32); wl_surface_commit(surface); diff --git a/lib/renderers/x11/window.c b/lib/renderers/x11/window.c index b671c92..b6a93b5 100644 --- a/lib/renderers/x11/window.c +++ b/lib/renderers/x11/window.c @@ -104,11 +104,15 @@ bm_x11_window_render(struct window *window, const struct bm_menu *menu) } if (oldw != window->width || oldh != window->height) { - if (window->bottom) { - XMoveResizeWindow(window->display, window->drawable, window->x, window->max_height - window->height, window->width, window->height); - } else { - XMoveResizeWindow(window->display, window->drawable, window->x, 0, window->width, window->height); + uint32_t win_y = 0; + + if(window->align == BM_ALIGN_CENTER) { + win_y = (window->max_height - window->height) / 2; + } else if(window->align == BM_ALIGN_BOTTOM) { + win_y = window->max_height - window->height; } + + XMoveResizeWindow(window->display, window->drawable, window->x, win_y, window->width, window->height); } if (buffer->created) { @@ -191,14 +195,26 @@ bm_x11_window_set_monitor(struct window *window, int32_t monitor) } window->x = info[i].x_org; - window->y = info[i].y_org + (window->bottom ? info[i].height - window->height : 0); + window->y = info[i].y_org; + if(window->align == BM_ALIGN_CENTER) { + window->y += (info[i].height - window->height) / 2; + } else if(window->align == BM_ALIGN_BOTTOM) { + window->y += info[i].height - window->height; + } + window->width = info[i].width; window->max_height = info[i].height; XFree(info); } else { window->max_height = DisplayHeight(window->display, window->screen); window->x = 0; - window->y = (window->bottom ? window->max_height - window->height : 0); + if(window->align == BM_ALIGN_CENTER) { + window->y = (window->max_height - window->height) / 2; + } else if(window->align == BM_ALIGN_BOTTOM) { + window->y = window->max_height - window->height; + } else { + window->y = 0; + } window->width = DisplayWidth(window->display, window->screen); } @@ -216,12 +232,12 @@ bm_x11_window_set_monitor(struct window *window, int32_t monitor) } void -bm_x11_window_set_bottom(struct window *window, bool bottom) +bm_x11_window_set_align(struct window *window, enum bm_align align) { - if (window->bottom == bottom) + if(window->align == align) return; - window->bottom = bottom; + window->align = align; bm_x11_window_set_monitor(window, window->monitor); } diff --git a/lib/renderers/x11/x11.c b/lib/renderers/x11/x11.c index 50c0235..7d85506 100644 --- a/lib/renderers/x11/x11.c +++ b/lib/renderers/x11/x11.c @@ -199,11 +199,11 @@ get_displayed_count(const struct bm_menu *menu) } static void -set_bottom(const struct bm_menu *menu, bool bottom) +set_align(const struct bm_menu *menu, enum bm_align align) { struct x11 *x11 = menu->renderer->internal; assert(x11); - bm_x11_window_set_bottom(&x11->window, bottom); + bm_x11_window_set_align(&x11->window, align); } static void @@ -276,7 +276,7 @@ constructor(struct bm_menu *menu) XSetClassHint(x11->window.display, x11->window.drawable, (XClassHint[]){{.res_name = (menu->title ? menu->title : "bemenu"), .res_class = "bemenu"}}); - x11->window.bottom = menu->bottom; + x11->window.align = menu->align; bm_x11_window_set_monitor(&x11->window, menu->monitor); x11->window.notify.render = bm_cairo_paint; @@ -295,7 +295,7 @@ register_renderer(struct render_api *api) api->get_displayed_count = get_displayed_count; api->poll_key = poll_key; api->render = render; - api->set_bottom = set_bottom; + api->set_align = set_align; api->set_hmargin_size = set_hmargin_size; api->set_monitor = set_monitor; api->grab_keyboard = grab_keyboard; diff --git a/lib/renderers/x11/x11.h b/lib/renderers/x11/x11.h index c276992..e6ef922 100644 --- a/lib/renderers/x11/x11.h +++ b/lib/renderers/x11/x11.h @@ -1,6 +1,8 @@ #ifndef _BM_X11_H_ #define _BM_X11_H_ +#include "internal.h" + #include #include @@ -36,7 +38,7 @@ struct window { uint32_t displayed; int32_t monitor; - bool bottom; + enum bm_align align; struct { void (*render)(struct cairo *cairo, uint32_t width, uint32_t max_height, const struct bm_menu *menu, struct cairo_paint_result *result); @@ -51,7 +53,7 @@ struct x11 { 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_bottom(struct window *window, bool bottom); +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); bool bm_x11_window_create(struct window *window, Display *display); void bm_x11_window_destroy(struct window *window);