i3bar: Allow child to specify signals to use
We now wait for the child process to send the first line before stopping it to use the signal which might be specified in the i3bar protocol header Since clients might use the same signal for both stop and cont, we also save the stopped state of the child to avoid stopping it while hidden!
This commit is contained in:
parent
1e114d7ab5
commit
8210c6be79
|
@ -10,6 +10,8 @@
|
|||
#ifndef CHILD_H_
|
||||
#define CHILD_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define STDIN_CHUNK_SIZE 1024
|
||||
|
||||
typedef struct {
|
||||
|
@ -21,6 +23,16 @@ typedef struct {
|
|||
* even an int8_t, but still…
|
||||
*/
|
||||
uint32_t version;
|
||||
|
||||
bool stopped;
|
||||
/**
|
||||
* The signal requested by the client to inform it of the hidden state of i3bar
|
||||
*/
|
||||
int stop_signal;
|
||||
/**
|
||||
* The signal requested by the client to inform it of theun hidden state of i3bar
|
||||
*/
|
||||
int cont_signal;
|
||||
} i3bar_child;
|
||||
|
||||
/*
|
||||
|
|
|
@ -13,15 +13,12 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Determines the JSON i3bar protocol version from the given buffer. In case
|
||||
* the buffer does not contain valid JSON, or no version field is found, this
|
||||
* function returns -1. The amount of bytes consumed by parsing the header is
|
||||
* returned in *consumed (if non-NULL).
|
||||
*
|
||||
* The return type is an int32_t to avoid machines with different sizes of
|
||||
* 'int' to allow different values here. It’s highly unlikely we ever exceed
|
||||
* even an int8_t, but still…
|
||||
/**
|
||||
* Parse the JSON protocol header to determine protocol version and features.
|
||||
* In case the buffer does not contain a valid header (invalid JSON, or no
|
||||
* version field found), the 'correct' field of the returned header is set to
|
||||
* false. The amount of bytes consumed by parsing the header is returned in
|
||||
* *consumed (if non-NULL).
|
||||
*
|
||||
*/
|
||||
void parse_json_header(i3bar_child *child, const unsigned char *buffer, int length, unsigned int *consumed);
|
||||
|
|
|
@ -251,6 +251,11 @@ void stdin_io_first_line_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
|
|||
* in the future, but for now, we just discard it. */
|
||||
parse_json_header(&child, buffer, rec, &consumed);
|
||||
if (child.version > 0) {
|
||||
/* If hide-on-modifier is set, we start of by sending the
|
||||
* child a SIGSTOP, because the bars aren't mapped at start */
|
||||
if (config.hide_on_modifier) {
|
||||
stop_child();
|
||||
}
|
||||
read_json_input(buffer + consumed, rec - consumed);
|
||||
} else {
|
||||
/* In case of plaintext, we just add a single block and change its
|
||||
|
@ -330,12 +335,6 @@ void start_child(char *command) {
|
|||
|
||||
dup2(fd[0], STDIN_FILENO);
|
||||
|
||||
/* If hide-on-modifier is set, we start of by sending the
|
||||
* child a SIGSTOP, because the bars aren't mapped at start */
|
||||
if (config.hide_on_modifier) {
|
||||
stop_child();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -361,7 +360,8 @@ void start_child(char *command) {
|
|||
*/
|
||||
void kill_child_at_exit(void) {
|
||||
if (child.pid > 0) {
|
||||
kill(child.pid, SIGCONT);
|
||||
if (child.cont_signal > 0 && child.stopped)
|
||||
kill(child.pid, child.cont_signal);
|
||||
kill(child.pid, SIGTERM);
|
||||
}
|
||||
}
|
||||
|
@ -373,7 +373,8 @@ void kill_child_at_exit(void) {
|
|||
*/
|
||||
void kill_child(void) {
|
||||
if (child.pid > 0) {
|
||||
kill(child.pid, SIGCONT);
|
||||
if (child.cont_signal > 0 && child.stopped)
|
||||
kill(child.pid, child.cont_signal);
|
||||
kill(child.pid, SIGTERM);
|
||||
int status;
|
||||
waitpid(child.pid, &status, 0);
|
||||
|
@ -386,8 +387,9 @@ void kill_child(void) {
|
|||
*
|
||||
*/
|
||||
void stop_child(void) {
|
||||
if (child.pid > 0) {
|
||||
kill(child.pid, SIGSTOP);
|
||||
if (child.stop_signal > 0 && !child.stopped) {
|
||||
child.stopped = true;
|
||||
kill(child.pid, child.stop_signal);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -396,7 +398,8 @@ void stop_child(void) {
|
|||
*
|
||||
*/
|
||||
void cont_child(void) {
|
||||
if (child.pid > 0) {
|
||||
kill(child.pid, SIGCONT);
|
||||
if (child.cont_signal > 0 && child.stopped) {
|
||||
child.stopped = false;
|
||||
kill(child.pid, child.cont_signal);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
static enum {
|
||||
KEY_VERSION,
|
||||
KEY_STOP_SIGNAL,
|
||||
KEY_CONT_SIGNAL,
|
||||
NO_KEY
|
||||
} current_key;
|
||||
|
||||
|
@ -43,6 +45,12 @@ static int header_integer(void *ctx, long val) {
|
|||
case KEY_VERSION:
|
||||
child->version = val;
|
||||
break;
|
||||
case KEY_STOP_SIGNAL:
|
||||
child->stop_signal = val;
|
||||
break;
|
||||
case KEY_CONT_SIGNAL:
|
||||
child->cont_signal = val;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -59,6 +67,10 @@ static int header_map_key(void *ctx, const unsigned char *stringval, unsigned in
|
|||
#endif
|
||||
if (CHECK_KEY("version")) {
|
||||
current_key = KEY_VERSION;
|
||||
} else if (CHECK_KEY("stop_signal")) {
|
||||
current_key = KEY_STOP_SIGNAL;
|
||||
} else if (CHECK_KEY("cont_signal")) {
|
||||
current_key = KEY_CONT_SIGNAL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -79,6 +91,8 @@ static yajl_callbacks version_callbacks = {
|
|||
|
||||
static void child_init(i3bar_child *child) {
|
||||
child->version = 0;
|
||||
child->stop_signal = SIGSTOP;
|
||||
child->cont_signal = SIGCONT;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue