Add option to respect panel position (#48)

* implement option to make menu respect panel boundaries

* fixup! implement option to make menu respect panel boundaries
This commit is contained in:
Ilia Bozhinov 2019-03-25 22:21:17 +01:00 committed by Jari Vetoniemi
parent b375ef8b0b
commit 38069992ec
8 changed files with 59 additions and 2 deletions

View File

@ -84,6 +84,7 @@ usage(FILE *out, const char *name)
" -b, --bottom appears at the bottom 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. (x)\n"
" --fn defines the font to be used ('name [size]'). (wx)\n"
" --tb defines the title background color. (wx)\n"
@ -122,6 +123,7 @@ parse_args(struct client *client, int *argc, char **argv[])
{ "bottom", no_argument, 0, 'b' },
{ "grab", no_argument, 0, 'f' },
{ "no-overlap", no_argument, 0, 'n' },
{ "monitor", required_argument, 0, 'm' },
{ "fn", required_argument, 0, 0x101 },
{ "tb", required_argument, 0, 0x102 },
@ -146,7 +148,7 @@ parse_args(struct client *client, int *argc, char **argv[])
* or parse them before running getopt.. */
for (;;) {
int32_t opt = getopt_long(*argc, *argv, "hviwl:I:p:P:I:bfm:", opts, NULL);
int32_t opt = getopt_long(*argc, *argv, "hviwl:I:p:P:I:bfm:n", opts, NULL);
if (opt < 0)
break;
@ -192,6 +194,9 @@ parse_args(struct client *client, int *argc, char **argv[])
case 'm':
client->monitor = strtol(optarg, NULL, 10);
break;
case 'n':
client->no_overlap = true;
break;
case 0x101:
client->font = optarg;
@ -284,6 +289,7 @@ run_menu(const struct client *client, struct bm_menu *menu, void (*item_cb)(stru
{
bm_menu_set_highlighted_index(menu, client->selected);
bm_menu_grab_keyboard(menu, true);
bm_menu_set_panel_overlap(menu, !client->no_overlap);
if (client->ifne && !bm_menu_get_items(menu, NULL))
return BM_RUN_RESULT_CANCEL;

View File

@ -17,6 +17,7 @@ struct client {
bool grab;
bool wrap;
bool ifne;
bool no_overlap;
};
void parse_args(struct client *client, int *argc, char **argv[]);

View File

@ -472,6 +472,11 @@ void bm_menu_grab_keyboard(struct bm_menu *menu, bool grab);
*/
bool bm_menu_is_keyboard_grabbed(struct bm_menu *menu);
/**
* Tell the renderer to position the menu that it can overlap panels.
*/
void bm_menu_set_panel_overlap(struct bm_menu *menu, bool overlap);
/** @} Properties */
/**

View File

@ -90,6 +90,11 @@ struct render_api {
*/
void (*grab_keyboard)(const struct bm_menu *menu, bool grab);
/**
* Control overlap with panels
*/
void (*set_overlap)(const struct bm_menu *menu, bool overlap);
/**
* Version of the plugin.
* Should match BM_PLUGIN_VERSION or failure.
@ -296,6 +301,11 @@ struct bm_menu {
* Is menu grabbed?
*/
bool grabbed;
/**
* Should the menu overlap panels
*/
bool overlap;
};
/* library.c */

View File

@ -370,6 +370,20 @@ bm_menu_is_keyboard_grabbed(struct bm_menu *menu)
return menu->grabbed;
}
void
bm_menu_set_panel_overlap(struct bm_menu *menu, bool overlap)
{
assert(menu);
if (menu->overlap == overlap)
return;
menu->overlap = overlap;
if (menu->renderer->api.set_overlap)
menu->renderer->api.set_overlap(menu, overlap);
}
bool
bm_menu_add_items_at(struct bm_menu *menu, struct bm_item *item, uint32_t index)
{

View File

@ -208,6 +208,18 @@ grab_keyboard(const struct bm_menu *menu, bool grab)
}
}
static void
set_overlap(const struct bm_menu *menu, bool overlap)
{
struct wayland *wayland = menu->renderer->internal;
assert(wayland);
struct window *window;
wl_list_for_each(window, &wayland->windows, link) {
bm_wl_window_set_overlap(window, wayland->display, overlap);
}
}
static void
destructor(struct bm_menu *menu)
{
@ -303,6 +315,7 @@ register_renderer(struct render_api *api)
api->render = render;
api->set_bottom = set_bottom;
api->grab_keyboard = grab_keyboard;
api->set_overlap = set_overlap;
api->priorty = BM_PRIO_GUI;
api->version = BM_PLUGIN_VERSION;
return "wayland";

View File

@ -122,6 +122,7 @@ 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_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);
void bm_wl_window_destroy(struct window *window);

View File

@ -310,6 +310,14 @@ bm_wl_window_grab_keyboard(struct window *window, struct wl_display *display, bo
wl_display_roundtrip(display);
}
void
bm_wl_window_set_overlap(struct window *window, struct wl_display *display, bool overlap)
{
zwlr_layer_surface_v1_set_exclusive_zone(window->layer_surface, overlap ? -1 : 0);
wl_surface_commit(window->surface);
wl_display_roundtrip(display);
}
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)
{
@ -317,7 +325,6 @@ 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_exclusive_zone(window->layer_surface, -1);
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_size(window->layer_surface, 0, 32);
wl_surface_commit(surface);