bemenu-run: add --fork option

Make terminal backends not fork by default.
Use this option to fork again on curses.
For non terminal backends this option is no-op.
This commit is contained in:
Jari Vetoniemi 2020-02-08 13:21:36 +02:00
parent b688425bf3
commit 56231f8119
7 changed files with 46 additions and 19 deletions

View File

@ -130,15 +130,17 @@ read_items_to_menu_from_path(struct bm_menu *menu)
static inline void ignore_ret(int useless, ...) { (void)useless; } static inline void ignore_ret(int useless, ...) { (void)useless; }
static void static void
launch(const char *bin) launch(const struct client *client, const char *bin)
{ {
if (!bin) if (!bin)
return; return;
if (fork() == 0) { if (!client->fork || fork() == 0) {
if (client->fork) {
setsid(); setsid();
ignore_ret(0, freopen("/dev/null", "w", stdout)); ignore_ret(0, freopen("/dev/null", "w", stdout));
ignore_ret(0, freopen("/dev/null", "w", stderr)); ignore_ret(0, freopen("/dev/null", "w", stderr));
}
char **tokens; char **tokens;
if (!(tokens = tokenize_quoted_to_argv(bin, NULL, NULL))) if (!(tokens = tokenize_quoted_to_argv(bin, NULL, NULL)))
@ -150,10 +152,9 @@ launch(const char *bin)
} }
static void static void
item_cb(struct bm_item *item, const char *text) item_cb(const struct client *client, struct bm_item *item)
{ {
(void)item; // may be null launch(client, bm_item_get_text(item));
launch(text);
} }
int int

View File

@ -48,9 +48,10 @@ read_items_to_menu_from_stdin(struct bm_menu *menu)
} }
static void static void
item_cb(struct bm_item *item, const char *text) item_cb(const struct client *client, struct bm_item *item)
{ {
(void)item; // may be null (void)client;
const char *text = bm_item_get_text(item);
printf("%s\n", (text ? text : "")); printf("%s\n", (text ? text : ""));
} }

View File

@ -174,7 +174,8 @@ usage(FILE *out, const char *name)
" -P, --prefix text to show before highlighted item.\n" " -P, --prefix text to show before highlighted item.\n"
" -I, --index select item at index automatically.\n" " -I, --index select item at index automatically.\n"
" --scrollbar display scrollbar. (always, autohide)\n" " --scrollbar display scrollbar. (always, autohide)\n"
" --ifne only display menu if there are items.\n\n" " --ifne only display menu if there are items.\n"
" --fork always fork. (bemenu-run)\n\n"
"Use BEMENU_BACKEND env variable to force backend:\n" "Use BEMENU_BACKEND env variable to force backend:\n"
" curses ncurses based terminal backend\n" " curses ncurses based terminal backend\n"
@ -226,6 +227,7 @@ do_getopt(struct client *client, int *argc, char **argv[])
{ "prefix", required_argument, 0, 'P' }, { "prefix", required_argument, 0, 'P' },
{ "scrollbar", required_argument, 0, 0x100 }, { "scrollbar", required_argument, 0, 0x100 },
{ "ifne", no_argument, 0, 0x115 }, { "ifne", no_argument, 0, 0x115 },
{ "fork", required_argument, 0, 0x116 },
{ "bottom", no_argument, 0, 'b' }, { "bottom", no_argument, 0, 'b' },
{ "grab", no_argument, 0, 'f' }, { "grab", no_argument, 0, 'f' },
@ -291,6 +293,9 @@ do_getopt(struct client *client, int *argc, char **argv[])
case 0x115: case 0x115:
client->ifne = true; client->ifne = true;
break; break;
case 0x116:
client->force_fork = true;
break;
case 'b': case 'b':
client->bottom = true; client->bottom = true;
@ -376,12 +381,14 @@ parse_args(struct client *client, int *argc, char **argv[])
} }
struct bm_menu* struct bm_menu*
menu_with_options(const struct client *client) menu_with_options(struct client *client)
{ {
struct bm_menu *menu; struct bm_menu *menu;
if (!(menu = bm_menu_new(NULL))) if (!(menu = bm_menu_new(NULL)))
return NULL; return NULL;
client->fork = (client->force_fork || (bm_renderer_get_priorty(bm_menu_get_renderer(menu)) != BM_PRIO_TERMINAL));
bm_menu_set_font(menu, client->font); bm_menu_set_font(menu, client->font);
bm_menu_set_line_height(menu, client->line_height); bm_menu_set_line_height(menu, client->line_height);
bm_menu_set_title(menu, client->title); bm_menu_set_title(menu, client->title);
@ -408,7 +415,7 @@ menu_with_options(const struct client *client)
} }
enum bm_run_result enum bm_run_result
run_menu(const struct client *client, struct bm_menu *menu, void (*item_cb)(struct bm_item *item, const char *text)) run_menu(const struct client *client, struct bm_menu *menu, void (*item_cb)(const struct client *client, struct bm_item *item))
{ {
bm_menu_set_highlighted_index(menu, client->selected); bm_menu_set_highlighted_index(menu, client->selected);
bm_menu_grab_keyboard(menu, true); bm_menu_grab_keyboard(menu, true);
@ -427,10 +434,7 @@ run_menu(const struct client *client, struct bm_menu *menu, void (*item_cb)(stru
if (status == BM_RUN_RESULT_SELECTED) { if (status == BM_RUN_RESULT_SELECTED) {
uint32_t i, count; uint32_t i, count;
struct bm_item **items = bm_menu_get_selected_items(menu, &count); struct bm_item **items = bm_menu_get_selected_items(menu, &count);
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) item_cb(client, items[i]);
const char *text = bm_item_get_text(items[i]);
item_cb(items[i], text);
}
} }
return status; return status;

View File

@ -20,13 +20,14 @@ struct client {
bool wrap; bool wrap;
bool ifne; bool ifne;
bool no_overlap; bool no_overlap;
bool force_fork, fork;
}; };
char* cstrcopy(const char *str, size_t size); char* cstrcopy(const char *str, size_t size);
char** tokenize_quoted_to_argv(const char *str, char *argv0, int *out_argc); char** tokenize_quoted_to_argv(const char *str, char *argv0, int *out_argc);
void parse_args(struct client *client, int *argc, char **argv[]); void parse_args(struct client *client, int *argc, char **argv[]);
struct bm_menu* menu_with_options(const struct client *client); struct bm_menu* menu_with_options(struct client *client);
enum bm_run_result run_menu(const struct client *client, struct bm_menu *menu, void (*item_cb)(struct bm_item *item, const char *text)); enum bm_run_result run_menu(const struct client *client, struct bm_menu *menu, void (*item_cb)(const struct client *client, struct bm_item *item));
#endif /* _BM_COMMON_H_ */ #endif /* _BM_COMMON_H_ */

View File

@ -252,6 +252,14 @@ void bm_menu_free_items(struct bm_menu *menu);
* @name Menu Properties * @name Menu Properties
* @{ */ * @{ */
/**
* Get the renderer from the bm_menu instance.
*
* @param menu bm_menu instance which renderer to get.
* @return Pointer to bm_renderer instance.
*/
const struct bm_renderer* bm_menu_get_renderer(struct bm_menu *menu);
/** /**
* Set userdata pointer to bm_menu instance. * Set userdata pointer to bm_menu instance.
* Userdata will be carried unmodified by the instance. * Userdata will be carried unmodified by the instance.

View File

@ -139,6 +139,13 @@ bm_menu_free_items(struct bm_menu *menu)
free(menu->filter_item); free(menu->filter_item);
} }
const struct bm_renderer*
bm_menu_get_renderer(struct bm_menu *menu)
{
assert(menu);
return menu->renderer;
}
void void
bm_menu_set_userdata(struct bm_menu *menu, void *userdata) bm_menu_set_userdata(struct bm_menu *menu, void *userdata)
{ {

View File

@ -91,6 +91,11 @@ Show scrollbar only when necessary.
.B \-\-ifne .B \-\-ifne
Only displays the menu when there are items. Only displays the menu when there are items.
.TP
.B \-\-fork
Always fork. (bemenu-run)
By default terminal backends won't fork.
.SS Backend-specific Options .SS Backend-specific Options
These options are only available on backends specified in the parentheses These options are only available on backends specified in the parentheses