diff --git a/client/common/common.c b/client/common/common.c index 0047a97..957e197 100644 --- a/client/common/common.c +++ b/client/common/common.c @@ -174,6 +174,7 @@ usage(FILE *out, const char *name) " -p, --prompt defines the prompt text to be displayed.\n" " -P, --prefix text to show before highlighted item.\n" " -I, --index select item at index automatically.\n" + " -x, --password hide input.\n" " --scrollbar display scrollbar. (none (default), always, autohide)\n" " --ifne only display menu if there are items.\n" " --fork always fork. (bemenu-run)\n" @@ -228,6 +229,7 @@ do_getopt(struct client *client, int *argc, char **argv[]) { "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 }, @@ -262,7 +264,7 @@ do_getopt(struct client *client, int *argc, char **argv[]) for (optind = 0;;) { int32_t opt; - if ((opt = getopt_long(*argc, *argv, "hviwl:I:p:P:I:bfm:H:n", opts, NULL)) < 0) + if ((opt = getopt_long(*argc, *argv, "hviwxl:I:p:P:I:bfm:H:n", opts, NULL)) < 0) break; switch (opt) { @@ -306,6 +308,9 @@ do_getopt(struct client *client, int *argc, char **argv[]) case 0x117: client->no_exec = true; break; + case 'x': + client->password = true; + break; case 'b': client->bottom = true; @@ -410,6 +415,7 @@ menu_with_options(struct client *client) bm_menu_set_monitor(menu, client->monitor); bm_menu_set_scrollbar(menu, client->scrollbar); bm_menu_set_panel_overlap(menu, !client->no_overlap); + bm_menu_set_password(menu, client->password); for (uint32_t i = 0; i < BM_COLOR_LAST; ++i) bm_menu_set_color(menu, i, client->colors[i]); diff --git a/client/common/common.h b/client/common/common.h index 8fbeeca..bbfb3c1 100644 --- a/client/common/common.h +++ b/client/common/common.h @@ -23,6 +23,7 @@ struct client { bool no_overlap; bool force_fork, fork; bool no_exec; + bool password; }; char* cstrcopy(const char *str, size_t size); diff --git a/lib/bemenu.h b/lib/bemenu.h index df5546f..4cbe79c 100644 --- a/lib/bemenu.h +++ b/lib/bemenu.h @@ -540,6 +540,23 @@ BM_PUBLIC bool bm_menu_is_keyboard_grabbed(struct bm_menu *menu); */ BM_PUBLIC void bm_menu_set_panel_overlap(struct bm_menu *menu, bool overlap); +/** + * Replace input with asterisks. + * + * @param menu bm_menu instance to set password mode for. + * @param password true for password mode, false for deafault behavior. + */ +BM_PUBLIC void bm_menu_set_password(struct bm_menu *menu, bool password); + +/** + * Is password mode activated and input hidden? + * + * @param menu bm_menu instance where to get password mode from. + * @return true if password mode, false otherwise. + */ +BM_PUBLIC bool bm_menu_get_password(struct bm_menu *menu); + + /** @} Properties */ /** diff --git a/lib/internal.h b/lib/internal.h index 4a6018d..db6035e 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -315,6 +315,11 @@ struct bm_menu { * Should the menu overlap panels */ bool overlap; + + /** + * Should the input be hidden + */ + bool password; }; /* library.c */ diff --git a/lib/menu.c b/lib/menu.c index 149d441..d65ceb0 100644 --- a/lib/menu.c +++ b/lib/menu.c @@ -414,6 +414,24 @@ bm_menu_set_panel_overlap(struct bm_menu *menu, bool overlap) menu->renderer->api.set_overlap(menu, overlap); } +void +bm_menu_set_password(struct bm_menu *menu, bool password) +{ + assert(menu); + + if (menu->password == password) + return; + + menu->password = password; +} + +bool +bm_menu_get_password(struct bm_menu *menu) +{ + assert(menu); + return menu->password; +} + bool bm_menu_add_item_at(struct bm_menu *menu, struct bm_item *item, uint32_t index) { diff --git a/lib/renderers/cairo.h b/lib/renderers/cairo.h index 6023f29..5a80d6e 100644 --- a/lib/renderers/cairo.h +++ b/lib/renderers/cairo.h @@ -247,7 +247,14 @@ bm_cairo_paint(struct cairo *cairo, uint32_t width, uint32_t max_height, const s paint.cursor = menu->cursor; paint.pos = (struct pos){ (menu->title ? 2 : 0) + result.x_advance, vpadding }; paint.box = (struct box){ (menu->title ? 2 : 4), 0, vpadding, vpadding, width - paint.pos.x, ascii_height }; - bm_cairo_draw_line(cairo, &paint, &result, "%s", (menu->filter ? menu->filter : "")); + + const char *filter_text = (menu->filter ? menu->filter : ""); + if (menu->password) { + bm_cairo_draw_line(cairo, &paint, &result, ""); + } else { + bm_cairo_draw_line(cairo, &paint, &result, "%s", filter_text); + } + paint.draw_cursor = false; const uint32_t titleh = result.height; out_result->height = titleh; diff --git a/lib/renderers/curses/curses.c b/lib/renderers/curses/curses.c index 8ddc8ba..445bcae 100644 --- a/lib/renderers/curses/curses.c +++ b/lib/renderers/curses/curses.c @@ -221,7 +221,12 @@ render(const struct bm_menu *menu) doffset -= (prev ? prev : 1); } - draw_line(0, 0, "%*s%s", title_len, "", (menu->filter ? menu->filter + doffset : "")); + const char *filter_text = (menu->filter ? menu->filter + doffset : ""); + if (menu->password) { + draw_line(0, 0, "%*s%s", title_len, ""); + } else { + draw_line(0, 0, "%*s%s", title_len, "", filter_text); + } if (menu->title && title_len > 0) { attron(COLOR_PAIR(1));