i3-nagbar: add button flag to execute action with /bin/sh directly.
Fixes #2765.
This commit is contained in:
parent
b56cb84e16
commit
2fe9d7bbd2
116
i3-nagbar/main.c
116
i3-nagbar/main.c
|
@ -50,6 +50,7 @@ static char *argv0 = NULL;
|
||||||
typedef struct {
|
typedef struct {
|
||||||
i3String *label;
|
i3String *label;
|
||||||
char *action;
|
char *action;
|
||||||
|
bool exec_in_terminal;
|
||||||
int16_t x;
|
int16_t x;
|
||||||
uint16_t width;
|
uint16_t width;
|
||||||
} button_t;
|
} button_t;
|
||||||
|
@ -123,6 +124,51 @@ static void start_application(const char *command) {
|
||||||
wait(0);
|
wait(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void execute_in_terminal(const char *command) {
|
||||||
|
/* We need to create a custom script containing our actual command
|
||||||
|
* since not every terminal emulator which is contained in
|
||||||
|
* i3-sensible-terminal supports -e with multiple arguments (and not
|
||||||
|
* all of them support -e with one quoted argument either).
|
||||||
|
*
|
||||||
|
* NB: The paths need to be unique, that is, don’t assume users close
|
||||||
|
* their nagbars at any point in time (and they still need to work).
|
||||||
|
* */
|
||||||
|
char *script_path = get_process_filename("nagbar-cmd");
|
||||||
|
|
||||||
|
int fd = open(script_path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||||
|
if (fd == -1) {
|
||||||
|
warn("Could not create temporary script to store the nagbar command");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FILE *script = fdopen(fd, "w");
|
||||||
|
if (script == NULL) {
|
||||||
|
warn("Could not fdopen() temporary script to store the nagbar command");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fprintf(script, "#!/bin/sh\nrm %s\n%s", script_path, command);
|
||||||
|
/* Also closes fd */
|
||||||
|
fclose(script);
|
||||||
|
|
||||||
|
char *link_path;
|
||||||
|
char *exe_path = get_exe_path(argv0);
|
||||||
|
sasprintf(&link_path, "%s.nagbar_cmd", script_path);
|
||||||
|
if (symlink(exe_path, link_path) == -1) {
|
||||||
|
err(EXIT_FAILURE, "Failed to symlink %s to %s", link_path, exe_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *terminal_cmd;
|
||||||
|
sasprintf(&terminal_cmd, "i3-sensible-terminal -e %s", link_path);
|
||||||
|
printf("argv0 = %s\n", argv0);
|
||||||
|
printf("terminal_cmd = %s\n", terminal_cmd);
|
||||||
|
|
||||||
|
start_application(terminal_cmd);
|
||||||
|
|
||||||
|
free(link_path);
|
||||||
|
free(terminal_cmd);
|
||||||
|
free(script_path);
|
||||||
|
free(exe_path);
|
||||||
|
}
|
||||||
|
|
||||||
static button_t *get_button_at(int16_t x, int16_t y) {
|
static button_t *get_button_at(int16_t x, int16_t y) {
|
||||||
for (int c = 0; c < buttoncnt; c++)
|
for (int c = 0; c < buttoncnt; c++)
|
||||||
if (x >= (buttons[c].x) && x <= (buttons[c].x + buttons[c].width))
|
if (x >= (buttons[c].x) && x <= (buttons[c].x + buttons[c].width))
|
||||||
|
@ -149,51 +195,15 @@ static void handle_button_release(xcb_connection_t *conn, xcb_button_release_eve
|
||||||
if (event->event_x >= btn_close.x && event->event_x < btn_close.x + btn_close.width)
|
if (event->event_x >= btn_close.x && event->event_x < btn_close.x + btn_close.width)
|
||||||
exit(0);
|
exit(0);
|
||||||
button_t *button = get_button_at(event->event_x, event->event_y);
|
button_t *button = get_button_at(event->event_x, event->event_y);
|
||||||
if (!button)
|
if (!button) {
|
||||||
return;
|
|
||||||
|
|
||||||
/* We need to create a custom script containing our actual command
|
|
||||||
* since not every terminal emulator which is contained in
|
|
||||||
* i3-sensible-terminal supports -e with multiple arguments (and not
|
|
||||||
* all of them support -e with one quoted argument either).
|
|
||||||
*
|
|
||||||
* NB: The paths need to be unique, that is, don’t assume users close
|
|
||||||
* their nagbars at any point in time (and they still need to work).
|
|
||||||
* */
|
|
||||||
char *script_path = get_process_filename("nagbar-cmd");
|
|
||||||
|
|
||||||
int fd = open(script_path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
|
||||||
if (fd == -1) {
|
|
||||||
warn("Could not create temporary script to store the nagbar command");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FILE *script = fdopen(fd, "w");
|
|
||||||
if (script == NULL) {
|
if (button->exec_in_terminal) {
|
||||||
warn("Could not fdopen() temporary script to store the nagbar command");
|
execute_in_terminal(button->action);
|
||||||
return;
|
} else {
|
||||||
|
start_application(button->action);
|
||||||
}
|
}
|
||||||
fprintf(script, "#!/bin/sh\nrm %s\n%s", script_path, button->action);
|
|
||||||
/* Also closes fd */
|
|
||||||
fclose(script);
|
|
||||||
|
|
||||||
char *link_path;
|
|
||||||
char *exe_path = get_exe_path(argv0);
|
|
||||||
sasprintf(&link_path, "%s.nagbar_cmd", script_path);
|
|
||||||
if (symlink(exe_path, link_path) == -1) {
|
|
||||||
err(EXIT_FAILURE, "Failed to symlink %s to %s", link_path, exe_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *terminal_cmd;
|
|
||||||
sasprintf(&terminal_cmd, "i3-sensible-terminal -e %s", link_path);
|
|
||||||
printf("argv0 = %s\n", argv0);
|
|
||||||
printf("terminal_cmd = %s\n", terminal_cmd);
|
|
||||||
|
|
||||||
start_application(terminal_cmd);
|
|
||||||
|
|
||||||
free(link_path);
|
|
||||||
free(terminal_cmd);
|
|
||||||
free(script_path);
|
|
||||||
free(exe_path);
|
|
||||||
|
|
||||||
/* TODO: unset flag, re-render */
|
/* TODO: unset flag, re-render */
|
||||||
}
|
}
|
||||||
|
@ -358,12 +368,13 @@ int main(int argc, char *argv[]) {
|
||||||
{"version", no_argument, 0, 'v'},
|
{"version", no_argument, 0, 'v'},
|
||||||
{"font", required_argument, 0, 'f'},
|
{"font", required_argument, 0, 'f'},
|
||||||
{"button", required_argument, 0, 'b'},
|
{"button", required_argument, 0, 'b'},
|
||||||
|
{"button-sh", required_argument, 0, 'B'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{"message", required_argument, 0, 'm'},
|
{"message", required_argument, 0, 'm'},
|
||||||
{"type", required_argument, 0, 't'},
|
{"type", required_argument, 0, 't'},
|
||||||
{0, 0, 0, 0}};
|
{0, 0, 0, 0}};
|
||||||
|
|
||||||
char *options_string = "b:f:m:t:vh";
|
char *options_string = "B:b:f:m:t:vh";
|
||||||
|
|
||||||
prompt = i3string_from_utf8("Please do not run this program.");
|
prompt = i3string_from_utf8("Please do not run this program.");
|
||||||
|
|
||||||
|
@ -385,15 +396,26 @@ int main(int argc, char *argv[]) {
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
printf("i3-nagbar " I3_VERSION "\n");
|
printf("i3-nagbar " I3_VERSION "\n");
|
||||||
printf("i3-nagbar [-m <message>] [-b <button> <action>] [-t warning|error] [-f <font>] [-v]\n");
|
printf("i3-nagbar [-m <message>] [-b <button> <terminal-action>] "
|
||||||
|
"[-B <button> <shell-action> [-t warning|error] [-f <font>] [-v]\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
/* falls through */
|
||||||
|
case 'B':
|
||||||
case 'b':
|
case 'b':
|
||||||
buttons = srealloc(buttons, sizeof(button_t) * (buttoncnt + 1));
|
buttons = srealloc(buttons, sizeof(button_t) * (buttoncnt + 1));
|
||||||
buttons[buttoncnt].label = i3string_from_utf8(optarg);
|
buttons[buttoncnt].label = i3string_from_utf8(optarg);
|
||||||
buttons[buttoncnt].action = argv[optind];
|
buttons[buttoncnt].action = argv[optind];
|
||||||
printf("button with label *%s* and action *%s*\n",
|
if (o == 'b') {
|
||||||
i3string_as_utf8(buttons[buttoncnt].label),
|
buttons[buttoncnt].exec_in_terminal = true;
|
||||||
buttons[buttoncnt].action);
|
printf("button with label *%s* and terminal action *%s*\n",
|
||||||
|
i3string_as_utf8(buttons[buttoncnt].label),
|
||||||
|
buttons[buttoncnt].action);
|
||||||
|
} else {
|
||||||
|
buttons[buttoncnt].exec_in_terminal = false;
|
||||||
|
printf("button with label *%s* and shell action *%s*\n",
|
||||||
|
i3string_as_utf8(buttons[buttoncnt].label),
|
||||||
|
buttons[buttoncnt].action);
|
||||||
|
}
|
||||||
buttoncnt++;
|
buttoncnt++;
|
||||||
printf("now %d buttons\n", buttoncnt);
|
printf("now %d buttons\n", buttoncnt);
|
||||||
if (optind < argc)
|
if (optind < argc)
|
||||||
|
|
|
@ -9,7 +9,7 @@ i3-nagbar - displays an error bar on top of your screen
|
||||||
|
|
||||||
== SYNOPSIS
|
== SYNOPSIS
|
||||||
|
|
||||||
i3-nagbar [-m <message>] [-b <button> <action>] [-t warning|error] [-f <font>] [-v]
|
i3-nagbar [-m <message>] [-b <button> <terminal-action>] [-B <button> <shell-action>] [-t warning|error] [-f <font>] [-v]
|
||||||
|
|
||||||
== OPTIONS
|
== OPTIONS
|
||||||
|
|
||||||
|
@ -29,9 +29,13 @@ Display 'message' as text on the left of the i3-nagbar.
|
||||||
*-f, --font* 'font'::
|
*-f, --font* 'font'::
|
||||||
Select font that is being used.
|
Select font that is being used.
|
||||||
|
|
||||||
*-b, --button* 'button' 'action'::
|
*-b, --button* 'button' 'terminal-action'::
|
||||||
Create a button with text 'button'. The 'action' are the shell commands that
|
Adds a button labelled 'button' to the bar. When pressed, the command given
|
||||||
will be executed by this button. Multiple buttons can be defined.
|
in 'terminal-action' is executed inside a terminal emulator, via i3-sensible-terminal(1).
|
||||||
|
Multiple buttons can be defined.
|
||||||
|
|
||||||
|
*-B, --button-sh* 'button' 'shell-action'::
|
||||||
|
Same as *--button*, except that the command given in 'shell-action' is executed directly by the shell.
|
||||||
|
|
||||||
== DESCRIPTION
|
== DESCRIPTION
|
||||||
|
|
||||||
|
@ -49,7 +53,7 @@ i3-nagbar -m 'You have an error in your i3 config file!' \
|
||||||
|
|
||||||
== SEE ALSO
|
== SEE ALSO
|
||||||
|
|
||||||
i3(1)
|
i3(1), i3-sensible-terminal(1)
|
||||||
|
|
||||||
== AUTHOR
|
== AUTHOR
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue