From 3de12beef6ffacd252c5cc5d365969436311940d Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 22 Nov 2010 00:07:52 +0100 Subject: [PATCH 01/55] make i3bar work with tree branch again (current_workspace is a string now) --- i3bar/src/outputs.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/i3bar/src/outputs.c b/i3bar/src/outputs.c index 3577d82b..20ff8276 100644 --- a/i3bar/src/outputs.c +++ b/i3bar/src/outputs.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -102,6 +103,22 @@ static int outputs_integer_cb(void *params_, long val) { static int outputs_string_cb(void *params_, const unsigned char *val, unsigned int len) { struct outputs_json_params *params = (struct outputs_json_params*) params_; + if (!strcmp(params->cur_key, "current_workspace")) { + char *copy = malloc(sizeof(const unsigned char) * (len + 1)); + strncpy(copy, (const char*) val, len); + copy[len] = '\0'; + + char *end; + errno = 0; + long parsed_num = strtol(copy, &end, 10); + if (errno == 0 && + (end && *end == '\0')) + params->outputs_walk->ws = parsed_num; + free(copy); + FREE(params->cur_key); + return 1; + } + if (strcmp(params->cur_key, "name")) { return 0; } From 537851b92952c060ebae153046dfbcd6a5177ff1 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Fri, 3 Dec 2010 17:59:16 +0100 Subject: [PATCH 02/55] Switch back ws_fg and ws_bg (Thanks julien) --- i3bar/src/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i3bar/src/main.c b/i3bar/src/main.c index 35ea9210..ec85d324 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -181,10 +181,10 @@ int main(int argc, char **argv) { read_color(&colors.inactive_ws_bg); break; case 'G': - read_color(&colors.urgent_ws_fg); + read_color(&colors.urgent_ws_bg); break; case 'H': - read_color(&colors.urgent_ws_bg); + read_color(&colors.urgent_ws_fg); break; default: print_usage(argv[0]); From cdf56f16bf4199379c976bcb204b65450b86808d Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sun, 26 Dec 2010 14:34:54 +0100 Subject: [PATCH 03/55] Revert "Double-fork() to avoid zombies" This reverts commit a4eafae108b63f5df76eea2958aee8cf95cb1ad6. --- i3bar/src/child.c | 51 +++++++++++------------------------------------ 1 file changed, 12 insertions(+), 39 deletions(-) diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 08d2bed9..7cd364e0 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -101,67 +100,41 @@ void child_sig_cb(struct ev_loop *loop, ev_child *watcher, int revents) { /* * Start a child-process with the specified command and reroute stdin. * We actually start a $SHELL to execute the command so we don't have to care - * about arguments and such. - * We also double-fork() to avoid zombies and pass the pid of the child through a - * temporary pipe back to i3bar + * about arguments and such * */ void start_child(char *command) { child_pid = 0; if (command != NULL) { - int fd[2], tmp[2]; - /* This pipe will be used to communicate between e.g. i3status and i3bar */ + int fd[2]; pipe(fd); - /* We also need this temporary pipe to get back the pid of i3status */ - pipe(tmp); - switch (fork()) { + child_pid = fork(); + switch (child_pid) { case -1: ELOG("Couldn't fork()\n"); exit(EXIT_FAILURE); case 0: - /* Double-fork(), so the child gets reparented to init */ - switch(child_pid = fork()) { - case -1: - ELOG("Couldn't fork() twice\n"); - exit(EXIT_FAILURE); - case 0: - /* Child-process. Reroute stdout and start shell */ - close(fd[0]); + /* Child-process. Reroute stdout and start shell */ + close(fd[0]); - dup2(fd[1], STDOUT_FILENO); + dup2(fd[1], STDOUT_FILENO); - static const char *shell = NULL; + static const char *shell = NULL; - if ((shell = getenv("SHELL")) == NULL) - shell = "/bin/sh"; + if ((shell = getenv("SHELL")) == NULL) + shell = "/bin/sh"; - execl(shell, shell, "-c", command, (char*) NULL); - return; - default: - /* Temporary parent. We tell i3bar about the pid of i3status and exit */ - write(tmp[1], &child_pid, sizeof(int)); - close(tmp[0]); - close(tmp[1]); - exit(EXIT_SUCCESS); - } + execl(shell, shell, "-c", command, (char*) NULL); + return; default: /* Parent-process. Rerout stdin */ close(fd[1]); dup2(fd[0], STDIN_FILENO); - /* We also need to get the pid of i3status from the temporary pipe */ - size_t rec = 0; - while (rec < sizeof(int)) { - rec += read(tmp[0], &child_pid, sizeof(int) - rec); - } - /* The temporary pipe is no longer needed */ - close(tmp[0]); - close(tmp[1]); break; } } - wait(0); /* We set O_NONBLOCK because blocking is evil in event-driven software */ fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); From ff0522fe95f9ac35754ac4a73d9d78195ebe6d05 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sun, 26 Dec 2010 14:45:31 +0100 Subject: [PATCH 04/55] Bugfix: Send child a SIGCONT, so it reacts to SIGTERM (no zombies \o/) --- i3bar/src/child.c | 1 + 1 file changed, 1 insertion(+) diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 7cd364e0..3092d527 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -157,6 +157,7 @@ void start_child(char *command) { */ void kill_child() { if (child_pid != 0) { + kill(child_pid, SIGCONT); kill(child_pid, SIGTERM); } cleanup(); From 3daab599cad45cb6b5b6c4576dae7e8b221ae153 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sun, 26 Dec 2010 19:29:57 +0100 Subject: [PATCH 05/55] Bugfix: Recover from closed socket --- i3bar/CHANGELOG | 2 + i3bar/include/ipc.h | 6 +++ i3bar/src/ipc.c | 89 ++++++++++++++++++++++++++++++++------------- i3bar/src/main.c | 4 +- 4 files changed, 74 insertions(+), 27 deletions(-) diff --git a/i3bar/CHANGELOG b/i3bar/CHANGELOG index b8030e43..cbacfb99 100644 --- a/i3bar/CHANGELOG +++ b/i3bar/CHANGELOG @@ -1,3 +1,5 @@ +- Bugfix: Recover from closed socket + v0.6 ===== - Add manpage diff --git a/i3bar/include/ipc.h b/i3bar/include/ipc.h index 0eba64fa..ee273a45 100644 --- a/i3bar/include/ipc.h +++ b/i3bar/include/ipc.h @@ -18,6 +18,12 @@ */ int init_connection(const char *socket_path); +/* + * Destroy the connection to i3. + * + */ +void destroy_connection(); + /* * Sends a Message to i3. * type must be a valid I3_IPC_MESSAGE_TYPE (see i3/ipc.h for further information) diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index 0ddccc25..bd7de75e 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -19,30 +19,40 @@ #include "common.h" -ev_io *i3_connection; +ev_io i3_connection; +ev_timer reconn; + +const char *sock_path; typedef void(*handler_t)(char*); /* - * Get a connect to the IPC-interface of i3 and return a filedescriptor + * Retry to connect. * */ -int get_ipc_fd(const char *socket_path) { - int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0); - if (sockfd == -1) { - ELOG("Could not create Socket!\n"); - exit(EXIT_FAILURE); +void retry_connection(struct ev_loop *loop, ev_timer *w, int events) { + static int retries = 8; + if (init_connection(sock_path) == 0) { + if (retries == 0) { + ELOG("Retried 8 times - connection failed!\n"); + exit(EXIT_FAILURE); + } + retries--; + return; } + retries = 8; + ev_timer_stop(loop, w); + subscribe_events(); + reconfig_windows(); +} - struct sockaddr_un addr; - memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_LOCAL; - strcpy(addr.sun_path, socket_path); - if (connect(sockfd, (const struct sockaddr*) &addr, sizeof(struct sockaddr_un)) < 0) { - ELOG("Could not connct to i3!\n"); - exit(EXIT_FAILURE); - } - return sockfd; +/* + * Schedule a reconnect + * + */ +void reconnect() { + ev_timer_init(&reconn, retry_connection, 0.25, 0.25); + ev_timer_start(main_loop, &reconn); } /* @@ -144,8 +154,12 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) { exit(EXIT_FAILURE); } if (n == 0) { - ELOG("Nothing to read!\n"); - exit(EXIT_FAILURE); + /* EOF received. We try to recover a few times, because most likely + * i3 just restarted */ + ELOG("EOF received, try to recover...\n"); + destroy_connection(); + reconnect(); + return; } rec += n; } @@ -167,8 +181,12 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) { * of the message */ char *buffer = malloc(size + 1); if (buffer == NULL) { - ELOG("Could not allocate memory!\n"); - exit(EXIT_FAILURE); + /* EOF received. We try to recover a few times, because most likely + * i3 just restarted */ + ELOG("EOF received, try to recover...\n"); + destroy_connection(); + reconnect(); + return; } rec = 0; @@ -234,7 +252,7 @@ int i3_send_msg(uint32_t type, const char *payload) { uint32_t written = 0; while (to_write > 0) { - int n = write(i3_connection->fd, buffer + written, to_write); + int n = write(i3_connection.fd, buffer + written, to_write); if (n == -1) { ELOG("write() failed!\n"); exit(EXIT_FAILURE); @@ -255,15 +273,36 @@ int i3_send_msg(uint32_t type, const char *payload) { * */ int init_connection(const char *socket_path) { - int sockfd = get_ipc_fd(socket_path); + sock_path = socket_path; + int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0); + if (sockfd == -1) { + ELOG("Could not create Socket!\n"); + exit(EXIT_FAILURE); + } - i3_connection = malloc(sizeof(ev_io)); - ev_io_init(i3_connection, &got_data, sockfd, EV_READ); - ev_io_start(main_loop, i3_connection); + struct sockaddr_un addr; + memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_LOCAL; + strcpy(addr.sun_path, sock_path); + if (connect(sockfd, (const struct sockaddr*) &addr, sizeof(struct sockaddr_un)) < 0) { + ELOG("Could not connct to i3!\n"); + reconnect(); + return 0; + } + ev_io_init(&i3_connection, &got_data, sockfd, EV_READ); + ev_io_start(main_loop, &i3_connection); return 1; } +/* + * Destroy the connection to i3. + */ +void destroy_connection() { + close(i3_connection.fd); + ev_io_stop(main_loop, &i3_connection); +} + /* * Subscribe to all the i3-events, we need * diff --git a/i3bar/src/main.c b/i3bar/src/main.c index ec85d324..7f27bdac 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -215,8 +215,6 @@ int main(int argc, char **argv) { init_outputs(); init_connection(socket_path); - FREE(socket_path); - /* We subscribe to the i3-events we need */ subscribe_events(); @@ -249,6 +247,8 @@ int main(int argc, char **argv) { kill_child(); + FREE(socket_path); + FREE(statusline); clean_xcb(); From 600c4ae95c129ac005689b7d6cf3c783e23682f7 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sat, 1 Jan 2011 15:07:28 +0100 Subject: [PATCH 06/55] Use "*buffer == '\0'" instead of "strlen(buffer) == 0" (thanks dothebart) --- i3bar/src/child.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 3092d527..0209e4cb 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -74,7 +74,7 @@ void stdin_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { } rec += n; } - if (strlen(buffer) == 0) { + if (*buffer == '\0') { FREE(buffer); return; } From 08a5a2fdb056a5bb9675042b93b1111ea7ee6afe Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sat, 1 Jan 2011 15:19:17 +0100 Subject: [PATCH 07/55] Only use font_info after we know, the request succeded --- i3bar/src/xcb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 326ca2ad..5361f411 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -552,12 +552,13 @@ void init_xcb(char *fontname) { font_info = xcb_query_font_reply(xcb_connection, query_font_cookie, NULL); - font_height = font_info->font_ascent + font_info->font_descent; if (xcb_request_failed(open_font_cookie, "Could not open font")) { exit(EXIT_FAILURE); } + font_height = font_info->font_ascent + font_info->font_descent; + if (xcb_query_font_char_infos_length(font_info) == 0) { font_table = NULL; } else { From b40b92122891d8c725364f352d4c8513625133c2 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sat, 1 Jan 2011 15:19:55 +0100 Subject: [PATCH 08/55] Fix typo (thx julien) --- i3bar/src/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index bd7de75e..08cc2fd7 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -285,7 +285,7 @@ int init_connection(const char *socket_path) { addr.sun_family = AF_LOCAL; strcpy(addr.sun_path, sock_path); if (connect(sockfd, (const struct sockaddr*) &addr, sizeof(struct sockaddr_un)) < 0) { - ELOG("Could not connct to i3!\n"); + ELOG("Could not connect to i3!\n"); reconnect(); return 0; } From 497a091fbbce5c93e5d2db75ddeb46d2131748ab Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sat, 1 Jan 2011 16:48:30 +0100 Subject: [PATCH 09/55] Use strerror() for more usefull errormessages --- i3bar/src/child.c | 4 ++-- i3bar/src/ipc.c | 15 ++++++++------- i3bar/src/main.c | 2 +- i3bar/src/workspaces.c | 3 ++- i3bar/src/xcb.c | 3 ++- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 0209e4cb..48541185 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -59,7 +59,7 @@ void stdin_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { buffer[rec-1] = '\0'; break; } - ELOG("read() failed!\n"); + ELOG("read() failed!: %s\n", strerror(errno)); exit(EXIT_FAILURE); } if (n == 0) { @@ -111,7 +111,7 @@ void start_child(char *command) { child_pid = fork(); switch (child_pid) { case -1: - ELOG("Couldn't fork()\n"); + ELOG("Couldn't fork(): %s\n", strerror(errno)); exit(EXIT_FAILURE); case 0: /* Child-process. Reroute stdout and start shell */ diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index 08cc2fd7..ce9f52cd 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -140,7 +141,7 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) { uint32_t header_len = strlen(I3_IPC_MAGIC) + sizeof(uint32_t)*2; char *header = malloc(header_len); if (header == NULL) { - ELOG("Could not allocate memory!\n"); + ELOG("Could not allocate memory: %s\n", strerror(errno)); exit(EXIT_FAILURE); } @@ -150,7 +151,7 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) { while (rec < header_len) { int n = read(fd, header + rec, header_len - rec); if (n == -1) { - ELOG("read() failed!\n"); + ELOG("read() failed: %s\n", strerror(errno)); exit(EXIT_FAILURE); } if (n == 0) { @@ -193,7 +194,7 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) { while (rec < size) { int n = read(fd, buffer + rec, size - rec); if (n == -1) { - ELOG("read() failed!\n"); + ELOG("read() failed: %s\n", strerror(errno)); exit(EXIT_FAILURE); } if (n == 0) { @@ -234,7 +235,7 @@ int i3_send_msg(uint32_t type, const char *payload) { * but we leave it for now */ char *buffer = malloc(to_write); if (buffer == NULL) { - ELOG("Could not allocate memory\n"); + ELOG("Could not allocate memory: %s\n", strerror(errno)); exit(EXIT_FAILURE); } @@ -254,7 +255,7 @@ int i3_send_msg(uint32_t type, const char *payload) { while (to_write > 0) { int n = write(i3_connection.fd, buffer + written, to_write); if (n == -1) { - ELOG("write() failed!\n"); + ELOG("write() failed: %s\n", strerror(errno)); exit(EXIT_FAILURE); } @@ -276,7 +277,7 @@ int init_connection(const char *socket_path) { sock_path = socket_path; int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0); if (sockfd == -1) { - ELOG("Could not create Socket!\n"); + ELOG("Could not create Socket: %s\n", strerror(errno)); exit(EXIT_FAILURE); } @@ -285,7 +286,7 @@ int init_connection(const char *socket_path) { addr.sun_family = AF_LOCAL; strcpy(addr.sun_path, sock_path); if (connect(sockfd, (const struct sockaddr*) &addr, sizeof(struct sockaddr_un)) < 0) { - ELOG("Could not connect to i3!\n"); + ELOG("Could not connect to i3: %s\n", strerror(errno)); reconnect(); return 0; } diff --git a/i3bar/src/main.c b/i3bar/src/main.c index 7f27bdac..c2cf53e2 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -30,7 +30,7 @@ char *expand_path(char *path) { } char *result = strdup(globbuf.gl_pathc > 0 ? globbuf.gl_pathv[0] : path); if (result == NULL) { - ELOG("malloc() failed\n"); + ELOG("malloc() failed: %s\n", strerror(errno)); exit(EXIT_FAILURE); } globfree(&globbuf); diff --git a/i3bar/src/workspaces.c b/i3bar/src/workspaces.c index 9f8acc1b..1e47bb81 100644 --- a/i3bar/src/workspaces.c +++ b/i3bar/src/workspaces.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "common.h" @@ -184,7 +185,7 @@ static int workspaces_map_key_cb(void *params_, const unsigned char *keyVal, uns params->cur_key = malloc(sizeof(unsigned char) * (keyLen + 1)); if (params->cur_key == NULL) { - ELOG("Could not allocate memory!\n"); + ELOG("Could not allocate memory: %s\n", strerror(errno)); exit(EXIT_FAILURE); } strncpy(params->cur_key, (const char*) keyVal, keyLen); diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 5361f411..6f023b4f 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -493,7 +494,7 @@ void init_xcb(char *fontname) { } if (fcntl(ConnectionNumber(xkb_dpy), F_SETFD, FD_CLOEXEC) == -1) { - ELOG("Could not set FD_CLOEXEC on xkbdpy\n"); + ELOG("Could not set FD_CLOEXEC on xkbdpy: %s\n", strerror(errno)); exit(EXIT_FAILURE); } From 2183435da6eaf5f2d97ef946c6f0224df359c606 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Thu, 6 Jan 2011 17:28:21 +0100 Subject: [PATCH 10/55] Bugfix: Recreate double-buffers on reconfiguring (thx sECuRE) --- i3bar/src/xcb.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 6f023b4f..0cb1201a 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -727,14 +727,30 @@ void reconfig_windows() { values[2] = walk->rect.w; values[3] = font_height + 6; values[4] = XCB_STACK_MODE_ABOVE; + + DLOG("Destroying buffer for output %s", walk->name); + xcb_free_pixmap(xcb_connection, walk->buffer); + DLOG("Reconfiguring Window for output %s to %d,%d\n", walk->name, values[0], values[1]); xcb_void_cookie_t cfg_cookie = xcb_configure_window_checked(xcb_connection, walk->bar, mask, values); + + DLOG("Recreating buffer for output %s", walk->name); + xcb_void_cookie_t pm_cookie = xcb_create_pixmap_checked(xcb_connection, + xcb_screen->root_depth, + walk->buffer, + walk->bar, + walk->rect.w, + walk->rect.h); + if (xcb_request_failed(cfg_cookie, "Could not reconfigure window")) { exit(EXIT_FAILURE); } + if (xcb_request_failed(pm_cookie, "Could not create pixmap")) { + exit(EXIT_FAILURE); + } } } } From 34dd4bc89eef50ed4dd6cc65fce8cd4fe458833c Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Thu, 6 Jan 2011 17:35:23 +0100 Subject: [PATCH 11/55] Bugfix: If hide-on-modifier is set, stop the child after starting --- i3bar/src/child.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 48541185..d7d55783 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -132,6 +132,10 @@ 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 */ + stop_child(); + break; } } From 29f153c6341c22ffb3ae83a5efcdbb518dd87171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Tarl=C3=A1=20Cardoso=20Lemos?= Date: Sun, 2 Jan 2011 22:39:49 -0200 Subject: [PATCH 12/55] Separate the lines received in a single read. Fixes the case where multiple lines are read in a single read syscall (it could be better optimized in the future). Also fixes a memory corruption issue when rec == 0. --- i3bar/include/common.h | 1 + i3bar/src/child.c | 23 ++++++++++++++++------- i3bar/src/main.c | 2 +- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/i3bar/include/common.h b/i3bar/include/common.h index 4ad33703..8b439ee0 100644 --- a/i3bar/include/common.h +++ b/i3bar/include/common.h @@ -14,6 +14,7 @@ typedef int bool; struct ev_loop* main_loop; char *statusline; +char *statusline_buffer; struct rect_t { int x; diff --git a/i3bar/src/child.c b/i3bar/src/child.c index d7d55783..1fae7593 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -27,6 +27,9 @@ pid_t child_pid; ev_io *stdin_io; ev_child *child_sig; +/* The buffer statusline points to */ +char *statusline_buffer = NULL; + /* * Stop and free() the stdin- and sigchild-watchers * @@ -36,7 +39,7 @@ void cleanup() { ev_child_stop(main_loop, child_sig); FREE(stdin_io); FREE(child_sig); - FREE(statusline); + FREE(statusline_buffer); } /* @@ -50,7 +53,7 @@ void stdin_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { int rec = 0; int buffer_len = STDIN_CHUNK_SIZE; char *buffer = malloc(buffer_len); - memset(buffer, '\0', buffer_len); + buffer[0] = '\0'; while(1) { n = read(fd, buffer + rec, buffer_len - rec); if (n == -1) { @@ -67,8 +70,10 @@ void stdin_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { buffer_len += STDIN_CHUNK_SIZE; buffer = realloc(buffer, buffer_len); } else { - /* remove trailing newline and finish up */ - buffer[rec-1] = '\0'; + if (rec != 0) { + /* remove trailing newline and finish up */ + buffer[rec-1] = '\0'; + } break; } } @@ -78,9 +83,13 @@ void stdin_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { FREE(buffer); return; } - FREE(statusline); - statusline = buffer; - DLOG("%s\n", buffer); + FREE(statusline_buffer); + statusline = statusline_buffer = buffer; + for (n = 0; buffer[n] != '\0'; ++n) { + if (buffer[n] == '\n') + statusline = &buffer[n + 1]; + } + DLOG("%s\n", statusline); draw_bars(); } diff --git a/i3bar/src/main.c b/i3bar/src/main.c index c2cf53e2..fce7fc29 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -249,7 +249,7 @@ int main(int argc, char **argv) { FREE(socket_path); - FREE(statusline); + FREE(statusline_buffer); clean_xcb(); ev_default_destroy(); From caca38b68e4bcfcdfae0a17694f2a4d087200053 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Tue, 11 Jan 2011 05:02:55 +0100 Subject: [PATCH 13/55] Use I3SOCK environment-variable --- i3bar/doc/i3bar.man | 8 ++++++++ i3bar/src/main.c | 4 +--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/i3bar/doc/i3bar.man b/i3bar/doc/i3bar.man index 9ee7f7ce..d446143c 100644 --- a/i3bar/doc/i3bar.man +++ b/i3bar/doc/i3bar.man @@ -54,6 +54,14 @@ For each specified option you need to give a HEX-colorcode. Be advised that this command-line-options are only temporary and are very likely to be removed, when we finally have a config-file. +== ENVIRONMENT + +=== I3SOCK + +If no ipc-socket is specified on the commandline, this variable is used +to determine the path, at wich the unix domain socket is expected, on which +to connect to i3. + == EXAMPLES To get a docked bar with some statusinformation, you use diff --git a/i3bar/src/main.c b/i3bar/src/main.c index fce7fc29..c0e07a22 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -113,7 +113,7 @@ void sig_cb(struct ev_loop *loop, ev_signal *watcher, int revents) { int main(int argc, char **argv) { int opt; int option_index = 0; - char *socket_path = NULL; + char *socket_path = getenv("I3SOCK"); char *command = NULL; char *fontname = NULL; char *i3_default_sock_path = "~/.i3/ipc.sock"; @@ -247,8 +247,6 @@ int main(int argc, char **argv) { kill_child(); - FREE(socket_path); - FREE(statusline_buffer); clean_xcb(); From 4762152e1c281e5a58a38d3cb840dcfc285eec67 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Fri, 14 Jan 2011 17:33:40 +0100 Subject: [PATCH 14/55] Display socket-path in connection-error-message --- i3bar/src/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index ce9f52cd..206b1b72 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -286,7 +286,7 @@ int init_connection(const char *socket_path) { addr.sun_family = AF_LOCAL; strcpy(addr.sun_path, sock_path); if (connect(sockfd, (const struct sockaddr*) &addr, sizeof(struct sockaddr_un)) < 0) { - ELOG("Could not connect to i3: %s\n", strerror(errno)); + ELOG("Could not connect to i3! %s: %s\n", sock_path, strerror(errno)); reconnect(); return 0; } From 1369e36d7c5238e56a14c393f654088b8f9293b9 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Fri, 14 Jan 2011 19:16:52 +0100 Subject: [PATCH 15/55] Use tree-command for workspace-switching --- i3bar/src/xcb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 0cb1201a..a6d667bc 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -353,8 +353,8 @@ void handle_button(xcb_button_press_event_t *event) { break; } - char buffer[50]; - snprintf(buffer, 50, "%d", cur_ws->num); + char buffer[strlen(cur_ws->name) + 11]; + snprintf(buffer, 50, "workspace %s", cur_ws->name); i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, buffer); } From c9ee3eb21ee6364a5f8bf09ee7c02007ae813e4c Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sat, 22 Jan 2011 17:41:24 +0100 Subject: [PATCH 16/55] Change default socketpath to /tmp/i3-ipc.sock --- i3bar/doc/i3bar.man | 2 +- i3bar/src/main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/i3bar/doc/i3bar.man b/i3bar/doc/i3bar.man index d446143c..f47108dd 100644 --- a/i3bar/doc/i3bar.man +++ b/i3bar/doc/i3bar.man @@ -14,7 +14,7 @@ i3bar - xcb-based status- and ws-bar == OPTIONS *-s, --socket* 'sock_path':: -Specifies the 'socketpath', via which *i3bar* connects to *i3*(1). If *i3bar* can not connect to *i3*, it will exit. Defaults to '~/.i3/ipc.sock' +Specifies the 'socketpath', via which *i3bar* connects to *i3*(1). If *i3bar* can not connect to *i3*, it will exit. Defaults to '/tmp/i3-ipc.sock' *-c, --command* 'command':: Execute '' to get 'stdin'. You can also simply pipe into 'stdin', but starting the coomand for itself, *i3bar* is able to send 'SIGCONT' and 'SIGSTOP', when combined with *-m* diff --git a/i3bar/src/main.c b/i3bar/src/main.c index c0e07a22..9c2a3181 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -116,7 +116,7 @@ int main(int argc, char **argv) { char *socket_path = getenv("I3SOCK"); char *command = NULL; char *fontname = NULL; - char *i3_default_sock_path = "~/.i3/ipc.sock"; + char *i3_default_sock_path = "/tmp/i3-ipc.sock"; struct xcb_color_strings_t colors = { NULL, }; /* Definition of the standard-config */ From 94ca5c73ccae65f8fe25b326fcf479eeed632bdd Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Wed, 26 Jan 2011 01:21:36 +0100 Subject: [PATCH 17/55] Bugfix: Test for outputs == NULL --- i3bar/src/workspaces.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/i3bar/src/workspaces.c b/i3bar/src/workspaces.c index 1e47bb81..a28ed2be 100644 --- a/i3bar/src/workspaces.c +++ b/i3bar/src/workspaces.c @@ -255,6 +255,9 @@ void parse_workspaces_json(char *json) { */ void free_workspaces() { i3_output *outputs_walk; + if (outputs == NULL) { + return; + } SLIST_FOREACH(outputs_walk, outputs, slist) { if (outputs_walk->workspaces != NULL && !TAILQ_EMPTY(outputs_walk->workspaces)) { FREE_TAILQ(outputs_walk->workspaces, i3_ws); From cc71c773295bb6910fefc9e2c66f980ee3eb1b38 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Wed, 26 Jan 2011 01:24:54 +0100 Subject: [PATCH 18/55] Bugfix: free() command-string, after it is not needed anymore --- i3bar/src/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/i3bar/src/main.c b/i3bar/src/main.c index 9c2a3181..41b0ea7b 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -227,6 +227,7 @@ int main(int argc, char **argv) { /* The name of this function is actually misleading. Even if no -c is specified, * this function initiates the watchers to listen on stdin and react accordingly */ start_child(command); + FREE(command); /* We listen to SIGTERM/QUIT/INT and try to exit cleanly, by stopping the main-loop. * We only need those watchers on the stack, so putting them on the stack saves us From da1b65dd867608ea08a7efacfb19ec83814cd744 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Wed, 26 Jan 2011 00:34:15 +0100 Subject: [PATCH 19/55] Bugfix: free() workspace-names seperately (thx dothebart) --- i3bar/src/workspaces.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/i3bar/src/workspaces.c b/i3bar/src/workspaces.c index a28ed2be..0393071e 100644 --- a/i3bar/src/workspaces.c +++ b/i3bar/src/workspaces.c @@ -258,8 +258,14 @@ void free_workspaces() { if (outputs == NULL) { return; } + i3_ws *ws_walk; + SLIST_FOREACH(outputs_walk, outputs, slist) { if (outputs_walk->workspaces != NULL && !TAILQ_EMPTY(outputs_walk->workspaces)) { + TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) { + FREE(ws_walk->name); + FREE(ws_walk->ucs2_name); + } FREE_TAILQ(outputs_walk->workspaces, i3_ws); } } From 7a7faff96d3ee7eb94babb1a0832ccf1a34117fb Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Wed, 26 Jan 2011 00:54:35 +0100 Subject: [PATCH 20/55] Remove superflous FREE_SLIST --- i3bar/src/main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/i3bar/src/main.c b/i3bar/src/main.c index 41b0ea7b..9771d2a3 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -254,7 +254,6 @@ int main(int argc, char **argv) { ev_default_destroy(); free_workspaces(); - FREE_SLIST(outputs, i3_output); return 0; } From 9d22b2916629330e4902dc9747da5a8b90c09d09 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Wed, 26 Jan 2011 01:38:48 +0100 Subject: [PATCH 21/55] Bugfix: free() workspace-list of outputs seperately (thx dothebart) --- i3bar/src/xcb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index a6d667bc..b48a6ad9 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -579,9 +579,10 @@ void init_xcb(char *fontname) { * */ void clean_xcb() { - i3_output *walk; - SLIST_FOREACH(walk, outputs, slist) { - destroy_window(walk); + i3_output *o_walk; + SLIST_FOREACH(o_walk, outputs, slist) { + destroy_window(o_walk); + FREE_TAILQ(o_walk->workspaces, i3_ws); } FREE_SLIST(outputs, i3_output); From d9f35859fa281a1239dc3bdd94e91020f90fcfca Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Wed, 26 Jan 2011 00:55:15 +0100 Subject: [PATCH 22/55] Bugfix: free() text, after drawing it (thx dothebart) --- i3bar/src/xcb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index b48a6ad9..1d7bcd3e 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -197,6 +197,8 @@ void refresh_statusline() { draw_text(statusline_pm, statusline_ctx, 0, 0, text, glyph_count); + FREE(text); + if (xcb_request_failed(sl_pm_cookie, "Could not allocate statusline-buffer")) { exit(EXIT_FAILURE); } From dc7cfeaa4f09938366dad48e65a7241ba012a40c Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Wed, 26 Jan 2011 01:51:46 +0100 Subject: [PATCH 23/55] Bugfix: Also free() the head of slist/tailq (Thx dothebart) --- i3bar/src/workspaces.c | 2 +- i3bar/src/xcb.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/i3bar/src/workspaces.c b/i3bar/src/workspaces.c index 0393071e..89f7757d 100644 --- a/i3bar/src/workspaces.c +++ b/i3bar/src/workspaces.c @@ -250,7 +250,7 @@ void parse_workspaces_json(char *json) { } /* - * free() all workspace data-structures + * free() all workspace data-structures. Does not free() the heads of the tailqueues. * */ void free_workspaces() { diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 1d7bcd3e..10afa923 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -585,8 +585,10 @@ void clean_xcb() { SLIST_FOREACH(o_walk, outputs, slist) { destroy_window(o_walk); FREE_TAILQ(o_walk->workspaces, i3_ws); + FREE(o_walk->workspaces); } FREE_SLIST(outputs, i3_output); + FREE(outputs); xcb_disconnect(xcb_connection); From 8fa720d6b9729daa74c55ed9243391a63b57323e Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Wed, 26 Jan 2011 12:02:09 +0100 Subject: [PATCH 24/55] Bugfix: free() output-names seperately (thx dothebart) --- i3bar/src/xcb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 10afa923..af472638 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -586,6 +586,7 @@ void clean_xcb() { destroy_window(o_walk); FREE_TAILQ(o_walk->workspaces, i3_ws); FREE(o_walk->workspaces); + FREE(o_walk->name); } FREE_SLIST(outputs, i3_output); FREE(outputs); From ff925f58e886c2b510167624ffba1637ecbefc19 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Wed, 26 Jan 2011 12:56:49 +0100 Subject: [PATCH 25/55] Bugfix: Use free-workspaces() in xcb-cleanup (thx dothebart) --- i3bar/src/xcb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index af472638..0f0e2973 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -582,9 +582,9 @@ void init_xcb(char *fontname) { */ void clean_xcb() { i3_output *o_walk; + free_workspaces(); SLIST_FOREACH(o_walk, outputs, slist) { destroy_window(o_walk); - FREE_TAILQ(o_walk->workspaces, i3_ws); FREE(o_walk->workspaces); FREE(o_walk->name); } From 972be13dc5e4005fa6c3d44a4d1e1bb6b606e1ee Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Fri, 4 Feb 2011 10:04:54 +0100 Subject: [PATCH 26/55] Bugfix: _only_ stop child, if hide_on_modifier is set (thx cradle) --- i3bar/src/child.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 1fae7593..795a10d3 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -143,7 +143,9 @@ void start_child(char *command) { /* If hide-on-modifier is set, we start of by sending the * child a SIGSTOP, because the bars aren't mapped at start */ - stop_child(); + if (config.hide_on_modifier) { + stop_child(); + } break; } From acb52fc654634419e49324c5fb34a079569974a4 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sat, 5 Feb 2011 15:20:40 +0100 Subject: [PATCH 27/55] Bugfix: Don't override DEBUG-env in Makefile --- i3bar/common.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/i3bar/common.mk b/i3bar/common.mk index 3d44b028..db0e549d 100644 --- a/i3bar/common.mk +++ b/i3bar/common.mk @@ -1,5 +1,7 @@ INSTALL=install +ifndef DEBUG DEBUG=1 +endif PREFIX=/usr # The escaping is absurd, but we need to escape for shell, sed, make, define From 23a98140907341c8f04ffddb1de5701ac7f7bcc0 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Wed, 16 Feb 2011 19:53:42 +0100 Subject: [PATCH 28/55] Correct typo --- i3bar/src/xcb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 0f0e2973..60b88fc8 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -365,7 +365,7 @@ void handle_button(xcb_button_press_event_t *event) { * then (and only then) * */ -void xcb_prep_cb(struct ev_loop *loop, ev_prepare *watcher, int revenst) { +void xcb_prep_cb(struct ev_loop *loop, ev_prepare *watcher, int revents) { xcb_flush(xcb_connection); } From 64f2a7561d885ab64905851626268d72051fe59f Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Mon, 21 Feb 2011 15:47:58 +0100 Subject: [PATCH 29/55] Implement dock-positioning --- i3bar/CHANGELOG | 2 ++ i3bar/doc/i3bar.man | 19 +++++++++---- i3bar/include/config.h | 7 +++++ i3bar/include/xcb_atoms.def | 2 +- i3bar/src/main.c | 30 ++++++++++++++++++-- i3bar/src/xcb.c | 56 +++++++++++++++++++++++++++++++++---- 6 files changed, 102 insertions(+), 14 deletions(-) diff --git a/i3bar/CHANGELOG b/i3bar/CHANGELOG index cbacfb99..0b6958d2 100644 --- a/i3bar/CHANGELOG +++ b/i3bar/CHANGELOG @@ -1,3 +1,5 @@ +- Implement different dock-positions +- Hide-on-modifier is now the default behavior - Bugfix: Recover from closed socket v0.6 diff --git a/i3bar/doc/i3bar.man b/i3bar/doc/i3bar.man index f47108dd..41a80bfa 100644 --- a/i3bar/doc/i3bar.man +++ b/i3bar/doc/i3bar.man @@ -9,7 +9,7 @@ i3bar - xcb-based status- and ws-bar == SYNOPSIS -*i3bar* [*-s* 'sock_path'] [*-c* 'command'] [*-m*] [*-f* 'font'] [*-V*] [*-h*] +*i3bar* [*-s* 'sock_path'] [*-c* 'command'] [*-m*|*-d*['pos']] [*-f* 'font'] [*-V*] [*-h*] == OPTIONS @@ -21,7 +21,12 @@ Execute '' to get 'stdin'. You can also simply pipe into 'stdin', but s *-m, --hide*:: Hide the bar, when 'mod4' is not pressed. With this, dockmode will not be set, and the bar is out of the way most of the time so you have more room. -If *-c* is specified, the childprocess is sent a 'SIGSTOP' on hiding and a 'SIGCONT' on unhiding of the bars +If *-c* is specified, the childprocess is sent a 'SIGSTOP' on hiding and a 'SIGCONT' on unhiding of the bars. +This is the default behavior of i3bar. + +*-d*['pos']*, --dock*[*=*'pos']:: +Put i3bar in dockmode. This will reserve some space for it, so it does not overlap other clients. +You can specify either *bottom* (default) or *top* as 'pos'. *-f, --font* 'font':: Specifies a 'X-core-font' to use. You can choose one with *xfontsel*(1). Defaults to '-misc-fixed-medium-r-semicondensed--12-110-75-75-c-60-iso10646-1'. @@ -66,11 +71,15 @@ to connect to i3. To get a docked bar with some statusinformation, you use -*i3status | i3bar* +*i3status | i3bar --dock* -If you want it to hide when not needed, you should instead use +If you rather have it displayed at the top of the screen, you use -*i3bar -c i3status -m* +*i3status | i3bar --dock=top* + +If you want it to hide when not needed, you should instead simply use + +*i3bar -c i3status* == SEE ALSO diff --git a/i3bar/include/config.h b/i3bar/include/config.h index 2dd0f532..d6abb45c 100644 --- a/i3bar/include/config.h +++ b/i3bar/include/config.h @@ -3,8 +3,15 @@ #include "common.h" +typedef enum { + DOCKPOS_NONE = 0, + DOCKPOS_TOP, + DOCKPOS_BOT +} dockpos_t; + typedef struct config_t { int hide_on_modifier; + dockpos_t dockpos; int verbose; xcb_colors_t *colors; } config_t; diff --git a/i3bar/include/xcb_atoms.def b/i3bar/include/xcb_atoms.def index 5084231c..2ac94acb 100644 --- a/i3bar/include/xcb_atoms.def +++ b/i3bar/include/xcb_atoms.def @@ -1,4 +1,4 @@ -ATOM_DO(ATOM) ATOM_DO(_NET_WM_WINDOW_TYPE) ATOM_DO(_NET_WM_WINDOW_TYPE_DOCK) +ATOM_DO(_NET_WM_STRUT_PARTIAL) #undef ATOM_DO diff --git a/i3bar/src/main.c b/i3bar/src/main.c index 9771d2a3..d33ddb4f 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -79,10 +79,11 @@ static void free_colors(struct xcb_color_strings_t *colors) { } void print_usage(char *elf_name) { - printf("Usage: %s [-s sock_path] [-c command] [-m] [-f font] [-V] [-h]\n", elf_name); + printf("Usage: %s [-s sock_path] [-c command] [-m|-d[pos]] [-f font] [-V] [-h]\n", elf_name); printf("-s \tConnect to i3 via \n"); printf("-c \tExecute to get stdin\n"); printf("-m\t\tHide the bars, when mod4 is not pressed.\n"); + printf("-d[]\tEnable dockmode. is \"top\" or \"bottom\". Default is bottom\n"); printf("\t\tIf -c is specified, the childprocess is sent a SIGSTOP on hiding,\n"); printf("\t\tand a SIGCONT on unhiding of the bars\n"); printf("-f \tUse X-Core-Font for display\n"); @@ -121,11 +122,13 @@ int main(int argc, char **argv) { /* Definition of the standard-config */ config.hide_on_modifier = 0; + config.dockpos = DOCKPOS_NONE; static struct option long_opt[] = { { "socket", required_argument, 0, 's' }, { "command", required_argument, 0, 'c' }, { "hide", no_argument, 0, 'm' }, + { "dock", optional_argument, 0, 'd' }, { "font", required_argument, 0, 'f' }, { "help", no_argument, 0, 'h' }, { "version", no_argument, 0, 'v' }, @@ -141,7 +144,7 @@ int main(int argc, char **argv) { { NULL, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "s:c:mf:hvVA:B:C:D:E:F:G:H:", long_opt, &option_index)) != -1) { + while ((opt = getopt_long(argc, argv, "s:c:d::mf:hvVA:B:C:D:E:F:G:H:", long_opt, &option_index)) != -1) { switch (opt) { case 's': socket_path = expand_path(optarg); @@ -152,6 +155,20 @@ int main(int argc, char **argv) { case 'm': config.hide_on_modifier = 1; break; + case 'd': + if (optarg == NULL) { + config.dockpos = DOCKPOS_BOT; + break; + } + if (!strcmp(optarg, "top")) { + config.dockpos = DOCKPOS_TOP; + } else if (!strcmp(optarg, "bottom")) { + config.dockpos = DOCKPOS_BOT; + } else { + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + break; case 'f': fontname = strdup(optarg); break; @@ -205,6 +222,15 @@ int main(int argc, char **argv) { socket_path = expand_path(i3_default_sock_path); } + if (config.dockpos != DOCKPOS_NONE) { + if (config.hide_on_modifier) { + ELOG("--dock and --hide are mutually exclusive!\n"); + exit(EXIT_FAILURE); + } + } else { + config.hide_on_modifier = 1; + } + main_loop = ev_default_loop(0); init_colors(&colors); diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 60b88fc8..f33a69cd 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -10,6 +10,7 @@ */ #include #include +#include #include #include #include @@ -688,15 +689,57 @@ void reconfig_windows() { /* We want dock-windows (for now). When override_redirect is set, i3 is ignoring * this one */ - xcb_void_cookie_t prop_cookie = xcb_change_property(xcb_connection, + xcb_void_cookie_t dock_cookie = xcb_change_property(xcb_connection, XCB_PROP_MODE_REPLACE, walk->bar, atoms[_NET_WM_WINDOW_TYPE], - atoms[ATOM], + XCB_ATOM_ATOM, 32, 1, (unsigned char*) &atoms[_NET_WM_WINDOW_TYPE_DOCK]); + /* We need to tell i3, where to reserve space for i3bar */ + /* left, right, top, bottom, left_start_y, left_end_y, + * right_start_y, right_end_y, top_start_x, top_end_x, bottom_start_x, + * bottom_end_x */ + /* A local struct to save the strut_partial property */ + struct { + uint32_t left; + uint32_t right; + uint32_t top; + uint32_t bottom; + uint32_t left_start_y; + uint32_t left_end_y; + uint32_t right_start_y; + uint32_t right_end_y; + uint32_t top_start_x; + uint32_t top_end_x; + uint32_t bottom_start_x; + uint32_t bottom_end_x; + } __attribute__((__packed__)) strut_partial = {0,}; + switch (config.dockpos) { + case DOCKPOS_NONE: + break; + case DOCKPOS_TOP: + strut_partial.top = font_height + 6; + strut_partial.top_start_x = walk->rect.x; + strut_partial.top_end_x = walk->rect.x + walk->rect.w; + break; + case DOCKPOS_BOT: + strut_partial.bottom = font_height + 6; + strut_partial.bottom_start_x = walk->rect.x; + strut_partial.bottom_end_x = walk->rect.x + walk->rect.w; + break; + } + xcb_void_cookie_t strut_cookie = xcb_change_property(xcb_connection, + XCB_PROP_MODE_REPLACE, + walk->bar, + atoms[_NET_WM_STRUT_PARTIAL], + XCB_ATOM_CARDINAL, + 32, + 12, + &strut_partial); + /* We also want a graphics-context for the bars (it defines the properties * with which we draw to them) */ walk->bargc = xcb_generate_id(xcb_connection); @@ -714,10 +757,11 @@ void reconfig_windows() { map_cookie = xcb_map_window_checked(xcb_connection, walk->bar); } - if (xcb_request_failed(win_cookie, "Could not create window") || - xcb_request_failed(pm_cookie, "Could not create pixmap") || - xcb_request_failed(prop_cookie, "Could not set dock mode") || - xcb_request_failed(gc_cookie, "Could not create graphical context") || + if (xcb_request_failed(win_cookie, "Could not create window") || + xcb_request_failed(pm_cookie, "Could not create pixmap") || + xcb_request_failed(dock_cookie, "Could not set dock mode") || + xcb_request_failed(strut_cookie, "Could not set strut") || + xcb_request_failed(gc_cookie, "Could not create graphical context") || (!config.hide_on_modifier && xcb_request_failed(map_cookie, "Could not map window"))) { exit(EXIT_FAILURE); } From c8032d552d112bc950069e04b80b0677fe4d8eb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Tarl=C3=A1=20Cardoso=20Lemos?= Date: Fri, 25 Feb 2011 21:45:52 -0300 Subject: [PATCH 30/55] Correct minor issues reported by the analyzer. Found with the Clang Static Analyzer. --- i3bar/src/ipc.c | 3 ++- i3bar/src/xcb.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index 206b1b72..dc2255ea 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -248,7 +248,8 @@ int i3_send_msg(uint32_t type, const char *payload) { memcpy(walk, &type, sizeof(uint32_t)); walk += sizeof(uint32_t); - strncpy(walk, payload, len); + if (payload != NULL) + strncpy(walk, payload, len); uint32_t written = 0; diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index f33a69cd..8d4f60b5 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -51,7 +51,7 @@ xcb_charinfo_t *font_table; /* These are only relevant for XKB, which we only need for grabbing modifiers */ Display *xkb_dpy; int xkb_event_base; -int mod_pressed; +int mod_pressed = 0; /* Because the statusline is the same on all outputs, we have * global buffer to render it on */ @@ -409,7 +409,7 @@ void xcb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { */ void xkb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { XkbEvent ev; - int modstate; + int modstate = 0; DLOG("Got XKB-Event!\n"); From dfd566511e4d374807e3dfd4c69c506004c3af13 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Mon, 14 Mar 2011 09:17:06 +0100 Subject: [PATCH 31/55] Bugfix: Don't segfault, if child was killed --- i3bar/src/child.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 795a10d3..890dce29 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -35,11 +36,13 @@ char *statusline_buffer = NULL; * */ void cleanup() { - ev_io_stop(main_loop, stdin_io); - ev_child_stop(main_loop, child_sig); - FREE(stdin_io); - FREE(child_sig); - FREE(statusline_buffer); + if (stdin_io != NULL) { + ev_io_stop(main_loop, stdin_io); + ev_child_stop(main_loop, child_sig); + FREE(stdin_io); + FREE(child_sig); + FREE(statusline_buffer); + } } /* @@ -174,8 +177,11 @@ void kill_child() { if (child_pid != 0) { kill(child_pid, SIGCONT); kill(child_pid, SIGTERM); + int status; + waitpid(child_pid, &status, 0); + child_pid = 0; + cleanup(); } - cleanup(); } /* From 7fb6258fbd9246e6983f508c44d84d63aa7ce7d1 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Mon, 14 Mar 2011 09:20:16 +0100 Subject: [PATCH 32/55] Use DISPLAY in XKB-code --- i3bar/src/xcb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 8d4f60b5..a7f1e51b 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -484,7 +484,11 @@ void init_xcb(char *fontname) { xkb_major = XkbMajorVersion; xkb_minor = XkbMinorVersion; - xkb_dpy = XkbOpenDisplay(":0", + char *dispname = getenv("DISPLAY"); + if (dispname == NULL) { + dispname = ":0"; + } + xkb_dpy = XkbOpenDisplay(dispname, &xkb_event_base, &xkb_errbase, &xkb_major, From 5219493ffe895ebbe4063e8d8367dd4c0a35877a Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Mon, 14 Mar 2011 09:24:32 +0100 Subject: [PATCH 33/55] Bugfix: Don't SIGSTOP child in dockmode --- i3bar/src/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/i3bar/src/main.c b/i3bar/src/main.c index d33ddb4f..8e632b7b 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -156,6 +156,7 @@ int main(int argc, char **argv) { config.hide_on_modifier = 1; break; case 'd': + config.hide_on_modifier = 0; if (optarg == NULL) { config.dockpos = DOCKPOS_BOT; break; From d993f8a3a1e278d7d32ca579415c4d0d4fb6600f Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sat, 19 Mar 2011 20:58:05 +0100 Subject: [PATCH 34/55] Auto-update NUM_ATOMS by putting it into the enum (thx sECuRE) --- i3bar/src/xcb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index a7f1e51b..5f4c58f7 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -27,11 +27,10 @@ #include "common.h" /* We save the Atoms in an easy to access array, indexed by an enum */ -#define NUM_ATOMS 3 - enum { #define ATOM_DO(name) name, #include "xcb_atoms.def" + NUM_ATOMS }; xcb_intern_atom_cookie_t atom_cookies[NUM_ATOMS]; From 2fd7449e2983de54504f0da55c6ea9ede246de69 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sat, 19 Mar 2011 22:06:08 +0100 Subject: [PATCH 35/55] Add support for I3_SOCKET_PATH-atom --- i3bar/include/xcb.h | 2 +- i3bar/include/xcb_atoms.def | 1 + i3bar/src/main.c | 16 ++++++++++------ i3bar/src/xcb.c | 25 ++++++++++++++++++++++++- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/i3bar/include/xcb.h b/i3bar/include/xcb.h index 5ace4f0b..0adb29ab 100644 --- a/i3bar/include/xcb.h +++ b/i3bar/include/xcb.h @@ -29,7 +29,7 @@ typedef struct xcb_colors_t xcb_colors_t; * Initialize xcb and use the specified fontname for text-rendering * */ -void init_xcb(); +char *init_xcb(); /* * Initialize the colors diff --git a/i3bar/include/xcb_atoms.def b/i3bar/include/xcb_atoms.def index 2ac94acb..5d168873 100644 --- a/i3bar/include/xcb_atoms.def +++ b/i3bar/include/xcb_atoms.def @@ -1,4 +1,5 @@ ATOM_DO(_NET_WM_WINDOW_TYPE) ATOM_DO(_NET_WM_WINDOW_TYPE_DOCK) ATOM_DO(_NET_WM_STRUT_PARTIAL) +ATOM_DO(I3_SOCKET_PATH) #undef ATOM_DO diff --git a/i3bar/src/main.c b/i3bar/src/main.c index 8e632b7b..b09a220f 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -218,11 +218,6 @@ int main(int argc, char **argv) { fontname = "-misc-fixed-medium-r-semicondensed--12-110-75-75-c-60-iso10646-1"; } - if (socket_path == NULL) { - ELOG("No Socket Path Specified, default to %s\n", i3_default_sock_path); - socket_path = expand_path(i3_default_sock_path); - } - if (config.dockpos != DOCKPOS_NONE) { if (config.hide_on_modifier) { ELOG("--dock and --hide are mutually exclusive!\n"); @@ -235,7 +230,16 @@ int main(int argc, char **argv) { main_loop = ev_default_loop(0); init_colors(&colors); - init_xcb(fontname); + char *atom_sock_path = init_xcb(fontname); + + if (socket_path == NULL) { + socket_path = atom_sock_path; + } + + if (socket_path == NULL) { + ELOG("No Socket Path Specified, default to %s\n", i3_default_sock_path); + socket_path = expand_path(i3_default_sock_path); + } free_colors(&colors); diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 5f4c58f7..f9f3f79a 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -445,7 +446,7 @@ void xkb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { * Initialize xcb and use the specified fontname for text-rendering * */ -void init_xcb(char *fontname) { +char *init_xcb(char *fontname) { /* FIXME: xcb_connect leaks Memory */ xcb_connection = xcb_connect(NULL, NULL); if (xcb_connection_has_error(xcb_connection)) { @@ -555,6 +556,26 @@ void init_xcb(char *fontname) { /* Now we get the atoms and save them in a nice data-structure */ get_atoms(); + xcb_get_property_cookie_t path_cookie; + path_cookie = xcb_get_property_unchecked(xcb_connection, + 0, + xcb_root, + atoms[I3_SOCKET_PATH], + XCB_GET_PROPERTY_TYPE_ANY, + 0, PATH_MAX); + + /* We check, if i3 set it's socket-path */ + xcb_get_property_reply_t *path_reply = xcb_get_property_reply(xcb_connection, + path_cookie, + NULL); + char *path = NULL; + if (path_reply) { + int len = xcb_get_property_value_length(path_reply); + if (len != 0) { + path = strndup(xcb_get_property_value(path_reply), len); + } + } + /* Now we save the font-infos */ font_info = xcb_query_font_reply(xcb_connection, query_font_cookie, @@ -577,6 +598,8 @@ void init_xcb(char *fontname) { if (xcb_request_failed(sl_ctx_cookie, "Could not create context for statusline")) { exit(EXIT_FAILURE); } + + return path; } /* From aaf60c632111463ccc34452fc09f29ba10e3e7c8 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sat, 19 Mar 2011 22:27:35 +0100 Subject: [PATCH 36/55] Don't reallocate the backbuffer on every refresh (thx sECuRE) --- i3bar/include/xcb.h | 6 ++++++ i3bar/src/ipc.c | 1 + i3bar/src/xcb.c | 46 ++++++++++++++++++++++++++++++--------------- 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/i3bar/include/xcb.h b/i3bar/include/xcb.h index 0adb29ab..931e7643 100644 --- a/i3bar/include/xcb.h +++ b/i3bar/include/xcb.h @@ -56,6 +56,12 @@ void get_atoms(); */ void destroy_window(i3_output *output); +/* + * Reallocate the statusline-buffer + * + */ +void realloc_sl_buffer(); + /* * Reconfigure all bars and create new for newly activated outputs * diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index dc2255ea..d5c18033 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -93,6 +93,7 @@ void got_output_reply(char *reply) { DLOG("Parsing Outputs-JSON...\n"); parse_outputs_json(reply); DLOG("Reconfiguring Windows...\n"); + realloc_sl_buffer(); reconfig_windows(); } diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index f9f3f79a..f717f487 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -187,22 +187,10 @@ void refresh_statusline() { xcb_char2b_t *text = (xcb_char2b_t*) convert_utf8_to_ucs2(statusline, &glyph_count); statusline_width = predict_text_extents(text, glyph_count); - xcb_free_pixmap(xcb_connection, statusline_pm); - statusline_pm = xcb_generate_id(xcb_connection); - xcb_void_cookie_t sl_pm_cookie = xcb_create_pixmap_checked(xcb_connection, - xcb_screen->root_depth, - statusline_pm, - xcb_root, - statusline_width, - font_height); - + xcb_clear_area(xcb_connection, 0, statusline_pm, 0, 0, xcb_screen->width_in_pixels, font_height); draw_text(statusline_pm, statusline_ctx, 0, 0, text, glyph_count); FREE(text); - - if (xcb_request_failed(sl_pm_cookie, "Could not allocate statusline-buffer")) { - exit(EXIT_FAILURE); - } } /* @@ -536,9 +524,14 @@ char *init_xcb(char *fontname) { mask, vals); - /* We only generate an id for the pixmap, because the width of it is dependent on the - * input we get */ statusline_pm = xcb_generate_id(xcb_connection); + xcb_void_cookie_t sl_pm_cookie = xcb_create_pixmap_checked(xcb_connection, + xcb_screen->root_depth, + statusline_pm, + xcb_root, + xcb_screen->width_in_pixels, + xcb_screen->height_in_pixels); + /* The varios Watchers to communicate with xcb */ xcb_io = malloc(sizeof(ev_io)); @@ -595,6 +588,10 @@ char *init_xcb(char *fontname) { DLOG("Calculated Font-height: %d\n", font_height); + if (xcb_request_failed(sl_pm_cookie, "Could not allocate statusline-buffer")) { + exit(EXIT_FAILURE); + } + if (xcb_request_failed(sl_ctx_cookie, "Could not create context for statusline")) { exit(EXIT_FAILURE); } @@ -663,6 +660,25 @@ void destroy_window(i3_output *output) { output->bar = XCB_NONE; } +/* + * Reallocate the statusline-buffer + * + */ +void realloc_sl_buffer() { + xcb_free_pixmap(xcb_connection, statusline_pm); + statusline_pm = xcb_generate_id(xcb_connection); + xcb_void_cookie_t sl_pm_cookie = xcb_create_pixmap_checked(xcb_connection, + xcb_screen->root_depth, + statusline_pm, + xcb_root, + xcb_screen->width_in_pixels, + xcb_screen->height_in_pixels); + if (xcb_request_failed(sl_pm_cookie, "Could not allocate statusline-buffer")) { + exit(EXIT_FAILURE); + } + +} + /* * Reconfigure all bars and create new for newly activated outputs * From a847454a42b4a54e9ebd8a56aa4c42e276d26f93 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sat, 19 Mar 2011 22:30:59 +0100 Subject: [PATCH 37/55] bugfix: Skip inactive outputs on redraw (thx sECuRE) --- i3bar/src/xcb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index f717f487..6c89c64e 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -951,6 +951,9 @@ void draw_bars() { void redraw_bars() { i3_output *outputs_walk; SLIST_FOREACH(outputs_walk, outputs, slist) { + if (!outputs_walk->active) { + continue; + } xcb_copy_area(xcb_connection, outputs_walk->buffer, outputs_walk->bar, From 1b2002e1c8e2a56e7a4d456547b5c45aca91e1b3 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sat, 19 Mar 2011 23:04:09 +0100 Subject: [PATCH 38/55] XClearArea can't be used on pixmaps (thx sECuRE) --- i3bar/src/xcb.c | 56 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 6c89c64e..49bb0d09 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -56,6 +56,7 @@ int mod_pressed = 0; /* Because the statusline is the same on all outputs, we have * global buffer to render it on */ xcb_gcontext_t statusline_ctx; +xcb_gcontext_t statusline_clear; xcb_pixmap_t statusline_pm; uint32_t statusline_width; @@ -83,7 +84,7 @@ struct xcb_colors_t colors; int _xcb_request_failed(xcb_void_cookie_t cookie, char *err_msg, int line) { xcb_generic_error_t *err; if ((err = xcb_request_check(xcb_connection, cookie)) != NULL) { - ELOG("%s. X Error Code: %d\n", err_msg, err->error_code); + fprintf(stderr, "[%s:%d] ERROR: %s. X Error Code: %d\n", __FILE__, line, err_msg, err->error_code); return err->error_code; } return 0; @@ -187,7 +188,8 @@ void refresh_statusline() { xcb_char2b_t *text = (xcb_char2b_t*) convert_utf8_to_ucs2(statusline, &glyph_count); statusline_width = predict_text_extents(text, glyph_count); - xcb_clear_area(xcb_connection, 0, statusline_pm, 0, 0, xcb_screen->width_in_pixels, font_height); + xcb_rectangle_t rect = { 0, 0, xcb_screen->width_in_pixels, font_height }; + xcb_poly_fill_rectangle(xcb_connection, statusline_pm, statusline_clear, 1, &rect); draw_text(statusline_pm, statusline_ctx, 0, 0, text, glyph_count); FREE(text); @@ -512,12 +514,19 @@ char *init_xcb(char *fontname) { /* We draw the statusline to a seperate pixmap, because it looks the same on all bars and * this way, we can choose to crop it */ - statusline_ctx = xcb_generate_id(xcb_connection); - uint32_t mask = XCB_GC_FOREGROUND | - XCB_GC_BACKGROUND | - XCB_GC_FONT; - uint32_t vals[3] = { colors.bar_fg, colors.bar_bg, xcb_font }; + uint32_t mask = XCB_GC_FOREGROUND; + uint32_t vals[3] = { colors.bar_bg, colors.bar_bg, xcb_font }; + statusline_clear = xcb_generate_id(xcb_connection); + xcb_void_cookie_t clear_ctx_cookie = xcb_create_gc_checked(xcb_connection, + statusline_clear, + xcb_root, + mask, + vals); + + mask |= XCB_GC_BACKGROUND | XCB_GC_FONT; + vals[0] = colors.bar_fg; + statusline_ctx = xcb_generate_id(xcb_connection); xcb_void_cookie_t sl_ctx_cookie = xcb_create_gc_checked(xcb_connection, statusline_ctx, xcb_root, @@ -588,11 +597,9 @@ char *init_xcb(char *fontname) { DLOG("Calculated Font-height: %d\n", font_height); - if (xcb_request_failed(sl_pm_cookie, "Could not allocate statusline-buffer")) { - exit(EXIT_FAILURE); - } - - if (xcb_request_failed(sl_ctx_cookie, "Could not create context for statusline")) { + if (xcb_request_failed(sl_pm_cookie, "Could not allocate statusline-buffer") || + xcb_request_failed(clear_ctx_cookie, "Could not allocate statusline-buffer-clearcontext") || + xcb_request_failed(sl_ctx_cookie, "Could not allocate statusline-buffer-context")) { exit(EXIT_FAILURE); } @@ -673,7 +680,30 @@ void realloc_sl_buffer() { xcb_root, xcb_screen->width_in_pixels, xcb_screen->height_in_pixels); - if (xcb_request_failed(sl_pm_cookie, "Could not allocate statusline-buffer")) { + + uint32_t mask = XCB_GC_FOREGROUND; + uint32_t vals[3] = { colors.bar_bg, colors.bar_bg, xcb_font }; + xcb_free_gc(xcb_connection, statusline_clear); + statusline_clear = xcb_generate_id(xcb_connection); + xcb_void_cookie_t clear_ctx_cookie = xcb_create_gc_checked(xcb_connection, + statusline_clear, + xcb_root, + mask, + vals); + + mask |= XCB_GC_BACKGROUND | XCB_GC_FONT; + vals[0] = colors.bar_fg; + statusline_ctx = xcb_generate_id(xcb_connection); + xcb_free_gc(xcb_connection, statusline_ctx); + xcb_void_cookie_t sl_ctx_cookie = xcb_create_gc_checked(xcb_connection, + statusline_ctx, + xcb_root, + mask, + vals); + + if (xcb_request_failed(sl_pm_cookie, "Could not allocate statusline-buffer") || + xcb_request_failed(clear_ctx_cookie, "Could not allocate statusline-buffer-clearcontext") || + xcb_request_failed(sl_ctx_cookie, "Could not allocate statusline-buffer-context")) { exit(EXIT_FAILURE); } From 682458f4d7c46557dfd1153579a9f84aef177729 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sat, 19 Mar 2011 23:27:50 +0100 Subject: [PATCH 39/55] Don't draw on backbuffer, when hiding (thx sECuRE) --- i3bar/src/xcb.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 49bb0d09..b52160df 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -220,6 +220,8 @@ void unhide_bars() { return; } + draw_bars(); + i3_output *walk; xcb_void_cookie_t cookie; uint32_t mask; @@ -882,6 +884,9 @@ void reconfig_windows() { * */ void draw_bars() { + if (config.hide_on_modifier && !mod_pressed) { + return; + } DLOG("Drawing Bars...\n"); int i = 0; From 16f7574851255c75c9d3dc6f19ea4b355b8b5f8a Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sat, 19 Mar 2011 23:28:10 +0100 Subject: [PATCH 40/55] Bugfix: Skip inactive outputs, when unmapping --- i3bar/src/xcb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index b52160df..9cb77f3f 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -206,6 +206,9 @@ void hide_bars() { i3_output *walk; SLIST_FOREACH(walk, outputs, slist) { + if (!walk->active) { + continue; + } xcb_unmap_window(xcb_connection, walk->bar); } stop_child(); From 52e70c3802e4e4ceac54bb4d1e4e2870affaff41 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sun, 20 Mar 2011 19:29:30 +0100 Subject: [PATCH 41/55] Add Color for focused ws (thx phnom) --- i3bar/doc/i3bar.man | 2 +- i3bar/include/xcb.h | 2 ++ i3bar/src/main.c | 12 +++++++++++- i3bar/src/xcb.c | 13 +++++++++++-- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/i3bar/doc/i3bar.man b/i3bar/doc/i3bar.man index 41a80bfa..44d5e8ac 100644 --- a/i3bar/doc/i3bar.man +++ b/i3bar/doc/i3bar.man @@ -53,7 +53,7 @@ Also, you should disable the internal workspace bar of *i3*(1), when using *i3ba For now this happens with the following command-line-options: -*--color-bar-fg, --color-bar-bg, --color-active-ws-fg, --color-active-ws-bg, --color-inactive-ws-fg, --color-inactive-ws-bg, color-urgent-ws-bg, color-urgent-ws-fg* +*--color-bar-fg, --color-bar-bg, --color-active-ws-fg, --color-active-ws-bg, --color-inactive-ws-fg, --color-inactive-ws-bg, --color-urgent-ws-bg, --color-urgent-ws-fg, --color-focus-ws-fg, --color-focus-ws-bg* For each specified option you need to give a HEX-colorcode. diff --git a/i3bar/include/xcb.h b/i3bar/include/xcb.h index 931e7643..b1732905 100644 --- a/i3bar/include/xcb.h +++ b/i3bar/include/xcb.h @@ -19,6 +19,8 @@ struct xcb_color_strings_t { char *active_ws_bg; char *inactive_ws_fg; char *inactive_ws_bg; + char *focus_ws_bg; + char *focus_ws_fg; char *urgent_ws_bg; char *urgent_ws_fg; }; diff --git a/i3bar/src/main.c b/i3bar/src/main.c index b09a220f..ad8a9993 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -75,6 +75,8 @@ static void free_colors(struct xcb_color_strings_t *colors) { FREE_COLOR(inactive_ws_bg); FREE_COLOR(urgent_ws_fg); FREE_COLOR(urgent_ws_bg); + FREE_COLOR(focus_ws_fg); + FREE_COLOR(focus_ws_bg); #undef FREE_COLOR } @@ -141,10 +143,12 @@ int main(int argc, char **argv) { { "color-inactive-ws-bg", required_argument, 0, 'F' }, { "color-urgent-ws-bg", required_argument, 0, 'G' }, { "color-urgent-ws-fg", required_argument, 0, 'H' }, + { "color-focus-ws-bg", required_argument, 0, 'I' }, + { "color-focus-ws-fg", required_argument, 0, 'J' }, { NULL, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "s:c:d::mf:hvVA:B:C:D:E:F:G:H:", long_opt, &option_index)) != -1) { + while ((opt = getopt_long(argc, argv, "s:c:d::mf:hvVA:B:C:D:E:F:G:H:I:J:", long_opt, &option_index)) != -1) { switch (opt) { case 's': socket_path = expand_path(optarg); @@ -204,6 +208,12 @@ int main(int argc, char **argv) { case 'H': read_color(&colors.urgent_ws_fg); break; + case 'I': + read_color(&colors.focus_ws_bg); + break; + case 'J': + read_color(&colors.focus_ws_fg); + break; default: print_usage(argv[0]); exit(EXIT_SUCCESS); diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 9cb77f3f..96dbe12e 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -76,6 +76,8 @@ struct xcb_colors_t { uint32_t inactive_ws_bg; uint32_t urgent_ws_bg; uint32_t urgent_ws_fg; + uint32_t focus_ws_bg; + uint32_t focus_ws_fg; }; struct xcb_colors_t colors; @@ -276,6 +278,8 @@ void init_colors(const struct xcb_color_strings_t *new_colors) { PARSE_COLOR(inactive_ws_bg, "240000"); PARSE_COLOR(urgent_ws_fg, "FFFFFF"); PARSE_COLOR(urgent_ws_bg, "002400"); + PARSE_COLOR(focus_ws_fg, "FFFFFF"); + PARSE_COLOR(focus_ws_bg, "480000"); #undef PARSE_COLOR } @@ -939,8 +943,13 @@ void draw_bars() { uint32_t fg_color = colors.inactive_ws_fg; uint32_t bg_color = colors.inactive_ws_bg; if (ws_walk->visible) { - fg_color = colors.active_ws_fg; - bg_color = colors.active_ws_bg; + if (!ws_walk->focused) { + fg_color = colors.active_ws_fg; + bg_color = colors.active_ws_bg; + } else { + fg_color = colors.focus_ws_fg; + bg_color = colors.focus_ws_bg; + } } if (ws_walk->urgent) { DLOG("WS %s is urgent!\n", ws_walk->name); From ba748d72ff6c60b3eb0696151d083563807967ca Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sun, 20 Mar 2011 19:49:59 +0100 Subject: [PATCH 42/55] Collapse two ChangeGC-calls (thx sECuRE) --- i3bar/src/xcb.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 96dbe12e..87d0c85b 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -958,14 +958,12 @@ void draw_bars() { /* The urgent-hint should get noticed, so we unhide the bars shortly */ unhide_bars(); } + uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND; + uint32_t vals[] = { bg_color, bg_color }; xcb_change_gc(xcb_connection, outputs_walk->bargc, - XCB_GC_FOREGROUND, - &bg_color); - xcb_change_gc(xcb_connection, - outputs_walk->bargc, - XCB_GC_BACKGROUND, - &bg_color); + mask, + vals); xcb_rectangle_t rect = { i + 1, 1, ws_walk->name_width + 8, font_height + 4 }; xcb_poly_fill_rectangle(xcb_connection, outputs_walk->buffer, From edcc37307788cdcf72381e3d040001ac52aeafb6 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sun, 20 Mar 2011 19:52:20 +0100 Subject: [PATCH 43/55] Fix typo in comment (thx sECuRE) --- i3bar/src/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index d5c18033..c6a85cf5 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -138,7 +138,7 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) { DLOG("Got data!\n"); int fd = watcher->fd; - /* First we only read the header, because we know it's length */ + /* First we only read the header, because we know its length */ uint32_t header_len = strlen(I3_IPC_MAGIC) + sizeof(uint32_t)*2; char *header = malloc(header_len); if (header == NULL) { From 26993574f5599365dd70cdd81fd6d4adcfc931e5 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Mon, 21 Mar 2011 17:29:11 +0100 Subject: [PATCH 44/55] Revert "Don't draw on backbuffer, when hiding (thx sECuRE)" This reverts commit f51ba2d7ecf3f560c8ce4d3ab8419ecf6265839c. This commit introduced a regression, which prevented i3bar to be redrawn at all in some circumstances. It will later be reintroduced in a bigger refactoring of event-dependencies --- i3bar/src/xcb.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 87d0c85b..2da2e6f7 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -225,8 +225,6 @@ void unhide_bars() { return; } - draw_bars(); - i3_output *walk; xcb_void_cookie_t cookie; uint32_t mask; @@ -891,9 +889,6 @@ void reconfig_windows() { * */ void draw_bars() { - if (config.hide_on_modifier && !mod_pressed) { - return; - } DLOG("Drawing Bars...\n"); int i = 0; From ed5ac7f41dd3b650026e13a2b9c0c77b7fbf07de Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Thu, 21 Apr 2011 20:24:02 +0200 Subject: [PATCH 45/55] =?UTF-8?q?Implement=20disabling=20the=20workspace?= =?UTF-8?q?=20buttons=20(=E2=80=9Ethx=E2=80=9C=20sECuRE)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- i3bar/include/config.h | 1 + i3bar/src/ipc.c | 10 ++++++++-- i3bar/src/main.c | 12 ++++++++++-- i3bar/src/xcb.c | 14 ++++++++++---- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/i3bar/include/config.h b/i3bar/include/config.h index d6abb45c..b3473917 100644 --- a/i3bar/include/config.h +++ b/i3bar/include/config.h @@ -14,6 +14,7 @@ typedef struct config_t { dockpos_t dockpos; int verbose; xcb_colors_t *colors; + int disable_ws; } config_t; config_t config; diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index c6a85cf5..d06864c7 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -121,7 +121,9 @@ void got_workspace_event(char *event) { void got_output_event(char *event) { DLOG("Got Output Event!\n"); i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_OUTPUTS, NULL); - i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL); + if (!config.disable_ws) { + i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL); + } } /* Data-structure to easily call the reply-handlers later */ @@ -311,5 +313,9 @@ void destroy_connection() { * */ void subscribe_events() { - i3_send_msg(I3_IPC_MESSAGE_TYPE_SUBSCRIBE, "[ \"workspace\", \"output\" ]"); + if (config.disable_ws) { + i3_send_msg(I3_IPC_MESSAGE_TYPE_SUBSCRIBE, "[ \"output\" ]"); + } else { + i3_send_msg(I3_IPC_MESSAGE_TYPE_SUBSCRIBE, "[ \"workspace\", \"output\" ]"); + } } diff --git a/i3bar/src/main.c b/i3bar/src/main.c index ad8a9993..4a859254 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -89,6 +89,7 @@ void print_usage(char *elf_name) { printf("\t\tIf -c is specified, the childprocess is sent a SIGSTOP on hiding,\n"); printf("\t\tand a SIGCONT on unhiding of the bars\n"); printf("-f \tUse X-Core-Font for display\n"); + printf("-w\t\tDisable workspace-buttons\n"); printf("-V\t\tBe (very) verbose with the debug-output\n"); printf("-h\t\tDisplay this help-message and exit\n"); } @@ -125,6 +126,7 @@ int main(int argc, char **argv) { /* Definition of the standard-config */ config.hide_on_modifier = 0; config.dockpos = DOCKPOS_NONE; + config.disable_ws = 0; static struct option long_opt[] = { { "socket", required_argument, 0, 's' }, @@ -132,6 +134,7 @@ int main(int argc, char **argv) { { "hide", no_argument, 0, 'm' }, { "dock", optional_argument, 0, 'd' }, { "font", required_argument, 0, 'f' }, + { "nows", no_argument, 0, 'w' }, { "help", no_argument, 0, 'h' }, { "version", no_argument, 0, 'v' }, { "verbose", no_argument, 0, 'V' }, @@ -148,7 +151,7 @@ int main(int argc, char **argv) { { NULL, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "s:c:d::mf:hvVA:B:C:D:E:F:G:H:I:J:", long_opt, &option_index)) != -1) { + while ((opt = getopt_long(argc, argv, "s:c:d::mf:whvVA:B:C:D:E:F:G:H:I:J:", long_opt, &option_index)) != -1) { switch (opt) { case 's': socket_path = expand_path(optarg); @@ -177,6 +180,9 @@ int main(int argc, char **argv) { case 'f': fontname = strdup(optarg); break; + case 'w': + config.disable_ws = 1; + break; case 'v': printf("i3bar version " I3BAR_VERSION " © 2010 Axel Wagner and contributors\n"); exit(EXIT_SUCCESS); @@ -263,7 +269,9 @@ int main(int argc, char **argv) { * workspaces. Everything else (creating the bars, showing the right workspace- * buttons and more) is taken care of by the event-driveniness of the code */ i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_OUTPUTS, NULL); - i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL); + if (!config.disable_ws) { + i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL); + } /* The name of this function is actually misleading. Even if no -c is specified, * this function initiates the watchers to listen on stdin and react accordingly */ diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 2da2e6f7..e7c08060 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -744,8 +744,10 @@ void reconfig_windows() { /* If hide_on_modifier is set, i3 is not supposed to manage our bar-windows */ values[1] = config.hide_on_modifier; /* The events we want to receive */ - values[2] = XCB_EVENT_MASK_EXPOSURE | - XCB_EVENT_MASK_BUTTON_PRESS; + values[2] = XCB_EVENT_MASK_EXPOSURE; + if (!config.disable_ws) { + values[2] |= XCB_EVENT_MASK_BUTTON_PRESS; + } xcb_void_cookie_t win_cookie = xcb_create_window_checked(xcb_connection, xcb_screen->root_depth, walk->bar, @@ -932,6 +934,10 @@ void draw_bars() { MIN(outputs_walk->rect.w - 4, statusline_width), font_height); } + if (config.disable_ws) { + continue; + } + i3_ws *ws_walk; TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) { DLOG("Drawing Button for WS %s at x = %d\n", ws_walk->name, i); @@ -978,10 +984,10 @@ void draw_bars() { i += 10 + ws_walk->name_width; } - redraw_bars(); - i = 0; } + + redraw_bars(); } /* From bf078c673fc641baaa83fdd1d9c10a76d6f14552 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Fri, 22 Apr 2011 00:42:24 +0200 Subject: [PATCH 46/55] Allow space after space --- i3bar/doc/i3bar.man | 4 ++-- i3bar/src/main.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/i3bar/doc/i3bar.man b/i3bar/doc/i3bar.man index 44d5e8ac..2ff7494b 100644 --- a/i3bar/doc/i3bar.man +++ b/i3bar/doc/i3bar.man @@ -9,7 +9,7 @@ i3bar - xcb-based status- and ws-bar == SYNOPSIS -*i3bar* [*-s* 'sock_path'] [*-c* 'command'] [*-m*|*-d*['pos']] [*-f* 'font'] [*-V*] [*-h*] +*i3bar* [*-s* 'sock_path'] [*-c* 'command'] [*-m*|*-d* ['pos']] [*-f* 'font'] [*-V*] [*-h*] == OPTIONS @@ -24,7 +24,7 @@ Hide the bar, when 'mod4' is not pressed. With this, dockmode will not be set, a If *-c* is specified, the childprocess is sent a 'SIGSTOP' on hiding and a 'SIGCONT' on unhiding of the bars. This is the default behavior of i3bar. -*-d*['pos']*, --dock*[*=*'pos']:: +*-d* \['pos']*, --dock*[*=*'pos']:: Put i3bar in dockmode. This will reserve some space for it, so it does not overlap other clients. You can specify either *bottom* (default) or *top* as 'pos'. diff --git a/i3bar/src/main.c b/i3bar/src/main.c index 4a859254..1c323643 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -81,11 +81,11 @@ static void free_colors(struct xcb_color_strings_t *colors) { } void print_usage(char *elf_name) { - printf("Usage: %s [-s sock_path] [-c command] [-m|-d[pos]] [-f font] [-V] [-h]\n", elf_name); + printf("Usage: %s [-s sock_path] [-c command] [-m|-d [pos]] [-f font] [-V] [-h]\n", elf_name); printf("-s \tConnect to i3 via \n"); printf("-c \tExecute to get stdin\n"); printf("-m\t\tHide the bars, when mod4 is not pressed.\n"); - printf("-d[]\tEnable dockmode. is \"top\" or \"bottom\". Default is bottom\n"); + printf("-d []\tEnable dockmode. is \"top\" or \"bottom\". Default is bottom\n"); printf("\t\tIf -c is specified, the childprocess is sent a SIGSTOP on hiding,\n"); printf("\t\tand a SIGCONT on unhiding of the bars\n"); printf("-f \tUse X-Core-Font for display\n"); @@ -151,7 +151,7 @@ int main(int argc, char **argv) { { NULL, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "s:c:d::mf:whvVA:B:C:D:E:F:G:H:I:J:", long_opt, &option_index)) != -1) { + while ((opt = getopt_long(argc, argv, "s:c:d:mf:whvVA:B:C:D:E:F:G:H:I:J:", long_opt, &option_index)) != -1) { switch (opt) { case 's': socket_path = expand_path(optarg); From d31384e9553a456c9a799396a5a6ba7e81536c27 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Fri, 22 Apr 2011 01:18:57 +0200 Subject: [PATCH 47/55] Revert "Allow space after space" This reverts commit c9334c922de120a08e66cb3a8c340fc1a453bf55. --- i3bar/doc/i3bar.man | 4 ++-- i3bar/src/main.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/i3bar/doc/i3bar.man b/i3bar/doc/i3bar.man index 2ff7494b..44d5e8ac 100644 --- a/i3bar/doc/i3bar.man +++ b/i3bar/doc/i3bar.man @@ -9,7 +9,7 @@ i3bar - xcb-based status- and ws-bar == SYNOPSIS -*i3bar* [*-s* 'sock_path'] [*-c* 'command'] [*-m*|*-d* ['pos']] [*-f* 'font'] [*-V*] [*-h*] +*i3bar* [*-s* 'sock_path'] [*-c* 'command'] [*-m*|*-d*['pos']] [*-f* 'font'] [*-V*] [*-h*] == OPTIONS @@ -24,7 +24,7 @@ Hide the bar, when 'mod4' is not pressed. With this, dockmode will not be set, a If *-c* is specified, the childprocess is sent a 'SIGSTOP' on hiding and a 'SIGCONT' on unhiding of the bars. This is the default behavior of i3bar. -*-d* \['pos']*, --dock*[*=*'pos']:: +*-d*['pos']*, --dock*[*=*'pos']:: Put i3bar in dockmode. This will reserve some space for it, so it does not overlap other clients. You can specify either *bottom* (default) or *top* as 'pos'. diff --git a/i3bar/src/main.c b/i3bar/src/main.c index 1c323643..4a859254 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -81,11 +81,11 @@ static void free_colors(struct xcb_color_strings_t *colors) { } void print_usage(char *elf_name) { - printf("Usage: %s [-s sock_path] [-c command] [-m|-d [pos]] [-f font] [-V] [-h]\n", elf_name); + printf("Usage: %s [-s sock_path] [-c command] [-m|-d[pos]] [-f font] [-V] [-h]\n", elf_name); printf("-s \tConnect to i3 via \n"); printf("-c \tExecute to get stdin\n"); printf("-m\t\tHide the bars, when mod4 is not pressed.\n"); - printf("-d []\tEnable dockmode. is \"top\" or \"bottom\". Default is bottom\n"); + printf("-d[]\tEnable dockmode. is \"top\" or \"bottom\". Default is bottom\n"); printf("\t\tIf -c is specified, the childprocess is sent a SIGSTOP on hiding,\n"); printf("\t\tand a SIGCONT on unhiding of the bars\n"); printf("-f \tUse X-Core-Font for display\n"); @@ -151,7 +151,7 @@ int main(int argc, char **argv) { { NULL, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "s:c:d:mf:whvVA:B:C:D:E:F:G:H:I:J:", long_opt, &option_index)) != -1) { + while ((opt = getopt_long(argc, argv, "s:c:d::mf:whvVA:B:C:D:E:F:G:H:I:J:", long_opt, &option_index)) != -1) { switch (opt) { case 's': socket_path = expand_path(optarg); From e7c2b25ddd4d589ad58bb8f1931d9ebd34e9db78 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Thu, 28 Apr 2011 19:54:31 +0200 Subject: [PATCH 48/55] Fix compiler-warnings from libev --- i3bar/src/ipc.c | 29 ++++++++++++++++++++--------- i3bar/src/main.c | 21 ++++++++++++++------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index d06864c7..f943b4f0 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -20,8 +20,8 @@ #include "common.h" -ev_io i3_connection; -ev_timer reconn; +ev_io *i3_connection; +ev_timer *reconn = NULL; const char *sock_path; @@ -52,8 +52,14 @@ void retry_connection(struct ev_loop *loop, ev_timer *w, int events) { * */ void reconnect() { - ev_timer_init(&reconn, retry_connection, 0.25, 0.25); - ev_timer_start(main_loop, &reconn); + if (reconn == NULL) { + if ((reconn = malloc(sizeof(ev_timer))) == NULL) { + ELOG("malloc() failed: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + } + ev_timer_init(reconn, retry_connection, 0.25, 0.25); + ev_timer_start(main_loop, reconn); } /* @@ -257,7 +263,7 @@ int i3_send_msg(uint32_t type, const char *payload) { uint32_t written = 0; while (to_write > 0) { - int n = write(i3_connection.fd, buffer + written, to_write); + int n = write(i3_connection->fd, buffer + written, to_write); if (n == -1) { ELOG("write() failed: %s\n", strerror(errno)); exit(EXIT_FAILURE); @@ -295,8 +301,13 @@ int init_connection(const char *socket_path) { return 0; } - ev_io_init(&i3_connection, &got_data, sockfd, EV_READ); - ev_io_start(main_loop, &i3_connection); + i3_connection = malloc(sizeof(ev_io)); + if (i3_connection == NULL) { + ELOG("malloc() failed: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + ev_io_init(i3_connection, &got_data, sockfd, EV_READ); + ev_io_start(main_loop, i3_connection); return 1; } @@ -304,8 +315,8 @@ int init_connection(const char *socket_path) { * Destroy the connection to i3. */ void destroy_connection() { - close(i3_connection.fd); - ev_io_stop(main_loop, &i3_connection); + close(i3_connection->fd); + ev_io_stop(main_loop, i3_connection); } /* diff --git a/i3bar/src/main.c b/i3bar/src/main.c index 4a859254..190b04a2 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -281,15 +281,22 @@ int main(int argc, char **argv) { /* We listen to SIGTERM/QUIT/INT and try to exit cleanly, by stopping the main-loop. * We only need those watchers on the stack, so putting them on the stack saves us * some calls to free() */ - ev_signal sig_term, sig_int, sig_hup; + ev_signal *sig_term = malloc(sizeof(ev_signal)); + ev_signal *sig_int = malloc(sizeof(ev_signal)); + ev_signal *sig_hup = malloc(sizeof(ev_signal)); - ev_signal_init(&sig_term, &sig_cb, SIGTERM); - ev_signal_init(&sig_int, &sig_cb, SIGINT); - ev_signal_init(&sig_hup, &sig_cb, SIGHUP); + if (sig_term == NULL || sig_int == NULL || sig_hup == NULL) { + ELOG("malloc() failed: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } - ev_signal_start(main_loop, &sig_term); - ev_signal_start(main_loop, &sig_int); - ev_signal_start(main_loop, &sig_hup); + ev_signal_init(sig_term, &sig_cb, SIGTERM); + ev_signal_init(sig_int, &sig_cb, SIGINT); + ev_signal_init(sig_hup, &sig_cb, SIGHUP); + + ev_signal_start(main_loop, sig_term); + ev_signal_start(main_loop, sig_int); + ev_signal_start(main_loop, sig_hup); /* From here on everything should run smooth for itself, just start listening for * events. We stop simply stop the event-loop, when we are finished */ From b150ec1c47cc8e02acc0a309bda762615d0efa70 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Thu, 28 Apr 2011 20:23:12 +0200 Subject: [PATCH 49/55] Apply ugly yajl-compatibility-fix (thx sECuRE) --- i3bar/common.mk | 4 ++++ i3bar/src/outputs.c | 23 +++++++++++++++++++++-- i3bar/src/workspaces.c | 22 ++++++++++++++++++++-- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/i3bar/common.mk b/i3bar/common.mk index db0e549d..1db1558a 100644 --- a/i3bar/common.mk +++ b/i3bar/common.mk @@ -7,6 +7,10 @@ PREFIX=/usr # The escaping is absurd, but we need to escape for shell, sed, make, define GIT_VERSION:="$(shell git describe --tags --always) ($(shell git log --pretty=format:%cd --date=short -n1), branch $(shell [ -f .git/HEAD ] && sed 's/ref: refs\/heads\/\(.*\)/\\\\\\"\1\\\\\\"/g' .git/HEAD || echo 'unknown'))" +# Fallback for libyajl 1 which did not include yajl_version.h. We need +# YAJL_MAJOR from that file to decide which code path should be used. +CFLAGS += -idirafter yajl-fallback + CFLAGS += -Wall CFLAGS += -pipe CFLAGS += -Iinclude diff --git a/i3bar/src/outputs.c b/i3bar/src/outputs.c index 20ff8276..0619d8b0 100644 --- a/i3bar/src/outputs.c +++ b/i3bar/src/outputs.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "common.h" @@ -60,7 +61,11 @@ static int outputs_boolean_cb(void *params_, bool val) { * Parse an integer (current_workspace or the rect) * */ +#if YAJL_MAJOR >= 2 +static int outputs_integer_cb(void *params_, long long val) { +#else static int outputs_integer_cb(void *params_, long val) { +#endif struct outputs_json_params *params = (struct outputs_json_params*) params_; if (!strcmp(params->cur_key, "current_workspace")) { @@ -100,7 +105,11 @@ static int outputs_integer_cb(void *params_, long val) { * Parse a string (name) * */ +#if YAJL_MAJOR >= 2 +static int outputs_string_cb(void *params_, const unsigned char *val, size_t len) { +#else static int outputs_string_cb(void *params_, const unsigned char *val, unsigned int len) { +#endif struct outputs_json_params *params = (struct outputs_json_params*) params_; if (!strcmp(params->cur_key, "current_workspace")) { @@ -186,7 +195,11 @@ static int outputs_end_map_cb(void *params_) { * Essentially we just save it in the parsing-state * */ -static int outputs_map_key_cb(void *params_, const unsigned char *keyVal, unsigned int keyLen) { +#if YAJL_MAJOR >= 2 +static int outputs_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) { +#else +static int outputs_map_key_cb(void *params_, const unsigned char *keyVal, unsigned keyLen) { +#endif struct outputs_json_params *params = (struct outputs_json_params*) params_; FREE(params->cur_key); @@ -233,10 +246,14 @@ void parse_outputs_json(char *json) { params.json = json; yajl_handle handle; - yajl_parser_config parse_conf = { 0, 0 }; yajl_status state; +#if YAJL_MAJOR < 2 + yajl_parser_config parse_conf = { 0, 0 }; handle = yajl_alloc(&outputs_callbacks, &parse_conf, NULL, (void*) ¶ms); +#else + handle = yajl_alloc(&outputs_callbacks, NULL, (void*) ¶ms); +#endif state = yajl_parse(handle, (const unsigned char*) json, strlen(json)); @@ -245,7 +262,9 @@ void parse_outputs_json(char *json) { case yajl_status_ok: break; case yajl_status_client_canceled: +#if YAJL_MAJOR < 2 case yajl_status_insufficient_data: +#endif case yajl_status_error: ELOG("Could not parse outputs-reply!\n"); exit(EXIT_FAILURE); diff --git a/i3bar/src/workspaces.c b/i3bar/src/workspaces.c index 89f7757d..50f7f754 100644 --- a/i3bar/src/workspaces.c +++ b/i3bar/src/workspaces.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "common.h" @@ -58,7 +59,11 @@ static int workspaces_boolean_cb(void *params_, bool val) { * Parse an integer (num or the rect) * */ +#if YAJL_MAJOR >= 2 +static int workspaces_integer_cb(void *params_, long long val) { +#else static int workspaces_integer_cb(void *params_, long val) { +#endif struct workspaces_json_params *params = (struct workspaces_json_params*) params_; if (!strcmp(params->cur_key, "num")) { @@ -99,8 +104,11 @@ static int workspaces_integer_cb(void *params_, long val) { * Parse a string (name, output) * */ +#if YAJL_MAJOR >= 2 +static int workspaces_string_cb(void *params_, const unsigned char *val, size_t len) { +#else static int workspaces_string_cb(void *params_, const unsigned char *val, unsigned int len) { - +#endif struct workspaces_json_params *params = (struct workspaces_json_params*) params_; char *output_name; @@ -179,7 +187,11 @@ static int workspaces_start_map_cb(void *params_) { * Essentially we just save it in the parsing-state * */ +#if YAJL_MAJOR >= 2 +static int workspaces_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) { +#else static int workspaces_map_key_cb(void *params_, const unsigned char *keyVal, unsigned int keyLen) { +#endif struct workspaces_json_params *params = (struct workspaces_json_params*) params_; FREE(params->cur_key); @@ -225,10 +237,14 @@ void parse_workspaces_json(char *json) { params.json = json; yajl_handle handle; - yajl_parser_config parse_conf = { 0, 0 }; yajl_status state; +#if YAJL_MAJOR < 2 + yajl_parser_config parse_conf = { 0, 0 }; handle = yajl_alloc(&workspaces_callbacks, &parse_conf, NULL, (void*) ¶ms); +#else + handle = yajl_alloc(&workspaces_callbacks, NULL, (void*) ¶ms); +#endif state = yajl_parse(handle, (const unsigned char*) json, strlen(json)); @@ -237,7 +253,9 @@ void parse_workspaces_json(char *json) { case yajl_status_ok: break; case yajl_status_client_canceled: +#if YAJL_MAJOR < 2 case yajl_status_insufficient_data: +#endif case yajl_status_error: ELOG("Could not parse workspaces-reply!\n"); exit(EXIT_FAILURE); From cdc5e6527f4a8f9e513170267268b824330744b5 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Thu, 28 Apr 2011 20:55:40 +0200 Subject: [PATCH 50/55] yajl-compatibility: Forgot to git-add that one --- i3bar/yajl-fallback/yajl/yajl_version.h | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 i3bar/yajl-fallback/yajl/yajl_version.h diff --git a/i3bar/yajl-fallback/yajl/yajl_version.h b/i3bar/yajl-fallback/yajl/yajl_version.h new file mode 100644 index 00000000..c6da442e --- /dev/null +++ b/i3bar/yajl-fallback/yajl/yajl_version.h @@ -0,0 +1,7 @@ +#ifndef YAJL_VERSION_H_ +#define YAJL_VERSION_H_ +/* Fallback for libyajl 1 which does not provide yajl_version.h */ +#define YAJL_MAJOR 1 +#define YAJL_MINOR 0 +#define YAJL_MICRO 0 +#endif From 778268c9bbd176f976ee0ea4c137d1f90a8bd229 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Tue, 3 May 2011 12:38:57 +0200 Subject: [PATCH 51/55] Fix unaligned memory access on sparc (Thanks David Coppa) --- i3bar/src/ipc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index f943b4f0..2f5d481c 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -183,9 +183,11 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) { } char *walk = header + strlen(I3_IPC_MAGIC); - uint32_t size = *((uint32_t*) walk); + uint32_t size; + memcpy(&size, (uint32_t*)walk, sizeof(uint32_t)); walk += sizeof(uint32_t); - uint32_t type = *((uint32_t*) walk); + uint32_t type; + memcpy(&type, (uint32_t*)walk, sizeof(uint32_t)); /* Now that we know, what to expect, we can start read()ing the rest * of the message */ From 97827372af134b85154a90b51df790723374c5b7 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 8 Jul 2011 23:16:33 +0200 Subject: [PATCH 52/55] Bugfix: Correctly handle EOF on stdin (Thanks woddf2) --- i3bar/src/child.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 890dce29..a8de6fb9 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -38,8 +38,12 @@ char *statusline_buffer = NULL; void cleanup() { if (stdin_io != NULL) { ev_io_stop(main_loop, stdin_io); - ev_child_stop(main_loop, child_sig); FREE(stdin_io); + FREE(statusline_buffer); + } + + if (child_sig != NULL) { + ev_child_stop(main_loop, child_sig); FREE(child_sig); FREE(statusline_buffer); } @@ -69,18 +73,23 @@ void stdin_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { exit(EXIT_FAILURE); } if (n == 0) { - if (rec == buffer_len) { - buffer_len += STDIN_CHUNK_SIZE; - buffer = realloc(buffer, buffer_len); - } else { - if (rec != 0) { - /* remove trailing newline and finish up */ - buffer[rec-1] = '\0'; - } - break; + if (rec != 0) { + /* remove trailing newline and finish up */ + buffer[rec-1] = '\0'; } + + /* end of file, kill the watcher */ + DLOG("stdin: EOF\n"); + ev_io_stop(loop, watcher); + FREE(stdin_io); + break; } rec += n; + + if (rec == buffer_len) { + buffer_len += STDIN_CHUNK_SIZE; + buffer = realloc(buffer, buffer_len); + } } if (*buffer == '\0') { FREE(buffer); From 3d05fe7a52a7c50fb09b441c329cf93a79c44753 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Sun, 10 Jul 2011 04:34:18 +0200 Subject: [PATCH 53/55] Use cleanup() in child.c --- i3bar/src/child.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/i3bar/src/child.c b/i3bar/src/child.c index a8de6fb9..982617ff 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -45,7 +45,6 @@ void cleanup() { if (child_sig != NULL) { ev_child_stop(main_loop, child_sig); FREE(child_sig); - FREE(statusline_buffer); } } @@ -80,8 +79,7 @@ void stdin_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { /* end of file, kill the watcher */ DLOG("stdin: EOF\n"); - ev_io_stop(loop, watcher); - FREE(stdin_io); + cleanup(); break; } rec += n; From 8734337fb5ae85de42db2feb3c5f97491fde04e2 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Fri, 15 Jul 2011 01:31:02 +0200 Subject: [PATCH 54/55] Stop the reconn-timer before starting it again, else it's running twice --- i3bar/src/ipc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index 2f5d481c..6bfbc3ec 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -57,6 +57,8 @@ void reconnect() { ELOG("malloc() failed: %s\n", strerror(errno)); exit(EXIT_FAILURE); } + } else { + ev_timer_stop(main_loop, reconn); } ev_timer_init(reconn, retry_connection, 0.25, 0.25); ev_timer_start(main_loop, reconn); From a2a7de5e542d50be3d8fc0709461091131099156 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Tue, 19 Jul 2011 04:21:36 +0200 Subject: [PATCH 55/55] Respect and use CPPFLAGS --- i3bar/Makefile | 2 +- i3bar/common.mk | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/i3bar/Makefile b/i3bar/Makefile index d4cc59b9..216e68cc 100644 --- a/i3bar/Makefile +++ b/i3bar/Makefile @@ -19,7 +19,7 @@ doc: src/%.o: src/%.c ${HEADERS} echo "CC $<" - $(CC) $(CFLAGS) -c -o $@ $< + $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< install: all echo "INSTALL" diff --git a/i3bar/common.mk b/i3bar/common.mk index 1db1558a..ec633007 100644 --- a/i3bar/common.mk +++ b/i3bar/common.mk @@ -13,9 +13,10 @@ CFLAGS += -idirafter yajl-fallback CFLAGS += -Wall CFLAGS += -pipe -CFLAGS += -Iinclude CFLAGS += -g -CFLAGS += -DI3BAR_VERSION=\"${GIT_VERSION}\" + +CPPFLAGS += -DI3BAR_VERSION=\"${GIT_VERSION}\" +CPPFLAGS += -Iinclude LDFLAGS += -lev LDFLAGS += -lyajl