From 7d7867acce523abac9b20f86fe3c476e8c92c7a8 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Thu, 5 Aug 2010 05:09:59 +0200 Subject: [PATCH] Be more strict with encapsulation I.e. move the xcb-event-handling into xcb.c and the child-process-communications into newly created child.c. Also change some includes. --- i3bar/include/child.h | 9 +++ i3bar/include/common.h | 10 ++- i3bar/include/ipc.h | 1 - i3bar/include/outputs.h | 1 - i3bar/include/workspaces.h | 1 - i3bar/include/xcb.h | 18 +---- i3bar/src/child.c | 135 ++++++++++++++++++++++++++++++++++ i3bar/src/ipc.c | 5 +- i3bar/src/main.c | 145 +------------------------------------ i3bar/src/outputs.c | 3 - i3bar/src/workspaces.c | 4 - i3bar/src/xcb.c | 59 ++++++++++++++- 12 files changed, 211 insertions(+), 180 deletions(-) create mode 100644 i3bar/include/child.h create mode 100644 i3bar/src/child.c diff --git a/i3bar/include/child.h b/i3bar/include/child.h new file mode 100644 index 00000000..3d3c28c9 --- /dev/null +++ b/i3bar/include/child.h @@ -0,0 +1,9 @@ +#ifndef CHILD_H_ +#define CHILD_H_ + +#define STDIN_CHUNK_SIZE 1024 + +void start_child(char *command); +void kill_child(); + +#endif diff --git a/i3bar/include/common.h b/i3bar/include/common.h index e2bfb40b..3feab698 100644 --- a/i3bar/include/common.h +++ b/i3bar/include/common.h @@ -1,8 +1,6 @@ #ifndef COMMON_H_ #define COMMON_H_ -#include "util.h" - typedef struct rect_t rect; typedef int bool; @@ -17,4 +15,12 @@ struct rect_t { int h; }; +#include "queue.h" +#include "child.h" +#include "ipc.h" +#include "outputs.h" +#include "util.h" +#include "workspaces.h" +#include "xcb.h" + #endif diff --git a/i3bar/include/ipc.h b/i3bar/include/ipc.h index 278077e0..b3760d2a 100644 --- a/i3bar/include/ipc.h +++ b/i3bar/include/ipc.h @@ -1,7 +1,6 @@ #ifndef IPC_H_ #define IPC_H_ -#include #include int init_connection(const char *socket_path); diff --git a/i3bar/include/outputs.h b/i3bar/include/outputs.h index 05383615..b00a93b4 100644 --- a/i3bar/include/outputs.h +++ b/i3bar/include/outputs.h @@ -4,7 +4,6 @@ #include #include "common.h" -#include "workspaces.h" typedef struct i3_output i3_output; diff --git a/i3bar/include/workspaces.h b/i3bar/include/workspaces.h index 64c1065e..ae3c1303 100644 --- a/i3bar/include/workspaces.h +++ b/i3bar/include/workspaces.h @@ -2,7 +2,6 @@ #define WORKSPACES_H_ #include "common.h" -#include "outputs.h" typedef struct i3_ws i3_ws; diff --git a/i3bar/include/xcb.h b/i3bar/include/xcb.h index d97113a9..a75b7154 100644 --- a/i3bar/include/xcb.h +++ b/i3bar/include/xcb.h @@ -1,22 +1,7 @@ #ifndef XCB_H_ #define XCB_H_ -#include - -#define NUM_ATOMS 3 - -enum { - #define ATOM_DO(name) name, - #include "xcb_atoms.def" -}; - -xcb_atom_t atoms[NUM_ATOMS]; - -xcb_connection_t *xcb_connection; -xcb_screen_t *xcb_screens; -xcb_window_t xcb_root; -xcb_font_t xcb_font; -int font_height; +int font_height; void init_xcb(); void clean_xcb(); @@ -25,6 +10,5 @@ void destroy_windows(); void create_windows(); void draw_bars(); int get_string_width(char *string); -void handle_xcb_event(xcb_generic_event_t *event); #endif diff --git a/i3bar/src/child.c b/i3bar/src/child.c new file mode 100644 index 00000000..5fe9ca8c --- /dev/null +++ b/i3bar/src/child.c @@ -0,0 +1,135 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +ev_io *child_io; +ev_child *child_sig; + +void cleanup() { + ev_io_stop(main_loop, child_io); + ev_child_stop(main_loop, child_sig); + FREE(child_io); + FREE(child_sig); + FREE(statusline); +} + +void strip_dzen_formats(char *buffer) { + char *src = buffer; + char *dest = buffer; + while (*src != '\0') { + if (*src == '^') { + if (!strncmp(src, "^ro", strlen("^ro"))) { + *(dest++) = ' '; + *(dest++) = '|'; + *(dest++) = ' '; + } + while (*src != ')') { + src++; + } + src++; + } else { + *dest = *src; + src++; + dest++; + } + } + *(--dest) = '\0'; +} + +void child_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { + int fd = watcher->fd; + int n = 0; + int rec = 0; + int buffer_len = STDIN_CHUNK_SIZE; + char *buffer = malloc(buffer_len); + memset(buffer, '\0', buffer_len); + while(1) { + n = read(fd, buffer + rec, buffer_len - rec); + if (n == -1) { + if (errno == EAGAIN) { + break; + } + printf("ERROR: read() failed!"); + exit(EXIT_FAILURE); + } + if (n == 0) { + if (rec == buffer_len) { + char *tmp = buffer; + buffer = malloc(buffer_len + STDIN_CHUNK_SIZE); + memset(buffer, '\0', buffer_len); + strncpy(buffer, tmp, buffer_len); + buffer_len += STDIN_CHUNK_SIZE; + FREE(tmp); + } else { + break; + } + } + rec += n; + } + if (strlen(buffer) == 0) { + FREE(buffer); + return; + } + strip_dzen_formats(buffer); + FREE(statusline); + statusline = buffer; + printf("%s", buffer); + draw_bars(); +} + +void child_sig_cb(struct ev_loop *loop, ev_child *watcher, int revents) { + printf("Child (pid: %d) unexpectedly exited with status %d\n", child_pid, watcher->rstatus); + cleanup(); +} + +void start_child(char *command) { + int fd[2]; + pipe(fd); + child_pid = fork(); + switch (child_pid) { + case -1: + printf("ERROR: Couldn't fork()"); + exit(EXIT_FAILURE); + case 0: + close(fd[0]); + + dup2(fd[1], STDOUT_FILENO); + + static const char *shell = NULL; + + if ((shell = getenv("SHELL")) == NULL) + shell = "/bin/sh"; + + execl(shell, shell, "-c", command, (char*) NULL); + break; + default: + close(fd[1]); + + dup2(fd[0], STDIN_FILENO); + fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); + + child_io = malloc(sizeof(ev_io)); + ev_io_init(child_io, &child_io_cb, STDIN_FILENO, EV_READ); + ev_io_start(main_loop, child_io); + + /* We must cleanup, if the child unexpectedly terminates */ + child_sig = malloc(sizeof(ev_io)); + ev_child_init(child_sig, &child_sig_cb, child_pid, 0); + ev_child_start(main_loop, child_sig); + + break; + } +} + +void kill_child() { + kill(child_pid, SIGQUIT); + cleanup(); +} diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index bf91420e..4b17a4bc 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -5,12 +5,9 @@ #include #include #include +#include #include "common.h" -#include "outputs.h" -#include "workspaces.h" -#include "xcb.h" -#include "ipc.h" ev_io *i3_connection; diff --git a/i3bar/src/main.c b/i3bar/src/main.c index ab362d5c..6ce7a38a 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -3,126 +3,10 @@ #include #include #include -#include #include #include -#include -#include "ipc.h" -#include "outputs.h" -#include "workspaces.h" #include "common.h" -#include "xcb.h" - -#define STDIN_CHUNK_SIZE 1024 - -void ev_prepare_cb(struct ev_loop *loop, ev_prepare *w, int revents) { - xcb_flush(xcb_connection); -} - -void ev_check_cb(struct ev_loop *loop, ev_check *w, int revents) { - xcb_generic_event_t *event; - if ((event = xcb_poll_for_event(xcb_connection)) != NULL) { - handle_xcb_event(event); - } - free(event); -} - -void xcb_io_cb(struct ev_loop *loop, ev_io *w, int revents) { -} - -void start_child(char *command) { - int fd[2]; - pipe(fd); - child_pid = fork(); - switch (child_pid) { - case -1: - printf("ERROR: Couldn't fork()"); - exit(EXIT_FAILURE); - case 0: - close(fd[0]); - - dup2(fd[1], STDOUT_FILENO); - - static const char *shell = NULL; - - if ((shell = getenv("SHELL")) == NULL) - shell = "/bin/sh"; - - execl(shell, shell, "-c", command, (char*) NULL); - break; - default: - close(fd[1]); - - dup2(fd[0], STDIN_FILENO); - - break; - } -} - -void strip_dzen_formats(char *buffer) { - char *src = buffer; - char *dest = buffer; - while (*src != '\0') { - if (*src == '^') { - if (!strncmp(src, "^ro", strlen("^ro"))) { - *(dest++) = ' '; - *(dest++) = '|'; - *(dest++) = ' '; - } - while (*src != ')') { - src++; - } - src++; - } else { - *dest = *src; - src++; - dest++; - } - } - *(--dest) = '\0'; -} - -void child_io_cb(struct ev_loop *loop, ev_io *w, int revents) { - int fd = w->fd; - int n = 0; - int rec = 0; - int buffer_len = STDIN_CHUNK_SIZE; - char *buffer = malloc(buffer_len); - memset(buffer, '\0', buffer_len); - while(1) { - n = read(fd, buffer + rec, buffer_len - rec); - if (n == -1) { - if (errno == EAGAIN) { - break; - } - printf("ERROR: read() failed!"); - exit(EXIT_FAILURE); - } - if (n == 0) { - if (rec == buffer_len) { - char *tmp = buffer; - buffer = malloc(buffer_len + STDIN_CHUNK_SIZE); - memset(buffer, '\0', buffer_len); - strncpy(buffer, tmp, buffer_len); - buffer_len += STDIN_CHUNK_SIZE; - FREE(tmp); - } else { - break; - } - } - rec += n; - } - if (strlen(buffer) == 0) { - FREE(buffer); - return; - } - strip_dzen_formats(buffer); - FREE(statusline); - statusline = buffer; - printf("%s", buffer); - draw_bars(); -} int main(int argc, char **argv) { main_loop = ev_default_loop(0); @@ -132,44 +16,19 @@ int main(int argc, char **argv) { subscribe_events(); - ev_io *xcb_io = malloc(sizeof(ev_io)); - ev_prepare *ev_prep = malloc(sizeof(ev_prepare)); - ev_check *ev_chk = malloc(sizeof(ev_check)); - - ev_io_init(xcb_io, &xcb_io_cb, xcb_get_file_descriptor(xcb_connection), EV_READ); - ev_prepare_init(ev_prep, &ev_prepare_cb); - ev_check_init(ev_chk, &ev_check_cb); - - ev_io_start(main_loop, xcb_io); - ev_prepare_start(main_loop, ev_prep); - ev_check_start(main_loop, ev_chk); - i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_OUTPUTS, NULL); i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL); start_child("i3status"); - fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); - ev_io *child_io = malloc(sizeof(ev_io)); - ev_io_init(child_io, &child_io_cb, STDIN_FILENO, EV_READ); - ev_io_start(main_loop, child_io); - ev_loop(main_loop, 0); - ev_prepare_stop(main_loop, ev_prep); - ev_check_stop(main_loop, ev_chk); - ev_io_stop(main_loop, xcb_io); - ev_io_stop(main_loop, child_io); - - FREE(xcb_io); - FREE(ev_prep); - FREE(ev_chk); - free(child_io); + kill_child(); FREE(statusline); - ev_default_destroy(); clean_xcb(); + ev_default_destroy(); free_workspaces(); FREE_SLIST(outputs, i3_output); diff --git a/i3bar/src/outputs.c b/i3bar/src/outputs.c index 18abff51..dc61cb47 100644 --- a/i3bar/src/outputs.c +++ b/i3bar/src/outputs.c @@ -2,12 +2,9 @@ #include #include #include - #include #include "common.h" -#include "outputs.h" -#include "ipc.h" struct outputs_json_params { struct outputs_head *outputs; diff --git a/i3bar/src/workspaces.c b/i3bar/src/workspaces.c index ee54c8b6..abc3a572 100644 --- a/i3bar/src/workspaces.c +++ b/i3bar/src/workspaces.c @@ -1,13 +1,9 @@ #include #include #include - #include #include "common.h" -#include "workspaces.h" -#include "xcb.h" -#include "ipc.h" struct workspaces_json_params { struct ws_head *workspaces; diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index eff74ac4..154af575 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -3,14 +3,28 @@ #include #include #include +#include -#include "xcb.h" -#include "outputs.h" -#include "workspaces.h" #include "common.h" -#include "ipc.h" + +#define NUM_ATOMS 3 + +enum { + #define ATOM_DO(name) name, + #include "xcb_atoms.def" +}; xcb_intern_atom_cookie_t atom_cookies[NUM_ATOMS]; +xcb_atom_t atoms[NUM_ATOMS]; + +xcb_connection_t *xcb_connection; +xcb_screen_t *xcb_screens; +xcb_window_t xcb_root; +xcb_font_t xcb_font; + +ev_prepare *xcb_prep; +ev_check *xcb_chk; +ev_io *xcb_io; uint32_t get_colorpixel(const char *s) { char strings[3][3] = { { s[0], s[1], '\0'} , @@ -97,6 +111,23 @@ void handle_xcb_event(xcb_generic_event_t *event) { } } +void xcb_prep_cb(struct ev_loop *loop, ev_prepare *watcher, int revenst) { + xcb_flush(xcb_connection); +} + +void xcb_chk_cb(struct ev_loop *loop, ev_check *watcher, int revents) { + xcb_generic_event_t *event; + if ((event = xcb_poll_for_event(xcb_connection)) != NULL) { + handle_xcb_event(event); + } + FREE(event); +} + +void xcb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { + /* Dummy Callback. We only need this, so that xcb-events trigger + * Prepare- and Check-Watchers */ +} + int get_string_width(char *string) { xcb_query_text_extents_cookie_t cookie; xcb_query_text_extents_reply_t *reply; @@ -150,12 +181,32 @@ void init_xcb() { FREE(reply); printf("Calculated Font-height: %d\n", font_height); + xcb_io = malloc(sizeof(ev_io)); + xcb_prep = malloc(sizeof(ev_prepare)); + xcb_chk = malloc(sizeof(ev_check)); + + ev_io_init(xcb_io, &xcb_io_cb, xcb_get_file_descriptor(xcb_connection), EV_READ); + ev_prepare_init(xcb_prep, &xcb_prep_cb); + ev_check_init(xcb_chk, &xcb_chk_cb); + + ev_io_start(main_loop, xcb_io); + ev_prepare_start(main_loop, xcb_prep); + ev_check_start(main_loop, xcb_chk); + /* FIXME: Maybe we can push that further backwards */ get_atoms(); } void clean_xcb() { xcb_disconnect(xcb_connection); + + ev_check_stop(main_loop, xcb_chk); + ev_prepare_stop(main_loop, xcb_prep); + ev_io_stop(main_loop, xcb_io); + + FREE(xcb_chk); + FREE(xcb_prep); + FREE(xcb_io); } void get_atoms() { -- 2.39.2