From 9ff230c3751957ce57a2ffbcf7a5d7667fa3d56c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 18 Feb 2015 20:01:32 +0100 Subject: [PATCH 01/99] remove unused statusline_buffer --- i3bar/include/common.h | 1 - i3bar/src/child.c | 4 ---- i3bar/src/main.c | 2 -- 3 files changed, 7 deletions(-) diff --git a/i3bar/include/common.h b/i3bar/include/common.h index e8b6be0a..90b11f78 100644 --- a/i3bar/include/common.h +++ b/i3bar/include/common.h @@ -17,7 +17,6 @@ typedef struct rect_t rect; 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 d0f0c5fb..c0ea3613 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -56,7 +56,6 @@ parser_ctx parser_context; /* The buffer statusline points to */ struct statusline_head statusline_head = TAILQ_HEAD_INITIALIZER(statusline_head); -char *statusline_buffer = NULL; int child_stdin; @@ -115,9 +114,6 @@ void cleanup(void) { if (stdin_io != NULL) { ev_io_stop(main_loop, stdin_io); FREE(stdin_io); - FREE(statusline_buffer); - /* statusline pointed to memory within statusline_buffer */ - statusline = NULL; } if (child_sig != NULL) { diff --git a/i3bar/src/main.c b/i3bar/src/main.c index 371aeec9..ee3d81b9 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -171,8 +171,6 @@ int main(int argc, char **argv) { kill_child(); - FREE(statusline_buffer); - clean_xcb(); ev_default_destroy(); From 296fbdde125a1fb76814eedd5c632b1cecb729f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 18 Feb 2015 20:11:42 +0100 Subject: [PATCH 02/99] Introduce a statusline buffer. A buffer is introduced for the statusline which will only be copied to the actual statusline once an entire statusline is parsed. This avoids a race condition where incompletely parsed statuslines were rendered, causing only some status blocks to be rendered which is visible to the user as a flickering. fixes #1480 --- i3bar/src/child.c | 63 ++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/i3bar/src/child.c b/i3bar/src/child.c index c0ea3613..1860b879 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -54,25 +54,40 @@ typedef struct parser_ctx { parser_ctx parser_context; -/* The buffer statusline points to */ struct statusline_head statusline_head = TAILQ_HEAD_INITIALIZER(statusline_head); +/* Used temporarily while reading a statusline */ +struct statusline_head statusline_buffer = TAILQ_HEAD_INITIALIZER(statusline_buffer); int child_stdin; /* - * Clears all blocks from the statusline structure in memory and frees their - * associated resources. + * Remove all blocks from the given statusline. + * If free_resources is set, the fields of each status block will be free'd. */ -static void clear_status_blocks() { +static void clear_statusline(struct statusline_head *head, bool free_resources) { struct status_block *first; - while (!TAILQ_EMPTY(&statusline_head)) { - first = TAILQ_FIRST(&statusline_head); - I3STRING_FREE(first->full_text); - TAILQ_REMOVE(&statusline_head, first, blocks); + while (!TAILQ_EMPTY(head)) { + first = TAILQ_FIRST(head); + if (free_resources) { + I3STRING_FREE(first->full_text); + FREE(first->color); + FREE(first->name); + } + + TAILQ_REMOVE(head, first, blocks); free(first); } } +static void copy_statusline(struct statusline_head *from, struct statusline_head *to) { + struct status_block *current; + TAILQ_FOREACH (current, from, blocks) { + struct status_block *new_block = smalloc(sizeof(struct status_block)); + memcpy(new_block, current, sizeof(struct status_block)); + TAILQ_INSERT_TAIL(to, new_block, blocks); + } +} + /* * Replaces the statusline in memory with an error message. Pass a format * string and format parameters as you would in `printf'. The next time @@ -80,7 +95,7 @@ static void clear_status_blocks() { * the space allocated for the statusline. */ __attribute__((format(printf, 1, 2))) static void set_statusline_error(const char *format, ...) { - clear_status_blocks(); + clear_statusline(&statusline_head, true); char *message; va_list args; @@ -126,20 +141,12 @@ void cleanup(void) { /* * The start of a new array is the start of a new status line, so we clear all - * previous entries. - * + * previous entries from the buffer. */ static int stdin_start_array(void *context) { - struct status_block *first; - while (!TAILQ_EMPTY(&statusline_head)) { - first = TAILQ_FIRST(&statusline_head); - I3STRING_FREE(first->full_text); - FREE(first->color); - FREE(first->name); - FREE(first->instance); - TAILQ_REMOVE(&statusline_head, first, blocks); - free(first); - } + // the blocks are still used by statusline_head, so we won't free the + // resources here. + clear_statusline(&statusline_buffer, false); return 1; } @@ -222,6 +229,10 @@ static int stdin_integer(void *context, long long val) { return 1; } +/* + * When a map is finished, we have an entire status block. + * Move it from the parser's context to the statusline buffer. + */ static int stdin_end_map(void *context) { parser_ctx *ctx = context; struct status_block *new_block = smalloc(sizeof(struct status_block)); @@ -232,11 +243,19 @@ static int stdin_end_map(void *context) { new_block->full_text = i3string_from_utf8("SPEC VIOLATION: full_text is NULL!"); if (new_block->urgent) ctx->has_urgent = true; - TAILQ_INSERT_TAIL(&statusline_head, new_block, blocks); + TAILQ_INSERT_TAIL(&statusline_buffer, new_block, blocks); return 1; } +/* + * When an array is finished, we have an entire statusline. + * Copy it from the buffer to the actual statusline. + */ static int stdin_end_array(void *context) { + DLOG("copying statusline_buffer to statusline_head\n"); + clear_statusline(&statusline_head, true); + copy_statusline(&statusline_buffer, &statusline_head); + DLOG("dumping statusline:\n"); struct status_block *current; TAILQ_FOREACH(current, &statusline_head, blocks) { From 1fde82d584fe5c341ac0bc6022032cd185dec393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 18 Feb 2015 20:23:26 +0100 Subject: [PATCH 03/99] removed forgotten declaration of unused variable --- i3bar/include/common.h | 1 - 1 file changed, 1 deletion(-) diff --git a/i3bar/include/common.h b/i3bar/include/common.h index 90b11f78..997a429e 100644 --- a/i3bar/include/common.h +++ b/i3bar/include/common.h @@ -16,7 +16,6 @@ typedef struct rect_t rect; struct ev_loop *main_loop; -char *statusline; struct rect_t { int x; From 801dd06c6da842e5e390132f549cd5dcc601e1c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 18 Feb 2015 20:29:11 +0100 Subject: [PATCH 04/99] free block->instance when cleaning up statusline --- i3bar/src/child.c | 1 + 1 file changed, 1 insertion(+) diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 1860b879..6d2f58b9 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -72,6 +72,7 @@ static void clear_statusline(struct statusline_head *head, bool free_resources) I3STRING_FREE(first->full_text); FREE(first->color); FREE(first->name); + FREE(first->instance); } TAILQ_REMOVE(head, first, blocks); From bf16c9123161a896ab7d08a244c626e539261201 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 21 Feb 2015 17:34:26 -0500 Subject: [PATCH 05/99] Config: use default system monospace Use the default monospace font for the system in the default config. This should be a bit more portable for systems that do not have the recommended font installed. --- i3.config | 5 ++++- i3.config.keycodes | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/i3.config b/i3.config index d7e96fe9..c53ecadf 100644 --- a/i3.config +++ b/i3.config @@ -11,9 +11,12 @@ # Font for window titles. Will also be used by the bar unless a different font # is used in the bar {} block below. +font pango:monospace 8 + # This font is widely installed, provides lots of unicode glyphs, right-to-left # text rendering and scalability on retina/hidpi displays (thanks to pango). -font pango:DejaVu Sans Mono 8 +#font pango:DejaVu Sans Mono 8 + # Before i3 v4.8, we used to recommend this one as the default: # font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 # The font above is very space-efficient, that is, it looks good, sharp and diff --git a/i3.config.keycodes b/i3.config.keycodes index 93528a54..0c978d0b 100644 --- a/i3.config.keycodes +++ b/i3.config.keycodes @@ -12,9 +12,12 @@ set $mod Mod1 # Font for window titles. Will also be used by the bar unless a different font # is used in the bar {} block below. +font pango:monospace 8 + # This font is widely installed, provides lots of unicode glyphs, right-to-left # text rendering and scalability on retina/hidpi displays (thanks to pango). -font pango:DejaVu Sans Mono 8 +#font pango:DejaVu Sans Mono 8 + # Before i3 v4.8, we used to recommend this one as the default: # font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 # The font above is very space-efficient, that is, it looks good, sharp and From 9e739de5d3ab0b1044d333097c3ed5b590cd1b99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sun, 1 Mar 2015 00:13:37 +0100 Subject: [PATCH 06/99] Glob filepath when calling append_layout fixes #1500 --- src/commands.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/commands.c b/src/commands.c index 498c25c8..3391fe5b 100644 --- a/src/commands.c +++ b/src/commands.c @@ -900,11 +900,15 @@ void cmd_nop(I3_CMD, char *comment) { void cmd_append_layout(I3_CMD, char *path) { LOG("Appending layout \"%s\"\n", path); + /* Make sure we allow paths like '~/.i3/layout.json' */ + path = resolve_tilde(path); + json_content_t content = json_determine_content(path); LOG("JSON content = %d\n", content); if (content == JSON_CONTENT_UNKNOWN) { ELOG("Could not determine the contents of \"%s\", not loading.\n", path); ysuccess(false); + free(path); return; } @@ -946,6 +950,7 @@ void cmd_append_layout(I3_CMD, char *path) { if (content == JSON_CONTENT_WORKSPACE) ipc_send_workspace_event("restored", parent, NULL); + free(path); cmd_output->needs_tree_render = true; } From 091f1db39ab2069e850718b7b42327f697a15060 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 1 Mar 2015 17:16:03 +0100 Subject: [PATCH 07/99] run clang-format (3.5.0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not quite sure why there are so many differences. Perhaps we’ve gotten out of the habit of running clang-format after every change. I guess it’d be best to have a travis hook that runs clang-format for us and reports any problems on pull requests. --- i3-config-wizard/main.c | 4 ++-- i3-input/main.c | 6 +++--- i3-nagbar/main.c | 14 +++++++------- i3bar/src/xcb.c | 17 ++++++++--------- src/con.c | 12 ++++++------ src/floating.c | 2 +- src/handlers.c | 24 ++++++++++++------------ src/ipc.c | 5 +++-- src/main.c | 6 +++--- src/manage.c | 4 ++-- src/render.c | 4 ++-- src/restore_layout.c | 10 +++++----- src/sighandler.c | 4 ++-- src/tree.c | 6 +++--- src/util.c | 16 ++++++++-------- src/window.c | 2 +- src/x.c | 36 ++++++++++++++++++------------------ src/xcb.c | 6 +++--- src/xcursor.c | 2 +- 19 files changed, 90 insertions(+), 90 deletions(-) diff --git a/i3-config-wizard/main.c b/i3-config-wizard/main.c index c09d459d..5a855c40 100644 --- a/i3-config-wizard/main.c +++ b/i3-config-wizard/main.c @@ -494,7 +494,7 @@ static char *resolve_tilde(const char *path) { static int handle_expose() { /* re-draw the background */ xcb_rectangle_t border = {0, 0, 300, (15 * font.height) + 8}; - xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#000000")}); + xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){get_colorpixel("#000000")}); xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border); set_font(&font); @@ -870,7 +870,7 @@ int main(int argc, char *argv[]) { XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */ XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, - (uint32_t[]) { + (uint32_t[]){ 0, /* back pixel: black */ XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS}); diff --git a/i3-input/main.c b/i3-input/main.c index 9f3ff174..7d523190 100644 --- a/i3-input/main.c +++ b/i3-input/main.c @@ -130,9 +130,9 @@ static int handle_expose(void *data, xcb_connection_t *conn, xcb_expose_event_t /* re-draw the background */ xcb_rectangle_t border = {0, 0, 500, font.height + 8}, inner = {2, 2, 496, font.height + 8 - 4}; - xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#FF0000")}); + xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){get_colorpixel("#FF0000")}); xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border); - xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#000000")}); + xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){get_colorpixel("#000000")}); xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &inner); /* restore font color */ @@ -410,7 +410,7 @@ int main(int argc, char *argv[]) { XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */ XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, - (uint32_t[]) { + (uint32_t[]){ 0, /* back pixel: black */ 1, /* override redirect: don’t manage this window */ XCB_EVENT_MASK_EXPOSURE}); diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c index 8dbc4a76..bdf6582b 100644 --- a/i3-nagbar/main.c +++ b/i3-nagbar/main.c @@ -188,7 +188,7 @@ static void handle_button_release(xcb_connection_t *conn, xcb_button_release_eve */ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { /* re-draw the background */ - xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {color_background}); + xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_background}); xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &rect); /* restore font color */ @@ -212,7 +212,7 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { xcb_rectangle_t close = {y - w - (2 * line_width), 0, w + (2 * line_width), rect.height}; xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close); - xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {color_border}); + xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_border}); xcb_point_t points[] = { {y - w - (2 * line_width), line_width / 2}, {y - (line_width / 2), line_width / 2}, @@ -238,11 +238,11 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { /* account for left/right padding, which seems to be set to 12px (total) below */ w += 12; y -= 30; - xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {color_button_background}); - close = (xcb_rectangle_t) {y - w - (2 * line_width), 2, w + (2 * line_width), rect.height - 6}; + xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_button_background}); + close = (xcb_rectangle_t){y - w - (2 * line_width), 2, w + (2 * line_width), rect.height - 6}; xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close); - xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {color_border}); + xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_border}); buttons[c].x = y - w - (2 * line_width); buttons[c].width = w; xcb_point_t points2[] = { @@ -415,7 +415,7 @@ int main(int argc, char *argv[]) { XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */ XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, - (uint32_t[]) { + (uint32_t[]){ 0, /* back pixel: black */ XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | @@ -512,7 +512,7 @@ int main(int argc, char *argv[]) { case XCB_CONFIGURE_NOTIFY: { xcb_configure_notify_event_t *configure_notify = (xcb_configure_notify_event_t *)event; - rect = (xcb_rectangle_t) { + rect = (xcb_rectangle_t){ configure_notify->x, configure_notify->y, configure_notify->width, diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 3a1b8cb2..8bda53c4 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -192,12 +192,12 @@ void refresh_statusline(void) { /* Draw the background */ uint32_t bg_color = colors.urgent_ws_bg; - uint32_t bg_values[] = { bg_color, bg_color }; + uint32_t bg_values[] = {bg_color, bg_color}; xcb_change_gc(xcb_connection, statusline_ctx, mask, bg_values); /* The urgent background “overshoots” by 2 px so that the text that * is printed onto it will not be look so cut off. */ - xcb_rectangle_t bg_rect = { x - logical_px(2), logical_px(1), block->width + logical_px(4), bar_height - logical_px(2) }; + xcb_rectangle_t bg_rect = {x - logical_px(2), logical_px(1), block->width + logical_px(4), bar_height - logical_px(2)}; xcb_poly_fill_rectangle(xcb_connection, statusline_pm, statusline_ctx, 1, &bg_rect); } else { fg_color = (block->color ? get_colorpixel(block->color) : colors.bar_fg); @@ -215,8 +215,8 @@ void refresh_statusline(void) { xcb_change_gc(xcb_connection, statusline_ctx, mask, values); xcb_poly_line(xcb_connection, XCB_COORD_MODE_ORIGIN, statusline_pm, statusline_ctx, 2, - (xcb_point_t[]) { { x - sep_offset, logical_px(4) }, - { x - sep_offset, bar_height - logical_px(4) } }); + (xcb_point_t[]){{x - sep_offset, logical_px(4)}, + {x - sep_offset, bar_height - logical_px(4)}}); } } } @@ -367,13 +367,12 @@ void handle_button(xcb_button_press_event_t *event) { struct status_block *block; int sep_offset_remainder = 0; - TAILQ_FOREACH (block, &statusline_head, blocks) { + TAILQ_FOREACH(block, &statusline_head, blocks) { if (i3string_get_num_bytes(block->full_text) == 0) continue; last_block_x = block_x; - block_x += block->width + block->x_offset + block->x_append - + get_sep_offset(block) + sep_offset_remainder; + block_x += block->width + block->x_offset + block->x_append + get_sep_offset(block) + sep_offset_remainder; if (x <= block_x && x >= last_block_x) { send_block_clicked(event->detail, block->name, block->instance, event->root_x, event->root_y); @@ -387,7 +386,7 @@ void handle_button(xcb_button_press_event_t *event) { } /* TODO: Move this to extern get_ws_for_output() */ - TAILQ_FOREACH (cur_ws, walk->workspaces, tailq) { + TAILQ_FOREACH(cur_ws, walk->workspaces, tailq) { if (cur_ws->visible) { break; } @@ -506,7 +505,7 @@ static void handle_visibility_notify(xcb_visibility_notify_event_t *event) { int num_visible = 0; i3_output *output; - SLIST_FOREACH (output, outputs, slist) { + SLIST_FOREACH(output, outputs, slist) { if (!output->active) { continue; } diff --git a/src/con.c b/src/con.c index 4957c303..b610b0c6 100644 --- a/src/con.c +++ b/src/con.c @@ -1149,12 +1149,12 @@ Rect con_border_style_rect(Con *con) { /* Shortcut to avoid calling con_adjacent_borders() on dock containers. */ int border_style = con_border_style(con); if (border_style == BS_NONE) - return (Rect) {0, 0, 0, 0}; + return (Rect){0, 0, 0, 0}; borders_to_hide = con_adjacent_borders(con) & config.hide_edge_borders; if (border_style == BS_NORMAL) { - result = (Rect) {border_width, 0, -(2 * border_width), -(border_width)}; + result = (Rect){border_width, 0, -(2 * border_width), -(border_width)}; } else { - result = (Rect) {border_width, border_width, -(2 * border_width), -(2 * border_width)}; + result = (Rect){border_width, border_width, -(2 * border_width), -(2 * border_width)}; } /* Floating windows are never adjacent to any other window, so @@ -1473,7 +1473,7 @@ Rect con_minimum_size(Con *con) { if (con_is_leaf(con)) { DLOG("leaf node, returning 75x50\n"); - return (Rect) {0, 0, 75, 50}; + return (Rect){0, 0, 75, 50}; } if (con->type == CT_FLOATING_CON) { @@ -1493,7 +1493,7 @@ Rect con_minimum_size(Con *con) { } DLOG("stacked/tabbed now, returning %d x %d + deco_rect = %d\n", max_width, max_height, deco_height); - return (Rect) {0, 0, max_width, max_height + deco_height}; + return (Rect){0, 0, max_width, max_height + deco_height}; } /* For horizontal/vertical split containers we sum up the width (h-split) @@ -1513,7 +1513,7 @@ Rect con_minimum_size(Con *con) { } } DLOG("split container, returning width = %d x height = %d\n", width, height); - return (Rect) {0, 0, width, height}; + return (Rect){0, 0, width, height}; } ELOG("Unhandled case, type = %d, layout = %d, split = %d\n", diff --git a/src/floating.c b/src/floating.c index 8a2fde2c..e6ca2d71 100644 --- a/src/floating.c +++ b/src/floating.c @@ -511,7 +511,7 @@ DRAGGING_CB(resize_window_callback) { dest_height = max(dest_height, (int)(dest_width / ratio)); } - con->rect = (Rect) {dest_x, dest_y, dest_width, dest_height}; + con->rect = (Rect){dest_x, dest_y, dest_width, dest_height}; /* Obey window size */ floating_check_size(con); diff --git a/src/handlers.c b/src/handlers.c index 3569710b..0b7e9b3f 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -651,18 +651,18 @@ static void handle_expose_event(xcb_expose_event_t *event) { return; } -#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0 -#define _NET_WM_MOVERESIZE_SIZE_TOP 1 -#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2 -#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3 -#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4 -#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5 -#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6 -#define _NET_WM_MOVERESIZE_SIZE_LEFT 7 -#define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */ -#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */ -#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */ -#define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */ +#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0 +#define _NET_WM_MOVERESIZE_SIZE_TOP 1 +#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2 +#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3 +#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4 +#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5 +#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6 +#define _NET_WM_MOVERESIZE_SIZE_LEFT 7 +#define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */ +#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */ +#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */ +#define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */ /* * Handle client messages (EWMH) diff --git a/src/ipc.c b/src/ipc.c index 7dbb6632..acd2267b 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -157,7 +157,7 @@ static void dump_binding(yajl_gen gen, Binding *bind) { y(integer, bind->keycode); ystr("input_type"); - ystr((const char*)(bind->input_type == B_KEYBOARD ? "keyboard" : "mouse")); + ystr((const char *)(bind->input_type == B_KEYBOARD ? "keyboard" : "mouse")); ystr("symbol"); if (bind->symbol == NULL) @@ -397,7 +397,8 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) { ystr("transient_for"); if (con->window->transient_for == XCB_NONE) y(null); - else y(integer, con->window->transient_for); + else + y(integer, con->window->transient_for); y(map_close); } diff --git a/src/main.c b/src/main.c index b696e031..ab1cc13d 100644 --- a/src/main.c +++ b/src/main.c @@ -502,7 +502,7 @@ int main(int argc, char *argv[]) { } xcb_void_cookie_t cookie; - cookie = xcb_change_window_attributes_checked(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]) {ROOT_EVENT_MASK}); + cookie = xcb_change_window_attributes_checked(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){ROOT_EVENT_MASK}); check_error(conn, cookie, "Another window manager seems to be running"); xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(conn, gcookie, NULL); @@ -742,10 +742,10 @@ int main(int argc, char *argv[]) { xcb_create_gc(conn, gc, root->root, XCB_GC_FUNCTION | XCB_GC_PLANE_MASK | XCB_GC_FILL_STYLE | XCB_GC_SUBWINDOW_MODE, - (uint32_t[]) {XCB_GX_COPY, ~0, XCB_FILL_STYLE_SOLID, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS}); + (uint32_t[]){XCB_GX_COPY, ~0, XCB_FILL_STYLE_SOLID, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS}); xcb_copy_area(conn, root->root, pixmap, gc, 0, 0, 0, 0, width, height); - xcb_change_window_attributes_checked(conn, root->root, XCB_CW_BACK_PIXMAP, (uint32_t[]) {pixmap}); + xcb_change_window_attributes_checked(conn, root->root, XCB_CW_BACK_PIXMAP, (uint32_t[]){pixmap}); xcb_flush(conn); xcb_free_gc(conn, gc); xcb_free_pixmap(conn, pixmap); diff --git a/src/manage.c b/src/manage.c index b7ea5e69..7c464b43 100644 --- a/src/manage.c +++ b/src/manage.c @@ -69,7 +69,7 @@ void restore_geometry(void) { /* Strictly speaking, this line doesn’t really belong here, but since we * are syncing, let’s un-register as a window manager first */ - xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]) {XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT}); + xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT}); /* Make sure our changes reach the X server, we restart/exit now */ xcb_aux_sync(conn); @@ -434,7 +434,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki * which are not managed by the wm anyways). We store the original geometry * here because it’s used for dock clients. */ if (nc->geometry.width == 0) - nc->geometry = (Rect) {geom->x, geom->y, geom->width, geom->height}; + nc->geometry = (Rect){geom->x, geom->y, geom->width, geom->height}; if (motif_border_style != BS_NORMAL) { DLOG("MOTIF_WM_HINTS specifies decorations (border_style = %d)\n", motif_border_style); diff --git a/src/render.c b/src/render.c index 7f92d4d4..d7d57667 100644 --- a/src/render.c +++ b/src/render.c @@ -154,7 +154,7 @@ void render_con(Con *con, bool render_fullscreen) { /* depending on the border style, the rect of the child window * needs to be smaller */ Rect *inset = &(con->window_rect); - *inset = (Rect) {0, 0, con->rect.width, con->rect.height}; + *inset = (Rect){0, 0, con->rect.width, con->rect.height}; if (!render_fullscreen) *inset = rect_add(*inset, con_border_style_rect(con)); @@ -299,7 +299,7 @@ void render_con(Con *con, bool render_fullscreen) { transient_con->window != NULL && transient_con->window->transient_for != XCB_NONE) { DLOG("transient_con = 0x%08x, transient_con->window->transient_for = 0x%08x, fullscreen_id = 0x%08x\n", - transient_con->window->id, transient_con->window->transient_for, fullscreen->window->id); + transient_con->window->id, transient_con->window->transient_for, fullscreen->window->id); if (transient_con->window->transient_for == fullscreen->window->id) { is_transient_for = true; break; diff --git a/src/restore_layout.c b/src/restore_layout.c index 3a657c90..11590a33 100644 --- a/src/restore_layout.c +++ b/src/restore_layout.c @@ -125,9 +125,9 @@ void restore_connect(void) { static void update_placeholder_contents(placeholder_state *state) { xcb_change_gc(restore_conn, state->gc, XCB_GC_FOREGROUND, - (uint32_t[]) {config.client.placeholder.background}); + (uint32_t[]){config.client.placeholder.background}); xcb_poly_fill_rectangle(restore_conn, state->pixmap, state->gc, 1, - (xcb_rectangle_t[]) {{0, 0, state->rect.width, state->rect.height}}); + (xcb_rectangle_t[]){{0, 0, state->rect.width, state->rect.height}}); // TODO: make i3font functions per-connection, at least these two for now…? xcb_flush(restore_conn); @@ -190,7 +190,7 @@ static void open_placeholder_window(Con *con) { XCURSOR_CURSOR_POINTER, true, XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, - (uint32_t[]) { + (uint32_t[]){ config.client.placeholder.background, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY, }); @@ -211,7 +211,7 @@ static void open_placeholder_window(Con *con) { xcb_create_pixmap(restore_conn, root_depth, state->pixmap, state->window, state->rect.width, state->rect.height); state->gc = xcb_generate_id(restore_conn); - xcb_create_gc(restore_conn, state->gc, state->pixmap, XCB_GC_GRAPHICS_EXPOSURES, (uint32_t[]) {0}); + xcb_create_gc(restore_conn, state->gc, state->pixmap, XCB_GC_GRAPHICS_EXPOSURES, (uint32_t[]){0}); update_placeholder_contents(state); TAILQ_INSERT_TAIL(&state_head, state, state); @@ -323,7 +323,7 @@ static void configure_notify(xcb_configure_notify_event_t *event) { xcb_create_pixmap(restore_conn, root_depth, state->pixmap, state->window, state->rect.width, state->rect.height); state->gc = xcb_generate_id(restore_conn); - xcb_create_gc(restore_conn, state->gc, state->pixmap, XCB_GC_GRAPHICS_EXPOSURES, (uint32_t[]) {0}); + xcb_create_gc(restore_conn, state->gc, state->pixmap, XCB_GC_GRAPHICS_EXPOSURES, (uint32_t[]){0}); update_placeholder_contents(state); xcb_copy_area(restore_conn, state->pixmap, state->window, state->gc, diff --git a/src/sighandler.c b/src/sighandler.c index 8b5bfed4..546b73d9 100644 --- a/src/sighandler.c +++ b/src/sighandler.c @@ -129,9 +129,9 @@ static int sig_draw_window(xcb_window_t win, int width, int height, int font_hei /* re-draw the background */ xcb_rectangle_t border = {0, 0, width, height}, inner = {2, 2, width - 4, height - 4}; - xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#FF0000")}); + xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){get_colorpixel("#FF0000")}); xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border); - xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#000000")}); + xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){get_colorpixel("#000000")}); xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &inner); /* restore font color */ diff --git a/src/tree.c b/src/tree.c index e99c5063..9b60fea6 100644 --- a/src/tree.c +++ b/src/tree.c @@ -76,7 +76,7 @@ bool tree_restore(const char *path, xcb_get_geometry_reply_t *geometry) { /* TODO: refactor the following */ croot = con_new(NULL, NULL); - croot->rect = (Rect) { + croot->rect = (Rect){ geometry->x, geometry->y, geometry->width, @@ -118,7 +118,7 @@ void tree_init(xcb_get_geometry_reply_t *geometry) { croot->name = "root"; croot->type = CT_ROOT; croot->layout = L_SPLITH; - croot->rect = (Rect) { + croot->rect = (Rect){ geometry->x, geometry->y, geometry->width, @@ -237,7 +237,7 @@ bool tree_close(Con *con, kill_window_t kill_window, bool dont_kill_parent, bool * unmap the window, * then reparent it to the root window. */ xcb_change_window_attributes(conn, con->window->id, - XCB_CW_EVENT_MASK, (uint32_t[]) {XCB_NONE}); + XCB_CW_EVENT_MASK, (uint32_t[]){XCB_NONE}); xcb_unmap_window(conn, con->window->id); cookie = xcb_reparent_window(conn, con->window->id, root, 0, 0); diff --git a/src/util.c b/src/util.c index b382a586..c5c22ba8 100644 --- a/src/util.c +++ b/src/util.c @@ -42,17 +42,17 @@ bool rect_contains(Rect rect, uint32_t x, uint32_t y) { } Rect rect_add(Rect a, Rect b) { - return (Rect) {a.x + b.x, - a.y + b.y, - a.width + b.width, - a.height + b.height}; + return (Rect){a.x + b.x, + a.y + b.y, + a.width + b.width, + a.height + b.height}; } Rect rect_sub(Rect a, Rect b) { - return (Rect) {a.x - b.x, - a.y - b.y, - a.width - b.width, - a.height - b.height}; + return (Rect){a.x - b.x, + a.y - b.y, + a.width - b.width, + a.height - b.height}; } /* diff --git a/src/window.c b/src/window.c index e406752a..ace109e3 100644 --- a/src/window.c +++ b/src/window.c @@ -189,7 +189,7 @@ void window_update_strut_partial(i3Window *win, xcb_get_property_reply_t *prop) DLOG("Reserved pixels changed to: left = %d, right = %d, top = %d, bottom = %d\n", strut[0], strut[1], strut[2], strut[3]); - win->reserved = (struct reservedpx) {strut[0], strut[1], strut[2], strut[3]}; + win->reserved = (struct reservedpx){strut[0], strut[1], strut[2], strut[3]}; free(prop); } diff --git a/src/x.c b/src/x.c index b39c19d0..9dd09117 100644 --- a/src/x.c +++ b/src/x.c @@ -352,8 +352,8 @@ void x_draw_decoration(Con *con) { Rect *r = &(con->rect); Rect *w = &(con->window_rect); - p->con_rect = (struct width_height) {r->width, r->height}; - p->con_window_rect = (struct width_height) {w->width, w->height}; + p->con_rect = (struct width_height){r->width, r->height}; + p->con_window_rect = (struct width_height){w->width, w->height}; p->con_deco_rect = con->deco_rect; p->background = config.client.background; p->con_is_leaf = con_is_leaf(con); @@ -403,7 +403,7 @@ void x_draw_decoration(Con *con) { ); #endif - xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {config.client.background}); + xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){config.client.background}); xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, sizeof(background) / sizeof(xcb_rectangle_t), background); } @@ -424,7 +424,7 @@ void x_draw_decoration(Con *con) { * (left, bottom and right part). We don’t just fill the whole * rectangle because some childs are not freely resizable and we want * their background color to "shine through". */ - xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->background}); + xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){p->color->background}); if (!(borders_to_hide & ADJ_LEFT_SCREEN_EDGE)) { xcb_rectangle_t leftline = {0, 0, br.x, r->height}; xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, &leftline); @@ -450,12 +450,12 @@ void x_draw_decoration(Con *con) { if (TAILQ_NEXT(con, nodes) == NULL && TAILQ_PREV(con, nodes_head, nodes) == NULL && con->parent->type != CT_FLOATING_CON) { - xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->indicator}); + xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){p->color->indicator}); if (p->parent_layout == L_SPLITH) - xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, (xcb_rectangle_t[]) { + xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, (xcb_rectangle_t[]){ {r->width + (br.width + br.x), br.y, -(br.width + br.x), r->height + br.height}}); else if (p->parent_layout == L_SPLITV) - xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, (xcb_rectangle_t[]) { + xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, (xcb_rectangle_t[]){ {br.x, r->height + (br.height + br.y), r->width + br.width, -(br.height + br.y)}}); } } @@ -466,20 +466,20 @@ void x_draw_decoration(Con *con) { goto copy_pixmaps; /* 4: paint the bar */ - xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->background}); + xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){p->color->background}); xcb_rectangle_t drect = {con->deco_rect.x, con->deco_rect.y, con->deco_rect.width, con->deco_rect.height}; xcb_poly_fill_rectangle(conn, parent->pixmap, parent->pm_gc, 1, &drect); /* 5: draw two unconnected horizontal lines in border color */ - xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->border}); + xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){p->color->border}); Rect *dr = &(con->deco_rect); adjacent_t borders_to_hide = con_adjacent_borders(con) & config.hide_edge_borders; int deco_diff_l = borders_to_hide & ADJ_LEFT_SCREEN_EDGE ? 0 : con->current_border_width; - int deco_diff_r = borders_to_hide & ADJ_RIGHT_SCREEN_EDGE ? 0 : con-> current_border_width; + int deco_diff_r = borders_to_hide & ADJ_RIGHT_SCREEN_EDGE ? 0 : con->current_border_width; if (parent->layout == L_TABBED || (parent->layout == L_STACKED && TAILQ_NEXT(con, nodes) != NULL)) { - deco_diff_l = 0; - deco_diff_r = 0; + deco_diff_l = 0; + deco_diff_r = 0; } xcb_segment_t segments[] = { {dr->x, dr->y, @@ -545,12 +545,12 @@ after_title: /* Draw a 1px separator line before and after every tab, so that tabs can * be easily distinguished. */ if (parent->layout == L_TABBED) { - xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->border}); + xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){p->color->border}); } else { - xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->background}); + xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){p->color->background}); } xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, parent->pixmap, parent->pm_gc, 6, - (xcb_point_t[]) { + (xcb_point_t[]){ {dr->x + dr->width, dr->y}, {dr->x + dr->width, dr->y + dr->height}, {dr->x + dr->width - 1, dr->y}, @@ -559,7 +559,7 @@ after_title: {dr->x, dr->y}, }); - xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->border}); + xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){p->color->border}); xcb_poly_segment(conn, parent->pixmap, parent->pm_gc, 2, segments); copy_pixmaps: @@ -975,9 +975,9 @@ void x_push_changes(Con *con) { Output *target = get_output_containing(mid_x, mid_y); if (current != target) { /* Ignore MotionNotify events generated by warping */ - xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]) {XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT}); + xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT}); xcb_warp_pointer(conn, XCB_NONE, root, 0, 0, 0, 0, mid_x, mid_y); - xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]) {ROOT_EVENT_MASK}); + xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){ROOT_EVENT_MASK}); } } warp_to = NULL; diff --git a/src/xcb.c b/src/xcb.c index cb0c29f1..5dda5cce 100644 --- a/src/xcb.c +++ b/src/xcb.c @@ -70,9 +70,9 @@ xcb_window_t create_window(xcb_connection_t *conn, Rect dims, */ void xcb_draw_line(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext_t gc, uint32_t colorpixel, uint32_t x, uint32_t y, uint32_t to_x, uint32_t to_y) { - xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, (uint32_t[]) {colorpixel}); + xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, (uint32_t[]){colorpixel}); xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, drawable, gc, 2, - (xcb_point_t[]) {{x, y}, {to_x, to_y}}); + (xcb_point_t[]){{x, y}, {to_x, to_y}}); } /* @@ -81,7 +81,7 @@ void xcb_draw_line(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext */ void xcb_draw_rect(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext_t gc, uint32_t colorpixel, uint32_t x, uint32_t y, uint32_t width, uint32_t height) { - xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, (uint32_t[]) {colorpixel}); + xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, (uint32_t[]){colorpixel}); xcb_rectangle_t rect = {x, y, width, height}; xcb_poly_fill_rectangle(conn, drawable, gc, 1, &rect); } diff --git a/src/xcursor.c b/src/xcursor.c index 6daeedba..0a8da425 100644 --- a/src/xcursor.c +++ b/src/xcursor.c @@ -56,7 +56,7 @@ void xcursor_load_cursors(void) { */ void xcursor_set_root_cursor(int cursor_id) { xcb_change_window_attributes(conn, root, XCB_CW_CURSOR, - (uint32_t[]) {xcursor_get_cursor(cursor_id)}); + (uint32_t[]){xcursor_get_cursor(cursor_id)}); } xcb_cursor_t xcursor_get_cursor(enum xcursor_cursor_t c) { From 11240416483a3b8bd4611d681f631c477a19bdb4 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 1 Mar 2015 17:19:42 +0100 Subject: [PATCH 08/99] clang-format --- 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 e83af94c..efe02884 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -82,7 +82,7 @@ static void clear_statusline(struct statusline_head *head, bool free_resources) static void copy_statusline(struct statusline_head *from, struct statusline_head *to) { struct status_block *current; - TAILQ_FOREACH (current, from, blocks) { + TAILQ_FOREACH(current, from, blocks) { struct status_block *new_block = smalloc(sizeof(struct status_block)); memcpy(new_block, current, sizeof(struct status_block)); TAILQ_INSERT_TAIL(to, new_block, blocks); From 73ecc56bd778495bae8750bd6915632806541f15 Mon Sep 17 00:00:00 2001 From: Michael Tipton Date: Mon, 2 Mar 2015 23:44:28 -0800 Subject: [PATCH 09/99] Fix scrolling in window decoration with hidden cursor. If the mouse cursor is hidden (by unclutter, for example), then scrolling in the window decoration creates an event with a child (i.e. event->child != XCB_NONE). This causes route_click() to be called with dest=CLICK_INSIDE, which prevents scrolling through a stacked layout. To fix this, check if a click is in the window decoration _before_ checking if the event has a child. --- src/click.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/click.c b/src/click.c index 51ffcf3a..55e7147c 100644 --- a/src/click.c +++ b/src/click.c @@ -380,11 +380,6 @@ int handle_button_press(xcb_button_press_event_t *event) { return 0; } - if (event->child != XCB_NONE) { - DLOG("event->child not XCB_NONE, so this is an event which originated from a click into the application, but the application did not handle it.\n"); - return route_click(con, event, mod_pressed, CLICK_INSIDE); - } - /* Check if the click was on the decoration of a child */ Con *child; TAILQ_FOREACH(child, &(con->nodes_head), nodes) { @@ -394,5 +389,10 @@ int handle_button_press(xcb_button_press_event_t *event) { return route_click(child, event, mod_pressed, CLICK_DECORATION); } + if (event->child != XCB_NONE) { + DLOG("event->child not XCB_NONE, so this is an event which originated from a click into the application, but the application did not handle it.\n"); + return route_click(con, event, mod_pressed, CLICK_INSIDE); + } + return route_click(con, event, mod_pressed, CLICK_BORDER); } From dcba0b46dd65a519c2fe54fdb2a5d6f3220d0ed4 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 3 Mar 2015 09:46:16 +0100 Subject: [PATCH 10/99] Fix keyboard layout change detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …by listening to XKB_NEW_KEYBOARD events and re-allocating the keysym map on both XKB_NEW_KEYBOARD and XKB_MAP_NOTIFY. fixes #1302 --- src/handlers.c | 11 ++++++++++- src/main.c | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/handlers.c b/src/handlers.c index 0b7e9b3f..37a61036 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -1257,12 +1257,21 @@ void handle_event(int type, xcb_generic_event_t *event) { DLOG("xkb event, need to handle it.\n"); xcb_xkb_state_notify_event_t *state = (xcb_xkb_state_notify_event_t *)event; - if (state->xkbType == XCB_XKB_MAP_NOTIFY) { + if (state->xkbType == XCB_XKB_NEW_KEYBOARD_NOTIFY) { + DLOG("xkb new keyboard notify, sequence %d, time %d\n", state->sequence, state->time); + xcb_key_symbols_free(keysyms); + keysyms = xcb_key_symbols_alloc(conn); + ungrab_all_keys(conn); + translate_keysyms(); + grab_all_keys(conn, false); + } else if (state->xkbType == XCB_XKB_MAP_NOTIFY) { if (event_is_ignored(event->sequence, type)) { DLOG("Ignoring map notify event for sequence %d.\n", state->sequence); } else { DLOG("xkb map notify, sequence %d, time %d\n", state->sequence, state->time); add_ignore_event(event->sequence, type); + xcb_key_symbols_free(keysyms); + keysyms = xcb_key_symbols_alloc(conn); ungrab_all_keys(conn); translate_keysyms(); grab_all_keys(conn, false); diff --git a/src/main.c b/src/main.c index ab1cc13d..708df38e 100644 --- a/src/main.c +++ b/src/main.c @@ -536,9 +536,9 @@ int main(int argc, char *argv[]) { xcb_xkb_use_extension(conn, XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION); xcb_xkb_select_events(conn, XCB_XKB_ID_USE_CORE_KBD, - XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY, + XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY, 0, - XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY, + XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY, 0xff, 0xff, NULL); From bcc1314a2d43e0889a5f5bad5b02119cfb9f44a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 4 Mar 2015 09:06:44 +0100 Subject: [PATCH 11/99] When renaming a workspace, look for assignments and move the renamed workspace to the appropriate output. --- src/commands.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/commands.c b/src/commands.c index 498c25c8..7d3c9e6e 100644 --- a/src/commands.c +++ b/src/commands.c @@ -2034,6 +2034,24 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) { Con *parent = workspace->parent; con_detach(workspace); con_attach(workspace, parent, false); + + /* Move the workspace to the correct output if it has an assignment */ + struct Workspace_Assignment *assignment = NULL; + TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) { + if (assignment->output == NULL) + continue; + if (strcmp(assignment->name, workspace->name) != 0 + && (!name_is_digits(assignment->name) || ws_name_to_number(assignment->name) != workspace->num)) { + + continue; + } + + /* Focus this workspace for now, we will restore the previous focus anyway. */ + con_focus(workspace); + cmd_move_workspace_to_output(current_match, cmd_output, assignment->output); + break; + } + /* Restore the previous focus since con_attach messes with the focus. */ con_focus(previously_focused); From eb73059c610752fc18e0fcc5c5402bb9b7770574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 4 Mar 2015 09:22:25 +0100 Subject: [PATCH 12/99] Refactor functions for easy reuse --- include/output.h | 7 +++ include/workspace.h | 7 +++ src/commands.c | 125 +++----------------------------------------- src/output.c | 22 ++++++++ src/workspace.c | 108 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 150 insertions(+), 119 deletions(-) diff --git a/include/output.h b/include/output.h index 10ee7d17..6514c477 100644 --- a/include/output.h +++ b/include/output.h @@ -14,3 +14,10 @@ * */ Con *output_get_content(Con *output); + +/** + * Returns an 'output' corresponding to one of left/right/down/up or a specific + * output name. + * + */ +Output *get_output_from_string(Output *current_output, const char *output_str); diff --git a/include/workspace.h b/include/workspace.h index 9ee6f156..d0f801e0 100644 --- a/include/workspace.h +++ b/include/workspace.h @@ -179,3 +179,10 @@ Con *workspace_attach_to(Con *ws); * The container inherits the layout from the workspace. */ Con *workspace_encapsulate(Con *ws); + +/** + * Move the given workspace to the specified output. + * This returns true if and only if moving the workspace was successful. + * + */ +bool workspace_move_to_output(Con *ws, char *output); diff --git a/src/commands.c b/src/commands.c index 7d3c9e6e..49005ba7 100644 --- a/src/commands.c +++ b/src/commands.c @@ -62,28 +62,6 @@ static bool definitelyGreaterThan(float a, float b, float epsilon) { return (a - b) > ((fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon); } -/* - * Returns an 'output' corresponding to one of left/right/down/up or a specific - * output name. - * - */ -static Output *get_output_from_string(Output *current_output, const char *output_str) { - Output *output; - - if (strcasecmp(output_str, "left") == 0) - output = get_output_next_wrap(D_LEFT, current_output); - else if (strcasecmp(output_str, "right") == 0) - output = get_output_next_wrap(D_RIGHT, current_output); - else if (strcasecmp(output_str, "up") == 0) - output = get_output_next_wrap(D_UP, current_output); - else if (strcasecmp(output_str, "down") == 0) - output = get_output_next_wrap(D_DOWN, current_output); - else - output = get_output_by_name(output_str); - - return output; -} - /* * Returns the output containing the given container. */ @@ -1259,101 +1237,12 @@ void cmd_move_workspace_to_output(I3_CMD, char *name) { owindow *current; TAILQ_FOREACH(current, &owindows, owindows) { - Output *current_output = get_output_of_con(current->con); - if (!current_output) { - ELOG("Cannot get current output. This is a bug in i3.\n"); - ysuccess(false); - return; - } - Output *output = get_output_from_string(current_output, name); - if (!output) { - ELOG("Could not get output from string \"%s\"\n", name); - ysuccess(false); - return; - } - - Con *content = output_get_content(output->con); - LOG("got output %p with content %p\n", output, content); - - Con *previously_visible_ws = TAILQ_FIRST(&(content->nodes_head)); - LOG("Previously visible workspace = %p / %s\n", previously_visible_ws, previously_visible_ws->name); - Con *ws = con_get_workspace(current->con); - LOG("should move workspace %p / %s\n", ws, ws->name); - bool workspace_was_visible = workspace_is_visible(ws); - - if (con_num_children(ws->parent) == 1) { - LOG("Creating a new workspace to replace \"%s\" (last on its output).\n", ws->name); - - /* check if we can find a workspace assigned to this output */ - bool used_assignment = false; - struct Workspace_Assignment *assignment; - TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) { - if (strcmp(assignment->output, current_output->name) != 0) - continue; - - /* check if this workspace is already attached to the tree */ - Con *workspace = NULL, *out; - TAILQ_FOREACH(out, &(croot->nodes_head), nodes) - GREP_FIRST(workspace, output_get_content(out), - !strcasecmp(child->name, assignment->name)); - if (workspace != NULL) - continue; - - /* so create the workspace referenced to by this assignment */ - LOG("Creating workspace from assignment %s.\n", assignment->name); - workspace_get(assignment->name, NULL); - used_assignment = true; - break; - } - - /* if we couldn't create the workspace using an assignment, create - * it on the output */ - if (!used_assignment) - create_workspace_on_output(current_output, ws->parent); - - /* notify the IPC listeners */ - ipc_send_workspace_event("init", ws, NULL); - } - DLOG("Detaching\n"); - - /* detach from the old output and attach to the new output */ - Con *old_content = ws->parent; - con_detach(ws); - if (workspace_was_visible) { - /* The workspace which we just detached was visible, so focus - * the next one in the focus-stack. */ - Con *focus_ws = TAILQ_FIRST(&(old_content->focus_head)); - LOG("workspace was visible, focusing %p / %s now\n", focus_ws, focus_ws->name); - workspace_show(focus_ws); - } - con_attach(ws, content, false); - - /* fix the coordinates of the floating containers */ - Con *floating_con; - TAILQ_FOREACH(floating_con, &(ws->floating_head), floating_windows) - floating_fix_coordinates(floating_con, &(old_content->rect), &(content->rect)); - - ipc_send_workspace_event("move", ws, NULL); - if (workspace_was_visible) { - /* Focus the moved workspace on the destination output. */ - workspace_show(ws); - } - - /* NB: We cannot simply work with previously_visible_ws since it might - * have been cleaned up by workspace_show() already, depending on the - * focus order/number of other workspaces on the output. - * Instead, we loop through the available workspaces and only work with - * previously_visible_ws if we still find it. */ - TAILQ_FOREACH(ws, &(content->nodes_head), nodes) { - if (ws != previously_visible_ws) - continue; - - /* Call the on_remove_child callback of the workspace which previously - * was visible on the destination output. Since it is no longer - * visible, it might need to get cleaned up. */ - CALL(previously_visible_ws, on_remove_child); - break; + bool success = workspace_move_to_output(ws, name); + if (!success) { + ELOG("Failed to move workspace to output.\n"); + ysuccess(false); + return; } } @@ -2046,9 +1935,7 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) { continue; } - /* Focus this workspace for now, we will restore the previous focus anyway. */ - con_focus(workspace); - cmd_move_workspace_to_output(current_match, cmd_output, assignment->output); + workspace_move_to_output(workspace, assignment->output); break; } diff --git a/src/output.c b/src/output.c index 6499c65d..822a0f88 100644 --- a/src/output.c +++ b/src/output.c @@ -24,3 +24,25 @@ Con *output_get_content(Con *output) { return NULL; } + +/* + * Returns an 'output' corresponding to one of left/right/down/up or a specific + * output name. + * + */ +Output *get_output_from_string(Output *current_output, const char *output_str) { + Output *output; + + if (strcasecmp(output_str, "left") == 0) + output = get_output_next_wrap(D_LEFT, current_output); + else if (strcasecmp(output_str, "right") == 0) + output = get_output_next_wrap(D_RIGHT, current_output); + else if (strcasecmp(output_str, "up") == 0) + output = get_output_next_wrap(D_UP, current_output); + else if (strcasecmp(output_str, "down") == 0) + output = get_output_next_wrap(D_DOWN, current_output); + else + output = get_output_by_name(output_str); + + return output; +} diff --git a/src/workspace.c b/src/workspace.c index a3056633..f55c920e 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -879,3 +879,111 @@ Con *workspace_encapsulate(Con *ws) { return new; } + +/** + * Move the given workspace to the specified output. + * This returns true if and only if moving the workspace was successful. + */ +bool workspace_move_to_output(Con *ws, char *name) { + LOG("Trying to move workspace %p / %s to output \"%s\".\n", ws, ws->name, name); + + Con *current_output_con = con_get_output(ws); + if (!current_output_con) { + ELOG("Could not get the output container for workspace %p / %s.\n", ws, ws->name); + return false; + } + + Output *current_output = get_output_by_name(current_output_con->name); + if (!current_output) { + ELOG("Cannot get current output. This is a bug in i3.\n"); + return false; + } + Output *output = get_output_from_string(current_output, name); + if (!output) { + ELOG("Could not get output from string \"%s\"\n", name); + return false; + } + + Con *content = output_get_content(output->con); + LOG("got output %p with content %p\n", output, content); + + Con *previously_visible_ws = TAILQ_FIRST(&(content->nodes_head)); + LOG("Previously visible workspace = %p / %s\n", previously_visible_ws, previously_visible_ws->name); + + bool workspace_was_visible = workspace_is_visible(ws); + if (con_num_children(ws->parent) == 1) { + LOG("Creating a new workspace to replace \"%s\" (last on its output).\n", ws->name); + + /* check if we can find a workspace assigned to this output */ + bool used_assignment = false; + struct Workspace_Assignment *assignment; + TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) { + if (assignment->output == NULL || strcmp(assignment->output, current_output->name) != 0) + continue; + + /* check if this workspace is already attached to the tree */ + Con *workspace = NULL, *out; + TAILQ_FOREACH(out, &(croot->nodes_head), nodes) + GREP_FIRST(workspace, output_get_content(out), + !strcasecmp(child->name, assignment->name)); + if (workspace != NULL) + continue; + + /* so create the workspace referenced to by this assignment */ + LOG("Creating workspace from assignment %s.\n", assignment->name); + workspace_get(assignment->name, NULL); + used_assignment = true; + break; + } + + /* if we couldn't create the workspace using an assignment, create + * it on the output */ + if (!used_assignment) + create_workspace_on_output(current_output, ws->parent); + + /* notify the IPC listeners */ + ipc_send_workspace_event("init", ws, NULL); + } + DLOG("Detaching\n"); + + /* detach from the old output and attach to the new output */ + Con *old_content = ws->parent; + con_detach(ws); + if (workspace_was_visible) { + /* The workspace which we just detached was visible, so focus + * the next one in the focus-stack. */ + Con *focus_ws = TAILQ_FIRST(&(old_content->focus_head)); + LOG("workspace was visible, focusing %p / %s now\n", focus_ws, focus_ws->name); + workspace_show(focus_ws); + } + con_attach(ws, content, false); + + /* fix the coordinates of the floating containers */ + Con *floating_con; + TAILQ_FOREACH(floating_con, &(ws->floating_head), floating_windows) + floating_fix_coordinates(floating_con, &(old_content->rect), &(content->rect)); + + ipc_send_workspace_event("move", ws, NULL); + if (workspace_was_visible) { + /* Focus the moved workspace on the destination output. */ + workspace_show(ws); + } + + /* NB: We cannot simply work with previously_visible_ws since it might + * have been cleaned up by workspace_show() already, depending on the + * focus order/number of other workspaces on the output. + * Instead, we loop through the available workspaces and only work with + * previously_visible_ws if we still find it. */ + TAILQ_FOREACH(ws, &(content->nodes_head), nodes) { + if (ws != previously_visible_ws) + continue; + + /* Call the on_remove_child callback of the workspace which previously + * was visible on the destination output. Since it is no longer + * visible, it might need to get cleaned up. */ + CALL(previously_visible_ws, on_remove_child); + break; + } + + return true; +} From 25ec389ecba8aef71bb6e729c438e1b0f3192258 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 4 Mar 2015 09:45:47 +0100 Subject: [PATCH 13/99] Added tests for #1473 --- testcases/t/522-rename-assigned-workspace.t | 90 +++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 testcases/t/522-rename-assigned-workspace.t diff --git a/testcases/t/522-rename-assigned-workspace.t b/testcases/t/522-rename-assigned-workspace.t new file mode 100644 index 00000000..aa69d66d --- /dev/null +++ b/testcases/t/522-rename-assigned-workspace.t @@ -0,0 +1,90 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Please read the following documents before working on tests: +# • http://build.i3wm.org/docs/testsuite.html +# (or docs/testsuite) +# +# • http://build.i3wm.org/docs/lib-i3test.html +# (alternatively: perldoc ./testcases/lib/i3test.pm) +# +# • http://build.i3wm.org/docs/ipc.html +# (or docs/ipc) +# +# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf +# (unless you are already familiar with Perl) +# +# +# Tests that workspaces are moved to the assigned output if they +# are renamed to an assigned name. +# Ticket: #1473 + +use i3test i3_autostart => 0; + +my $config = <connect->recv; + +# Returns the name of the output on which this workspace resides +sub get_output_for_workspace { + my $ws_name = shift @_; + + foreach (grep { not $_->{name} =~ /^__/ } @{$i3->get_tree->recv->{nodes}}) { + my $output = $_->{name}; + foreach (grep { $_->{name} =~ "content" } @{$_->{nodes}}) { + return $output if $_->{nodes}[0]->{name} =~ $ws_name; + } + } +} + +########################################################################## +# Renaming the workspace to an unassigned name does not move the workspace +# (regression test) +########################################################################## + +cmd 'focus output fake-0'; +cmd 'rename workspace to unassigned'; +is(get_output_for_workspace('unassigned'), 'fake-0', + 'Unassigned workspace should stay on its output when being renamed'); + +########################################################################## +# Renaming a workspace by number only triggers the assignment +########################################################################## + +cmd 'focus output fake-0'; +cmd 'rename workspace to 2'; +is(get_output_for_workspace('2'), 'fake-1', + 'Renaming the workspace to a number should move it to the assigned output'); + +########################################################################## +# Renaming a workspace by number and name triggers the assignment +########################################################################## + +cmd 'focus output fake-0'; +cmd 'rename workspace to "2:foo"'; +is(get_output_for_workspace('2:foo'), 'fake-1', + 'Renaming the workspace to a number and name should move it to the assigned output'); + +########################################################################## +# Renaming a workspace by name only triggers the assignment +########################################################################## + +cmd 'focus output fake-0'; +cmd 'rename workspace to baz'; +is(get_output_for_workspace('baz'), 'fake-1', + 'Renaming the workspace to a number and name should move it to the assigned output'); + + +exit_gracefully($pid); +done_testing; From acb79bd02fb1d650091c7a41761a9d503e540b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 4 Mar 2015 14:01:42 +0100 Subject: [PATCH 14/99] Improve error messages on failing commands --- src/commands.c | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/src/commands.c b/src/commands.c index 498c25c8..13e0fa7e 100644 --- a/src/commands.c +++ b/src/commands.c @@ -27,16 +27,19 @@ y(map_close); \ } \ } while (0) -#define yerror(message) \ - do { \ - if (cmd_output->json_gen != NULL) { \ - y(map_open); \ - ystr("success"); \ - y(bool, false); \ - ystr("error"); \ - ystr(message); \ - y(map_close); \ - } \ +#define yerror(format, ...) \ + do { \ + if (cmd_output->json_gen != NULL) { \ + char *message; \ + sasprintf(&message, format, ##__VA_ARGS__); \ + y(map_open); \ + ystr("success"); \ + y(bool, false); \ + ystr("error"); \ + ystr(message); \ + y(map_close); \ + free(message); \ + } \ } while (0) /** When the command did not include match criteria (!), we use the currently @@ -574,8 +577,7 @@ void cmd_move_con_to_workspace_number(I3_CMD, char *which) { if (parsed_num == -1) { LOG("Could not parse initial part of \"%s\" as a number.\n", which); - // TODO: better error message - yerror("Could not parse number"); + yerror("Could not parse number \"%s\"", which); return; } @@ -1002,8 +1004,7 @@ void cmd_workspace_number(I3_CMD, char *which) { if (parsed_num == -1) { LOG("Could not parse initial part of \"%s\" as a number.\n", which); - // TODO: better error message - yerror("Could not parse number"); + yerror("Could not parse number \"%s\"", which); return; } @@ -2002,10 +2003,7 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) { } if (!workspace) { - // TODO: we should include the old workspace name here and use yajl for - // generating the reply. - // TODO: better error message - yerror("Old workspace not found"); + yerror("Old workspace \"%s\" not found", old_name); return; } @@ -2015,10 +2013,7 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) { !strcasecmp(child->name, new_name)); if (check_dest != NULL) { - // TODO: we should include the new workspace name here and use yajl for - // generating the reply. - // TODO: better error message - yerror("New workspace already exists"); + yerror("New workspace \"%s\" already exists", new_name); return; } From c572176429ba756c5c2227a2108100ea328cee97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Thu, 5 Mar 2015 14:00:24 +0100 Subject: [PATCH 15/99] Use the already existing function to get rid of some code duplication --- src/commands.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/commands.c b/src/commands.c index 0a64b2b8..c41352bd 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1177,28 +1177,13 @@ void cmd_move_con_to_output(I3_CMD, char *name) { HANDLE_EMPTY_MATCH; - /* get the output */ Output *current_output = NULL; - Output *output; - // TODO: fix the handling of criteria TAILQ_FOREACH(current, &owindows, owindows) current_output = get_output_of_con(current->con); - assert(current_output != NULL); - // TODO: clean this up with commands.spec as soon as we switched away from the lex/yacc command parser - if (strcasecmp(name, "up") == 0) - output = get_output_next_wrap(D_UP, current_output); - else if (strcasecmp(name, "down") == 0) - output = get_output_next_wrap(D_DOWN, current_output); - else if (strcasecmp(name, "left") == 0) - output = get_output_next_wrap(D_LEFT, current_output); - else if (strcasecmp(name, "right") == 0) - output = get_output_next_wrap(D_RIGHT, current_output); - else - output = get_output_by_name(name); - + Output *output = get_output_from_string(current_output, name); if (!output) { LOG("No such output found.\n"); ysuccess(false); From dadf83360770bed306b827fcd65c86624f3d3fcd Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 7 Mar 2015 20:31:38 +0100 Subject: [PATCH 16/99] update debian/changelog for the new release --- debian/changelog | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 3b5cdb21..1dcfc9f9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,14 @@ -i3-wm (4.9.1-1) experimental; urgency=medium +i3-wm (4.9.2-1) experimental; urgency=medium * NOT YET RELEASED. - -- Michael Stapelberg Sat, 28 Feb 2015 15:04:25 +0100 + -- Michael Stapelberg Sat, 07 Mar 2015 20:31:31 +0100 + +i3-wm (4.9.1-1) experimental; urgency=medium + + * New upstream release. + + -- Michael Stapelberg Sat, 07 Mar 2015 20:01:46 +0100 i3-wm (4.9-1) experimental; urgency=medium From 10a58725cd481192576f5598cfd0f2d7fea88b13 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 7 Mar 2015 20:37:34 +0100 Subject: [PATCH 17/99] add release.sh, a script to prepare a new i3 release --- release.sh | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100755 release.sh diff --git a/release.sh b/release.sh new file mode 100755 index 00000000..db5ca09b --- /dev/null +++ b/release.sh @@ -0,0 +1,193 @@ +#!/bin/zsh +# This script is used to prepare a new release of i3. + +export RELEASE_VERSION="4.9.1" +export PREVIOUS_VERSION="4.9" +export RELEASE_BRANCH="master" + +if [ ! -e "../i3.github.io" ] +then + echo "../i3.github.io does not exist." + echo "Use git clone git://github.com/i3/i3.github.io" + exit 1 +fi + +if [ ! -e "RELEASE-NOTES-${RELEASE_VERSION}" ] +then + echo "RELEASE-NOTES-${RELEASE_VERSION} not found." + exit 1 +fi + +if git diff-files --quiet --exit-code debian/changelog +then + echo "Expected debian/changelog to be changed (containing the changelog for ${RELEASE_VERSION})." + exit 1 +fi + +eval $(gpg-agent --daemon) +export GPG_AGENT_INFO + +################################################################################ +# Section 1: update git and build the release tarball +################################################################################ + +STARTDIR=$PWD + +TMPDIR=$(mktemp -d) +cd $TMPDIR +if ! wget http://i3wm.org/downloads/i3-${PREVIOUS_VERSION}.tar.bz2; then + echo "Could not download i3-${PREVIOUS_VERSION}.tar.bz2 (required for comparing files)." + exit 1 +fi +git clone --quiet --branch "${RELEASE_BRANCH}" file://${STARTDIR} +cd i3 +if [ ! -e "${STARTDIR}/RELEASE-NOTES-${RELEASE_VERSION}" ]; then + echo "Required file RELEASE-NOTES-${RELEASE_VERSION} not found." + exit 1 +fi +git checkout -b release-${RELEASE_VERSION} +cp "${STARTDIR}/RELEASE-NOTES-${RELEASE_VERSION}" "RELEASE-NOTES-${RELEASE_VERSION}" +git add RELEASE-NOTES-${RELEASE_VERSION} +git rm RELEASE-NOTES-${PREVIOUS_VERSION} +sed -i "s,[^<]*,${RELEASE_VERSION},g" man/asciidoc.conf +git commit -a -m "release i3 ${RELEASE_VERSION}" +git tag "${RELEASE_VERSION}" -m "release i3 ${RELEASE_VERSION}" --sign --local-user=0x4AC8EE1D + +make dist + +echo "Differences in the release tarball file lists:" + +diff -u \ + <(tar tf ../i3-${PREVIOUS_VERSION}.tar.bz2 | sed "s,i3-${PREVIOUS_VERSION}/,,g" | sort) \ + <(tar tf i3-${RELEASE_VERSION}.tar.bz2 | sed "s,i3-${RELEASE_VERSION}/,,g" | sort) \ + | colordiff + +if ! tar xf i3-${RELEASE_VERSION}.tar.bz2 --to-stdout --strip-components=1 i3-${RELEASE_VERSION}/I3_VERSION | grep -q "^${RELEASE_VERSION} " +then + echo "I3_VERSION file does not start with ${RELEASE_VERSION}" + exit 1 +fi + +gpg --armor -b i3-${RELEASE_VERSION}.tar.bz2 + +if [ "${RELEASE_BRANCH}" = "master" ]; then + git checkout master + git merge --no-ff release-${RELEASE_VERSION} -m "Merge branch 'release-${RELEASE_VERSION}'" + git checkout next + git merge --no-ff master -m "Merge branch 'master' into next" +else + git checkout next + git merge --no-ff release-${RELEASE_VERSION} -m "Merge branch 'release-${RELEASE_VERSION}'" + git checkout master + git merge --no-ff next -m "Merge branch 'next' into master" +fi + +################################################################################ +# Section 2: Debian packaging +################################################################################ + +cd "${TMPDIR}" +mkdir debian + +# Copy over the changelog because we expect it to be locally modified in the +# start directory. +cp "${STARTDIR}/debian/changelog" i3/debian/changelog + +cat > ${TMPDIR}/Dockerfile < debian/source/format +WORKDIR /usr/src +RUN mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' i3-${RELEASE_VERSION}/debian/control +WORKDIR /usr/src/i3-${RELEASE_VERSION} +RUN dpkg-buildpackage -sa -j8 +EOT + +CONTAINER_NAME=$(echo "i3-${TMPDIR}" | sed 's,/,,g') +docker build -t i3 . +for file in $(docker run --name "${CONTAINER_NAME}" i3 /bin/sh -c "ls /usr/src/i3*_${RELEASE_VERSION}*") +do + docker cp "${CONTAINER_NAME}:${file}" ${TMPDIR}/debian/ +done + +echo "Content of resulting package’s .changes file:" +cat ${TMPDIR}/debian/*.changes + +# debsign is in devscripts, which is available in fedora and debian +debsign -k4AC8EE1D ${TMPDIR}/debian/*.changes + +# TODO: docker cleanup + +################################################################################ +# Section 3: website +################################################################################ + +cd ${TMPDIR} +git clone --quiet ${STARTDIR}/../i3.github.io +cd i3.github.io +cp ${TMPDIR}/i3/i3-${RELEASE_VERSION}.tar.bz2* downloads/ +git add downloads/i3-${RELEASE_VERSION}.tar.bz2* +cp ${TMPDIR}/i3/RELEASE-NOTES-${RELEASE_VERSION} downloads/RELEASE-NOTES-${RELEASE_VERSION}.txt +git add downloads/RELEASE-NOTES-${RELEASE_VERSION}.txt +sed -i "s,

Documentation for i3 v[^<]*

,

Documentation for i3 v${RELEASE_VERSION}

,g" docs/index.html +sed -i "s,[^<]*,${RELEASE_VERSION},g" index.html +sed -i "s,The current stable version is .*$,The current stable version is ${RELEASE_VERSION}.,g" downloads/index.html +sed -i "s,,\n \n ${RELEASE_VERSION}\n i3-${RELEASE_VERSION}.tar.bz2\n $(ls -lh ../i3/i3-${RELEASE_VERSION}.tar.bz2 | awk -F " " {'print $5'} | sed 's/K$/ KiB/g')\n signature\n $(date +'%Y-%m-%d')\n release notes\n \n,g" downloads/index.html + +git commit -a -m "add ${RELEASE_VERSION} release" + +mkdir docs/${PREVIOUS_VERSION} +tar cf - '--exclude=[0-9]\.[0-9e]*' docs | tar xf - --strip-components=1 -C docs/${PREVIOUS_VERSION} +git add docs/${PREVIOUS_VERSION} +git commit -a -m "save docs for ${PREVIOUS_VERSION}" + +for i in $(find _docs -maxdepth 1 -and -type f -and \! -regex ".*\.\(html\|man\)$" -and \! -name "Makefile") +do + base="$(basename $i)" + [ -e "${STARTDIR}/docs/${base}" ] && cp "${STARTDIR}/docs/${base}" "_docs/${base}" +done + +(cd _docs && make) + +for i in $(find _docs -maxdepth 1 -and -type f -and \! -regex ".*\.\(html\|man\)$" -and \! -name "Makefile") +do + base="$(basename $i)" + [ -e "${STARTDIR}/docs/${base}" ] && cp "_docs/${base}.html" docs/ +done + +git commit -a -m "update docs for ${RELEASE_VERSION}" + +################################################################################ +# Section 4: final push instructions +################################################################################ + +echo "As a final sanity check, install the debian package and see whether i3 works." + +echo "When satisfied, run:" +echo " cd ${TMPDIR}/i3" +echo " git checkout next" +echo " vi debian/changelog" +# TODO: can we just set up the remote spec properly? +echo " git push git@github.com:i3/i3 next" +echo " git push git@github.com:i3/i3 master" +echo " git push git@github.com:i3/i3 --tags" +echo "" +echo " cd ${TMPDIR}/i3.github.io" +# TODO: can we just set up the remote spec properly? +echo " git push git@github.com:i3/i3.github.io master" +echo "" +echo " cd ${TMPDIR}/debian" +echo " dput *.changes" +echo "" +echo "Announce on:" +echo " twitter" +echo " google+" +echo " mailing list" +echo " #i3 topic" From 94b1e76af45431f8cb5878679591cd504f629e60 Mon Sep 17 00:00:00 2001 From: Diana Thayer Date: Wed, 11 Mar 2015 21:41:43 -0700 Subject: [PATCH 18/99] degendered terms --- docs/hacking-howto | 2 +- i3-dmenu-desktop | 2 +- i3-migrate-config-to-v4 | 2 +- i3-nagbar/main.c | 2 +- i3.config | 2 +- include/config.h | 2 +- include/data.h | 2 +- include/key_press.h | 2 +- libi3/font.c | 2 +- man/i3-sensible-editor.man | 2 +- man/i3-sensible-pager.man | 2 +- man/i3-sensible-terminal.man | 4 ++-- src/config_parser.c | 4 ++-- src/handlers.c | 6 +++--- src/main.c | 2 +- 15 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/hacking-howto b/docs/hacking-howto index a591047e..12d6b14e 100644 --- a/docs/hacking-howto +++ b/docs/hacking-howto @@ -1012,7 +1012,7 @@ gets started in any way) and the window(s) which appear. Imagine for example using dmenu: The user starts dmenu by pressing Mod+d, dmenu gets started with PID 3390. The user then decides to launch Firefox, which -takes a long time. So he enters firefox into dmenu and presses enter. Firefox +takes a long time. So they enter firefox into dmenu and press enter. Firefox gets started with PID 4001. When it finally finishes loading, it creates an X11 window and uses MapWindow to make it visible. This is the first time i3 actually gets in touch with Firefox. It decides to map the window, but it has diff --git a/i3-dmenu-desktop b/i3-dmenu-desktop index 2c54233d..a941ce1b 100755 --- a/i3-dmenu-desktop +++ b/i3-dmenu-desktop @@ -306,7 +306,7 @@ for my $app (keys %apps) { # }; # ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Run dmenu to ask the user for her choice ┃ +# ┃ Run dmenu to ask the user for their choice ┃ # ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ # open2 will just make dmenu’s STDERR go to our own STDERR. diff --git a/i3-migrate-config-to-v4 b/i3-migrate-config-to-v4 index ae5bf4de..b78378be 100755 --- a/i3-migrate-config-to-v4 +++ b/i3-migrate-config-to-v4 @@ -341,7 +341,7 @@ sub convert_command { # NOTE: This is not 100% accurate, as it only works for one level # of nested containers. As this is a common use case, we use 'focus # parent; $command' nevertheless. For advanced use cases, the user - # has to modify his config. + # has to modify their config. print "$statement $key focus parent; $command\n"; } return; diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c index bdf6582b..b501ff6a 100644 --- a/i3-nagbar/main.c +++ b/i3-nagbar/main.c @@ -5,7 +5,7 @@ * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE) * * i3-nagbar is a utility which displays a nag message, for example in the case - * when the user has an error in his configuration file. + * when the user has an error in their configuration file. * */ #include diff --git a/i3.config b/i3.config index c53ecadf..f7722d36 100644 --- a/i3.config +++ b/i3.config @@ -169,7 +169,7 @@ bar { ####################################################################### # automatically start i3-config-wizard to offer the user to create a -# keysym-based config which used his favorite modifier (alt or windows) +# keysym-based config which used their favorite modifier (alt or windows) # # i3-config-wizard will not launch if there already is a config file # in ~/.i3/config. diff --git a/include/config.h b/include/config.h index dea26d96..afafb64b 100644 --- a/include/config.h +++ b/include/config.h @@ -105,7 +105,7 @@ struct Config { /** By default, focus follows mouse. If the user explicitly wants to * turn this off (and instead rely only on the keyboard for changing - * focus), we allow him to do this with this relatively special option. + * focus), we allow them to do this with this relatively special option. * It is not planned to add any different focus models. */ bool disable_focus_follows_mouse; diff --git a/include/data.h b/include/data.h index 8f2c197d..eba0f968 100644 --- a/include/data.h +++ b/include/data.h @@ -450,7 +450,7 @@ struct Match { /** * An Assignment makes specific windows go to a specific workspace/output or * run a command for that window. With this mechanism, the user can -- for - * example -- assign his browser to workspace "www". Checking if a window is + * example -- assign their browser to workspace "www". Checking if a window is * assigned works by comparing the Match data structure with the window (see * match_matches_window()). * diff --git a/include/key_press.h b/include/key_press.h index 9712e8b9..86cc6836 100644 --- a/include/key_press.h +++ b/include/key_press.h @@ -19,7 +19,7 @@ void handle_key_press(xcb_key_press_event_t *event); /** * Kills the commanderror i3-nagbar process, if any. * - * Called when reloading/restarting, since the user probably fixed his wrong + * Called when reloading/restarting, since the user probably fixed their wrong * keybindings. * * If wait_for_it is set (restarting), this function will waitpid(), otherwise, diff --git a/libi3/font.c b/libi3/font.c index df478fb4..cb92d52f 100644 --- a/libi3/font.c +++ b/libi3/font.c @@ -455,7 +455,7 @@ static int xcb_query_text_width(const xcb_char2b_t *text, size_t text_len) { cookie, &error); if (reply == NULL) { /* We return a safe estimate because a rendering error is better than - * a crash. Plus, the user will see the error in his log. */ + * a crash. Plus, the user will see the error in their log. */ fprintf(stderr, "Could not get text extents (X error code %d)\n", error->error_code); return savedFont->specific.xcb.info->max_bounds.character_width * text_len; diff --git a/man/i3-sensible-editor.man b/man/i3-sensible-editor.man index 2a044881..19b0f3a5 100644 --- a/man/i3-sensible-editor.man +++ b/man/i3-sensible-editor.man @@ -30,7 +30,7 @@ It tries to start one of the following (in that order): * gedit * mc-edit -Please don’t complain about the order: If the user has any preference, he will +Please don’t complain about the order: If the user has any preference, they will have $VISUAL or $EDITOR set. == SEE ALSO diff --git a/man/i3-sensible-pager.man b/man/i3-sensible-pager.man index 6b04c431..22754c0b 100644 --- a/man/i3-sensible-pager.man +++ b/man/i3-sensible-pager.man @@ -23,7 +23,7 @@ It tries to start one of the following (in that order): * w3m * i3-sensible-editor(1) -Please don’t complain about the order: If the user has any preference, he will +Please don’t complain about the order: If the user has any preference, they will have $PAGER set. == SEE ALSO diff --git a/man/i3-sensible-terminal.man b/man/i3-sensible-terminal.man index d1ad5198..6fa91ac8 100644 --- a/man/i3-sensible-terminal.man +++ b/man/i3-sensible-terminal.man @@ -33,8 +33,8 @@ It tries to start one of the following (in that order): * roxterm * xfce4-terminal -Please don’t complain about the order: If the user has any preference, she will -have $TERMINAL set or modified her i3 configuration file. +Please don’t complain about the order: If the user has any preference, they will +have $TERMINAL set or modified their i3 configuration file. == SEE ALSO diff --git a/src/config_parser.c b/src/config_parser.c index 24cebcec..b229b445 100644 --- a/src/config_parser.c +++ b/src/config_parser.c @@ -823,11 +823,11 @@ static char *migrate_config(char *input, off_t size) { fprintf(stderr, "Migration process exit code was != 0\n"); if (returncode == 2) { fprintf(stderr, "could not start the migration script\n"); - /* TODO: script was not found. tell the user to fix his system or create a v4 config */ + /* TODO: script was not found. tell the user to fix their system or create a v4 config */ } else if (returncode == 1) { fprintf(stderr, "This already was a v4 config. Please add the following line to your config file:\n"); fprintf(stderr, "# i3 config file (v4)\n"); - /* TODO: nag the user with a message to include a hint for i3 in his config file */ + /* TODO: nag the user with a message to include a hint for i3 in their config file */ } return NULL; } diff --git a/src/handlers.c b/src/handlers.c index 1e6b634c..0cd397fd 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -106,7 +106,7 @@ static void check_crossing_screen_boundary(uint32_t x, uint32_t y) { return; } - /* Focus the output on which the user moved his cursor */ + /* Focus the output on which the user moved their cursor */ Con *old_focused = focused; Con *next = con_descend_focused(output_get_content(output->con)); /* Since we are switching outputs, this *must* be a different workspace, so @@ -149,7 +149,7 @@ static void handle_enter_notify(xcb_enter_notify_event_t *event) { enter_child = true; } - /* If not, then the user moved his cursor to the root window. In that case, we adjust c_ws */ + /* If not, then the user moved their cursor to the root window. In that case, we adjust c_ws */ if (con == NULL) { DLOG("Getting screen at %d x %d\n", event->root_x, event->root_y); check_crossing_screen_boundary(event->root_x, event->root_y); @@ -1315,7 +1315,7 @@ void handle_event(int type, xcb_generic_event_t *event) { handle_motion_notify((xcb_motion_notify_event_t *)event); break; - /* Enter window = user moved his mouse over the window */ + /* Enter window = user moved their mouse over the window */ case XCB_ENTER_NOTIFY: handle_enter_notify((xcb_enter_notify_event_t *)event); break; diff --git a/src/main.c b/src/main.c index 708df38e..8b514178 100644 --- a/src/main.c +++ b/src/main.c @@ -778,7 +778,7 @@ int main(int argc, char *argv[]) { ELOG("Could not setup signal handler"); /* Ignore SIGPIPE to survive errors when an IPC client disconnects - * while we are sending him a message */ + * while we are sending them a message */ signal(SIGPIPE, SIG_IGN); /* Autostarting exec-lines */ From 9a355dcb928707d9751ae6422649bb744e8fa5ff Mon Sep 17 00:00:00 2001 From: Micha Rosenbaum Date: Thu, 12 Mar 2015 11:18:12 +0100 Subject: [PATCH 19/99] Fix comment box --- i3-dmenu-desktop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i3-dmenu-desktop b/i3-dmenu-desktop index a941ce1b..cc72f101 100755 --- a/i3-dmenu-desktop +++ b/i3-dmenu-desktop @@ -306,7 +306,7 @@ for my $app (keys %apps) { # }; # ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Run dmenu to ask the user for their choice ┃ +# ┃ Run dmenu to ask the user for their choice ┃ # ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ # open2 will just make dmenu’s STDERR go to our own STDERR. From 92d8b4d469f1a9fcf6296e505344cccef99749b3 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 13 Mar 2015 10:06:57 +0100 Subject: [PATCH 20/99] add configuration for travis-ci.com --- .travis.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..210f15f9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +language: c +compiler: + - gcc + - clang +before_install: + - sudo apt-get update + - sudo apt-get install -y devscripts +install: + - sudo mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' debian/control + - sudo apt-get install --no-install-recommends -y libanyevent-perl libanyevent-i3-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-c-perl + - sudo cpanm X11::XCB; sudo cpanm -n X11::XCB +script: make -j && (cd testcases && xvfb-run ./complete-run.pl) From f549089c30565c2b3bd5f65a689c7055bb0a168d Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 13 Mar 2015 10:09:21 +0100 Subject: [PATCH 21/99] travis: mk-build-deps needs equivs --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 210f15f9..42df9106 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ compiler: - clang before_install: - sudo apt-get update - - sudo apt-get install -y devscripts + - sudo apt-get install -y devscripts equivs install: - sudo mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' debian/control - sudo apt-get install --no-install-recommends -y libanyevent-perl libanyevent-i3-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-c-perl From b370c5ac7132ffd974ff30c36fc80d007fdcbf6d Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 13 Mar 2015 10:12:00 +0100 Subject: [PATCH 22/99] travis runs on ubuntu 12.04, so use libinline-perl --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 42df9106..1ce410a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,6 @@ before_install: - sudo apt-get install -y devscripts equivs install: - sudo mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' debian/control - - sudo apt-get install --no-install-recommends -y libanyevent-perl libanyevent-i3-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-c-perl + - sudo apt-get install --no-install-recommends -y libanyevent-perl libanyevent-i3-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-perl - sudo cpanm X11::XCB; sudo cpanm -n X11::XCB script: make -j && (cd testcases && xvfb-run ./complete-run.pl) From 439cadf441794f84e145354d4178aae2af65084e Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 13 Mar 2015 10:21:02 +0100 Subject: [PATCH 23/99] travis: directly use cpanm -n to skip tests X11::XCB currently fails its tests --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1ce410a1..791633e6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,5 +8,5 @@ before_install: install: - sudo mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' debian/control - sudo apt-get install --no-install-recommends -y libanyevent-perl libanyevent-i3-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-perl - - sudo cpanm X11::XCB; sudo cpanm -n X11::XCB + - sudo cpanm -n X11::XCB script: make -j && (cd testcases && xvfb-run ./complete-run.pl) From 5776edcc84d15a9a6dbdafc7fe7f3177004fee86 Mon Sep 17 00:00:00 2001 From: Michael Hofmann Date: Sat, 7 Mar 2015 00:14:47 +0100 Subject: [PATCH 24/99] Test: startup workspaces updating on rename. --- testcases/t/175-startup-notification.t | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/testcases/t/175-startup-notification.t b/testcases/t/175-startup-notification.t index 9f0c046a..4ca41799 100644 --- a/testcases/t/175-startup-notification.t +++ b/testcases/t/175-startup-notification.t @@ -142,12 +142,17 @@ is_num_children($first_ws, 2, 'two containers on the first workspace'); complete_startup(); sync_with_i3; +# even when renaming the workspace, windows should end up on the correct one +cmd "rename workspace $first_ws to temp"; + # Startup has completed but the 30-second deletion time hasn't elapsed, # so this window should still go on the leader's initial workspace. $win = open_window({ dont_map => 1, client_leader => $leader }); $win->map; sync_with_i3; +cmd "rename workspace temp to $first_ws"; + is_num_children($first_ws, 3, 'three containers on the first workspace'); # Switch to the first workspace and move the focused window to the From 44f748a663fc0ae96b2a750a804cf470dcad1675 Mon Sep 17 00:00:00 2001 From: Michael Hofmann Date: Sat, 7 Mar 2015 00:13:54 +0100 Subject: [PATCH 25/99] Rename workspaces in startup sequences. When renaming workspaces, any workspace names in pending startup sequences also need to be renamed. --- include/startup.h | 6 ++++++ src/commands.c | 2 ++ src/startup.c | 16 ++++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/include/startup.h b/include/startup.h index 2f28baa7..cb784913 100644 --- a/include/startup.h +++ b/include/startup.h @@ -44,6 +44,12 @@ void startup_sequence_delete(struct Startup_Sequence *sequence); */ void startup_monitor_event(SnMonitorEvent *event, void *userdata); +/** + * Renames workspaces that are mentioned in the startup sequences. + * + */ +void startup_sequence_rename_workspace(char *old_name, char *new_name); + /** * Gets the stored startup sequence for the _NET_STARTUP_ID of a given window. * diff --git a/src/commands.c b/src/commands.c index 92203e39..d3e2a6e3 100644 --- a/src/commands.c +++ b/src/commands.c @@ -2044,6 +2044,8 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) { ewmh_update_desktop_names(); ewmh_update_desktop_viewport(); ewmh_update_current_desktop(); + + startup_sequence_rename_workspace(old_name, new_name); } /* diff --git a/src/startup.c b/src/startup.c index ebe8c1d9..aa347bd7 100644 --- a/src/startup.c +++ b/src/startup.c @@ -257,6 +257,22 @@ void startup_monitor_event(SnMonitorEvent *event, void *userdata) { } } +/** + * Renames workspaces that are mentioned in the startup sequences. + * + */ +void startup_sequence_rename_workspace(char *old_name, char *new_name) { + struct Startup_Sequence *current; + TAILQ_FOREACH(current, &startup_sequences, sequences) { + if (strcmp(current->workspace, old_name) != 0) + continue; + DLOG("Renaming workspace \"%s\" to \"%s\" in startup sequence %s.\n", + old_name, new_name, current->id); + free(current->workspace); + current->workspace = sstrdup(new_name); + } +} + /** * Gets the stored startup sequence for the _NET_STARTUP_ID of a given window. * From 9088fa03bc41a253c967282762f0f7bc7bf0b1ee Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 13 Mar 2015 11:39:59 +0100 Subject: [PATCH 26/99] travis: cpanm: set -v so that we get error messages in the travis output --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 791633e6..5a9065e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,5 +8,5 @@ before_install: install: - sudo mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' debian/control - sudo apt-get install --no-install-recommends -y libanyevent-perl libanyevent-i3-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-perl - - sudo cpanm -n X11::XCB + - sudo cpanm -n -v X11::XCB script: make -j && (cd testcases && xvfb-run ./complete-run.pl) From 0b3601c2ef73b70a81676cf787b50bc6d5d53c76 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 13 Mar 2015 13:24:02 +0100 Subject: [PATCH 27/99] travis: also cat cpanm build logs after failure --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 5a9065e5..d2920ce0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,3 +10,4 @@ install: - sudo apt-get install --no-install-recommends -y libanyevent-perl libanyevent-i3-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-perl - sudo cpanm -n -v X11::XCB script: make -j && (cd testcases && xvfb-run ./complete-run.pl) +after_failure: cat /home/travis/.cpanm/build.log From 8dd6591c59d062204cb25dd66b33f1a35976f03c Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 13 Mar 2015 20:52:53 +0100 Subject: [PATCH 28/99] travis: install more perl dependencies, pull in trusty packages --- .travis.yml | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index d2920ce0..4bd70116 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,11 +3,21 @@ compiler: - gcc - clang before_install: + # The travis VMs run on Ubuntu 12.04 which is very old and a huge pain to get + # into a state where we can build a recent version of i3 :(. + - echo 'deb http://archive.ubuntu.com/ubuntu/ trusty main universe' | sudo tee /etc/apt/sources.list.d/trusty.list + - echo 'APT::Default-Release "precise";' | sudo tee /etc/apt/apt.conf.d/default-release + - echo -e "Package: libc6\nPin: release n=trusty\nPin-Priority: 999" | sudo tee /etc/apt/preferences.d/00-libc6 + - echo -e "Package: libxkbcommon*\nPin: release n=trusty\nPin-Priority: 999" | sudo tee /etc/apt/preferences.d/01-xkbcommon + - echo -e "Package: libyajl*\nPin: release n=trusty\nPin-Priority: 999" | sudo tee /etc/apt/preferences.d/02-yajl + - echo -e "Package: libxcb-image*\nPin: release n=trusty\nPin-Priority: 999" | sudo tee /etc/apt/preferences.d/03-xcb-image - sudo apt-get update - - sudo apt-get install -y devscripts equivs + - sudo apt-get install -t trusty libc6 libc6-dev + - sudo apt-get install --no-install-recommends devscripts equivs install: - - sudo mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' debian/control - - sudo apt-get install --no-install-recommends -y libanyevent-perl libanyevent-i3-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-perl - - sudo cpanm -n -v X11::XCB + - sudo mk-build-deps --install --remove --tool 'apt-get --no-install-recommends' debian/control + # Install as many dependencies as possible via apt because cpanm is not very reliable/easy to debug. + - sudo apt-get install --no-install-recommends libanyevent-perl libanyevent-i3-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-perl libxml-simple-perl libmouse-perl libmousex-nativetraits-perl libextutils-depends-perl perl-modules libtest-deep-perl libtest-exception-perl libxml-parser-perl libtest-simple-perl libtest-fatal-perl libdata-dump-perl libtest-differences-perl libxml-tokeparser-perl libtest-use-ok-perl + - sudo /bin/sh -c 'cpanm -n -v X11::XCB || true' script: make -j && (cd testcases && xvfb-run ./complete-run.pl) after_failure: cat /home/travis/.cpanm/build.log From f8ac5fcfe2677922ac484bc9ab200564f9dcf6fc Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 13 Mar 2015 21:04:03 +0100 Subject: [PATCH 29/99] travis: escape strings for YAML --- .travis.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4bd70116..fc01df70 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,12 +5,12 @@ compiler: before_install: # The travis VMs run on Ubuntu 12.04 which is very old and a huge pain to get # into a state where we can build a recent version of i3 :(. - - echo 'deb http://archive.ubuntu.com/ubuntu/ trusty main universe' | sudo tee /etc/apt/sources.list.d/trusty.list - - echo 'APT::Default-Release "precise";' | sudo tee /etc/apt/apt.conf.d/default-release - - echo -e "Package: libc6\nPin: release n=trusty\nPin-Priority: 999" | sudo tee /etc/apt/preferences.d/00-libc6 - - echo -e "Package: libxkbcommon*\nPin: release n=trusty\nPin-Priority: 999" | sudo tee /etc/apt/preferences.d/01-xkbcommon - - echo -e "Package: libyajl*\nPin: release n=trusty\nPin-Priority: 999" | sudo tee /etc/apt/preferences.d/02-yajl - - echo -e "Package: libxcb-image*\nPin: release n=trusty\nPin-Priority: 999" | sudo tee /etc/apt/preferences.d/03-xcb-image + - "echo 'deb http://archive.ubuntu.com/ubuntu/ trusty main universe' | sudo tee /etc/apt/sources.list.d/trusty.list" + - "echo 'APT::Default-Release \"precise\";' | sudo tee /etc/apt/apt.conf.d/default-release" + - "echo -e \"Package: libc6\nPin: release n=trusty\nPin-Priority: 999\" | sudo tee /etc/apt/preferences.d/00-libc6" + - "echo -e \"Package: libxkbcommon*\nPin: release n=trusty\nPin-Priority: 999\" | sudo tee /etc/apt/preferences.d/01-xkbcommon" + - "echo -e \"Package: libyajl*\nPin: release n=trusty\nPin-Priority: 999\" | sudo tee /etc/apt/preferences.d/02-yajl" + - "echo -e \"Package: libxcb-image*\nPin: release n=trusty\nPin-Priority: 999\" | sudo tee /etc/apt/preferences.d/03-xcb-image" - sudo apt-get update - sudo apt-get install -t trusty libc6 libc6-dev - sudo apt-get install --no-install-recommends devscripts equivs From 2cf40f4867729ab0788c290eba5894bb7f88c299 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 13 Mar 2015 23:38:13 +0100 Subject: [PATCH 30/99] travis: fix pinning setup (newlines and YAML are complicated) --- .travis.yml | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index fc01df70..1c801609 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,10 +7,28 @@ before_install: # into a state where we can build a recent version of i3 :(. - "echo 'deb http://archive.ubuntu.com/ubuntu/ trusty main universe' | sudo tee /etc/apt/sources.list.d/trusty.list" - "echo 'APT::Default-Release \"precise\";' | sudo tee /etc/apt/apt.conf.d/default-release" - - "echo -e \"Package: libc6\nPin: release n=trusty\nPin-Priority: 999\" | sudo tee /etc/apt/preferences.d/00-libc6" - - "echo -e \"Package: libxkbcommon*\nPin: release n=trusty\nPin-Priority: 999\" | sudo tee /etc/apt/preferences.d/01-xkbcommon" - - "echo -e \"Package: libyajl*\nPin: release n=trusty\nPin-Priority: 999\" | sudo tee /etc/apt/preferences.d/02-yajl" - - "echo -e \"Package: libxcb-image*\nPin: release n=trusty\nPin-Priority: 999\" | sudo tee /etc/apt/preferences.d/03-xcb-image" + + - "echo 'Package: libc6' > /tmp/pin" + - "echo 'Pin: release n=trusty' >> /tmp/pin" + - "echo 'Pin-Priority: 999' >> /tmp/pin" + - "echo '' >> /tmp/pin" + + - "echo 'Package: libxkbcommon*' >> /tmp/pin" + - "echo 'Pin: release n=trusty' >> /tmp/pin" + - "echo 'Pin-Priority: 999' >> /tmp/pin" + - "echo '' >> /tmp/pin" + + - "echo 'Package: libyajl*' >> /tmp/pin" + - "echo 'Pin: release n=trusty' >> /tmp/pin" + - "echo 'Pin-Priority: 999' >> /tmp/pin" + - "echo '' >> /tmp/pin" + + - "echo 'Package: libxcb-image*' >> /tmp/pin" + - "echo 'Pin: release n=trusty' >> /tmp/pin" + - "echo 'Pin-Priority: 999' >> /tmp/pin" + - "echo '' >> /tmp/pin" + + - sudo cp /tmp/pin /etc/apt/preferences.d/trustypin - sudo apt-get update - sudo apt-get install -t trusty libc6 libc6-dev - sudo apt-get install --no-install-recommends devscripts equivs From 26d17c6b883282442f50105d0dc7a78780ee0ca8 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 13 Mar 2015 23:38:33 +0100 Subject: [PATCH 31/99] travis: install as many perl pkgs as possible via apt instead of cpanm --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1c801609..7b843044 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,7 @@ before_install: install: - sudo mk-build-deps --install --remove --tool 'apt-get --no-install-recommends' debian/control # Install as many dependencies as possible via apt because cpanm is not very reliable/easy to debug. - - sudo apt-get install --no-install-recommends libanyevent-perl libanyevent-i3-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-perl libxml-simple-perl libmouse-perl libmousex-nativetraits-perl libextutils-depends-perl perl-modules libtest-deep-perl libtest-exception-perl libxml-parser-perl libtest-simple-perl libtest-fatal-perl libdata-dump-perl libtest-differences-perl libxml-tokeparser-perl libtest-use-ok-perl + - sudo apt-get install --no-install-recommends libanyevent-perl libanyevent-i3-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-perl libxml-simple-perl libmouse-perl libmousex-nativetraits-perl libextutils-depends-perl perl-modules libtest-deep-perl libtest-exception-perl libxml-parser-perl libtest-simple-perl libtest-fatal-perl libdata-dump-perl libtest-differences-perl libxml-tokeparser-perl libtest-use-ok-perl libipc-run-perl - sudo /bin/sh -c 'cpanm -n -v X11::XCB || true' script: make -j && (cd testcases && xvfb-run ./complete-run.pl) after_failure: cat /home/travis/.cpanm/build.log From 69be6e4a8ea7b006dbe01528ae83ad802264307a Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 13 Mar 2015 23:38:56 +0100 Subject: [PATCH 32/99] travis: run tests serialized, install latest AnyEvent::I3 --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7b843044..c866e7c0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,5 +37,6 @@ install: # Install as many dependencies as possible via apt because cpanm is not very reliable/easy to debug. - sudo apt-get install --no-install-recommends libanyevent-perl libanyevent-i3-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-perl libxml-simple-perl libmouse-perl libmousex-nativetraits-perl libextutils-depends-perl perl-modules libtest-deep-perl libtest-exception-perl libxml-parser-perl libtest-simple-perl libtest-fatal-perl libdata-dump-perl libtest-differences-perl libxml-tokeparser-perl libtest-use-ok-perl libipc-run-perl - sudo /bin/sh -c 'cpanm -n -v X11::XCB || true' -script: make -j && (cd testcases && xvfb-run ./complete-run.pl) + - sudo /bin/sh -c 'cpanm -n -v AnyEvent::I3 || true' +script: make -j && (cd testcases && xvfb-run ./complete-run.pl --parallel=1) after_failure: cat /home/travis/.cpanm/build.log From aa4aec41f5bade8d8ea2fe26e314c9202a9c0181 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 14 Mar 2015 12:33:54 +0100 Subject: [PATCH 33/99] =?UTF-8?q?tests:=20don=E2=80=99t=20print=20interact?= =?UTF-8?q?ive=20status=20when=20running=20on=20travis?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (or without a tty) --- testcases/lib/StatusLine.pm | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/testcases/lib/StatusLine.pm b/testcases/lib/StatusLine.pm index 823c6713..379fd3d6 100644 --- a/testcases/lib/StatusLine.pm +++ b/testcases/lib/StatusLine.pm @@ -15,6 +15,13 @@ my %ansi_line_upwards; my $tests_total; +sub noninteractive { + # CONTINUOUS_INTEGRATION gets set when running under Travis, see + # http://docs.travis-ci.com/user/ci-environment/ and + # https://github.com/travis-ci/travis-ci/issues/1337 + return (! -t STDOUT) || $ENV{CONTINUOUS_INTEGRATION} eq 'true'; +} + # setup %ansi_line_upwards to map all working displays to the # specific movement commands and initialize all status lines sub status_init { @@ -22,6 +29,8 @@ sub status_init { my $displays = $args{displays}; $tests_total = $args{tests}; + return if noninteractive(); + for my $n (1 .. @$displays) { # since we are moving upwards, get $display in reverse order my $display = $displays->[-$n]; @@ -41,6 +50,8 @@ sub status { my ($display, $msg) = @_; my $status = "[$display] $msg"; + return $status if noninteractive(); + print $ansi_save_cursor, $ansi_line_upwards{$display}, @@ -53,6 +64,9 @@ sub status { sub status_completed { my $num = shift; + + return if noninteractive(); + print $ansi_save_cursor, $ansi_clear_line, From f0ef712ed046554ebc5ad66fe4e3d9f511f4a1e9 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 14 Mar 2015 12:34:34 +0100 Subject: [PATCH 34/99] tests: exit with status 1 when tests fail --- testcases/complete-run.pl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/testcases/complete-run.pl b/testcases/complete-run.pl index 61f2ef52..eaf57bde 100755 --- a/testcases/complete-run.pl +++ b/testcases/complete-run.pl @@ -227,7 +227,7 @@ if ($numtests == 1) { END { cleanup() } -exit 0; +exit ($aggregator->failed > 0); # # Takes a test from the beginning of @testfiles and runs it. @@ -324,8 +324,9 @@ sub take_job { } sub cleanup { + my $exitcode = $?; $_->() for our @CLEANUP; - exit; + exit $exitcode; } # must be in a begin block because we C above From 8eb5656c691d882192dd8825de229a1b07a85b3f Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 14 Mar 2015 12:35:01 +0100 Subject: [PATCH 35/99] travis: cat complete-run.log on failures --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c866e7c0..c2179044 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,4 +39,4 @@ install: - sudo /bin/sh -c 'cpanm -n -v X11::XCB || true' - sudo /bin/sh -c 'cpanm -n -v AnyEvent::I3 || true' script: make -j && (cd testcases && xvfb-run ./complete-run.pl --parallel=1) -after_failure: cat /home/travis/.cpanm/build.log +after_failure: cat testcases/latest/complete-run.log From 513510de6934e987cf8f02627368e2ff25b910df Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 14 Mar 2015 22:31:58 +0100 Subject: [PATCH 36/99] clang-format src/commands.c --- src/commands.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/commands.c b/src/commands.c index 13a28093..a3901df4 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1914,9 +1914,7 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) { TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) { if (assignment->output == NULL) continue; - if (strcmp(assignment->name, workspace->name) != 0 - && (!name_is_digits(assignment->name) || ws_name_to_number(assignment->name) != workspace->num)) { - + if (strcmp(assignment->name, workspace->name) != 0 && (!name_is_digits(assignment->name) || ws_name_to_number(assignment->name) != workspace->num)) { continue; } From cd48bcf2a55e425ca270cb1b01569acbd99ac26d Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 14 Mar 2015 22:32:03 +0100 Subject: [PATCH 37/99] travis: verify code was formatted using clang-format --- .travis.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c2179044..5876ae62 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ before_install: # into a state where we can build a recent version of i3 :(. - "echo 'deb http://archive.ubuntu.com/ubuntu/ trusty main universe' | sudo tee /etc/apt/sources.list.d/trusty.list" - "echo 'APT::Default-Release \"precise\";' | sudo tee /etc/apt/apt.conf.d/default-release" + - "echo 'deb http://archive.ubuntu.com/ubuntu/ utopic main universe' | sudo tee /etc/apt/sources.list.d/utopic.list" - "echo 'Package: libc6' > /tmp/pin" - "echo 'Pin: release n=trusty' >> /tmp/pin" @@ -32,11 +33,15 @@ before_install: - sudo apt-get update - sudo apt-get install -t trusty libc6 libc6-dev - sudo apt-get install --no-install-recommends devscripts equivs + - sudo apt-get install -t utopic clang-format-3.5 + - clang-format-3.5 --version install: - sudo mk-build-deps --install --remove --tool 'apt-get --no-install-recommends' debian/control # Install as many dependencies as possible via apt because cpanm is not very reliable/easy to debug. - sudo apt-get install --no-install-recommends libanyevent-perl libanyevent-i3-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-perl libxml-simple-perl libmouse-perl libmousex-nativetraits-perl libextutils-depends-perl perl-modules libtest-deep-perl libtest-exception-perl libxml-parser-perl libtest-simple-perl libtest-fatal-perl libdata-dump-perl libtest-differences-perl libxml-tokeparser-perl libtest-use-ok-perl libipc-run-perl - sudo /bin/sh -c 'cpanm -n -v X11::XCB || true' - sudo /bin/sh -c 'cpanm -n -v AnyEvent::I3 || true' -script: make -j && (cd testcases && xvfb-run ./complete-run.pl --parallel=1) -after_failure: cat testcases/latest/complete-run.log +script: + - make -j + - (cd testcases && xvfb-run ./complete-run.pl --parallel=1 || (cat latest/complete-run.log; false)) + - clang-format-3.5 -i **/*.[ch] && git diff --exit-code || (echo 'Code was not formatted using clang-format!'; false) From 123de9a25f341bc66beed0189f70132a4f589960 Mon Sep 17 00:00:00 2001 From: shdown Date: Sun, 15 Mar 2015 10:32:17 +0300 Subject: [PATCH 38/99] Fix incorrect y-offset for text in i3bar (2) 014aa7ff7441a8a2bb53bd0956aff61faaf6f37f fixed incorrect align of small symbols, but also introduced a problem with texts with mixed large and normal symbols. Fix it by centering the text vertically only if its height is smaller that the saved font height. Fixes #1543. --- libi3/font.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libi3/font.c b/libi3/font.c index df478fb4..b6d9d42e 100644 --- a/libi3/font.c +++ b/libi3/font.c @@ -126,7 +126,10 @@ static void draw_text_pango(const char *text, size_t text_len, cairo_set_source_rgb(cr, pango_font_red, pango_font_green, pango_font_blue); pango_cairo_update_layout(cr, layout); pango_layout_get_pixel_size(layout, NULL, &height); - cairo_move_to(cr, x, y - 0.5 * (height - savedFont->height)); + /* Center the piece of text vertically if its height is smaller than the + * cached font height, and just let "high" symbols fall out otherwise. */ + int yoffset = (height < savedFont->height ? 0.5 : 1) * (height - savedFont->height); + cairo_move_to(cr, x, y - yoffset); pango_cairo_show_layout(cr, layout); /* Free resources */ From 6b150b1ac2e742b296f09105e539cfbf3757b5d5 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 15 Mar 2015 23:30:00 -0400 Subject: [PATCH 39/99] bugfix: workspace rename focus mismatch When renaming a workspace on another output that moves the workspace to the current output, the renamed workspace would be shown even though it does not contain the focused container. Explicitly show the focused workspace after the move. This is necessary because `workspace_move_to_output` will show the workspace that is moved. --- src/commands.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/commands.c b/src/commands.c index a3901df4..80f57b81 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1919,6 +1919,10 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) { } workspace_move_to_output(workspace, assignment->output); + + if (previously_focused) + workspace_show(con_get_workspace(previously_focused)); + break; } From 52f918309b833c6d13a1c39fb5876eb101fd6600 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Mon, 16 Mar 2015 20:18:03 +0100 Subject: [PATCH 40/99] Remove the A_TO_OUTPUT option as it is not needed anymore and will not be implemented in favor of normal assignments. --- include/data.h | 7 ++----- src/config.c | 2 -- src/manage.c | 27 ++++++++++++--------------- 3 files changed, 14 insertions(+), 22 deletions(-) diff --git a/include/data.h b/include/data.h index 8f2c197d..b3cac928 100644 --- a/include/data.h +++ b/include/data.h @@ -460,7 +460,6 @@ struct Assignment { * * A_COMMAND = run the specified command for the matching window * A_TO_WORKSPACE = assign the matching window to the specified workspace - * A_TO_OUTPUT = assign the matching window to the specified output * * While the type is a bitmask, only one value can be set at a time. It is * a bitmask to allow filtering for multiple types, for example in the @@ -470,18 +469,16 @@ struct Assignment { enum { A_ANY = 0, A_COMMAND = (1 << 0), - A_TO_WORKSPACE = (1 << 1), - A_TO_OUTPUT = (1 << 2) + A_TO_WORKSPACE = (1 << 1) } type; /** the criteria to check if a window matches */ Match match; - /** destination workspace/output/command, depending on the type */ + /** destination workspace/command, depending on the type */ union { char *command; char *workspace; - char *output; } dest; TAILQ_ENTRY(Assignment) assignments; diff --git a/src/config.c b/src/config.c index b41f0e1b..6f906b8c 100644 --- a/src/config.c +++ b/src/config.c @@ -158,8 +158,6 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath, assign = TAILQ_FIRST(&assignments); if (assign->type == A_TO_WORKSPACE) FREE(assign->dest.workspace); - else if (assign->type == A_TO_OUTPUT) - FREE(assign->dest.output); else if (assign->type == A_COMMAND) FREE(assign->dest.command); match_free(&(assign->match)); diff --git a/src/manage.c b/src/manage.c index 7c464b43..077d5720 100644 --- a/src/manage.c +++ b/src/manage.c @@ -253,23 +253,20 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki /* See if any container swallows this new window */ nc = con_for_window(search_at, cwindow, &match); if (nc == NULL) { - /* If not, check if it is assigned to a specific workspace / output */ - if ((assignment = assignment_for(cwindow, A_TO_WORKSPACE | A_TO_OUTPUT))) { + /* If not, check if it is assigned to a specific workspace */ + if ((assignment = assignment_for(cwindow, A_TO_WORKSPACE))) { DLOG("Assignment matches (%p)\n", match); - if (assignment->type == A_TO_WORKSPACE) { - Con *assigned_ws = workspace_get(assignment->dest.workspace, NULL); - nc = con_descend_tiling_focused(assigned_ws); - DLOG("focused on ws %s: %p / %s\n", assigned_ws->name, nc, nc->name); - if (nc->type == CT_WORKSPACE) - nc = tree_open_con(nc, cwindow); - else - nc = tree_open_con(nc->parent, cwindow); + Con *assigned_ws = workspace_get(assignment->dest.workspace, NULL); + nc = con_descend_tiling_focused(assigned_ws); + DLOG("focused on ws %s: %p / %s\n", assigned_ws->name, nc, nc->name); + if (nc->type == CT_WORKSPACE) + nc = tree_open_con(nc, cwindow); + else + nc = tree_open_con(nc->parent, cwindow); - /* set the urgency hint on the window if the workspace is not visible */ - if (!workspace_is_visible(assigned_ws)) - urgency_hint = true; - } - /* TODO: handle assignments with type == A_TO_OUTPUT */ + /* set the urgency hint on the window if the workspace is not visible */ + if (!workspace_is_visible(assigned_ws)) + urgency_hint = true; } else if (startup_ws) { /* If it’s not assigned, but was started on a specific workspace, * we want to open it there */ From c35b3160f6e0c07cfbaa3a09baed6ebde48c8417 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 16 Mar 2015 22:37:45 +0100 Subject: [PATCH 41/99] relax timings of t/200-urgency-timer.t to reduce flakiness --- testcases/t/200-urgency-timer.t | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testcases/t/200-urgency-timer.t b/testcases/t/200-urgency-timer.t index 0fb8c8be..b6ebc876 100644 --- a/testcases/t/200-urgency-timer.t +++ b/testcases/t/200-urgency-timer.t @@ -31,7 +31,7 @@ my $config = <{urgent} } @content; is(@urgent, 0, 'window not marked as urgent anymore'); @@ -142,7 +142,7 @@ cmd "workspace $tmp3"; $split_left->delete_hint('urgency'); sync_with_i3; -sleep(0.2); +sleep(0.6); is(count_total_urgent(get_ws($tmp3)), 0, "no more urgent windows on workspace $tmp3"); exit_gracefully($pid); From d1f99abf75bbb6df520f48a45b954d24eb5c42c7 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 16 Mar 2015 22:38:39 +0100 Subject: [PATCH 42/99] fix warnings when CONTINUOUS_INTEGRATION env var is unset --- testcases/lib/StatusLine.pm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/testcases/lib/StatusLine.pm b/testcases/lib/StatusLine.pm index 379fd3d6..f2487797 100644 --- a/testcases/lib/StatusLine.pm +++ b/testcases/lib/StatusLine.pm @@ -19,7 +19,9 @@ sub noninteractive { # CONTINUOUS_INTEGRATION gets set when running under Travis, see # http://docs.travis-ci.com/user/ci-environment/ and # https://github.com/travis-ci/travis-ci/issues/1337 - return (! -t STDOUT) || $ENV{CONTINUOUS_INTEGRATION} eq 'true'; + return (! -t STDOUT) || ( + defined($ENV{CONTINUOUS_INTEGRATION}) && + $ENV{CONTINUOUS_INTEGRATION} eq 'true'); } # setup %ansi_line_upwards to map all working displays to the From d217cddb42b835e974af40294994385eb2cf9a52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 18 Mar 2015 21:37:37 +0100 Subject: [PATCH 43/99] Make the --workspace optional by defaulting to the focused workspace. If no option is given, i3-save-tree should default to the currently focused workspace. Specifying both --workspace and --output will still yield an error. --- i3-save-tree | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/i3-save-tree b/i3-save-tree index c64fc72a..04c7e38a 100755 --- a/i3-save-tree +++ b/i3-save-tree @@ -13,6 +13,7 @@ use POSIX qw(locale_h); use File::Find; use File::Basename qw(basename); use File::Temp qw(tempfile); +use List::Util qw(first); use Getopt::Long; use Pod::Usage; use AnyEvent::I3; @@ -41,11 +42,7 @@ my $result = GetOptions( die "Could not parse command line options" unless $result; -if (!defined($workspace) && !defined($output)) { - die "One of --workspace or --output need to be specified"; -} - -unless (defined($workspace) ^ defined($output)) { +if (defined($workspace) && defined($output)) { die "Only one of --workspace or --output can be specified"; } @@ -57,6 +54,15 @@ if (!$i3->connect->recv) { die "Could not connect to i3"; } +sub get_current_workspace { + my $current = first { $_->{focused} } @{$i3->get_workspaces->recv}; + return $current->{name}; +} + +if (!defined($workspace) && !defined($output)) { + $workspace = get_current_workspace(); +} + sub filter_containers { my ($tree, $pred) = @_; From 80f119f0e248211babadcfbfb0ffecfd66ea8e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Thu, 19 Mar 2015 18:59:25 +0100 Subject: [PATCH 44/99] adapted usage text --- i3-save-tree | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/i3-save-tree b/i3-save-tree index 04c7e38a..b6ed085e 100755 --- a/i3-save-tree +++ b/i3-save-tree @@ -265,19 +265,19 @@ specification. When a window is mapped (made visible on the screen) that matches the specification, i3 will put it into that place and kill the placeholder. +If neither argument is specified, the currently focused workspace will be used. + =head1 OPTIONS =over =item B<--workspace=name> -Specifies the workspace that should be dumped, e.g. 1. Either this or --output -need to be specified. +Specifies the workspace that should be dumped, e.g. 1. =item B<--output=name> -Specifies the output that should be dumped, e.g. LVDS-1. Either this or ---workspace need to be specified. +Specifies the output that should be dumped, e.g. LVDS-1. =back From 5efcfda2eda208ce6f45e90734dfcdebfee4baad Mon Sep 17 00:00:00 2001 From: shdown Date: Sat, 21 Mar 2015 19:00:11 +0300 Subject: [PATCH 45/99] i3bar: fix clearing of the statusline pixmap This fixes the bug when statusline pixmap wasn't entirely cleared that caused random artifacts to appear when the statusline width is greater than the screen width. --- 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 8bda53c4..79e9ad9c 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -174,7 +174,7 @@ void refresh_statusline(void) { realloc_sl_buffer(); /* Clear the statusline pixmap. */ - xcb_rectangle_t rect = {0, 0, root_screen->width_in_pixels, bar_height}; + xcb_rectangle_t rect = {0, 0, MAX(root_screen->width_in_pixels, statusline_width), bar_height}; xcb_poly_fill_rectangle(xcb_connection, statusline_pm, statusline_clear, 1, &rect); /* Draw the text of each block. */ From ccd6ae8eaff5c827d85dcc80ec944e8d079fb565 Mon Sep 17 00:00:00 2001 From: shdown Date: Sat, 21 Mar 2015 19:08:40 +0300 Subject: [PATCH 46/99] i3bar: cut long statuslines from the left This draws the statusline after drawing (and calculating width of) the workspace buttons and fixes calculation of its maximum visible width. This (hopefully) guarantees that these two will never overlap. --- i3bar/src/xcb.c | 60 ++++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 79e9ad9c..aa24fc22 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -1763,34 +1763,6 @@ void draw_bars(bool unhide) { 1, &rect); - if (!TAILQ_EMPTY(&statusline_head)) { - DLOG("Printing statusline!\n"); - - /* Luckily we already prepared a seperate pixmap containing the rendered - * statusline, we just have to copy the relevant parts to the relevant - * position */ - trayclient *trayclient; - int traypx = 0; - TAILQ_FOREACH(trayclient, outputs_walk->trayclients, tailq) { - if (!trayclient->mapped) - continue; - /* We assume the tray icons are quadratic (we use the font - * *height* as *width* of the icons) because we configured them - * like this. */ - traypx += font.height + logical_px(2); - } - /* Add 2px of padding if there are any tray icons */ - if (traypx > 0) - traypx += logical_px(2); - xcb_copy_area(xcb_connection, - statusline_pm, - outputs_walk->buffer, - outputs_walk->bargc, - MAX(0, (int16_t)(statusline_width - outputs_walk->rect.w + logical_px(4))), 0, - MAX(0, (int16_t)(outputs_walk->rect.w - statusline_width - traypx - logical_px(4))), 0, - MIN(outputs_walk->rect.w - traypx - logical_px(4), (int)statusline_width), bar_height); - } - if (!config.disable_ws) { i3_ws *ws_walk; TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) { @@ -1888,6 +1860,38 @@ void draw_bars(bool unhide) { unhide = true; } + if (!TAILQ_EMPTY(&statusline_head)) { + DLOG("Printing statusline!\n"); + + /* Luckily we already prepared a seperate pixmap containing the rendered + * statusline, we just have to copy the relevant parts to the relevant + * position */ + trayclient *trayclient; + int traypx = 0; + TAILQ_FOREACH(trayclient, outputs_walk->trayclients, tailq) { + if (!trayclient->mapped) + continue; + /* We assume the tray icons are quadratic (we use the font + * *height* as *width* of the icons) because we configured them + * like this. */ + traypx += font.height + logical_px(2); + } + /* Add 2px of padding if there are any tray icons */ + if (traypx > 0) + traypx += logical_px(2); + + int edge_offset = logical_px(4); + int visible_statusline_width = MIN(statusline_width, outputs_walk->rect.w - i - traypx - 2*edge_offset); + + xcb_copy_area(xcb_connection, + statusline_pm, + outputs_walk->buffer, + outputs_walk->bargc, + (int16_t)(statusline_width - visible_statusline_width), 0, + (int16_t)(outputs_walk->rect.w - traypx - edge_offset - visible_statusline_width), 0, + (int16_t)visible_statusline_width, (int16_t)bar_height); + } + i = 0; } From 0e0581c6cbf81471dc3bb6aeb98a48abcb00da6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 21 Mar 2015 17:10:20 +0100 Subject: [PATCH 47/99] Allow referencing the workspace by number. This allows "--workspace 3" for numbered workspaces, e.g., if the name is actually "3:foo". This introduces the same functionality the IPC already offers in many places. --- i3-save-tree | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/i3-save-tree b/i3-save-tree index b6ed085e..289fd8c6 100755 --- a/i3-save-tree +++ b/i3-save-tree @@ -222,7 +222,7 @@ my $tree = $i3->get_tree->recv; my $dump; if (defined($workspace)) { $dump = filter_containers($tree, sub { - $_->{type} eq 'workspace' && $_->{name} eq $workspace + $_->{type} eq 'workspace' && ($_->{name} eq $workspace || ($workspace =~ /^\d+$/ && $_->{num} eq $workspace)) }); } else { $dump = filter_containers($tree, sub { @@ -252,7 +252,7 @@ for my $key (qw(nodes floating_nodes)) { =head1 SYNOPSIS - i3-save-tree [--workspace=name] [--output=name] + i3-save-tree [--workspace=name|number] [--output=name] =head1 DESCRIPTION @@ -271,9 +271,10 @@ If neither argument is specified, the currently focused workspace will be used. =over -=item B<--workspace=name> +=item B<--workspace=name|number> -Specifies the workspace that should be dumped, e.g. 1. +Specifies the workspace that should be dumped, e.g. 1. This can either be a +name or the number of a workspace. =item B<--output=name> From b28bb20caae6d7b04b4f99e906b97b5b540c16c2 Mon Sep 17 00:00:00 2001 From: shdown Date: Sat, 21 Mar 2015 19:12:29 +0300 Subject: [PATCH 48/99] i3bar: add binding indicator width to workspace buttons width Just to prevent the indicator from being overlapped by the statusline. --- i3bar/src/xcb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index aa24fc22..79ac211d 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -1858,6 +1858,7 @@ void draw_bars(bool unhide) { draw_text(binding.name, outputs_walk->buffer, outputs_walk->bargc, i + 5, 3, binding.width); unhide = true; + i += logical_px(10) + binding.width + logical_px(1); } if (!TAILQ_EMPTY(&statusline_head)) { From 4d3867f1784c7be052fcadadbdcbb38cb60cbd53 Mon Sep 17 00:00:00 2001 From: shdown Date: Sat, 21 Mar 2015 19:17:05 +0300 Subject: [PATCH 49/99] i3bar: rename a variable Give it a more meaningful name. --- i3bar/src/xcb.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 79ac211d..fc198349 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -1736,7 +1736,7 @@ void reconfig_windows(bool redraw_bars) { */ void draw_bars(bool unhide) { DLOG("Drawing Bars...\n"); - int i = 0; + int workspace_width = 0; refresh_statusline(); @@ -1767,7 +1767,7 @@ void draw_bars(bool unhide) { i3_ws *ws_walk; TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) { DLOG("Drawing Button for WS %s at x = %d, len = %d\n", - i3string_as_utf8(ws_walk->name), i, ws_walk->name_width); + i3string_as_utf8(ws_walk->name), workspace_width, ws_walk->name_width); uint32_t fg_color = colors.inactive_ws_fg; uint32_t bg_color = colors.inactive_ws_bg; uint32_t border_color = colors.inactive_ws_border; @@ -1795,7 +1795,7 @@ void draw_bars(bool unhide) { outputs_walk->bargc, mask, vals_border); - xcb_rectangle_t rect_border = {i, + xcb_rectangle_t rect_border = {workspace_width, logical_px(1), ws_walk->name_width + logical_px(10), font.height + logical_px(4)}; @@ -1809,7 +1809,7 @@ void draw_bars(bool unhide) { outputs_walk->bargc, mask, vals); - xcb_rectangle_t rect = {i + logical_px(1), + xcb_rectangle_t rect = {workspace_width + logical_px(1), 2 * logical_px(1), ws_walk->name_width + logical_px(8), font.height + logical_px(2)}; @@ -1820,8 +1820,8 @@ void draw_bars(bool unhide) { &rect); set_font_colors(outputs_walk->bargc, fg_color, bg_color); draw_text(ws_walk->name, outputs_walk->buffer, outputs_walk->bargc, - i + logical_px(5), 3 * logical_px(1), ws_walk->name_width); - i += logical_px(10) + ws_walk->name_width + logical_px(1); + workspace_width + logical_px(5), 3 * logical_px(1), ws_walk->name_width); + workspace_width += logical_px(10) + ws_walk->name_width + logical_px(1); } } @@ -1835,7 +1835,7 @@ void draw_bars(bool unhide) { outputs_walk->bargc, mask, vals_border); - xcb_rectangle_t rect_border = {i, 1, binding.width + 10, font.height + 4}; + xcb_rectangle_t rect_border = {workspace_width, 1, binding.width + 10, font.height + 4}; xcb_poly_fill_rectangle(xcb_connection, outputs_walk->buffer, outputs_walk->bargc, @@ -1847,7 +1847,7 @@ void draw_bars(bool unhide) { outputs_walk->bargc, mask, vals); - xcb_rectangle_t rect = {i + 1, 2, binding.width + 8, font.height + 2}; + xcb_rectangle_t rect = {workspace_width + 1, 2, binding.width + 8, font.height + 2}; xcb_poly_fill_rectangle(xcb_connection, outputs_walk->buffer, outputs_walk->bargc, @@ -1855,10 +1855,10 @@ void draw_bars(bool unhide) { &rect); set_font_colors(outputs_walk->bargc, fg_color, bg_color); - draw_text(binding.name, outputs_walk->buffer, outputs_walk->bargc, i + 5, 3, binding.width); + draw_text(binding.name, outputs_walk->buffer, outputs_walk->bargc, workspace_width + 5, 3, binding.width); unhide = true; - i += logical_px(10) + binding.width + logical_px(1); + workspace_width += logical_px(10) + binding.width + logical_px(1); } if (!TAILQ_EMPTY(&statusline_head)) { @@ -1882,7 +1882,8 @@ void draw_bars(bool unhide) { traypx += logical_px(2); int edge_offset = logical_px(4); - int visible_statusline_width = MIN(statusline_width, outputs_walk->rect.w - i - traypx - 2*edge_offset); + int visible_statusline_width = MIN(statusline_width, + outputs_walk->rect.w - workspace_width - traypx - 2*edge_offset); xcb_copy_area(xcb_connection, statusline_pm, @@ -1893,7 +1894,7 @@ void draw_bars(bool unhide) { (int16_t)visible_statusline_width, (int16_t)bar_height); } - i = 0; + workspace_width = 0; } /* Assure the bar is hidden/unhidden according to the specified hidden_state and mode */ From b1c7c7eea4f63062f050d3e65dcc93f6fd406680 Mon Sep 17 00:00:00 2001 From: shdown Date: Sat, 21 Mar 2015 19:22:31 +0300 Subject: [PATCH 50/99] i3bar: fix spelling is messages --- i3bar/src/xcb.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index fc198349..915d94d0 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -273,7 +273,7 @@ void unhide_bars(void) { values[2] = walk->rect.w; values[3] = bar_height; values[4] = XCB_STACK_MODE_ABOVE; - DLOG("Reconfiguring Window for output %s to %d,%d\n", walk->name, values[0], values[1]); + DLOG("Reconfiguring window for output %s to %d,%d\n", walk->name, values[0], values[1]); cookie = xcb_configure_window_checked(xcb_connection, walk->bar, mask, @@ -335,14 +335,14 @@ void handle_button(xcb_button_press_event_t *event) { } if (walk == NULL) { - DLOG("Unknown Bar klicked!\n"); + DLOG("Unknown bar clicked!\n"); return; } int32_t x = event->event_x >= 0 ? event->event_x : 0; int32_t original_x = x; - DLOG("Got Button %d\n", event->detail); + DLOG("Got button %d\n", event->detail); if (child_want_click_events()) { /* If the child asked for click events, @@ -393,7 +393,7 @@ void handle_button(xcb_button_press_event_t *event) { } if (cur_ws == NULL) { - DLOG("No Workspace active?\n"); + DLOG("No workspace active?\n"); return; } @@ -1170,7 +1170,7 @@ void init_xcb_late(char *fontname) { /* Load the font */ font = load_font(fontname, true); set_font(&font); - DLOG("Calculated Font-height: %d\n", font.height); + DLOG("Calculated font height: %d\n", font.height); bar_height = font.height + logical_px(6); xcb_flush(xcb_connection); @@ -1369,7 +1369,7 @@ void get_atoms(void) { free(reply); #include "xcb_atoms.def" - DLOG("Got Atoms\n"); + DLOG("Got atoms\n"); } /* @@ -1495,7 +1495,7 @@ void reconfig_windows(bool redraw_bars) { continue; } if (walk->bar == XCB_NONE) { - DLOG("Creating Window for output %s\n", walk->name); + DLOG("Creating window for output %s\n", walk->name); walk->bar = xcb_generate_id(xcb_connection); walk->buffer = xcb_generate_id(xcb_connection); @@ -1677,7 +1677,7 @@ void reconfig_windows(bool redraw_bars) { DLOG("Destroying buffer for output %s\n", 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]); + 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, @@ -1685,7 +1685,7 @@ void reconfig_windows(bool redraw_bars) { mask = XCB_CW_OVERRIDE_REDIRECT; values[0] = (config.hide_on_modifier == M_DOCK ? 0 : 1); - DLOG("Changing Window attribute override_redirect for output %s to %d\n", walk->name, values[0]); + DLOG("Changing window attribute override_redirect for output %s to %d\n", walk->name, values[0]); xcb_void_cookie_t chg_cookie = xcb_change_window_attributes(xcb_connection, walk->bar, mask, @@ -1735,7 +1735,7 @@ void reconfig_windows(bool redraw_bars) { * */ void draw_bars(bool unhide) { - DLOG("Drawing Bars...\n"); + DLOG("Drawing bars...\n"); int workspace_width = 0; refresh_statusline(); @@ -1766,7 +1766,7 @@ void draw_bars(bool unhide) { if (!config.disable_ws) { i3_ws *ws_walk; TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) { - DLOG("Drawing Button for WS %s at x = %d, len = %d\n", + DLOG("Drawing button for WS %s at x = %d, len = %d\n", i3string_as_utf8(ws_walk->name), workspace_width, ws_walk->name_width); uint32_t fg_color = colors.inactive_ws_fg; uint32_t bg_color = colors.inactive_ws_bg; From b2309b86816978d99d712d0337116c3bbfdd80c7 Mon Sep 17 00:00:00 2001 From: shdown Date: Sat, 21 Mar 2015 19:41:38 +0300 Subject: [PATCH 51/99] i3bar: fix click events for workspace buttons with long statusline This combines detecting of current and clicked workspaces into one cycle and then checks if the x coordinate of the clicked point is greater than the workspace buttons width. --- i3bar/src/xcb.c | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 915d94d0..e1ad03e8 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -323,8 +323,6 @@ void init_colors(const struct xcb_color_strings_t *new_colors) { * */ void handle_button(xcb_button_press_event_t *event) { - i3_ws *cur_ws; - /* Determine, which bar was clicked */ i3_output *walk; xcb_window_t bar = event->event; @@ -344,7 +342,19 @@ void handle_button(xcb_button_press_event_t *event) { DLOG("Got button %d\n", event->detail); - if (child_want_click_events()) { + int workspace_width = 0; + i3_ws *cur_ws = NULL, *clicked_ws = NULL, *ws_walk; + + TAILQ_FOREACH(ws_walk, walk->workspaces, tailq) { + int w = logical_px(10) + ws_walk->name_width; + if (x >= workspace_width && x <= workspace_width + w) + clicked_ws = ws_walk; + if (ws_walk->visible) + cur_ws = ws_walk; + workspace_width += w + logical_px(1); + } + + if (x > workspace_width && child_want_click_events()) { /* If the child asked for click events, * check if a status block has been clicked. */ @@ -385,13 +395,6 @@ void handle_button(xcb_button_press_event_t *event) { x = original_x; } - /* TODO: Move this to extern get_ws_for_output() */ - TAILQ_FOREACH(cur_ws, walk->workspaces, tailq) { - if (cur_ws->visible) { - break; - } - } - if (cur_ws == NULL) { DLOG("No workspace active?\n"); return; @@ -435,17 +438,10 @@ void handle_button(xcb_button_press_event_t *event) { cur_ws = TAILQ_NEXT(cur_ws, tailq); break; case 1: - /* Check if this event regards a workspace button */ - TAILQ_FOREACH(cur_ws, walk->workspaces, tailq) { - DLOG("x = %d\n", x); - if (x >= 0 && x < cur_ws->name_width + logical_px(10)) { - break; - } - x -= cur_ws->name_width + logical_px(11); - } + cur_ws = clicked_ws; - /* Otherwise, focus our currently visible workspace if it is not - * already focused */ + /* if no workspace was clicked, focus our currently visible + * workspace if it is not already focused */ if (cur_ws == NULL) { TAILQ_FOREACH(cur_ws, walk->workspaces, tailq) { if (cur_ws->visible && !cur_ws->focused) From 32f3248b573cd3152a735a8b455f335720b2587b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 21 Mar 2015 19:32:40 +0100 Subject: [PATCH 52/99] Added a troubleshooting section to the restoring layout docs and described solution for vertically split containers --- docs/layout-saving | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/layout-saving b/docs/layout-saving index 2b798df5..5897036e 100644 --- a/docs/layout-saving +++ b/docs/layout-saving @@ -231,3 +231,31 @@ layouts, you can either use a JSON parser that supports these deviations (for example libyajl), transform the layout file to a JSON-conforming file, or link:http://cr.i3wm.org/[submit a patch] to make +i3-save-tree(1)+ optionally output standard-conforming JSON. + +== Troubleshooting + +=== Restoring a vertically split workspace + +When using +i3-save-tree+ with the +--workspace+ switch, only the *contents* of +the workspace will be dumped. This means that properties of the workspace +itself will be lost. + +This is relevant for, e.g., a vertically split container as the base container of +a workspace. Since the split mode is a property of the workspace, it will not be +stored. In this case, you will have to manually wrap your layout in such a +container: + +-------------------------------------------------------------------------------- +// vim:ts=4:sw=4:et +{ + // this is a manually added container to restore the vertical split + "layout": "splitv", + "percent": 0.5, + "type": "con", + "nodes": [ + + // the dumped workspace layout goes here + + ] +} +-------------------------------------------------------------------------------- From 2772c377ec36b3c47d81e431e433b91f13d2b32f Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 21 Mar 2015 22:22:37 +0100 Subject: [PATCH 53/99] increase timeouts for travis See https://travis-ci.org/i3/i3/jobs/55319961 (line 4064) for a job where the window could not be mapped within 2 seconds. --- testcases/lib/i3test.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testcases/lib/i3test.pm b/testcases/lib/i3test.pm index 212e78fd..c149cbd1 100644 --- a/testcases/lib/i3test.pm +++ b/testcases/lib/i3test.pm @@ -226,7 +226,7 @@ you might have to map it on your own and use this function: sub wait_for_map { my ($win) = @_; my $id = (blessed($win) && $win->isa('X11::XCB::Window')) ? $win->id : $win; - wait_for_event 2, sub { + wait_for_event 4, sub { $_[0]->{response_type} == MAP_NOTIFY and $_[0]->{window} == $id }; } @@ -248,7 +248,7 @@ event. sub wait_for_unmap { my ($win) = @_; # my $id = (blessed($win) && $win->isa('X11::XCB::Window')) ? $win->id : $win; - wait_for_event 2, sub { + wait_for_event 4, sub { $_[0]->{response_type} == UNMAP_NOTIFY # and $_[0]->{window} == $id }; sync_with_i3(); @@ -718,7 +718,7 @@ sub sync_with_i3 { return $myrnd if $args{dont_wait_for_event}; # now wait until the reply is here - return wait_for_event 2, sub { + return wait_for_event 4, sub { my ($event) = @_; # TODO: const return 0 unless $event->{response_type} == 161; From 9493b61bb4b04763371be40760b6f49a2a0339db Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 21 Mar 2015 22:50:48 +0100 Subject: [PATCH 54/99] i3bar: set correct initial position when reconfiguring fixes #1542 --- i3bar/src/xcb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index e1ad03e8..8b93902e 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -1665,7 +1665,10 @@ void reconfig_windows(bool redraw_bars) { XCB_CONFIG_WINDOW_HEIGHT | XCB_CONFIG_WINDOW_STACK_MODE; values[0] = walk->rect.x; - values[1] = walk->rect.y + walk->rect.h - bar_height; + if (config.position == POS_TOP) + values[1] = walk->rect.y; + else + values[1] = walk->rect.y + walk->rect.h - bar_height; values[2] = walk->rect.w; values[3] = bar_height; values[4] = XCB_STACK_MODE_ABOVE; From 2190bb9386eeb98d25647ab7181d64ce4e15f254 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 21 Mar 2015 23:02:35 +0100 Subject: [PATCH 55/99] =?UTF-8?q?Don=E2=80=99t=20overwrite=20border=20widt?= =?UTF-8?q?h=20when=20already=20set=20(placeholders).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes #1501 --- src/manage.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/manage.c b/src/manage.c index 077d5720..2b3c6743 100644 --- a/src/manage.c +++ b/src/manage.c @@ -452,7 +452,9 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki } /* explicitly set the border width to the default */ - nc->current_border_width = (want_floating ? config.default_floating_border_width : config.default_border_width); + if (nc->current_border_width == -1) { + nc->current_border_width = (want_floating ? config.default_floating_border_width : config.default_border_width); + } /* to avoid getting an UnmapNotify event due to reparenting, we temporarily * declare no interest in any state change event of this window */ From 6fb7fc9bc64909a4ee86aabb71075ce04273b149 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 22 Mar 2015 05:46:52 -0400 Subject: [PATCH 56/99] Bugfix: validation segfault When `new_window` is given in the config, config validation with `i3 -C` would segfault. Add a NULL check in logical_px() to check for the case when the config is being validated without an X server to prevent this. --- libi3/dpi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libi3/dpi.c b/libi3/dpi.c index 37d5b215..6f58d57a 100644 --- a/libi3/dpi.c +++ b/libi3/dpi.c @@ -17,6 +17,12 @@ extern xcb_screen_t *root_screen; * */ int logical_px(const int logical) { + if (root_screen == NULL) { + /* Dpi info may not be available when parsing a config without an X + * server, such as for config file validation. */ + return logical; + } + const int dpi = (double)root_screen->height_in_pixels * 25.4 / (double)root_screen->height_in_millimeters; /* There are many misconfigurations out there, i.e. systems with screens From 62e4caa06c65b4733f3d0ad32ec307486c22a0e4 Mon Sep 17 00:00:00 2001 From: shdown Date: Sat, 21 Mar 2015 20:46:36 +0300 Subject: [PATCH 57/99] i3bar: refactor magic numbers to *_px constants --- i3bar/src/xcb.c | 71 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index e1ad03e8..ce697dc1 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -106,6 +106,14 @@ struct xcb_colors_t { }; struct xcb_colors_t colors; +const static int ws_hoff_px = 4, /* Horizontal offset between a workspace label and button borders */ + ws_voff_px = 3, /* Vertical offset between a workspace label and button borders */ + ws_spacing_px = 1, /* Offset between two workspace buttons */ + sb_hoff_px = 4, /* Offset between the statusline and 1) workspace buttons on the left + * 2) the tray or screen edge on the right */ + tray_loff_px = 2, /* Additional offset between the tray and the statusline, if the tray is not empty */ + sep_voff_px = 4; /* Vertical offset between the bar and a separator */ + /* We define xcb_request_failed as a macro to include the relevant line-number */ #define xcb_request_failed(cookie, err_msg) _xcb_request_failed(cookie, err_msg, __LINE__) int _xcb_request_failed(xcb_void_cookie_t cookie, char *err_msg, int line) { @@ -204,7 +212,7 @@ void refresh_statusline(void) { } set_font_colors(statusline_ctx, fg_color, colors.bar_bg); - draw_text(block->full_text, statusline_pm, statusline_ctx, x + block->x_offset, 3, block->width); + draw_text(block->full_text, statusline_pm, statusline_ctx, x + block->x_offset, logical_px(ws_voff_px), block->width); x += block->width + block->sep_block_width + block->x_offset + block->x_append; uint32_t sep_offset = get_sep_offset(block); @@ -215,8 +223,8 @@ void refresh_statusline(void) { xcb_change_gc(xcb_connection, statusline_ctx, mask, values); xcb_poly_line(xcb_connection, XCB_COORD_MODE_ORIGIN, statusline_pm, statusline_ctx, 2, - (xcb_point_t[]){{x - sep_offset, logical_px(4)}, - {x - sep_offset, bar_height - logical_px(4)}}); + (xcb_point_t[]){{x - sep_offset, logical_px(sep_voff_px)}, + {x - sep_offset, bar_height - logical_px(sep_voff_px)}}); } } } @@ -346,12 +354,14 @@ void handle_button(xcb_button_press_event_t *event) { i3_ws *cur_ws = NULL, *clicked_ws = NULL, *ws_walk; TAILQ_FOREACH(ws_walk, walk->workspaces, tailq) { - int w = logical_px(10) + ws_walk->name_width; + int w = 2*logical_px(ws_hoff_px) + 2*logical_px(1) + ws_walk->name_width; if (x >= workspace_width && x <= workspace_width + w) clicked_ws = ws_walk; if (ws_walk->visible) cur_ws = ws_walk; - workspace_width += w + logical_px(1); + workspace_width += w; + if (TAILQ_NEXT(ws_walk, tailq) != NULL) + workspace_width += logical_px(ws_spacing_px); } if (x > workspace_width && child_want_click_events()) { @@ -367,10 +377,10 @@ void handle_button(xcb_button_press_event_t *event) { tray_width += (font.height + logical_px(2)); } if (tray_width > 0) - tray_width += logical_px(2); + tray_width += logical_px(tray_loff_px); int block_x = 0, last_block_x; - int offset = walk->rect.w - statusline_width - tray_width - logical_px(4); + int offset = walk->rect.w - statusline_width - tray_width - logical_px(sb_hoff_px); x = original_x - offset; if (x >= 0) { @@ -1167,7 +1177,7 @@ void init_xcb_late(char *fontname) { font = load_font(fontname, true); set_font(&font); DLOG("Calculated font height: %d\n", font.height); - bar_height = font.height + logical_px(6); + bar_height = font.height + 2*logical_px(ws_voff_px); xcb_flush(xcb_connection); @@ -1793,8 +1803,8 @@ void draw_bars(bool unhide) { vals_border); xcb_rectangle_t rect_border = {workspace_width, logical_px(1), - ws_walk->name_width + logical_px(10), - font.height + logical_px(4)}; + ws_walk->name_width + 2*logical_px(ws_hoff_px) + 2*logical_px(1), + font.height + 2*logical_px(ws_voff_px) - 2*logical_px(1)}; xcb_poly_fill_rectangle(xcb_connection, outputs_walk->buffer, outputs_walk->bargc, @@ -1807,8 +1817,8 @@ void draw_bars(bool unhide) { vals); xcb_rectangle_t rect = {workspace_width + logical_px(1), 2 * logical_px(1), - ws_walk->name_width + logical_px(8), - font.height + logical_px(2)}; + ws_walk->name_width + 2*logical_px(ws_hoff_px), + font.height + 2*logical_px(ws_voff_px) - 4*logical_px(1)}; xcb_poly_fill_rectangle(xcb_connection, outputs_walk->buffer, outputs_walk->bargc, @@ -1816,12 +1826,19 @@ void draw_bars(bool unhide) { &rect); set_font_colors(outputs_walk->bargc, fg_color, bg_color); draw_text(ws_walk->name, outputs_walk->buffer, outputs_walk->bargc, - workspace_width + logical_px(5), 3 * logical_px(1), ws_walk->name_width); - workspace_width += logical_px(10) + ws_walk->name_width + logical_px(1); + workspace_width + logical_px(ws_hoff_px) + logical_px(1), + logical_px(ws_voff_px), + ws_walk->name_width); + + workspace_width += 2*logical_px(ws_hoff_px) + 2*logical_px(1) + ws_walk->name_width; + if (TAILQ_NEXT(ws_walk, tailq) != NULL) + workspace_width += logical_px(ws_spacing_px); } } if (binding.name && !config.disable_binding_mode_indicator) { + workspace_width += logical_px(ws_spacing_px); + uint32_t fg_color = colors.urgent_ws_fg; uint32_t bg_color = colors.urgent_ws_bg; uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND; @@ -1831,7 +1848,10 @@ void draw_bars(bool unhide) { outputs_walk->bargc, mask, vals_border); - xcb_rectangle_t rect_border = {workspace_width, 1, binding.width + 10, font.height + 4}; + xcb_rectangle_t rect_border = {workspace_width, + logical_px(1), + binding.width + 2*logical_px(ws_hoff_px) + 2*logical_px(1), + font.height + 2*logical_px(ws_voff_px) - 2*logical_px(1)}; xcb_poly_fill_rectangle(xcb_connection, outputs_walk->buffer, outputs_walk->bargc, @@ -1843,7 +1863,10 @@ void draw_bars(bool unhide) { outputs_walk->bargc, mask, vals); - xcb_rectangle_t rect = {workspace_width + 1, 2, binding.width + 8, font.height + 2}; + xcb_rectangle_t rect = {workspace_width + logical_px(1), + 2*logical_px(1), + binding.width + 2*logical_px(ws_hoff_px), + font.height + 2*logical_px(ws_voff_px) - 4*logical_px(1)}; xcb_poly_fill_rectangle(xcb_connection, outputs_walk->buffer, outputs_walk->bargc, @@ -1851,10 +1874,15 @@ void draw_bars(bool unhide) { &rect); set_font_colors(outputs_walk->bargc, fg_color, bg_color); - draw_text(binding.name, outputs_walk->buffer, outputs_walk->bargc, workspace_width + 5, 3, binding.width); + draw_text(binding.name, + outputs_walk->buffer, + outputs_walk->bargc, + workspace_width + logical_px(ws_hoff_px) + logical_px(1), + logical_px(ws_voff_px), + binding.width); unhide = true; - workspace_width += logical_px(10) + binding.width + logical_px(1); + workspace_width += 2*logical_px(ws_hoff_px) + 2*logical_px(1) + binding.width; } if (!TAILQ_EMPTY(&statusline_head)) { @@ -1875,18 +1903,17 @@ void draw_bars(bool unhide) { } /* Add 2px of padding if there are any tray icons */ if (traypx > 0) - traypx += logical_px(2); + traypx += logical_px(tray_loff_px); - int edge_offset = logical_px(4); int visible_statusline_width = MIN(statusline_width, - outputs_walk->rect.w - workspace_width - traypx - 2*edge_offset); + outputs_walk->rect.w - workspace_width - traypx - 2*logical_px(sb_hoff_px)); xcb_copy_area(xcb_connection, statusline_pm, outputs_walk->buffer, outputs_walk->bargc, (int16_t)(statusline_width - visible_statusline_width), 0, - (int16_t)(outputs_walk->rect.w - traypx - edge_offset - visible_statusline_width), 0, + (int16_t)(outputs_walk->rect.w - traypx - logical_px(sb_hoff_px) - visible_statusline_width), 0, (int16_t)visible_statusline_width, (int16_t)bar_height); } From f19fa0e3c95ab6b963258041f836fa93f363f007 Mon Sep 17 00:00:00 2001 From: shdown Date: Sun, 22 Mar 2015 13:08:31 +0300 Subject: [PATCH 58/99] i3bar: introduce get_tray_width() function to reduce duplication --- i3bar/src/xcb.c | 44 +++++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index ce697dc1..0f01fe23 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -131,6 +131,19 @@ uint32_t get_sep_offset(struct status_block *block) { return 0; } +int get_tray_width(struct tc_head* trayclients) { + trayclient *trayclient; + int tray_width = 0; + TAILQ_FOREACH_REVERSE(trayclient, trayclients, tc_head, tailq) { + if (!trayclient->mapped) + continue; + tray_width += font.height + logical_px(2); + } + if (tray_width > 0) + tray_width += logical_px(tray_loff_px); + return tray_width; +} + /* * Redraws the statusline to the buffer * @@ -367,18 +380,7 @@ void handle_button(xcb_button_press_event_t *event) { if (x > workspace_width && child_want_click_events()) { /* If the child asked for click events, * check if a status block has been clicked. */ - - /* First calculate width of tray area */ - trayclient *trayclient; - int tray_width = 0; - TAILQ_FOREACH_REVERSE(trayclient, walk->trayclients, tc_head, tailq) { - if (!trayclient->mapped) - continue; - tray_width += (font.height + logical_px(2)); - } - if (tray_width > 0) - tray_width += logical_px(tray_loff_px); - + int tray_width = get_tray_width(walk->trayclients); int block_x = 0, last_block_x; int offset = walk->rect.w - statusline_width - tray_width - logical_px(sb_hoff_px); @@ -1891,29 +1893,17 @@ void draw_bars(bool unhide) { /* Luckily we already prepared a seperate pixmap containing the rendered * statusline, we just have to copy the relevant parts to the relevant * position */ - trayclient *trayclient; - int traypx = 0; - TAILQ_FOREACH(trayclient, outputs_walk->trayclients, tailq) { - if (!trayclient->mapped) - continue; - /* We assume the tray icons are quadratic (we use the font - * *height* as *width* of the icons) because we configured them - * like this. */ - traypx += font.height + logical_px(2); - } - /* Add 2px of padding if there are any tray icons */ - if (traypx > 0) - traypx += logical_px(tray_loff_px); + int tray_width = get_tray_width(outputs_walk->trayclients); int visible_statusline_width = MIN(statusline_width, - outputs_walk->rect.w - workspace_width - traypx - 2*logical_px(sb_hoff_px)); + outputs_walk->rect.w - workspace_width - tray_width - 2*logical_px(sb_hoff_px)); xcb_copy_area(xcb_connection, statusline_pm, outputs_walk->buffer, outputs_walk->bargc, (int16_t)(statusline_width - visible_statusline_width), 0, - (int16_t)(outputs_walk->rect.w - traypx - logical_px(sb_hoff_px) - visible_statusline_width), 0, + (int16_t)(outputs_walk->rect.w - tray_width - logical_px(sb_hoff_px) - visible_statusline_width), 0, (int16_t)visible_statusline_width, (int16_t)bar_height); } From 658d106fcec9d166ea87fd7318339bec0350c10f Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 23 Mar 2015 09:21:06 +0100 Subject: [PATCH 59/99] fix travis config with regards to clang-format --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5876ae62..ebabbfaf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,4 +44,4 @@ install: script: - make -j - (cd testcases && xvfb-run ./complete-run.pl --parallel=1 || (cat latest/complete-run.log; false)) - - clang-format-3.5 -i **/*.[ch] && git diff --exit-code || (echo 'Code was not formatted using clang-format!'; false) + - clang-format-3.5 -i $(find . -name "*.[ch]" | tr '\n' ' ') && git diff --exit-code || (echo 'Code was not formatted using clang-format!'; false) From 8d0fb482d98ff8932b40b30eb8dd78acf51f4aef Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 23 Mar 2015 09:23:01 +0100 Subject: [PATCH 60/99] clang-format and rearrange comments in i3bar/src/xcb.c --- i3bar/src/xcb.c | 55 +++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index b7c3ea97..96fcb3fa 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -106,13 +106,24 @@ struct xcb_colors_t { }; struct xcb_colors_t colors; -const static int ws_hoff_px = 4, /* Horizontal offset between a workspace label and button borders */ - ws_voff_px = 3, /* Vertical offset between a workspace label and button borders */ - ws_spacing_px = 1, /* Offset between two workspace buttons */ - sb_hoff_px = 4, /* Offset between the statusline and 1) workspace buttons on the left - * 2) the tray or screen edge on the right */ - tray_loff_px = 2, /* Additional offset between the tray and the statusline, if the tray is not empty */ - sep_voff_px = 4; /* Vertical offset between the bar and a separator */ +/* Horizontal offset between a workspace label and button borders */ +const static int ws_hoff_px = 4; + +/* Vertical offset between a workspace label and button borders */ +const static int ws_voff_px = 3; + +/* Offset between two workspace buttons */ +const static int ws_spacing_px = 1; + +/* Offset between the statusline and 1) workspace buttons on the left + * 2) the tray or screen edge on the right */ +const static int sb_hoff_px = 4; + +/* Additional offset between the tray and the statusline, if the tray is not empty */ +const static int tray_loff_px = 2; + +/* Vertical offset between the bar and a separator */ +const static int sep_voff_px = 4; /* We define xcb_request_failed as a macro to include the relevant line-number */ #define xcb_request_failed(cookie, err_msg) _xcb_request_failed(cookie, err_msg, __LINE__) @@ -131,7 +142,7 @@ uint32_t get_sep_offset(struct status_block *block) { return 0; } -int get_tray_width(struct tc_head* trayclients) { +int get_tray_width(struct tc_head *trayclients) { trayclient *trayclient; int tray_width = 0; TAILQ_FOREACH_REVERSE(trayclient, trayclients, tc_head, tailq) { @@ -367,7 +378,7 @@ void handle_button(xcb_button_press_event_t *event) { i3_ws *cur_ws = NULL, *clicked_ws = NULL, *ws_walk; TAILQ_FOREACH(ws_walk, walk->workspaces, tailq) { - int w = 2*logical_px(ws_hoff_px) + 2*logical_px(1) + ws_walk->name_width; + int w = 2 * logical_px(ws_hoff_px) + 2 * logical_px(1) + ws_walk->name_width; if (x >= workspace_width && x <= workspace_width + w) clicked_ws = ws_walk; if (ws_walk->visible) @@ -1179,7 +1190,7 @@ void init_xcb_late(char *fontname) { font = load_font(fontname, true); set_font(&font); DLOG("Calculated font height: %d\n", font.height); - bar_height = font.height + 2*logical_px(ws_voff_px); + bar_height = font.height + 2 * logical_px(ws_voff_px); xcb_flush(xcb_connection); @@ -1808,8 +1819,8 @@ void draw_bars(bool unhide) { vals_border); xcb_rectangle_t rect_border = {workspace_width, logical_px(1), - ws_walk->name_width + 2*logical_px(ws_hoff_px) + 2*logical_px(1), - font.height + 2*logical_px(ws_voff_px) - 2*logical_px(1)}; + ws_walk->name_width + 2 * logical_px(ws_hoff_px) + 2 * logical_px(1), + font.height + 2 * logical_px(ws_voff_px) - 2 * logical_px(1)}; xcb_poly_fill_rectangle(xcb_connection, outputs_walk->buffer, outputs_walk->bargc, @@ -1822,8 +1833,8 @@ void draw_bars(bool unhide) { vals); xcb_rectangle_t rect = {workspace_width + logical_px(1), 2 * logical_px(1), - ws_walk->name_width + 2*logical_px(ws_hoff_px), - font.height + 2*logical_px(ws_voff_px) - 4*logical_px(1)}; + ws_walk->name_width + 2 * logical_px(ws_hoff_px), + font.height + 2 * logical_px(ws_voff_px) - 4 * logical_px(1)}; xcb_poly_fill_rectangle(xcb_connection, outputs_walk->buffer, outputs_walk->bargc, @@ -1835,7 +1846,7 @@ void draw_bars(bool unhide) { logical_px(ws_voff_px), ws_walk->name_width); - workspace_width += 2*logical_px(ws_hoff_px) + 2*logical_px(1) + ws_walk->name_width; + workspace_width += 2 * logical_px(ws_hoff_px) + 2 * logical_px(1) + ws_walk->name_width; if (TAILQ_NEXT(ws_walk, tailq) != NULL) workspace_width += logical_px(ws_spacing_px); } @@ -1855,8 +1866,8 @@ void draw_bars(bool unhide) { vals_border); xcb_rectangle_t rect_border = {workspace_width, logical_px(1), - binding.width + 2*logical_px(ws_hoff_px) + 2*logical_px(1), - font.height + 2*logical_px(ws_voff_px) - 2*logical_px(1)}; + binding.width + 2 * logical_px(ws_hoff_px) + 2 * logical_px(1), + font.height + 2 * logical_px(ws_voff_px) - 2 * logical_px(1)}; xcb_poly_fill_rectangle(xcb_connection, outputs_walk->buffer, outputs_walk->bargc, @@ -1869,9 +1880,9 @@ void draw_bars(bool unhide) { mask, vals); xcb_rectangle_t rect = {workspace_width + logical_px(1), - 2*logical_px(1), - binding.width + 2*logical_px(ws_hoff_px), - font.height + 2*logical_px(ws_voff_px) - 4*logical_px(1)}; + 2 * logical_px(1), + binding.width + 2 * logical_px(ws_hoff_px), + font.height + 2 * logical_px(ws_voff_px) - 4 * logical_px(1)}; xcb_poly_fill_rectangle(xcb_connection, outputs_walk->buffer, outputs_walk->bargc, @@ -1887,7 +1898,7 @@ void draw_bars(bool unhide) { binding.width); unhide = true; - workspace_width += 2*logical_px(ws_hoff_px) + 2*logical_px(1) + binding.width; + workspace_width += 2 * logical_px(ws_hoff_px) + 2 * logical_px(1) + binding.width; } if (!TAILQ_EMPTY(&statusline_head)) { @@ -1899,7 +1910,7 @@ void draw_bars(bool unhide) { int tray_width = get_tray_width(outputs_walk->trayclients); int visible_statusline_width = MIN(statusline_width, - outputs_walk->rect.w - workspace_width - tray_width - 2*logical_px(sb_hoff_px)); + outputs_walk->rect.w - workspace_width - tray_width - 2 * logical_px(sb_hoff_px)); xcb_copy_area(xcb_connection, statusline_pm, From dd488818a979f237c7642a5d4aa9e55c7c5ebbd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 21 Mar 2015 21:33:38 +0100 Subject: [PATCH 61/99] Introduce the short_text property on blocks and parse it according to the documentation. --- i3bar/include/common.h | 1 + i3bar/src/child.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/i3bar/include/common.h b/i3bar/include/common.h index 997a429e..3744df27 100644 --- a/i3bar/include/common.h +++ b/i3bar/include/common.h @@ -35,6 +35,7 @@ typedef enum { * up one status line. */ struct status_block { i3String *full_text; + i3String *short_text; char *color; uint32_t min_width; diff --git a/i3bar/src/child.c b/i3bar/src/child.c index efe02884..521951f5 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -70,6 +70,7 @@ static void clear_statusline(struct statusline_head *head, bool free_resources) first = TAILQ_FIRST(head); if (free_resources) { I3STRING_FREE(first->full_text); + I3STRING_FREE(first->short_text); FREE(first->color); FREE(first->name); FREE(first->instance); @@ -188,6 +189,9 @@ static int stdin_string(void *context, const unsigned char *val, size_t len) { if (strcasecmp(ctx->last_map_key, "full_text") == 0) { ctx->block.full_text = i3string_from_markup_with_length((const char *)val, len); } + if (strcasecmp(ctx->last_map_key, "short_text") == 0) { + ctx->block.short_text = i3string_from_markup_with_length((const char *)val, len); + } if (strcasecmp(ctx->last_map_key, "color") == 0) { sasprintf(&(ctx->block.color), "%.*s", len, val); } @@ -261,6 +265,7 @@ static int stdin_end_array(void *context) { struct status_block *current; TAILQ_FOREACH(current, &statusline_head, blocks) { DLOG("full_text = %s\n", i3string_as_utf8(current->full_text)); + DLOG("short_text = %s\n", i3string_as_utf8(current->short_text)); DLOG("color = %s\n", current->color); } DLOG("end of dump\n"); From 827292411727f6e2e775380ea54566a703bdb10f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 21 Mar 2015 21:33:53 +0100 Subject: [PATCH 62/99] Introduce a function to copy i3strings --- include/libi3.h | 6 ++++++ libi3/string.c | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/libi3.h b/include/libi3.h index c1a11dfc..b60dda5c 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -169,6 +169,12 @@ i3String *i3string_from_markup_with_length(const char *from_markup, size_t num_b */ i3String *i3string_from_ucs2(const xcb_char2b_t *from_ucs2, size_t num_glyphs); +/** + * Copies the given i3string. + * Note that this will not free the source string. + */ +i3String *i3string_copy(i3String *str); + /** * Free an i3String. * diff --git a/libi3/string.c b/libi3/string.c index afeca974..a28cc899 100644 --- a/libi3/string.c +++ b/libi3/string.c @@ -109,6 +109,17 @@ i3String *i3string_from_ucs2(const xcb_char2b_t *from_ucs2, size_t num_glyphs) { return str; } +/** + * Copies the given i3string. + * Note that this will not free the source string. + */ +i3String *i3string_copy(i3String *str) { + if (str->is_markup) + return i3string_from_markup(i3string_as_utf8(str)); + else + return i3string_from_utf8(i3string_as_utf8(str)); +} + /* * Free an i3String. * From c9019ada4e489402eff68b799c817c8c28ab6a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 21 Mar 2015 21:36:15 +0100 Subject: [PATCH 63/99] Add support for short_text When the statusline is too long, try to use the short_text property of each status block before falling back to truncating it. fixes #1092 --- i3bar/src/xcb.c | 23 ++++++++++++++++------- libi3/string.c | 7 +++---- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 96fcb3fa..06eac7ea 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -159,7 +159,7 @@ int get_tray_width(struct tc_head *trayclients) { * Redraws the statusline to the buffer * */ -void refresh_statusline(void) { +void refresh_statusline(bool use_short_text) { struct status_block *block; uint32_t old_statusline_width = statusline_width; @@ -167,6 +167,12 @@ void refresh_statusline(void) { /* Predict the text width of all blocks (in pixels). */ TAILQ_FOREACH(block, &statusline_head, blocks) { + /* Try to use the shorter text if necessary and possible. */ + if (use_short_text && block->short_text != NULL) { + I3STRING_FREE(block->full_text); + block->full_text = i3string_copy(block->short_text); + } + if (i3string_get_num_bytes(block->full_text) == 0) continue; @@ -1760,7 +1766,7 @@ void draw_bars(bool unhide) { DLOG("Drawing bars...\n"); int workspace_width = 0; - refresh_statusline(); + refresh_statusline(false); i3_output *outputs_walk; SLIST_FOREACH(outputs_walk, outputs, slist) { @@ -1904,14 +1910,17 @@ void draw_bars(bool unhide) { if (!TAILQ_EMPTY(&statusline_head)) { DLOG("Printing statusline!\n"); + int tray_width = get_tray_width(outputs_walk->trayclients); + int max_statusline_width = outputs_walk->rect.w - workspace_width - tray_width - 2 * logical_px(sb_hoff_px); + + /* If the statusline is too long, try to use short texts. */ + if (statusline_width > max_statusline_width) + refresh_statusline(true); + /* Luckily we already prepared a seperate pixmap containing the rendered * statusline, we just have to copy the relevant parts to the relevant * position */ - int tray_width = get_tray_width(outputs_walk->trayclients); - - int visible_statusline_width = MIN(statusline_width, - outputs_walk->rect.w - workspace_width - tray_width - 2 * logical_px(sb_hoff_px)); - + int visible_statusline_width = MIN(statusline_width, max_statusline_width); xcb_copy_area(xcb_connection, statusline_pm, outputs_walk->buffer, diff --git a/libi3/string.c b/libi3/string.c index a28cc899..88fd1986 100644 --- a/libi3/string.c +++ b/libi3/string.c @@ -114,10 +114,9 @@ i3String *i3string_from_ucs2(const xcb_char2b_t *from_ucs2, size_t num_glyphs) { * Note that this will not free the source string. */ i3String *i3string_copy(i3String *str) { - if (str->is_markup) - return i3string_from_markup(i3string_as_utf8(str)); - else - return i3string_from_utf8(i3string_as_utf8(str)); + i3String *copy = i3string_from_utf8(i3string_as_utf8(str)); + copy->is_markup = str->is_markup; + return copy; } /* From e5317fc4e9ea1a9818052c26704a1c46b5b8bbc9 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 23 Mar 2015 13:03:57 -0400 Subject: [PATCH 64/99] testcases: dont run valgrind verbose --- testcases/lib/SocketActivation.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testcases/lib/SocketActivation.pm b/testcases/lib/SocketActivation.pm index d32f6051..83ca9255 100644 --- a/testcases/lib/SocketActivation.pm +++ b/testcases/lib/SocketActivation.pm @@ -109,7 +109,7 @@ sub activate_i3 { if ($args{valgrind}) { $i3cmd = - qq|valgrind -v --log-file="$outdir/valgrind-for-$test.log" | . + qq|valgrind --log-file="$outdir/valgrind-for-$test.log" | . qq|--suppressions="./valgrind.supp" | . qq|--leak-check=full --track-origins=yes --num-callers=20 | . qq|--tool=memcheck -- $i3cmd|; From e8704bb33b8df68cc6112e2a58f7c78ec7b114ad Mon Sep 17 00:00:00 2001 From: shdown Date: Mon, 23 Mar 2015 22:56:49 +0300 Subject: [PATCH 65/99] i3bar: spelling fixes --- i3bar/include/child.h | 12 ++++++------ i3bar/include/config.h | 2 +- i3bar/include/ipc.h | 2 +- i3bar/include/mode.h | 4 ++-- i3bar/include/outputs.h | 8 ++++---- i3bar/include/util.h | 2 +- i3bar/include/workspaces.h | 8 ++++---- i3bar/include/xcb.h | 6 +++--- i3bar/src/child.c | 20 ++++++++++---------- i3bar/src/config.c | 6 +++--- i3bar/src/ipc.c | 22 +++++++++++----------- i3bar/src/main.c | 8 ++++---- i3bar/src/mode.c | 10 +++++----- i3bar/src/outputs.c | 14 +++++++------- i3bar/src/workspaces.c | 12 ++++++------ i3bar/src/xcb.c | 38 +++++++++++++++++++------------------- 16 files changed, 87 insertions(+), 87 deletions(-) diff --git a/i3bar/include/child.h b/i3bar/include/child.h index 72272b24..09123062 100644 --- a/i3bar/include/child.h +++ b/i3bar/include/child.h @@ -41,7 +41,7 @@ typedef struct { } i3bar_child; /* - * Start a child-process with the specified command and reroute stdin. + * 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 * @@ -49,26 +49,26 @@ typedef struct { void start_child(char *command); /* - * kill()s the child-process (if any). Called when exit()ing. + * kill()s the child process (if any). Called when exit()ing. * */ void kill_child_at_exit(void); /* - * kill()s the child-process (if any) and closes and - * free()s the stdin- and sigchild-watchers + * kill()s the child process (if any) and closes and + * free()s the stdin- and SIGCHLD-watchers * */ void kill_child(void); /* - * Sends a SIGSTOP to the child-process (if existent) + * Sends a SIGSTOP to the child process (if existent) * */ void stop_child(void); /* - * Sends a SIGCONT to the child-process (if existent) + * Sends a SIGCONT to the child process (if existent) * */ void cont_child(void); diff --git a/i3bar/include/config.h b/i3bar/include/config.h index 2c399305..fe04bf31 100644 --- a/i3bar/include/config.h +++ b/i3bar/include/config.h @@ -49,7 +49,7 @@ typedef struct config_t { config_t config; /** - * Start parsing the received bar configuration json-string + * Start parsing the received bar configuration JSON string * */ void parse_config_json(char *json); diff --git a/i3bar/include/ipc.h b/i3bar/include/ipc.h index c357be89..d1fcb069 100644 --- a/i3bar/include/ipc.h +++ b/i3bar/include/ipc.h @@ -13,7 +13,7 @@ /* * Initiate a connection to i3. - * socket-path must be a valid path to the ipc_socket of i3 + * socket_path must be a valid path to the ipc_socket of i3 * */ int init_connection(const char *socket_path); diff --git a/i3bar/include/mode.h b/i3bar/include/mode.h index 6c3833f4..37e8e017 100644 --- a/i3bar/include/mode.h +++ b/i3bar/include/mode.h @@ -4,7 +4,7 @@ * i3bar - an xcb-based status- and ws-bar for i3 * © 2010-2012 Axel Wagner and contributors (see also: LICENSE) * - * mode.c: Handle mode-event and show current binding mode in the bar + * mode.c: Handle "mode" event and show current binding mode in the bar * */ #pragma once @@ -22,7 +22,7 @@ struct mode { typedef struct mode mode; /* - * Start parsing the received json-string + * Start parsing the received JSON string * */ void parse_mode_json(char *json); diff --git a/i3bar/include/outputs.h b/i3bar/include/outputs.h index bd41e776..73fbf33f 100644 --- a/i3bar/include/outputs.h +++ b/i3bar/include/outputs.h @@ -4,7 +4,7 @@ * i3bar - an xcb-based status- and ws-bar for i3 * © 2010-2012 Axel Wagner and contributors (see also: LICENSE) * - * outputs.c: Maintaining the output-list + * outputs.c: Maintaining the outputs list * */ #pragma once @@ -19,13 +19,13 @@ SLIST_HEAD(outputs_head, i3_output); struct outputs_head* outputs; /* - * Start parsing the received json-string + * Start parsing the received JSON string * */ void parse_outputs_json(char* json); /* - * Initiate the output-list + * Initiate the outputs list * */ void init_outputs(void); @@ -42,7 +42,7 @@ struct i3_output { bool primary; /* If it is the primary output */ bool visible; /* If the bar is visible on this output */ int ws; /* The number of the currently visible ws */ - rect rect; /* The rect (relative to the root-win) */ + rect rect; /* The rect (relative to the root window) */ xcb_window_t bar; /* The id of the bar of the output */ xcb_pixmap_t buffer; /* An extra pixmap for double-buffering */ diff --git a/i3bar/include/util.h b/i3bar/include/util.h index cb0903c1..52abc9b9 100644 --- a/i3bar/include/util.h +++ b/i3bar/include/util.h @@ -51,7 +51,7 @@ #if defined(DLOG) #undef DLOG #endif -/* Use cool logging-macros */ +/* Use cool logging macros */ #define DLOG(fmt, ...) \ do { \ if (config.verbose) { \ diff --git a/i3bar/include/workspaces.h b/i3bar/include/workspaces.h index b9cefa84..1b8c6c72 100644 --- a/i3bar/include/workspaces.h +++ b/i3bar/include/workspaces.h @@ -4,7 +4,7 @@ * i3bar - an xcb-based status- and ws-bar for i3 * © 2010-2012 Axel Wagner and contributors (see also: LICENSE) * - * workspaces.c: Maintaining the workspace-lists + * workspaces.c: Maintaining the workspace lists * */ #pragma once @@ -18,13 +18,13 @@ typedef struct i3_ws i3_ws; TAILQ_HEAD(ws_head, i3_ws); /* - * Start parsing the received json-string + * Start parsing the received JSON string * */ void parse_workspaces_json(char *json); /* - * free() all workspace data-structures + * free() all workspace data structures * */ void free_workspaces(void); @@ -36,7 +36,7 @@ struct i3_ws { int name_width; /* The rendered width of the name */ bool visible; /* If the ws is currently visible on an output */ bool focused; /* If the ws is currently focused */ - bool urgent; /* If the urgent-hint of the ws is set */ + bool urgent; /* If the urgent hint of the ws is set */ rect rect; /* The rect of the ws (not used (yet)) */ struct i3_output *output; /* The current output of the ws */ diff --git a/i3bar/include/xcb.h b/i3bar/include/xcb.h index 32b52f4d..d8411a0a 100644 --- a/i3bar/include/xcb.h +++ b/i3bar/include/xcb.h @@ -65,14 +65,14 @@ void init_xcb_late(char *fontname); void init_colors(const struct xcb_color_strings_t *colors); /* - * Cleanup the xcb-stuff. + * Cleanup the xcb stuff. * Called once, before the program terminates. * */ void clean_xcb(void); /* - * Get the earlier requested atoms and save them in the prepared data-structure + * Get the earlier requested atoms and save them in the prepared data structure * */ void get_atoms(void); @@ -104,7 +104,7 @@ void init_tray_colors(void); void destroy_window(i3_output *output); /* - * Reallocate the statusline-buffer + * Reallocate the statusline buffer * */ void realloc_sl_buffer(void); diff --git a/i3bar/src/child.c b/i3bar/src/child.c index efe02884..654efdca 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -30,7 +30,7 @@ /* Global variables for child_*() */ i3bar_child child; -/* stdin- and sigchild-watchers */ +/* stdin- and SIGCHLD-watchers */ ev_io *stdin_io; ev_child *child_sig; @@ -123,7 +123,7 @@ __attribute__((format(printf, 1, 2))) static void set_statusline_error(const cha } /* - * Stop and free() the stdin- and sigchild-watchers + * Stop and free() the stdin- and SIGCHLD-watchers * */ void cleanup(void) { @@ -402,8 +402,8 @@ void stdin_io_first_line_cb(struct ev_loop *loop, ev_io *watcher, int revents) { } /* - * We received a sigchild, meaning, that the child-process terminated. - * We simply free the respective data-structures and don't care for input + * We received a SIGCHLD, meaning, that the child process terminated. + * We simply free the respective data structures and don't care for input * anymore * */ @@ -440,7 +440,7 @@ void child_write_output(void) { } /* - * Start a child-process with the specified command and reroute stdin. + * 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. * @@ -568,7 +568,7 @@ void send_block_clicked(int button, const char *name, const char *instance, int } /* - * kill()s the child-process (if any). Called when exit()ing. + * kill()s the child process (if any). Called when exit()ing. * */ void kill_child_at_exit(void) { @@ -580,8 +580,8 @@ void kill_child_at_exit(void) { } /* - * kill()s the child-process (if existent) and closes and - * free()s the stdin- and sigchild-watchers + * kill()s the child process (if existent) and closes and + * free()s the stdin- and SIGCHLD-watchers * */ void kill_child(void) { @@ -596,7 +596,7 @@ void kill_child(void) { } /* - * Sends a SIGSTOP to the child-process (if existent) + * Sends a SIGSTOP to the child process (if existent) * */ void stop_child(void) { @@ -607,7 +607,7 @@ void stop_child(void) { } /* - * Sends a SIGCONT to the child-process (if existent) + * Sends a SIGCONT to the child process (if existent) * */ void cont_child(void) { diff --git a/i3bar/src/config.c b/i3bar/src/config.c index bb322619..c568ac5b 100644 --- a/i3bar/src/config.c +++ b/i3bar/src/config.c @@ -38,7 +38,7 @@ static int config_map_key_cb(void *params_, const unsigned char *keyVal, size_t } /* - * Parse a null-value (current_workspace) + * Parse a null value (current_workspace) * */ static int config_null_cb(void *params_) { @@ -231,7 +231,7 @@ static yajl_callbacks outputs_callbacks = { }; /* - * Start parsing the received bar configuration json-string + * Start parsing the received bar configuration JSON string * */ void parse_config_json(char *json) { @@ -247,7 +247,7 @@ void parse_config_json(char *json) { break; case yajl_status_client_canceled: case yajl_status_error: - ELOG("Could not parse config-reply!\n"); + ELOG("Could not parse config reply!\n"); exit(EXIT_FAILURE); break; } diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index e1b343e5..c6e67eb6 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -32,11 +32,11 @@ typedef void (*handler_t)(char *); * */ void got_command_reply(char *reply) { - /* TODO: Error handling for command-replies */ + /* TODO: Error handling for command replies */ } /* - * Called, when we get a reply with workspaces-data + * Called, when we get a reply with workspaces data * */ void got_workspace_reply(char *reply) { @@ -52,11 +52,11 @@ void got_workspace_reply(char *reply) { */ void got_subscribe_reply(char *reply) { DLOG("Got Subscribe Reply: %s\n", reply); - /* TODO: Error handling for subscribe-commands */ + /* TODO: Error handling for subscribe commands */ } /* - * Called, when we get a reply with outputs-data + * Called, when we get a reply with outputs data * */ void got_output_reply(char *reply) { @@ -80,7 +80,7 @@ void got_output_reply(char *reply) { */ void got_bar_config(char *reply) { DLOG("Received bar config \"%s\"\n", reply); - /* We initiate the main-function by requesting infos about the outputs and + /* We initiate the main function by requesting infos about the outputs and * workspaces. Everything else (creating the bars, showing the right workspace- * buttons and more) is taken care of by the event-drivenness of the code */ i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_OUTPUTS, NULL); @@ -104,7 +104,7 @@ void got_bar_config(char *reply) { FREE(config.command); } -/* Data-structure to easily call the reply-handlers later */ +/* Data-structure to easily call the reply handlers later */ handler_t reply_handlers[] = { &got_command_reply, &got_workspace_reply, @@ -116,7 +116,7 @@ handler_t reply_handlers[] = { }; /* - * Called, when a workspace-event arrives (i.e. the user changed the workspace) + * Called, when a workspace event arrives (i.e. the user changed the workspace) * */ void got_workspace_event(char *event) { @@ -125,7 +125,7 @@ void got_workspace_event(char *event) { } /* - * Called, when an output-event arrives (i.e. the screen-configuration changed) + * Called, when an output event arrives (i.e. the screen-configuration changed) * */ void got_output_event(char *event) { @@ -137,7 +137,7 @@ void got_output_event(char *event) { } /* - * Called, when a mode-event arrives (i3 changed binding mode). + * Called, when a mode event arrives (i3 changed binding mode). * */ void got_mode_event(char *event) { @@ -180,7 +180,7 @@ void got_bar_config_update(char *event) { draw_bars(false); } -/* Data-structure to easily call the event-handlers later */ +/* Data-structure to easily call the event handlers later */ handler_t event_handlers[] = { &got_workspace_event, &got_output_event, @@ -316,7 +316,7 @@ int i3_send_msg(uint32_t type, const char *payload) { /* * Initiate a connection to i3. - * socket-path must be a valid path to the ipc_socket of i3 + * socket_path must be a valid path to the ipc_socket of i3 * */ int init_connection(const char *socket_path) { diff --git a/i3bar/src/main.c b/i3bar/src/main.c index ee3d81b9..34fc807b 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -60,7 +60,7 @@ void print_usage(char *elf_name) { printf("\n"); printf("-b, --bar_id \tBar ID for which to get the configuration\n"); printf("-s, --socket \tConnect to i3 via \n"); - printf("-h, --help Display this help-message and exit\n"); + printf("-h, --help Display this help message and exit\n"); printf("-v, --version Display version number and exit\n"); printf("\n"); printf(" PLEASE NOTE that i3bar will be automatically started by i3\n" @@ -71,7 +71,7 @@ void print_usage(char *elf_name) { /* * We watch various signals, that are there to make our application stop. - * If we get one of those, we ev_unloop() and invoke the cleanup-routines + * If we get one of those, we ev_unloop() and invoke the cleanup routines * in main() with that * */ @@ -150,7 +150,7 @@ int main(int argc, char **argv) { i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_BAR_CONFIG, config.bar_id); } - /* We listen to SIGTERM/QUIT/INT and try to exit cleanly, by stopping the main-loop. + /* 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 = smalloc(sizeof(ev_signal)); @@ -166,7 +166,7 @@ int main(int argc, char **argv) { 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 */ + * events. We stop simply stop the event loop, when we are finished */ ev_loop(main_loop, 0); kill_child(); diff --git a/i3bar/src/mode.c b/i3bar/src/mode.c index 813d4aab..05f6de1a 100644 --- a/i3bar/src/mode.c +++ b/i3bar/src/mode.c @@ -4,7 +4,7 @@ * i3bar - an xcb-based status- and ws-bar for i3 * © 2010-2012 Axel Wagner and contributors (see also: LICENSE) * - * mode.c: Handle mode-event and show current binding mode in the bar + * mode.c: Handle mode event and show current binding mode in the bar * */ #include @@ -48,7 +48,7 @@ static int mode_string_cb(void *params_, const unsigned char *val, size_t len) { /* * Parse a key. * - * Essentially we just save it in the parsing-state + * Essentially we just save it in the parsing state * */ static int mode_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) { @@ -69,11 +69,11 @@ static yajl_callbacks mode_callbacks = { }; /* - * Start parsing the received json-string + * Start parsing the received JSON string * */ void parse_mode_json(char *json) { - /* FIXME: Fasciliate stream-processing, i.e. allow starting to interpret + /* FIXME: Fasciliate stream processing, i.e. allow starting to interpret * JSON in chunks */ struct mode_json_params params; @@ -96,7 +96,7 @@ void parse_mode_json(char *json) { break; case yajl_status_client_canceled: case yajl_status_error: - ELOG("Could not parse mode-event!\n"); + ELOG("Could not parse mode event!\n"); exit(EXIT_FAILURE); break; } diff --git a/i3bar/src/outputs.c b/i3bar/src/outputs.c index 02b718d3..8f5c95dc 100644 --- a/i3bar/src/outputs.c +++ b/i3bar/src/outputs.c @@ -4,7 +4,7 @@ * i3bar - an xcb-based status- and ws-bar for i3 * © 2010-2012 Axel Wagner and contributors (see also: LICENSE) * - * outputs.c: Maintaining the output-list + * outputs.c: Maintaining the outputs list * */ #include @@ -27,7 +27,7 @@ struct outputs_json_params { }; /* - * Parse a null-value (current_workspace) + * Parse a null value (current_workspace) * */ static int outputs_null_cb(void *params_) { @@ -139,7 +139,7 @@ static int outputs_string_cb(void *params_, const unsigned char *val, size_t len } /* - * We hit the start of a json-map (rect or a new output) + * We hit the start of a JSON map (rect or a new output) * */ static int outputs_start_map_cb(void *params_) { @@ -221,7 +221,7 @@ static int outputs_end_map_cb(void *params_) { /* * Parse a key. * - * Essentially we just save it in the parsing-state + * Essentially we just save it in the parsing state * */ static int outputs_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) { @@ -247,7 +247,7 @@ static yajl_callbacks outputs_callbacks = { }; /* - * Initiate the output-list + * Initiate the outputs list * */ void init_outputs(void) { @@ -256,7 +256,7 @@ void init_outputs(void) { } /* - * Start parsing the received json-string + * Start parsing the received JSON string * */ void parse_outputs_json(char *json) { @@ -279,7 +279,7 @@ void parse_outputs_json(char *json) { break; case yajl_status_client_canceled: case yajl_status_error: - ELOG("Could not parse outputs-reply!\n"); + ELOG("Could not parse outputs reply!\n"); exit(EXIT_FAILURE); break; } diff --git a/i3bar/src/workspaces.c b/i3bar/src/workspaces.c index 45b511ff..fa981f4e 100644 --- a/i3bar/src/workspaces.c +++ b/i3bar/src/workspaces.c @@ -4,7 +4,7 @@ * i3bar - an xcb-based status- and ws-bar for i3 * © 2010-2012 Axel Wagner and contributors (see also: LICENSE) * - * workspaces.c: Maintaining the workspace-lists + * workspaces.c: Maintaining the workspace lists * */ #include @@ -167,7 +167,7 @@ static int workspaces_string_cb(void *params_, const unsigned char *val, size_t } /* - * We hit the start of a json-map (rect or a new output) + * We hit the start of a JSON map (rect or a new output) * */ static int workspaces_start_map_cb(void *params_) { @@ -195,7 +195,7 @@ static int workspaces_start_map_cb(void *params_) { /* * Parse a key. * - * Essentially we just save it in the parsing-state + * Essentially we just save it in the parsing state * */ static int workspaces_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) { @@ -219,11 +219,11 @@ static yajl_callbacks workspaces_callbacks = { }; /* - * Start parsing the received json-string + * Start parsing the received JSON string * */ void parse_workspaces_json(char *json) { - /* FIXME: Fasciliate stream-processing, i.e. allow starting to interpret + /* FIXME: Fasciliate stream processing, i.e. allow starting to interpret * JSON in chunks */ struct workspaces_json_params params; @@ -256,7 +256,7 @@ void parse_workspaces_json(char *json) { } /* - * free() all workspace data-structures. Does not free() the heads of the tailqueues. + * free() all workspace data structures. Does not free() the heads of the tailqueues. * */ void free_workspaces(void) { diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 96fcb3fa..3360485a 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -125,7 +125,7 @@ const static int tray_loff_px = 2; /* Vertical offset between the bar and a separator */ const static int sep_voff_px = 4; -/* We define xcb_request_failed as a macro to include the relevant line-number */ +/* We define xcb_request_failed as a macro to include the relevant line number */ #define xcb_request_failed(cookie, err_msg) _xcb_request_failed(cookie, err_msg, __LINE__) int _xcb_request_failed(xcb_void_cookie_t cookie, char *err_msg, int line) { xcb_generic_error_t *err; @@ -349,8 +349,8 @@ void init_colors(const struct xcb_color_strings_t *new_colors) { } /* - * Handle a button-press-event (i.e. a mouse click on one of our bars). - * We determine, whether the click occured on a ws-button or if the scroll- + * Handle a button press event (i.e. a mouse click on one of our bars). + * We determine, whether the click occured on a workspace button or if the scroll- * wheel was used and change the workspace appropriately * */ @@ -516,7 +516,7 @@ void handle_button(xcb_button_press_event_t *event) { /* * Handle visibility notifications: when none of the bars are visible, e.g. - * if windows are in full-screen on each output, suspend the child process. + * if windows are in fullscreen on each output, suspend the child process. * */ static void handle_visibility_notify(xcb_visibility_notify_event_t *event) { @@ -881,7 +881,7 @@ static void handle_property_notify(xcb_property_notify_event_t *event) { DLOG("xembed version = %d\n", xembed[0]); DLOG("xembed flags = %d\n", xembed[1]); bool map_it = ((xembed[1] & XEMBED_MAPPED) == XEMBED_MAPPED); - DLOG("map-state now %d\n", map_it); + DLOG("map state now %d\n", map_it); if (trayclient->mapped && !map_it) { /* need to unmap the window */ xcb_unmap_window(xcb_connection, trayclient->win); @@ -1020,7 +1020,7 @@ void xcb_chk_cb(struct ev_loop *loop, ev_check *watcher, int revents) { redraw_bars(); break; case XCB_BUTTON_PRESS: - /* Button-press-events are mouse-buttons clicked on one of our bars */ + /* Button press events are mouse-buttons clicked on one of our bars */ handle_button((xcb_button_press_event_t *)event); break; case XCB_CLIENT_MESSAGE: @@ -1127,9 +1127,9 @@ char *init_xcb_early() { char *path = root_atom_contents("I3_SOCKET_PATH", xcb_connection, screen); - 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")) { + 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); } @@ -1137,7 +1137,7 @@ char *init_xcb_early() { } /* - * Register for xkb keyevents. To grab modifiers without blocking other applications from receiving key-events + * Register for xkb keyevents. To grab modifiers without blocking other applications from receiving key events * involving that modifier, we sadly have to use xkb which is not yet fully supported * in xcb. * @@ -1343,7 +1343,7 @@ void init_tray_colors(void) { } /* - * Cleanup the xcb-stuff. + * Cleanup the xcb stuff. * Called once, before the program terminates. * */ @@ -1453,11 +1453,11 @@ void destroy_window(i3_output *output) { } /* - * Reallocate the statusline-buffer + * Reallocate the statusline buffer * */ void realloc_sl_buffer(void) { - DLOG("Re-allocating statusline-buffer, statusline_width = %d, root_screen->width_in_pixels = %d\n", + DLOG("Re-allocating statusline buffer, statusline_width = %d, root_screen->width_in_pixels = %d\n", statusline_width, root_screen->width_in_pixels); xcb_free_pixmap(xcb_connection, statusline_pm); statusline_pm = xcb_generate_id(xcb_connection); @@ -1488,9 +1488,9 @@ void realloc_sl_buffer(void) { 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")) { + 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); } } @@ -1521,7 +1521,7 @@ void reconfig_windows(bool redraw_bars) { mask = XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; /* Black background */ values[0] = colors.bar_bg; - /* If hide_on_modifier is set to hide or invisible mode, i3 is not supposed to manage our bar-windows */ + /* If hide_on_modifier is set to hide or invisible mode, i3 is not supposed to manage our bar windows */ values[1] = (config.hide_on_modifier == M_DOCK ? 0 : 1); /* We enable the following EventMask fields: * EXPOSURE, to get expose events (we have to re-draw then) @@ -1583,7 +1583,7 @@ void reconfig_windows(bool redraw_bars) { name); free(name); - /* We want dock-windows (for now). When override_redirect is set, i3 is ignoring + /* We want dock windows (for now). When override_redirect is set, i3 is ignoring * this one */ xcb_void_cookie_t dock_cookie = xcb_change_property(xcb_connection, XCB_PROP_MODE_REPLACE, @@ -1638,7 +1638,7 @@ void reconfig_windows(bool redraw_bars) { 12, &strut_partial); - /* We also want a graphics-context for the bars (it defines the properties + /* 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); xcb_void_cookie_t gc_cookie = xcb_create_gc_checked(xcb_connection, From e681f34ec1af4b19f9dfd9c0e8d9c29beaf3e2db Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 24 Mar 2015 02:27:38 -0400 Subject: [PATCH 66/99] i3bar: set markup per block Add `markup` to the i3bar protocol as a block member. This is a string that determines how the block should be parsed as markup. "pango" indicates the block should be parsed as Pango markup. "none" indicates the block should not be parsed as markup. --- docs/i3bar-protocol | 4 ++++ i3bar/include/common.h | 7 +++++++ i3bar/src/child.c | 25 ++++++++++++++++++++++--- include/libi3.h | 5 +++++ libi3/string.c | 7 +++++++ 5 files changed, 45 insertions(+), 3 deletions(-) diff --git a/docs/i3bar-protocol b/docs/i3bar-protocol index 8fd51ae9..ccc76346 100644 --- a/docs/i3bar-protocol +++ b/docs/i3bar-protocol @@ -172,6 +172,10 @@ separator_block_width:: this gap, a separator line will be drawn unless +separator+ is disabled. Normally, you want to set this to an odd value (the default is 9 pixels), since the separator line is drawn in the middle. +markup:: + A string that indicates how the text of the block should be parsed. Set to + +"pango"+ to use https://developer.gnome.org/pango/stable/PangoMarkupFormat.html[Pango markup] + (default). Set to +"none"+ to not use any markup. If you want to put in your own entries into a block, prefix the key with an underscore (_). i3bar will ignore all keys it doesn’t understand, and prefixing diff --git a/i3bar/include/common.h b/i3bar/include/common.h index 3744df27..22b9a28a 100644 --- a/i3bar/include/common.h +++ b/i3bar/include/common.h @@ -38,11 +38,18 @@ struct status_block { i3String *short_text; char *color; + + /* min_width can be specified either as a numeric value (in pixels) or as a + * string. For strings, we set min_width to the measured text width of + * min_width_str. */ uint32_t min_width; + char *min_width_str; + blockalign_t align; bool urgent; bool no_separator; + bool is_markup; /* The amount of pixels necessary to render a separater after the block. */ uint32_t sep_block_width; diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 894bd4a3..402e6351 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -74,6 +74,7 @@ static void clear_statusline(struct statusline_head *head, bool free_resources) FREE(first->color); FREE(first->name); FREE(first->instance); + FREE(first->min_width_str); } TAILQ_REMOVE(head, first, blocks); @@ -163,6 +164,9 @@ static int stdin_start_map(void *context) { /* Default width of the separator block. */ ctx->block.sep_block_width = logical_px(9); + /* Use markup by default */ + ctx->block.is_markup = true; + return 1; } @@ -195,6 +199,9 @@ static int stdin_string(void *context, const unsigned char *val, size_t len) { if (strcasecmp(ctx->last_map_key, "color") == 0) { sasprintf(&(ctx->block.color), "%.*s", len, val); } + if (strcasecmp(ctx->last_map_key, "markup") == 0) { + ctx->block.is_markup = (len == strlen("pango") && !strncasecmp((const char *)val, "pango", strlen("pango"))); + } if (strcasecmp(ctx->last_map_key, "align") == 0) { if (len == strlen("center") && !strncmp((const char *)val, "center", strlen("center"))) { ctx->block.align = ALIGN_CENTER; @@ -204,9 +211,10 @@ static int stdin_string(void *context, const unsigned char *val, size_t len) { ctx->block.align = ALIGN_LEFT; } } else if (strcasecmp(ctx->last_map_key, "min_width") == 0) { - i3String *text = i3string_from_markup_with_length((const char *)val, len); - ctx->block.min_width = (uint32_t)predict_text_width(text); - i3string_free(text); + char *copy = (char *)malloc(len + 1); + strncpy(copy, (const char *)val, len); + copy[len] = 0; + ctx->block.min_width_str = copy; } if (strcasecmp(ctx->last_map_key, "name") == 0) { char *copy = (char *)malloc(len + 1); @@ -248,6 +256,17 @@ static int stdin_end_map(void *context) { new_block->full_text = i3string_from_utf8("SPEC VIOLATION: full_text is NULL!"); if (new_block->urgent) ctx->has_urgent = true; + + if (new_block->min_width_str) { + i3String *text = i3string_from_utf8(new_block->min_width_str); + i3string_set_markup(text, new_block->is_markup); + new_block->min_width = (uint32_t)predict_text_width(text); + i3string_free(text); + } + + i3string_set_markup(new_block->full_text, new_block->is_markup); + i3string_set_markup(new_block->short_text, new_block->is_markup); + TAILQ_INSERT_TAIL(&statusline_buffer, new_block, blocks); return 1; } diff --git a/include/libi3.h b/include/libi3.h index b60dda5c..c8d2e956 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -217,6 +217,11 @@ size_t i3string_get_num_bytes(i3String *str); */ bool i3string_is_markup(i3String *str); +/** + * Set whether the i3String should use Pango markup. + */ +void i3string_set_markup(i3String *str, bool is_markup); + /** * Returns the number of glyphs in an i3String. * diff --git a/libi3/string.c b/libi3/string.c index 88fd1986..e6297f9e 100644 --- a/libi3/string.c +++ b/libi3/string.c @@ -178,6 +178,13 @@ bool i3string_is_markup(i3String *str) { return str->is_markup; } +/* + * Set whether the i3String should use Pango markup. + */ +void i3string_set_markup(i3String *str, bool is_markup) { + str->is_markup = is_markup; +} + /* * Returns the number of glyphs in an i3String. * From 822cd3bf1b95a61667bfa186ff2093ecd317a3a6 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 24 Mar 2015 09:27:42 +0100 Subject: [PATCH 67/99] Revert "Workspace command number selection" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit cbd51ce6642be4e1163a64dce8ec20a454f1bf05. If you’ve started using this feature, I’m very sorry, but I think it’s better to revert it entirely, as it will only cause more problems in the future as more and more people upgrade and get bitten by this if we didn’t revert it… fixes #1536 --- src/commands.c | 47 +---------------- .../t/232-cmd-workspace-number-selection.t | 52 ------------------- 2 files changed, 2 insertions(+), 97 deletions(-) delete mode 100644 testcases/t/232-cmd-workspace-number-selection.t diff --git a/src/commands.c b/src/commands.c index 80f57b81..9b51b3ec 100644 --- a/src/commands.c +++ b/src/commands.c @@ -494,27 +494,7 @@ void cmd_move_con_to_workspace_name(I3_CMD, char *name) { LOG("should move window to workspace %s\n", name); /* get the workspace */ - Con *ws = NULL; - Con *output = NULL; - - /* first look for a workspace with this name */ - TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { - GREP_FIRST(ws, output_get_content(output), !strcasecmp(child->name, name)); - } - - /* if the name is plain digits, we interpret this as a "workspace number" - * command */ - if (!ws && name_is_digits(name)) { - long parsed_num = ws_name_to_number(name); - TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { - GREP_FIRST(ws, output_get_content(output), - child->num == parsed_num); - } - } - - /* if no workspace was found, make a new one */ - if (!ws) - ws = workspace_get(name, NULL); + Con *ws = workspace_get(name, NULL); ws = maybe_auto_back_and_forth_workspace(ws); @@ -1049,30 +1029,7 @@ void cmd_workspace_name(I3_CMD, char *name) { DLOG("should switch to workspace %s\n", name); if (maybe_back_and_forth(cmd_output, name)) return; - - Con *ws = NULL; - Con *output = NULL; - - /* first look for a workspace with this name */ - TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { - GREP_FIRST(ws, output_get_content(output), !strcasecmp(child->name, name)); - } - - /* if the name is only digits, we interpret this as a "workspace number" - * command */ - if (!ws && name_is_digits(name)) { - long parsed_num = ws_name_to_number(name); - TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { - GREP_FIRST(ws, output_get_content(output), - child->num == parsed_num); - } - } - - /* if no workspace was found, make a new one */ - if (!ws) - ws = workspace_get(name, NULL); - - workspace_show(ws); + workspace_show_by_name(name); cmd_output->needs_tree_render = true; // XXX: default reply for now, make this a better reply diff --git a/testcases/t/232-cmd-workspace-number-selection.t b/testcases/t/232-cmd-workspace-number-selection.t deleted file mode 100644 index bda05643..00000000 --- a/testcases/t/232-cmd-workspace-number-selection.t +++ /dev/null @@ -1,52 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Please read the following documents before working on tests: -# • http://build.i3wm.org/docs/testsuite.html -# (or docs/testsuite) -# -# • http://build.i3wm.org/docs/lib-i3test.html -# (alternatively: perldoc ./testcases/lib/i3test.pm) -# -# • http://build.i3wm.org/docs/ipc.html -# (or docs/ipc) -# -# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf -# (unless you are already familiar with Perl) -# -# Test that `workspace {N}` acts like `workspace number {N}` when N is a plain -# digit, and likewise for `move to workspace {N}`. -# Ticket: #1238 -# Bug still in: 4.8-16-g3f5a0f0 -use i3test; - -cmd 'workspace 5:foo'; -open_window; -fresh_workspace; -cmd 'workspace 5'; - -is(focused_ws, '5:foo', - 'a command to switch to a workspace with a bare number should switch to a workspace of that number'); - -fresh_workspace; -my $win = open_window; -cmd '[id="' . $win->{id} . '"] move to workspace 5'; - -is(@{get_ws('5:foo')->{nodes}}, 2, - 'a command to move a container to a workspace with a bare number should move that container to a workspace of that number'); - -fresh_workspace; -cmd 'workspace 7'; -open_window; -cmd 'workspace 7:foo'; -$win = open_window; - -cmd 'workspace 7'; -is(focused_ws, '7', - 'a workspace with a name that is a matching plain number should be preferred when switching'); - -cmd '[id="' . $win->{id} . '"] move to workspace 7'; -is(@{get_ws('7')->{nodes}}, 2, - 'a workspace with a name that is a matching plain number should be preferred when moving'); - -done_testing; From 0962c7f011b0e8e68eae23ae1842989b39b41603 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 24 Mar 2015 05:45:20 -0400 Subject: [PATCH 68/99] i3bar: check block text for NULL Add a null check to `full_text` and `short_text` for a block before setting the markup property to avoid a segfault. --- 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 402e6351..a461c931 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -265,7 +265,9 @@ static int stdin_end_map(void *context) { } i3string_set_markup(new_block->full_text, new_block->is_markup); - i3string_set_markup(new_block->short_text, new_block->is_markup); + + if (new_block->short_text != NULL) + i3string_set_markup(new_block->short_text, new_block->is_markup); TAILQ_INSERT_TAIL(&statusline_buffer, new_block, blocks); return 1; From 177c03debd8f7329be8a173247a12b99dc5aa4c8 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 24 Mar 2015 06:00:26 -0400 Subject: [PATCH 69/99] i3bar: check `short_text` for NULL on dump Check `short_text` for NULL on statusline dump, since this value can be NULL when not given. Fixes a segfault in that case. --- 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 a461c931..5347632a 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -286,7 +286,7 @@ static int stdin_end_array(void *context) { struct status_block *current; TAILQ_FOREACH(current, &statusline_head, blocks) { DLOG("full_text = %s\n", i3string_as_utf8(current->full_text)); - DLOG("short_text = %s\n", i3string_as_utf8(current->short_text)); + DLOG("short_text = %s\n", (current->short_text == NULL ? NULL : i3string_as_utf8(current->short_text))); DLOG("color = %s\n", current->color); } DLOG("end of dump\n"); From 6922a820a661c15b07136bd3028ed1e35f552a5c Mon Sep 17 00:00:00 2001 From: shdown Date: Tue, 24 Mar 2015 15:41:16 +0300 Subject: [PATCH 70/99] i3bar: spelling fixes (2) --- i3bar/include/child.h | 2 +- i3bar/include/ipc.h | 2 +- i3bar/include/util.h | 4 ++-- i3bar/include/xcb.h | 2 +- i3bar/src/child.c | 2 +- i3bar/src/config.c | 2 +- i3bar/src/ipc.c | 24 ++++++++++++------------ i3bar/src/main.c | 2 +- i3bar/src/mode.c | 2 +- i3bar/src/workspaces.c | 6 +++--- i3bar/src/xcb.c | 14 +++++++------- 11 files changed, 31 insertions(+), 31 deletions(-) diff --git a/i3bar/include/child.h b/i3bar/include/child.h index 09123062..b87cfaac 100644 --- a/i3bar/include/child.h +++ b/i3bar/include/child.h @@ -4,7 +4,7 @@ * i3bar - an xcb-based status- and ws-bar for i3 * © 2010-2012 Axel Wagner and contributors (see also: LICENSE) * - * child.c: Getting Input for the statusline + * child.c: Getting input for the statusline * */ #pragma once diff --git a/i3bar/include/ipc.h b/i3bar/include/ipc.h index d1fcb069..a60a1eba 100644 --- a/i3bar/include/ipc.h +++ b/i3bar/include/ipc.h @@ -25,7 +25,7 @@ int init_connection(const char *socket_path); void destroy_connection(void); /* - * Sends a Message to i3. + * 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/include/util.h b/i3bar/include/util.h index 52abc9b9..ac137998 100644 --- a/i3bar/include/util.h +++ b/i3bar/include/util.h @@ -26,7 +26,7 @@ } \ } while (0) -/* Securely fee single-linked list */ +/* Securely free single-linked list */ #define FREE_SLIST(l, type) \ do { \ type *walk = SLIST_FIRST(l); \ @@ -37,7 +37,7 @@ } \ } while (0) -/* Securely fee tail-queues */ +/* Securely free tail queue */ #define FREE_TAILQ(l, type) \ do { \ type *walk = TAILQ_FIRST(l); \ diff --git a/i3bar/include/xcb.h b/i3bar/include/xcb.h index d8411a0a..8e48c0c1 100644 --- a/i3bar/include/xcb.h +++ b/i3bar/include/xcb.h @@ -90,7 +90,7 @@ void kick_tray_clients(i3_output *output); /* * We need to set the _NET_SYSTEM_TRAY_COLORS atom on the tray selection window - * to make GTK+ 3 applets with Symbolic Icons visible. If the colors are unset, + * to make GTK+ 3 applets with symbolic icons visible. If the colors are unset, * they assume a light background. * See also https://bugzilla.gnome.org/show_bug.cgi?id=679591 * diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 654efdca..a47ca4db 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -4,7 +4,7 @@ * i3bar - an xcb-based status- and ws-bar for i3 * © 2010-2012 Axel Wagner and contributors (see also: LICENSE) * - * child.c: Getting Input for the statusline + * child.c: Getting input for the statusline * */ #include diff --git a/i3bar/src/config.c b/i3bar/src/config.c index c568ac5b..5cc11a41 100644 --- a/i3bar/src/config.c +++ b/i3bar/src/config.c @@ -241,7 +241,7 @@ void parse_config_json(char *json) { state = yajl_parse(handle, (const unsigned char *)json, strlen(json)); - /* FIXME: Proper errorhandling for JSON-parsing */ + /* FIXME: Proper error handling for JSON parsing */ switch (state) { case yajl_status_ok: break; diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index c6e67eb6..ff6f5779 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -40,7 +40,7 @@ void got_command_reply(char *reply) { * */ void got_workspace_reply(char *reply) { - DLOG("Got Workspace-Data!\n"); + DLOG("Got workspace data!\n"); parse_workspaces_json(reply); draw_bars(false); } @@ -51,7 +51,7 @@ void got_workspace_reply(char *reply) { * */ void got_subscribe_reply(char *reply) { - DLOG("Got Subscribe Reply: %s\n", reply); + DLOG("Got subscribe reply: %s\n", reply); /* TODO: Error handling for subscribe commands */ } @@ -60,9 +60,9 @@ void got_subscribe_reply(char *reply) { * */ void got_output_reply(char *reply) { - DLOG("Parsing Outputs-JSON...\n"); + DLOG("Parsing outputs JSON...\n"); parse_outputs_json(reply); - DLOG("Reconfiguring Windows...\n"); + DLOG("Reconfiguring windows...\n"); realloc_sl_buffer(); reconfig_windows(false); @@ -104,7 +104,7 @@ void got_bar_config(char *reply) { FREE(config.command); } -/* Data-structure to easily call the reply handlers later */ +/* Data structure to easily call the reply handlers later */ handler_t reply_handlers[] = { &got_command_reply, &got_workspace_reply, @@ -120,16 +120,16 @@ handler_t reply_handlers[] = { * */ void got_workspace_event(char *event) { - DLOG("Got Workspace Event!\n"); + DLOG("Got workspace event!\n"); i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL); } /* - * Called, when an output event arrives (i.e. the screen-configuration changed) + * Called, when an output event arrives (i.e. the screen configuration changed) * */ void got_output_event(char *event) { - DLOG("Got Output Event!\n"); + DLOG("Got output event!\n"); i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_OUTPUTS, NULL); if (!config.disable_ws) { i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL); @@ -141,7 +141,7 @@ void got_output_event(char *event) { * */ void got_mode_event(char *event) { - DLOG("Got Mode Event!\n"); + DLOG("Got mode event!\n"); parse_mode_json(event); draw_bars(false); } @@ -180,7 +180,7 @@ void got_bar_config_update(char *event) { draw_bars(false); } -/* Data-structure to easily call the event handlers later */ +/* Data structure to easily call the event handlers later */ handler_t event_handlers[] = { &got_workspace_event, &got_output_event, @@ -201,7 +201,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 = smalloc(header_len); - /* We first parse the fixed-length IPC-header, to know, how much data + /* We first parse the fixed-length IPC header, to know, how much data * we have to expect */ uint32_t rec = 0; while (rec < header_len) { @@ -268,7 +268,7 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) { } /* - * Sends a Message to i3. + * 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/main.c b/i3bar/src/main.c index 34fc807b..a9a972db 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -140,7 +140,7 @@ int main(int argc, char **argv) { } if (socket_path == NULL) { - ELOG("No Socket Path Specified, default to %s\n", i3_default_sock_path); + ELOG("No socket path specified, default to %s\n", i3_default_sock_path); socket_path = expand_path(i3_default_sock_path); } diff --git a/i3bar/src/mode.c b/i3bar/src/mode.c index 05f6de1a..0ff8ba4f 100644 --- a/i3bar/src/mode.c +++ b/i3bar/src/mode.c @@ -90,7 +90,7 @@ void parse_mode_json(char *json) { state = yajl_parse(handle, (const unsigned char *)json, strlen(json)); - /* FIXME: Propper errorhandling for JSON-parsing */ + /* FIXME: Propper error handling for JSON parsing */ switch (state) { case yajl_status_ok: break; diff --git a/i3bar/src/workspaces.c b/i3bar/src/workspaces.c index fa981f4e..e3032526 100644 --- a/i3bar/src/workspaces.c +++ b/i3bar/src/workspaces.c @@ -135,7 +135,7 @@ static int workspaces_string_cb(void *params_, const unsigned char *val, size_t params->workspaces_walk->name_width = predict_text_width(params->workspaces_walk->name); - DLOG("Got Workspace canonical: %s, name: '%s', name_width: %d, glyphs: %zu\n", + DLOG("Got workspace canonical: %s, name: '%s', name_width: %d, glyphs: %zu\n", params->workspaces_walk->canonical_name, i3string_as_utf8(params->workspaces_walk->name), params->workspaces_walk->name_width, @@ -239,13 +239,13 @@ void parse_workspaces_json(char *json) { state = yajl_parse(handle, (const unsigned char *)json, strlen(json)); - /* FIXME: Propper errorhandling for JSON-parsing */ + /* FIXME: Propper error handling for JSON parsing */ switch (state) { case yajl_status_ok: break; case yajl_status_client_canceled: case yajl_status_error: - ELOG("Could not parse workspaces-reply!\n"); + ELOG("Could not parse workspaces reply!\n"); exit(EXIT_FAILURE); break; } diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 3360485a..ea9d1fce 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -34,7 +34,7 @@ #include "common.h" #include "libi3.h" -/* We save the Atoms in an easy to access array, indexed by an enum */ +/* We save the atoms in an easy to access array, indexed by an enum */ enum { #define ATOM_DO(name) name, #include "xcb_atoms.def" @@ -74,7 +74,7 @@ xcb_gcontext_t statusline_clear; xcb_pixmap_t statusline_pm; uint32_t statusline_width; -/* Event-Watchers, to interact with the user */ +/* Event watchers, to interact with the user */ ev_prepare *xcb_prep; ev_check *xcb_chk; ev_io *xcb_io; @@ -1020,7 +1020,7 @@ void xcb_chk_cb(struct ev_loop *loop, ev_check *watcher, int revents) { redraw_bars(); break; case XCB_BUTTON_PRESS: - /* Button press events are mouse-buttons clicked on one of our bars */ + /* Button press events are mouse buttons clicked on one of our bars */ handle_button((xcb_button_press_event_t *)event); break; case XCB_CLIENT_MESSAGE: @@ -1053,7 +1053,7 @@ void xcb_chk_cb(struct ev_loop *loop, ev_check *watcher, int revents) { } /* - * Dummy Callback. We only need this, so that the Prepare- and Check-Watchers + * Dummy callback. We only need this, so that the prepare and check watchers * are triggered * */ @@ -1066,7 +1066,7 @@ void xcb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { * */ char *init_xcb_early() { - /* FIXME: xcb_connect leaks Memory */ + /* FIXME: xcb_connect leaks memory */ xcb_connection = xcb_connect(NULL, &screen); if (xcb_connection_has_error(xcb_connection)) { ELOG("Cannot open display\n"); @@ -1109,7 +1109,7 @@ char *init_xcb_early() { root_screen->width_in_pixels, root_screen->height_in_pixels); - /* The various Watchers to communicate with xcb */ + /* The various watchers to communicate with xcb */ xcb_io = smalloc(sizeof(ev_io)); xcb_prep = smalloc(sizeof(ev_prepare)); xcb_chk = smalloc(sizeof(ev_check)); @@ -1303,7 +1303,7 @@ void init_tray(void) { /* * We need to set the _NET_SYSTEM_TRAY_COLORS atom on the tray selection window - * to make GTK+ 3 applets with Symbolic Icons visible. If the colors are unset, + * to make GTK+ 3 applets with symbolic icons visible. If the colors are unset, * they assume a light background. * See also https://bugzilla.gnome.org/show_bug.cgi?id=679591 * From 6d8891894ebdfdadab6b6878dac604aacf6b0df9 Mon Sep 17 00:00:00 2001 From: shdown Date: Wed, 25 Mar 2015 21:30:38 +0300 Subject: [PATCH 71/99] Allow escaping backslashes Fixes #1577. --- i3bar/src/xcb.c | 4 ++-- src/commands_parser.c | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 3360485a..c9f8e6cb 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -489,7 +489,7 @@ void handle_button(xcb_button_press_event_t *event) { size_t namelen = 0; const char *utf8_name = cur_ws->canonical_name; for (const char *walk = utf8_name; *walk != '\0'; walk++) { - if (*walk == '"') + if (*walk == '"' || *walk == '\\') num_quotes++; /* While we’re looping through the name anyway, we can save one * strlen(). */ @@ -503,7 +503,7 @@ void handle_button(xcb_button_press_event_t *event) { for (inpos = 0, outpos = strlen("workspace \""); inpos < namelen; inpos++, outpos++) { - if (utf8_name[inpos] == '"') { + if (utf8_name[inpos] == '"' || utf8_name[inpos] == '\\') { buffer[outpos] = '\\'; outpos++; } diff --git a/src/commands_parser.c b/src/commands_parser.c index f325a048..fa4c2360 100644 --- a/src/commands_parser.c +++ b/src/commands_parser.c @@ -216,8 +216,9 @@ char *parse_string(const char **walk, bool as_word) { if (**walk == '"') { beginning++; (*walk)++; - while (**walk != '\0' && (**walk != '"' || *(*walk - 1) == '\\')) - (*walk)++; + for (; **walk != '\0' && **walk != '"'; (*walk)++) + if (**walk == '\\' && *(*walk + 1) != '\0') + (*walk)++; } else { if (!as_word) { /* For a string (starting with 's'), the delimiters are @@ -248,10 +249,10 @@ char *parse_string(const char **walk, bool as_word) { for (inpos = 0, outpos = 0; inpos < (*walk - beginning); inpos++, outpos++) { - /* We only handle escaped double quotes to not break - * backwards compatibility with people using \w in - * regular expressions etc. */ - if (beginning[inpos] == '\\' && beginning[inpos + 1] == '"') + /* We only handle escaped double quotes and backslashes to not break + * backwards compatibility with people using \w in regular expressions + * etc. */ + if (beginning[inpos] == '\\' && (beginning[inpos + 1] == '"' || beginning[inpos + 1] == '\\')) inpos++; str[outpos] = beginning[inpos]; } From f790fedce385862c7a22df53d527960e82eff920 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 25 Mar 2015 20:48:51 +0100 Subject: [PATCH 72/99] Restore placeholder windows after restarting (Thanks Airblader). fixes #1502 --- src/restore_layout.c | 4 +++- src/tree.c | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/restore_layout.c b/src/restore_layout.c index 0f6e54f9..c6a87f06 100644 --- a/src/restore_layout.c +++ b/src/restore_layout.c @@ -180,7 +180,9 @@ static void update_placeholder_contents(placeholder_state *state) { static void open_placeholder_window(Con *con) { if (con_is_leaf(con) && - (con->window == NULL || con->window->id == XCB_NONE)) { + (con->window == NULL || con->window->id == XCB_NONE) && + !TAILQ_EMPTY(&(con->swallow_head)) && + con->type == CT_CON) { xcb_window_t placeholder = create_window( restore_conn, con->rect, diff --git a/src/tree.c b/src/tree.c index 9b60fea6..b40ba2a2 100644 --- a/src/tree.c +++ b/src/tree.c @@ -104,6 +104,8 @@ bool tree_restore(const char *path, xcb_get_geometry_reply_t *geometry) { TAILQ_INSERT_HEAD(&(croot->nodes_head), __i3, nodes); } + restore_open_placeholder_windows(croot); + return true; } From 26237508eadb5f71befe4c64ab65430757d4b213 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 25 Mar 2015 20:49:19 +0100 Subject: [PATCH 73/99] Bugfix: skip restart_mode swallow specifications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise, placeholder windows would accumulate these over restarts. The worst part is that they don’t get dumped properly, meaning an empty swallows specification ends up in the state, which matches any window, so other random windows would be matched into the placeholder (e.g. i3bar). fixes #1502 --- src/ipc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ipc.c b/src/ipc.c index acd2267b..ff2cd820 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -450,6 +450,10 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) { y(array_open); Match *match; TAILQ_FOREACH(match, &(con->swallow_head), matches) { + /* We will generate a new restart_mode match specification after this + * loop, so skip this one. */ + if (match->restart_mode) + continue; y(map_open); if (match->dock != -1) { ystr("dock"); From 80da100ac84890890594f8df951cc20a522d7922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Tue, 24 Mar 2015 23:07:25 +0100 Subject: [PATCH 74/99] Add support for a custom separator symbol This introduces a "separator_symbol" property for the i3bar configuration. If set, the specified string will be used as a separator instead of a vertical line. Since it is an optional configuration, complete backwards compatibility is given. fixes #1472 --- docs/userguide | 18 +++++++++++++ i3bar/include/config.h | 1 + i3bar/src/config.c | 7 +++++ i3bar/src/xcb.c | 46 +++++++++++++++++++++++++-------- include/config.h | 3 +++ include/config_directives.h | 1 + parser-specs/config.spec | 5 ++++ src/config_directives.c | 5 ++++ src/ipc.c | 5 ++++ testcases/t/201-config-parser.t | 2 +- 10 files changed, 81 insertions(+), 12 deletions(-) diff --git a/docs/userguide b/docs/userguide index 45b05a06..d60eefb2 100644 --- a/docs/userguide +++ b/docs/userguide @@ -1249,6 +1249,24 @@ bar { } -------------------------------------------------------------- +=== Custom separator symbol + +Specifies a custom symbol to be used for the separator as opposed to the vertical, +one pixel thick separator. Note that you may have to adjust the +sep_block_width+ +property. + +*Syntax*: +------------------------- +separator_symbol +------------------------- + +*Example*: +------------------------ +bar { + separator_symbol ":|:" +} +------------------------ + === Workspace buttons Specifies whether workspace buttons should be shown or not. This is useful if diff --git a/i3bar/include/config.h b/i3bar/include/config.h index fe04bf31..fdc37445 100644 --- a/i3bar/include/config.h +++ b/i3bar/include/config.h @@ -35,6 +35,7 @@ typedef struct config_t { char *bar_id; char *command; char *fontname; + i3String *separator_symbol; char *tray_output; int num_outputs; char **outputs; diff --git a/i3bar/src/config.c b/i3bar/src/config.c index c568ac5b..a83ca0aa 100644 --- a/i3bar/src/config.c +++ b/i3bar/src/config.c @@ -144,6 +144,13 @@ static int config_string_cb(void *params_, const unsigned char *val, size_t _len return 1; } + if (!strcmp(cur_key, "separator_symbol")) { + DLOG("separator = %.*s\n", len, val); + I3STRING_FREE(config.separator_symbol); + config.separator_symbol = i3string_from_utf8_with_length((const char *)val, len); + return 1; + } + if (!strcmp(cur_key, "outputs")) { DLOG("+output %.*s\n", len, val); int new_num_outputs = config.num_outputs + 1; diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index d87e56e4..85efd88b 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -63,6 +63,9 @@ static i3Font font; /* Overall height of the bar (based on font size) */ int bar_height; +/* Cached width of the custom separator if one was set */ +int separator_symbol_width; + /* These are only relevant for XKB, which we only need for grabbing modifiers */ int xkb_base; int mod_pressed = 0; @@ -155,6 +158,33 @@ int get_tray_width(struct tc_head *trayclients) { return tray_width; } +/* + * Draws a separator for the given block if necessary. + * + */ +static void draw_separator(uint32_t x, struct status_block *block) { + uint32_t sep_offset = get_sep_offset(block); + if (TAILQ_NEXT(block, blocks) == NULL || sep_offset == 0) + return; + + uint32_t center_x = x - sep_offset; + if (config.separator_symbol == NULL) { + /* Draw a classic one pixel, vertical separator. */ + uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_LINE_WIDTH; + uint32_t values[] = {colors.sep_fg, colors.bar_bg, logical_px(1)}; + xcb_change_gc(xcb_connection, statusline_ctx, mask, values); + xcb_poly_line(xcb_connection, XCB_COORD_MODE_ORIGIN, statusline_pm, statusline_ctx, 2, + (xcb_point_t[]){{center_x, logical_px(sep_voff_px)}, + {center_x, bar_height - logical_px(sep_voff_px)}}); + } else { + /* Draw a custom separator. */ + uint32_t separator_x = MAX(x - block->sep_block_width, center_x - separator_symbol_width / 2); + set_font_colors(statusline_ctx, colors.sep_fg, colors.bar_bg); + draw_text(config.separator_symbol, statusline_pm, statusline_ctx, + separator_x, logical_px(ws_voff_px), x - separator_x); + } +} + /* * Redraws the statusline to the buffer * @@ -245,17 +275,8 @@ void refresh_statusline(bool use_short_text) { draw_text(block->full_text, statusline_pm, statusline_ctx, x + block->x_offset, logical_px(ws_voff_px), block->width); x += block->width + block->sep_block_width + block->x_offset + block->x_append; - uint32_t sep_offset = get_sep_offset(block); - if (TAILQ_NEXT(block, blocks) != NULL && sep_offset > 0) { - /* This is not the last block, draw a separator. */ - uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_LINE_WIDTH; - uint32_t values[] = {colors.sep_fg, colors.bar_bg, logical_px(1)}; - xcb_change_gc(xcb_connection, statusline_ctx, mask, values); - xcb_poly_line(xcb_connection, XCB_COORD_MODE_ORIGIN, statusline_pm, - statusline_ctx, 2, - (xcb_point_t[]){{x - sep_offset, logical_px(sep_voff_px)}, - {x - sep_offset, bar_height - logical_px(sep_voff_px)}}); - } + /* If this is not the last block, draw a separator. */ + draw_separator(x, block); } } @@ -1198,6 +1219,9 @@ void init_xcb_late(char *fontname) { DLOG("Calculated font height: %d\n", font.height); bar_height = font.height + 2 * logical_px(ws_voff_px); + if (config.separator_symbol) + separator_symbol_width = predict_text_width(config.separator_symbol); + xcb_flush(xcb_connection); if (config.hide_on_modifier == M_HIDE) diff --git a/include/config.h b/include/config.h index afafb64b..9a0af0e6 100644 --- a/include/config.h +++ b/include/config.h @@ -285,6 +285,9 @@ struct Barconfig { /** Font specification for all text rendered on the bar. */ char *font; + /** A custom separator to use instead of a vertical line. */ + char *separator_symbol; + /** Hide workspace buttons? Configuration option is 'workspace_buttons no' * but we invert the bool to get the correct default when initializing with * zero. */ diff --git a/include/config_directives.h b/include/config_directives.h index 0f1a6620..6c960b1f 100644 --- a/include/config_directives.h +++ b/include/config_directives.h @@ -67,6 +67,7 @@ CFGFUN(enter_mode, const char *mode); CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *whole_window, const char *command); CFGFUN(bar_font, const char *font); +CFGFUN(bar_separator_symbol, const char *separator); CFGFUN(bar_mode, const char *mode); CFGFUN(bar_hidden_state, const char *hidden_state); CFGFUN(bar_id, const char *bar_id); diff --git a/parser-specs/config.spec b/parser-specs/config.spec index dbdf83c2..25be5cf1 100644 --- a/parser-specs/config.spec +++ b/parser-specs/config.spec @@ -370,6 +370,7 @@ state BAR: 'output' -> BAR_OUTPUT 'tray_output' -> BAR_TRAY_OUTPUT 'font' -> BAR_FONT + 'separator_symbol' -> BAR_SEPARATOR_SYMBOL 'binding_mode_indicator' -> BAR_BINDING_MODE_INDICATOR 'workspace_buttons' -> BAR_WORKSPACE_BUTTONS 'strip_workspace_numbers' -> BAR_STRIP_WORKSPACE_NUMBERS @@ -435,6 +436,10 @@ state BAR_FONT: font = string -> call cfg_bar_font($font); BAR +state BAR_SEPARATOR_SYMBOL: + separator = string + -> call cfg_bar_separator_symbol($separator); BAR + state BAR_BINDING_MODE_INDICATOR: value = word -> call cfg_bar_binding_mode_indicator($value); BAR diff --git a/src/config_directives.c b/src/config_directives.c index 80d7876b..c8b25c76 100644 --- a/src/config_directives.c +++ b/src/config_directives.c @@ -421,6 +421,11 @@ CFGFUN(bar_font, const char *font) { current_bar.font = sstrdup(font); } +CFGFUN(bar_separator_symbol, const char *separator) { + FREE(current_bar.separator_symbol); + current_bar.separator_symbol = sstrdup(separator); +} + CFGFUN(bar_mode, const char *mode) { current_bar.mode = (strcmp(mode, "dock") == 0 ? M_DOCK : (strcmp(mode, "hide") == 0 ? M_HIDE : M_INVISIBLE)); } diff --git a/src/ipc.c b/src/ipc.c index acd2267b..ea6a7de9 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -594,6 +594,11 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) { YSTR_IF_SET(status_command); YSTR_IF_SET(font); + if (config->separator_symbol) { + ystr("separator_symbol"); + ystr(config->separator_symbol); + } + ystr("workspace_buttons"); y(bool, !config->hide_workspace_buttons); diff --git a/testcases/t/201-config-parser.t b/testcases/t/201-config-parser.t index 9643aa42..1e91d47f 100644 --- a/testcases/t/201-config-parser.t +++ b/testcases/t/201-config-parser.t @@ -647,7 +647,7 @@ EOT $expected = <<'EOT'; cfg_bar_output(LVDS-1) -ERROR: CONFIG: Expected one of these tokens: , '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'hidden_state', 'id', 'modifier', 'wheel_up_cmd', 'wheel_down_cmd', 'position', 'output', 'tray_output', 'font', 'binding_mode_indicator', 'workspace_buttons', 'strip_workspace_numbers', 'verbose', 'colors', '}' +ERROR: CONFIG: Expected one of these tokens: , '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'hidden_state', 'id', 'modifier', 'wheel_up_cmd', 'wheel_down_cmd', 'position', 'output', 'tray_output', 'font', 'separator_symbol', 'binding_mode_indicator', 'workspace_buttons', 'strip_workspace_numbers', 'verbose', 'colors', '}' ERROR: CONFIG: (in file ) ERROR: CONFIG: Line 1: bar { ERROR: CONFIG: Line 2: output LVDS-1 From fa93f275bb03462e6d236fd50da0b96ddbd690da Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 25 Mar 2015 22:47:23 +0100 Subject: [PATCH 75/99] =?UTF-8?q?Don=E2=80=99t=20focus=20placeholder=20win?= =?UTF-8?q?dows.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/restore_layout.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/restore_layout.c b/src/restore_layout.c index c6a87f06..53a70d69 100644 --- a/src/restore_layout.c +++ b/src/restore_layout.c @@ -196,6 +196,11 @@ static void open_placeholder_window(Con *con) { config.client.placeholder.background, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY, }); + /* Make i3 not focus this window. */ + xcb_icccm_wm_hints_t hints; + xcb_icccm_wm_hints_set_none(&hints); + xcb_icccm_wm_hints_set_input(&hints, 0); + xcb_icccm_set_wm_hints(restore_conn, placeholder, &hints); /* Set the same name as was stored in the layout file. While perhaps * slightly confusing in the first instant, this brings additional * clarity to which placeholder is waiting for which actual window. */ From 3f3b2d9a3fde5cc3d206d23cad0d97885341c068 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 25 Mar 2015 19:17:06 -0400 Subject: [PATCH 76/99] i3bar: reconfigure strut partial on reload Strut partial tells i3 where to reserve space for i3bar. It is affected by the `position` bar config directive. --- i3bar/src/xcb.c | 92 ++++++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 205e277a..81f0bb4a 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -1525,6 +1525,50 @@ void realloc_sl_buffer(void) { } } +/* Strut partial tells i3 where to reserve space for i3bar. This is determined + * by the `position` bar config directive. */ +xcb_void_cookie_t config_strut_partial(i3_output *output) { + /* 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; + memset(&strut_partial, 0, sizeof(strut_partial)); + + switch (config.position) { + case POS_NONE: + break; + case POS_TOP: + strut_partial.top = bar_height; + strut_partial.top_start_x = output->rect.x; + strut_partial.top_end_x = output->rect.x + output->rect.w; + break; + case POS_BOT: + strut_partial.bottom = bar_height; + strut_partial.bottom_start_x = output->rect.x; + strut_partial.bottom_end_x = output->rect.x + output->rect.w; + break; + } + return xcb_change_property(xcb_connection, + XCB_PROP_MODE_REPLACE, + output->bar, + atoms[_NET_WM_STRUT_PARTIAL], + XCB_ATOM_CARDINAL, + 32, + 12, + &strut_partial); +} + /* * Reconfigure all bars and create new bars for recently activated outputs * @@ -1624,49 +1668,7 @@ void reconfig_windows(bool redraw_bars) { 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; - memset(&strut_partial, 0, sizeof(strut_partial)); - - switch (config.position) { - case POS_NONE: - break; - case POS_TOP: - strut_partial.top = bar_height; - strut_partial.top_start_x = walk->rect.x; - strut_partial.top_end_x = walk->rect.x + walk->rect.w; - break; - case POS_BOT: - strut_partial.bottom = bar_height; - 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); + xcb_void_cookie_t strut_cookie = config_strut_partial(walk); /* We also want a graphics context for the bars (it defines the properties * with which we draw to them) */ @@ -1726,6 +1728,9 @@ void reconfig_windows(bool redraw_bars) { values[3] = bar_height; values[4] = XCB_STACK_MODE_ABOVE; + DLOG("Reconfiguring strut partial property for output %s\n", walk->name); + xcb_void_cookie_t strut_cookie = config_strut_partial(walk); + DLOG("Destroying buffer for output %s\n", walk->name); xcb_free_pixmap(xcb_connection, walk->buffer); @@ -1774,6 +1779,7 @@ void reconfig_windows(bool redraw_bars) { if (xcb_request_failed(cfg_cookie, "Could not reconfigure window") || xcb_request_failed(chg_cookie, "Could not change window") || xcb_request_failed(pm_cookie, "Could not create pixmap") || + xcb_request_failed(strut_cookie, "Could not set strut") || (redraw_bars && (xcb_request_failed(umap_cookie, "Could not unmap window") || (config.hide_on_modifier == M_DOCK && xcb_request_failed(map_cookie, "Could not map window"))))) { exit(EXIT_FAILURE); From 49510427b945f3b9014254d129ba4f48d01e96a5 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 25 Mar 2015 19:45:42 -0400 Subject: [PATCH 77/99] Handle strut partial changes for dock clients Handle changes to the property _NET_WM_STRUT_PARTIAL by reallocating screen space in the dock area when the dock client requests a new position. This will allow changes to the bar config directive `position` to be effective on the `reload` command. fixes #1294 --- src/handlers.c | 85 +++++++++++++++++++++++++++++++++++++++++- testcases/t/102-dock.t | 16 ++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/src/handlers.c b/src/handlers.c index 0cd397fd..4b5c87d4 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -1159,6 +1159,87 @@ static bool handle_class_change(void *data, xcb_connection_t *conn, uint8_t stat return true; } +/* + * Handles the _NET_WM_STRUT_PARTIAL property for allocating space for dock clients. + * + */ +static bool handle_strut_partial_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, + xcb_atom_t name, xcb_get_property_reply_t *prop) { + DLOG("strut partial change for window 0x%08x\n", window); + + Con *con; + if ((con = con_by_window_id(window)) == NULL || con->window == NULL) { + return false; + } + + if (prop == NULL) { + xcb_generic_error_t *err = NULL; + xcb_get_property_cookie_t strut_cookie = xcb_get_property(conn, false, window, A__NET_WM_STRUT_PARTIAL, + XCB_GET_PROPERTY_TYPE_ANY, 0, UINT32_MAX); + prop = xcb_get_property_reply(conn, strut_cookie, &err); + + if (err != NULL) { + DLOG("got error when getting strut partial property: %d\n", err->error_code); + free(err); + return false; + } + + if (prop == NULL) { + return false; + } + } + + DLOG("That is con %p / %s\n", con, con->name); + + window_update_strut_partial(con->window, prop); + + /* we only handle this change for dock clients */ + if (con->parent == NULL || con->parent->type != CT_DOCKAREA) { + return true; + } + + Con *search_at = croot; + Con *output = con_get_output(con); + if (output != NULL) { + DLOG("Starting search at output %s\n", output->name); + search_at = output; + } + + /* find out the desired position of this dock window */ + if (con->window->reserved.top > 0 && con->window->reserved.bottom == 0) { + DLOG("Top dock client\n"); + con->window->dock = W_DOCK_TOP; + } else if (con->window->reserved.top == 0 && con->window->reserved.bottom > 0) { + DLOG("Bottom dock client\n"); + con->window->dock = W_DOCK_BOTTOM; + } else { + DLOG("Ignoring invalid reserved edges (_NET_WM_STRUT_PARTIAL), using position as fallback:\n"); + if (con->geometry.y < (int16_t)(search_at->rect.height / 2)) { + DLOG("geom->y = %d < rect.height / 2 = %d, it is a top dock client\n", + con->geometry.y, (search_at->rect.height / 2)); + con->window->dock = W_DOCK_TOP; + } else { + DLOG("geom->y = %d >= rect.height / 2 = %d, it is a bottom dock client\n", + con->geometry.y, (search_at->rect.height / 2)); + con->window->dock = W_DOCK_BOTTOM; + } + } + + /* find the dockarea */ + Con *dockarea = con_for_window(search_at, con->window, NULL); + assert(dockarea != NULL); + + /* attach the dock to the dock area */ + con_detach(con); + con->parent = dockarea; + TAILQ_INSERT_HEAD(&(dockarea->focus_head), con, focused); + TAILQ_INSERT_HEAD(&(dockarea->nodes_head), con, nodes); + + tree_render(); + + return true; +} + /* Returns false if the event could not be processed (e.g. the window could not * be found), true otherwise */ typedef bool (*cb_property_handler_t)(void *data, xcb_connection_t *c, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *property); @@ -1177,7 +1258,8 @@ static struct property_handler_t property_handlers[] = { {0, UINT_MAX, handle_clientleader_change}, {0, UINT_MAX, handle_transient_for}, {0, 128, handle_windowrole_change}, - {0, 128, handle_class_change}}; + {0, 128, handle_class_change}, + {0, UINT_MAX, handle_strut_partial_change}}; #define NUM_HANDLERS (sizeof(property_handlers) / sizeof(struct property_handler_t)) /* @@ -1196,6 +1278,7 @@ void property_handlers_init(void) { property_handlers[5].atom = XCB_ATOM_WM_TRANSIENT_FOR; property_handlers[6].atom = A_WM_WINDOW_ROLE; property_handlers[7].atom = XCB_ATOM_WM_CLASS; + property_handlers[8].atom = A__NET_WM_STRUT_PARTIAL; } static void property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom) { diff --git a/testcases/t/102-dock.t b/testcases/t/102-dock.t index 1bac40f0..bb9c71c9 100644 --- a/testcases/t/102-dock.t +++ b/testcases/t/102-dock.t @@ -143,6 +143,22 @@ wait_for_map $window; @docked = get_dock_clients('top'); is(@docked, 1, 'dock client on top'); +# now change strut_partial to reserve space on the bottom and the dock should +# be moved to the bottom dock area +$x->change_property( + PROP_MODE_REPLACE, + $window->id, + $atomname->id, + $atomtype->id, + 32, # 32 bit integer + 12, + pack('L12', 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 1280, 0) +); + +sync_with_i3; +@docked = get_dock_clients('bottom'); +is(@docked, 1, 'dock client on bottom'); + $window->destroy; wait_for_unmap $window; From ebf594145611cc6ccec1df6847b63379d57a6491 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Thu, 26 Mar 2015 09:19:15 +0100 Subject: [PATCH 78/99] debian: promote suggests to recommends to install a terminal emulator fixes #1587 --- debian/control | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/debian/control b/debian/control index cc9660f7..52fb1538 100644 --- a/debian/control +++ b/debian/control @@ -40,8 +40,7 @@ Package: i3-wm Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, x11-utils Provides: x-window-manager -Suggests: rxvt-unicode | x-terminal-emulator -Recommends: xfonts-base, fonts-dejavu-core, libanyevent-i3-perl (>= 0.12), libjson-xs-perl +Recommends: xfonts-base, fonts-dejavu-core, libanyevent-i3-perl (>= 0.12), libjson-xs-perl, rxvt-unicode | x-terminal-emulator Description: improved dynamic tiling window manager Key features of i3 are good documentation, reasonable defaults (changeable in a simple configuration file) and good multi-monitor support. The user From d97aeffcd4761a118d11871a9b5b88718e90932d Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Thu, 26 Mar 2015 09:21:40 +0100 Subject: [PATCH 79/99] i3-sensible-terminal: launch i3-nagbar when no terminal is found fixes #1587 --- i3-sensible-terminal | 2 ++ 1 file changed, 2 insertions(+) diff --git a/i3-sensible-terminal b/i3-sensible-terminal index 747a9280..dd4b075a 100755 --- a/i3-sensible-terminal +++ b/i3-sensible-terminal @@ -13,3 +13,5 @@ for terminal in $TERMINAL x-terminal-emulator urxvt rxvt terminator Eterm aterm exec $terminal "$@" fi done + +i3-nagbar -m 'i3-sensible-terminal could not find a terminal emulator. Please install one.' From d91bf5d4918808ec4310411a08b08eead1e8c4f3 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Thu, 26 Mar 2015 09:44:46 +0100 Subject: [PATCH 80/99] make i3-nagbar work properly on hi-dpi displays --- i3-nagbar/main.c | 56 +++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c index b501ff6a..16559c96 100644 --- a/i3-nagbar/main.c +++ b/i3-nagbar/main.c @@ -131,7 +131,7 @@ static void handle_button_release(xcb_connection_t *conn, xcb_button_release_eve printf("button released on x = %d, y = %d\n", event->event_x, event->event_y); /* If the user hits the close button, we exit(0) */ - if (event->event_x >= (rect.width - 32)) + if (event->event_x >= (rect.width - logical_px(32))) exit(0); button_t *button = get_button_at(event->event_x, event->event_y); if (!button) @@ -194,15 +194,17 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { /* restore font color */ set_font_colors(pixmap_gc, color_text, color_background); draw_text(prompt, pixmap, pixmap_gc, - 4 + 4, 4 + 4, rect.width - 4 - 4); + logical_px(4) + logical_px(4), + logical_px(4) + logical_px(4), + rect.width - logical_px(4) - logical_px(4)); /* render close button */ const char *close_button_label = "X"; - int line_width = 4; + int line_width = logical_px(4); /* set width to the width of the label */ int w = predict_text_width(i3string_from_utf8(close_button_label)); /* account for left/right padding, which seems to be set to 8px (total) below */ - w += 8; + w += logical_px(8); int y = rect.width; uint32_t values[3]; values[0] = color_button_background; @@ -216,19 +218,21 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { xcb_point_t points[] = { {y - w - (2 * line_width), line_width / 2}, {y - (line_width / 2), line_width / 2}, - {y - (line_width / 2), (rect.height - (line_width / 2)) - 2}, - {y - w - (2 * line_width), (rect.height - (line_width / 2)) - 2}, + {y - (line_width / 2), (rect.height - (line_width / 2)) - logical_px(2)}, + {y - w - (2 * line_width), (rect.height - (line_width / 2)) - logical_px(2)}, {y - w - (2 * line_width), line_width / 2}}; xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 5, points); values[0] = 1; set_font_colors(pixmap_gc, color_text, color_button_background); /* the x term here seems to set left/right padding */ - draw_text_ascii(close_button_label, pixmap, pixmap_gc, y - w - line_width + w / 2 - 4, - 4 + 4 - 1, rect.width - y + w + line_width - w / 2 + 4); + draw_text_ascii(close_button_label, pixmap, pixmap_gc, + y - w - line_width + w / 2 - logical_px(4), + logical_px(4) + logical_px(3), + rect.width - y + w + line_width - w / 2 + logical_px(4)); y -= w; - y -= 20; + y -= logical_px(20); /* render custom buttons */ line_width = 1; @@ -236,21 +240,21 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { /* set w to the width of the label */ w = predict_text_width(buttons[c].label); /* account for left/right padding, which seems to be set to 12px (total) below */ - w += 12; - y -= 30; + w += logical_px(12); + y -= logical_px(30); xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_button_background}); - close = (xcb_rectangle_t){y - w - (2 * line_width), 2, w + (2 * line_width), rect.height - 6}; + close = (xcb_rectangle_t){y - w - (2 * line_width), logical_px(2), w + (2 * line_width), rect.height - logical_px(6)}; xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close); xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_border}); buttons[c].x = y - w - (2 * line_width); buttons[c].width = w; xcb_point_t points2[] = { - {y - w - (2 * line_width), (line_width / 2) + 2}, - {y - (line_width / 2), (line_width / 2) + 2}, - {y - (line_width / 2), (rect.height - 4 - (line_width / 2))}, - {y - w - (2 * line_width), (rect.height - 4 - (line_width / 2))}, - {y - w - (2 * line_width), (line_width / 2) + 2}}; + {y - w - (2 * line_width), (line_width / 2) + logical_px(2)}, + {y - (line_width / 2), (line_width / 2) + logical_px(2)}, + {y - (line_width / 2), (rect.height - logical_px(4) - (line_width / 2))}, + {y - w - (2 * line_width), (rect.height - logical_px(4) - (line_width / 2))}, + {y - w - (2 * line_width), (line_width / 2) + logical_px(2)}}; xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 5, points2); values[0] = color_text; @@ -258,13 +262,15 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { set_font_colors(pixmap_gc, color_text, color_button_background); /* the x term seems to set left/right padding */ draw_text(buttons[c].label, pixmap, pixmap_gc, - y - w - line_width + 6, 4 + 3, rect.width - y + w + line_width - 6); + y - w - line_width + logical_px(6), + logical_px(4) + logical_px(3), + rect.width - y + w + line_width - logical_px(6)); y -= w; } /* border line at the bottom */ - line_width = 2; + line_width = logical_px(2); values[0] = color_border_bottom; values[1] = line_width; xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND | XCB_GC_LINE_WIDTH, values); @@ -408,10 +414,10 @@ int main(int argc, char *argv[]) { xcb_create_window( conn, XCB_COPY_FROM_PARENT, - win, /* the window id */ - root, /* parent == root */ - 50, 50, 500, font.height + 8 + 8 /* 8 px padding */, /* dimensions */ - 0, /* x11 border = 0, we draw our own */ + win, /* the window id */ + root, /* parent == root */ + 50, 50, 500, font.height + logical_px(8) + logical_px(8) /* 8 px padding */, /* dimensions */ + 0, /* x11 border = 0, we draw our own */ XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */ XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, @@ -465,7 +471,7 @@ int main(int argc, char *argv[]) { } __attribute__((__packed__)) strut_partial; memset(&strut_partial, 0, sizeof(strut_partial)); - strut_partial.top = font.height + 6; + strut_partial.top = font.height + logical_px(6); strut_partial.top_start_x = 0; strut_partial.top_end_x = 800; @@ -481,7 +487,7 @@ int main(int argc, char *argv[]) { /* Create pixmap */ pixmap = xcb_generate_id(conn); pixmap_gc = xcb_generate_id(conn); - xcb_create_pixmap(conn, root_screen->root_depth, pixmap, win, 500, font.height + 8); + xcb_create_pixmap(conn, root_screen->root_depth, pixmap, win, 500, font.height + logical_px(8)); xcb_create_gc(conn, pixmap_gc, pixmap, 0, 0); /* Grab the keyboard to get all input */ From 414290df56bed1e99fe1433f85460fded8de36d3 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Thu, 26 Mar 2015 09:58:10 +0100 Subject: [PATCH 81/99] make i3-config-wizard work properly on hi-dpi displays --- i3-config-wizard/main.c | 60 ++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/i3-config-wizard/main.c b/i3-config-wizard/main.c index 5a855c40..d94ad96f 100644 --- a/i3-config-wizard/main.c +++ b/i3-config-wizard/main.c @@ -493,7 +493,7 @@ static char *resolve_tilde(const char *path) { */ static int handle_expose() { /* re-draw the background */ - xcb_rectangle_t border = {0, 0, 300, (15 * font.height) + 8}; + xcb_rectangle_t border = {0, 0, logical_px(300), (logical_px(15) * font.height) + logical_px(8)}; xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){get_colorpixel("#000000")}); xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border); @@ -501,62 +501,62 @@ static int handle_expose() { #define txt(x, row, text) \ draw_text_ascii(text, pixmap, pixmap_gc, \ - x, (row - 1) * font.height + 4, 300 - x * 2) + x, (row - 1) * font.height + logical_px(4), logical_px(500) - x * 2) if (current_step == STEP_WELCOME) { /* restore font color */ set_font_colors(pixmap_gc, get_colorpixel("#FFFFFF"), get_colorpixel("#000000")); - txt(10, 2, "You have not configured i3 yet."); - txt(10, 3, "Do you want me to generate ~/.i3/config?"); - txt(85, 5, "Yes, generate ~/.i3/config"); - txt(85, 7, "No, I will use the defaults"); + txt(logical_px(10), 2, "You have not configured i3 yet."); + txt(logical_px(10), 3, "Do you want me to generate ~/.i3/config?"); + txt(logical_px(85), 5, "Yes, generate ~/.i3/config"); + txt(logical_px(85), 7, "No, I will use the defaults"); /* green */ set_font_colors(pixmap_gc, get_colorpixel("#00FF00"), get_colorpixel("#000000")); - txt(25, 5, ""); + txt(logical_px(25), 5, ""); /* red */ set_font_colors(pixmap_gc, get_colorpixel("#FF0000"), get_colorpixel("#000000")); - txt(31, 7, ""); + txt(logical_px(31), 7, ""); } if (current_step == STEP_GENERATE) { set_font_colors(pixmap_gc, get_colorpixel("#FFFFFF"), get_colorpixel("#000000")); - txt(10, 2, "Please choose either:"); - txt(85, 4, "Win as default modifier"); - txt(85, 5, "Alt as default modifier"); - txt(10, 7, "Afterwards, press"); - txt(85, 9, "to write ~/.i3/config"); - txt(85, 10, "to abort"); + txt(logical_px(10), 2, "Please choose either:"); + txt(logical_px(85), 4, "Win as default modifier"); + txt(logical_px(85), 5, "Alt as default modifier"); + txt(logical_px(10), 7, "Afterwards, press"); + txt(logical_px(85), 9, "to write ~/.i3/config"); + txt(logical_px(85), 10, "to abort"); /* the not-selected modifier */ if (modifier == MOD_Mod4) - txt(31, 5, ""); + txt(logical_px(31), 5, ""); else - txt(31, 4, ""); + txt(logical_px(31), 4, ""); /* the selected modifier */ set_font(&bold_font); set_font_colors(pixmap_gc, get_colorpixel("#FFFFFF"), get_colorpixel("#000000")); if (modifier == MOD_Mod4) - txt(10, 4, "-> "); + txt(logical_px(10), 4, "-> "); else - txt(10, 5, "-> "); + txt(logical_px(10), 5, "-> "); /* green */ set_font(&font); set_font_colors(pixmap_gc, get_colorpixel("#00FF00"), get_colorpixel("#000000")); - txt(25, 9, ""); + txt(logical_px(25), 9, ""); /* red */ set_font_colors(pixmap_gc, get_colorpixel("#FF0000"), get_colorpixel("#000000")); - txt(31, 10, ""); + txt(logical_px(31), 10, ""); } /* Copy the contents of the pixmap to the real window */ - xcb_copy_area(conn, pixmap, win, pixmap_gc, 0, 0, 0, 0, /* */ 500, 500); + xcb_copy_area(conn, pixmap, win, pixmap_gc, 0, 0, 0, 0, logical_px(500), logical_px(500)); xcb_flush(conn); return 1; @@ -637,14 +637,14 @@ static void handle_button_press(xcb_button_press_event_t *event) { if (current_step != STEP_GENERATE) return; - if (event->event_x >= 32 && event->event_x <= 68 && - event->event_y >= 45 && event->event_y <= 54) { + if (event->event_x >= logical_px(32) && event->event_x <= logical_px(68) && + event->event_y >= logical_px(45) && event->event_y <= logical_px(54)) { modifier = MOD_Mod4; handle_expose(); } - if (event->event_x >= 32 && event->event_x <= 68 && - event->event_y >= 56 && event->event_y <= 70) { + if (event->event_x >= logical_px(32) && event->event_x <= logical_px(68) && + event->event_y >= logical_px(56) && event->event_y <= logical_px(70)) { modifier = MOD_Mod1; handle_expose(); } @@ -863,10 +863,10 @@ int main(int argc, char *argv[]) { xcb_create_window( conn, XCB_COPY_FROM_PARENT, - win, /* the window id */ - root, /* parent == root */ - 490, 297, 300, 205, /* dimensions */ - 0, /* X11 border = 0, we draw our own */ + win, /* the window id */ + root, /* parent == root */ + logical_px(490), logical_px(297), logical_px(300), logical_px(205), /* dimensions */ + 0, /* X11 border = 0, we draw our own */ XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */ XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, @@ -914,7 +914,7 @@ int main(int argc, char *argv[]) { /* Create pixmap */ pixmap = xcb_generate_id(conn); pixmap_gc = xcb_generate_id(conn); - xcb_create_pixmap(conn, root_screen->root_depth, pixmap, win, 500, 500); + xcb_create_pixmap(conn, root_screen->root_depth, pixmap, win, logical_px(500), logical_px(500)); xcb_create_gc(conn, pixmap_gc, pixmap, 0, 0); /* Grab the keyboard to get all input */ From 7d49f55c55143e1bb9b916a3d2d283b997b36e80 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Thu, 26 Mar 2015 10:03:14 +0100 Subject: [PATCH 82/99] make i3-input work properly on hi-dpi displays --- i3-input/main.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/i3-input/main.c b/i3-input/main.c index 7d523190..1f9cfe04 100644 --- a/i3-input/main.c +++ b/i3-input/main.c @@ -129,7 +129,8 @@ static int handle_expose(void *data, xcb_connection_t *conn, xcb_expose_event_t printf("expose!\n"); /* re-draw the background */ - xcb_rectangle_t border = {0, 0, 500, font.height + 8}, inner = {2, 2, 496, font.height + 8 - 4}; + xcb_rectangle_t border = {0, 0, logical_px(500), font.height + logical_px(8)}, + inner = {logical_px(2), logical_px(2), logical_px(496), font.height + logical_px(8) - logical_px(4)}; xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){get_colorpixel("#FF0000")}); xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border); xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){get_colorpixel("#000000")}); @@ -140,17 +141,17 @@ static int handle_expose(void *data, xcb_connection_t *conn, xcb_expose_event_t /* draw the prompt … */ if (prompt != NULL) { - draw_text(prompt, pixmap, pixmap_gc, 4, 4, 492); + draw_text(prompt, pixmap, pixmap_gc, logical_px(4), logical_px(4), logical_px(492)); } /* … and the text */ if (input_position > 0) { i3String *input = i3string_from_ucs2(glyphs_ucs, input_position); - draw_text(input, pixmap, pixmap_gc, prompt_offset + 4, 4, 492); + draw_text(input, pixmap, pixmap_gc, prompt_offset + logical_px(4), logical_px(4), logical_px(492)); i3string_free(input); } /* Copy the contents of the pixmap to the real window */ - xcb_copy_area(conn, pixmap, win, pixmap_gc, 0, 0, 0, 0, /* */ 500, font.height + 8); + xcb_copy_area(conn, pixmap, win, pixmap_gc, 0, 0, 0, 0, logical_px(500), font.height + logical_px(8)); xcb_flush(conn); return 1; @@ -234,6 +235,9 @@ static void finish_input() { static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press_event_t *event) { printf("Keypress %d, state raw = %d\n", event->detail, event->state); + // TODO: port the input handling code from i3lock once libxkbcommon ≥ 0.5.0 + // is available in distros. + /* See the documentation of xcb_key_symbols_get_keysym for this one. * Basically: We get either col 0 or col 1, depending on whether shift is * pressed. */ @@ -403,10 +407,10 @@ int main(int argc, char *argv[]) { xcb_create_window( conn, XCB_COPY_FROM_PARENT, - win, /* the window id */ - root, /* parent == root */ - 50, 50, 500, font.height + 8, /* dimensions */ - 0, /* X11 border = 0, we draw our own */ + win, /* the window id */ + root, /* parent == root */ + logical_px(50), logical_px(50), logical_px(500), font.height + logical_px(8), /* dimensions */ + 0, /* X11 border = 0, we draw our own */ XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */ XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, @@ -421,7 +425,7 @@ int main(int argc, char *argv[]) { /* Create pixmap */ pixmap = xcb_generate_id(conn); pixmap_gc = xcb_generate_id(conn); - xcb_create_pixmap(conn, root_screen->root_depth, pixmap, win, 500, font.height + 8); + xcb_create_pixmap(conn, root_screen->root_depth, pixmap, win, logical_px(500), font.height + logical_px(8)); xcb_create_gc(conn, pixmap_gc, pixmap, 0, 0); /* Set input focus (we have override_redirect=1, so the wm will not do From ad31b13cb66f65431189f0ade323b9634cc26e8c Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Thu, 26 Mar 2015 10:03:30 +0100 Subject: [PATCH 83/99] update default fonts for i3-{input,config-wizard,nagbar} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We’ve done this a while ago in i3.config itself, but the tools in question aren’t hooked up to that setting, so we need to do it here as well. --- i3-config-wizard/main.c | 4 ++-- i3-input/main.c | 2 +- i3-nagbar/main.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/i3-config-wizard/main.c b/i3-config-wizard/main.c index d94ad96f..f052d6d5 100644 --- a/i3-config-wizard/main.c +++ b/i3-config-wizard/main.c @@ -760,8 +760,8 @@ static void finish() { int main(int argc, char *argv[]) { config_path = resolve_tilde("~/.i3/config"); socket_path = getenv("I3SOCK"); - char *pattern = "-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1"; - char *patternbold = "-misc-fixed-bold-r-normal--13-120-75-75-C-70-iso10646-1"; + char *pattern = "pango:monospace 8"; + char *patternbold = "pango:monospace bold 8"; int o, option_index = 0; static struct option long_options[] = { diff --git a/i3-input/main.c b/i3-input/main.c index 1f9cfe04..996fc0ea 100644 --- a/i3-input/main.c +++ b/i3-input/main.c @@ -317,7 +317,7 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press int main(int argc, char *argv[]) { format = strdup("%s"); socket_path = getenv("I3SOCK"); - char *pattern = sstrdup("-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1"); + char *pattern = sstrdup("pango:monospace 8"); int o, option_index = 0; static struct option long_options[] = { diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c index 16559c96..805066f8 100644 --- a/i3-nagbar/main.c +++ b/i3-nagbar/main.c @@ -322,7 +322,7 @@ int main(int argc, char *argv[]) { argv0 = argv[0]; - char *pattern = sstrdup("-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1"); + char *pattern = sstrdup("pango:monospace 8"); int o, option_index = 0; enum { TYPE_ERROR = 0, TYPE_WARNING = 1 } bar_type = TYPE_ERROR; From 4e871c75f9b3ed4fd91cf534bac218a339f313ea Mon Sep 17 00:00:00 2001 From: shdown Date: Wed, 25 Mar 2015 22:55:26 +0300 Subject: [PATCH 84/99] Add tests for backslash unescaping --- testcases/t/187-commands-parser.t | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/testcases/t/187-commands-parser.t b/testcases/t/187-commands-parser.t index 5ee94f87..6d67731a 100644 --- a/testcases/t/187-commands-parser.t +++ b/testcases/t/187-commands-parser.t @@ -156,7 +156,7 @@ is(parser_calls('move something to somewhere'), 'error for unknown literal ok'); ################################################################################ -# 3: Verify that escaping of double quotes works correctly +# 3: Verify that escaping works correctly ################################################################################ is(parser_calls('workspace "foo"'), @@ -171,6 +171,18 @@ is(parser_calls('workspace "foo \"bar"'), 'cmd_workspace_name(foo "bar)', 'Command with escaped double quotes ok'); +is(parser_calls('workspace "foo \\'), + 'cmd_workspace_name(foo \\)', + 'Command with single backslash in the end ok'); + +is(parser_calls('workspace "foo\\\\bar"'), + 'cmd_workspace_name(foo\\bar)', + 'Command with escaped backslashes ok'); + +is(parser_calls('workspace "foo\\\\\\"bar"'), + 'cmd_workspace_name(foo\\"bar)', + 'Command with escaped double quotes after escaped backslashes ok'); + ################################################################################ # 4: Verify that resize commands with a "px or ppt"-construction are parsed # correctly From 6adc7e8bfbdd6c6b646bd893eb6439090e697cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Thu, 26 Mar 2015 19:27:28 +0100 Subject: [PATCH 85/99] Return in child parsing as soon as the match was made. As soon as we found the current key for which the value should be handled we can return from the function to save some string comparisons. --- i3bar/src/child.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 3de754e7..20fbd9b0 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -181,10 +181,13 @@ static int stdin_boolean(void *context, int val) { parser_ctx *ctx = context; if (strcasecmp(ctx->last_map_key, "urgent") == 0) { ctx->block.urgent = val; + return 1; } if (strcasecmp(ctx->last_map_key, "separator") == 0) { ctx->block.no_separator = !val; + return 1; } + return 1; } @@ -192,15 +195,19 @@ static int stdin_string(void *context, const unsigned char *val, size_t len) { parser_ctx *ctx = context; if (strcasecmp(ctx->last_map_key, "full_text") == 0) { ctx->block.full_text = i3string_from_markup_with_length((const char *)val, len); + return 1; } if (strcasecmp(ctx->last_map_key, "short_text") == 0) { ctx->block.short_text = i3string_from_markup_with_length((const char *)val, len); + return 1; } if (strcasecmp(ctx->last_map_key, "color") == 0) { sasprintf(&(ctx->block.color), "%.*s", len, val); + return 1; } if (strcasecmp(ctx->last_map_key, "markup") == 0) { ctx->block.is_markup = (len == strlen("pango") && !strncasecmp((const char *)val, "pango", strlen("pango"))); + return 1; } if (strcasecmp(ctx->last_map_key, "align") == 0) { if (len == strlen("center") && !strncmp((const char *)val, "center", strlen("center"))) { @@ -210,24 +217,30 @@ static int stdin_string(void *context, const unsigned char *val, size_t len) { } else { ctx->block.align = ALIGN_LEFT; } - } else if (strcasecmp(ctx->last_map_key, "min_width") == 0) { + return 1; + } + if (strcasecmp(ctx->last_map_key, "min_width") == 0) { char *copy = (char *)malloc(len + 1); strncpy(copy, (const char *)val, len); copy[len] = 0; ctx->block.min_width_str = copy; + return 1; } if (strcasecmp(ctx->last_map_key, "name") == 0) { char *copy = (char *)malloc(len + 1); strncpy(copy, (const char *)val, len); copy[len] = 0; ctx->block.name = copy; + return 1; } if (strcasecmp(ctx->last_map_key, "instance") == 0) { char *copy = (char *)malloc(len + 1); strncpy(copy, (const char *)val, len); copy[len] = 0; ctx->block.instance = copy; + return 1; } + return 1; } @@ -235,10 +248,13 @@ static int stdin_integer(void *context, long long val) { parser_ctx *ctx = context; if (strcasecmp(ctx->last_map_key, "min_width") == 0) { ctx->block.min_width = (uint32_t)val; + return 1; } if (strcasecmp(ctx->last_map_key, "separator_block_width") == 0) { ctx->block.sep_block_width = (uint32_t)val; + return 1; } + return 1; } From e0332b6f0799834238676307c145fe72d477dd72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 25 Mar 2015 17:50:06 +0100 Subject: [PATCH 86/99] Allow nop command without argument fixes #1318 --- docs/userguide | 21 +++++++++++++++++++++ parser-specs/commands.spec | 2 ++ 2 files changed, 23 insertions(+) diff --git a/docs/userguide b/docs/userguide index 45b05a06..8528d684 100644 --- a/docs/userguide +++ b/docs/userguide @@ -2011,6 +2011,27 @@ bindsym $mod+minus scratchpad show bindsym mod4+s [title="^Sup ::"] scratchpad show ------------------------------------------------ +=== Nop + +There is a no operation command +nop+ which allows you to override default +behavior. This can be useful for, e.g., disabling a focus change on clicks with +the middle mouse button. + +The optional +comment+ argument is ignored, but will be printed to the log file +for debugging purposes. + +*Syntax*: +--------------- +nop [] +--------------- + +*Example*: +---------------------------------------------- +# Disable focus change for clicks on titlebars +# with the middle mouse button +bindsym button2 nop +---------------------------------------------- + === i3bar control There are two options in the configuration of each i3bar instance that can be diff --git a/parser-specs/commands.spec b/parser-specs/commands.spec index 82348df7..315a9218 100644 --- a/parser-specs/commands.spec +++ b/parser-specs/commands.spec @@ -353,6 +353,8 @@ state MODE: state NOP: comment = string -> call cmd_nop($comment) + end + -> call cmd_nop(NULL) state SCRATCHPAD: 'show' From beaf90494300640e3f811b3b99bb84296cd716e7 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Fri, 27 Mar 2015 19:00:32 -0400 Subject: [PATCH 87/99] i3bar: don't parse markup on statusline by default fixes #1565 --- docs/i3bar-protocol | 10 ++++------ i3bar/src/child.c | 3 --- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/docs/i3bar-protocol b/docs/i3bar-protocol index ccc76346..6cb04bf6 100644 --- a/docs/i3bar-protocol +++ b/docs/i3bar-protocol @@ -117,10 +117,8 @@ click_events:: === Blocks in detail full_text:: - The most simple block you can think of is one which just includes the - only required key, the +full_text+ key. i3bar will display the string - value parsed as - https://developer.gnome.org/pango/stable/PangoMarkupFormat.html[Pango markup]. + The +full_text+ will be displayed by i3bar on the status line. This is the + only required key. short_text:: Where appropriate, the +short_text+ (string) entry should also be provided. It will be used in case the status line needs to be shortened @@ -174,8 +172,8 @@ separator_block_width:: is 9 pixels), since the separator line is drawn in the middle. markup:: A string that indicates how the text of the block should be parsed. Set to - +"pango"+ to use https://developer.gnome.org/pango/stable/PangoMarkupFormat.html[Pango markup] - (default). Set to +"none"+ to not use any markup. + +"pango"+ to use https://developer.gnome.org/pango/stable/PangoMarkupFormat.html[Pango markup]. + Set to +"none"+ to not use any markup (default). If you want to put in your own entries into a block, prefix the key with an underscore (_). i3bar will ignore all keys it doesn’t understand, and prefixing diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 3de754e7..55dad274 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -164,9 +164,6 @@ static int stdin_start_map(void *context) { /* Default width of the separator block. */ ctx->block.sep_block_width = logical_px(9); - /* Use markup by default */ - ctx->block.is_markup = true; - return 1; } From 95fa121c56cc0de9cebdbe7cb3349d6b4fc56fc8 Mon Sep 17 00:00:00 2001 From: Deiz Date: Sat, 28 Mar 2015 12:56:36 -0400 Subject: [PATCH 88/99] Switch the wizard's modifier choice when up or down are pressed --- i3-config-wizard/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/i3-config-wizard/main.c b/i3-config-wizard/main.c index f052d6d5..b3404424 100644 --- a/i3-config-wizard/main.c +++ b/i3-config-wizard/main.c @@ -592,6 +592,12 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press finish(); } + /* Swap between modifiers when up or down is pressed. */ + if (sym == XK_Up || sym == XK_Down) { + modifier = (modifier == MOD_Mod1) ? MOD_Mod4 : MOD_Mod1; + handle_expose(); + } + /* cancel any time */ if (sym == XK_Escape) exit(0); From 0aa18a602d654dd04af103ea1d029fdd49969176 Mon Sep 17 00:00:00 2001 From: Deiz Date: Thu, 26 Mar 2015 15:34:37 -0400 Subject: [PATCH 89/99] Make wizard window size and click coordinates dependent on font This guarantees the whole visible area of the pixmap is reinitialized, and ensures that the click bounding boxes are properly aligned with the displayed text. --- i3-config-wizard/main.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/i3-config-wizard/main.c b/i3-config-wizard/main.c index b3404424..35770dc9 100644 --- a/i3-config-wizard/main.c +++ b/i3-config-wizard/main.c @@ -67,6 +67,11 @@ #include "xcb.h" #include "libi3.h" +#define row_y(row) \ + (((row)-1) * font.height + logical_px(4)) +#define window_height() \ + (row_y(15) + font.height) + enum { STEP_WELCOME, STEP_GENERATE } current_step = STEP_WELCOME; enum { MOD_Mod1, @@ -80,6 +85,7 @@ xcb_screen_t *root_screen; static xcb_get_modifier_mapping_reply_t *modmap_reply; static i3Font font; static i3Font bold_font; +static int char_width; static char *socket_path; static xcb_window_t win; static xcb_pixmap_t pixmap; @@ -493,7 +499,7 @@ static char *resolve_tilde(const char *path) { */ static int handle_expose() { /* re-draw the background */ - xcb_rectangle_t border = {0, 0, logical_px(300), (logical_px(15) * font.height) + logical_px(8)}; + xcb_rectangle_t border = {0, 0, logical_px(300), window_height()}; xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){get_colorpixel("#000000")}); xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border); @@ -501,7 +507,7 @@ static int handle_expose() { #define txt(x, row, text) \ draw_text_ascii(text, pixmap, pixmap_gc, \ - x, (row - 1) * font.height + logical_px(4), logical_px(500) - x * 2) + x, row_y(row), logical_px(500) - x * 2) if (current_step == STEP_WELCOME) { /* restore font color */ @@ -643,14 +649,16 @@ static void handle_button_press(xcb_button_press_event_t *event) { if (current_step != STEP_GENERATE) return; - if (event->event_x >= logical_px(32) && event->event_x <= logical_px(68) && - event->event_y >= logical_px(45) && event->event_y <= logical_px(54)) { + if (event->event_x < logical_px(32) || + event->event_x > (logical_px(32) + char_width * 5)) + return; + + if (event->event_y >= row_y(4) && event->event_y <= (row_y(4) + font.height)) { modifier = MOD_Mod4; handle_expose(); } - if (event->event_x >= logical_px(32) && event->event_x <= logical_px(68) && - event->event_y >= logical_px(56) && event->event_y <= logical_px(70)) { + if (event->event_y >= row_y(5) && event->event_y <= (row_y(5) + font.height)) { modifier = MOD_Mod1; handle_expose(); } @@ -864,6 +872,10 @@ int main(int argc, char *argv[]) { font = load_font(pattern, true); bold_font = load_font(patternbold, true); + /* Determine character width in the default font. */ + set_font(&font); + char_width = predict_text_width(i3string_from_utf8("a")); + /* Open an input window */ win = xcb_generate_id(conn); xcb_create_window( @@ -871,7 +883,7 @@ int main(int argc, char *argv[]) { XCB_COPY_FROM_PARENT, win, /* the window id */ root, /* parent == root */ - logical_px(490), logical_px(297), logical_px(300), logical_px(205), /* dimensions */ + logical_px(490), logical_px(297), logical_px(300), window_height(), /* dimensions */ 0, /* X11 border = 0, we draw our own */ XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */ From 42515308e72e4ea6f6b49508c1ba286263dded64 Mon Sep 17 00:00:00 2001 From: hwangcc Date: Tue, 24 Mar 2015 20:57:06 +0800 Subject: [PATCH 90/99] Add a safe wrapper for write and fix some warnings 1. Add a function writeall and make swrite wrap that function. Use either writeall or swrite, depending on whether we want to exit on errors or not. 2. Fix warnings when compiling with a higher optimisation level. (CFLAGS ?= -pipe -O3 -march=native -mtune=native -freorder-blocks-and-partition) Signed-off-by: hwangcc --- i3-dump-log/main.c | 11 +++-------- i3-nagbar/main.c | 4 +++- i3bar/src/child.c | 17 ++++++++++++++--- i3bar/src/ipc.c | 13 +------------ include/libi3.h | 14 ++++++++++++++ libi3/ipc_send_message.c | 30 ++++-------------------------- libi3/safewrappers.c | 29 +++++++++++++++++++++++++++++ src/click.c | 3 +++ src/config_parser.c | 13 ++++--------- src/load_layout.c | 2 +- src/sighandler.c | 10 ++++++++-- src/util.c | 24 ++++++------------------ 12 files changed, 90 insertions(+), 80 deletions(-) diff --git a/i3-dump-log/main.c b/i3-dump-log/main.c index 86b39338..1b0d593c 100644 --- a/i3-dump-log/main.c +++ b/i3-dump-log/main.c @@ -43,8 +43,7 @@ static int check_for_wrap(void) { * of the log. */ wrap_count = header->wrap_count; const int len = (logbuffer + header->offset_last_wrap) - walk; - if (write(STDOUT_FILENO, walk, len) != len) - err(EXIT_FAILURE, "write()"); + swrite(STDOUT_FILENO, walk, len); walk = logbuffer + sizeof(i3_shmlog_header); return 1; } @@ -52,12 +51,8 @@ static int check_for_wrap(void) { static void print_till_end(void) { check_for_wrap(); const int len = (logbuffer + header->offset_next_write) - walk; - const int n = write(STDOUT_FILENO, walk, len); - if (len != n) - err(EXIT_FAILURE, "write()"); - if (n > 0) { - walk += n; - } + swrite(STDOUT_FILENO, walk, len); + walk += len; } int main(int argc, char *argv[]) { diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c index b501ff6a..91de317f 100644 --- a/i3-nagbar/main.c +++ b/i3-nagbar/main.c @@ -164,7 +164,9 @@ static void handle_button_release(xcb_connection_t *conn, xcb_button_release_eve char *link_path; char *exe_path = get_exe_path(argv0); sasprintf(&link_path, "%s.nagbar_cmd", script_path); - symlink(exe_path, link_path); + if (symlink(exe_path, link_path) == -1) { + err(EXIT_FAILURE, "Failed to symlink %s to %s", link_path, exe_path); + } char *terminal_cmd; sasprintf(&terminal_cmd, "i3-sensible-terminal -e %s", link_path); diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 402e6351..818ce784 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -103,7 +103,7 @@ __attribute__((format(printf, 1, 2))) static void set_statusline_error(const cha char *message; va_list args; va_start(args, format); - vasprintf(&message, format, args); + (void)vasprintf(&message, format, args); struct status_block *err_block = scalloc(sizeof(struct status_block)); err_block->full_text = i3string_from_utf8("Error: "); @@ -455,11 +455,22 @@ void child_write_output(void) { if (child.click_events) { const unsigned char *output; size_t size; + ssize_t n; yajl_gen_get_buf(gen, &output, &size); - write(child_stdin, output, size); - write(child_stdin, "\n", 1); + + n = writeall(child_stdin, output, size); + if (n != -1) + n = writeall(child_stdin, "\n", 1); + yajl_gen_clear(gen); + + if (n == -1) { + child.click_events = false; + kill_child(); + set_statusline_error("child_write_output failed"); + draw_bars(false); + } } } diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index c6e67eb6..edc9d73f 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -296,18 +296,7 @@ int i3_send_msg(uint32_t type, const char *payload) { if (payload != NULL) strncpy(walk, payload, len); - uint32_t written = 0; - - while (to_write > 0) { - int n = write(i3_connection->fd, buffer + written, to_write); - if (n == -1) { - ELOG("write() failed: %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - - to_write -= n; - written += n; - } + swrite(i3_connection->fd, buffer, to_write); FREE(buffer); diff --git a/include/libi3.h b/include/libi3.h index c8d2e956..3a125827 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -134,6 +134,20 @@ char *sstrdup(const char *str); */ int sasprintf(char **strp, const char *fmt, ...); +/** + * Wrapper around correct write which returns -1 (meaning that + * write failed) or count (meaning that all bytes were written) + * + */ +ssize_t writeall(int fd, const void *buf, size_t count); + +/** + * Safe-wrapper around writeall which exits if it returns -1 (meaning that + * write failed) + * + */ +ssize_t swrite(int fd, const void *buf, size_t count); + /** * Build an i3String from an UTF-8 encoded string. * Returns the newly-allocated i3String. diff --git a/libi3/ipc_send_message.c b/libi3/ipc_send_message.c index 28cb8359..80709ed3 100644 --- a/libi3/ipc_send_message.c +++ b/libi3/ipc_send_message.c @@ -32,33 +32,11 @@ int ipc_send_message(int sockfd, const uint32_t message_size, .size = message_size, .type = message_type}; - size_t sent_bytes = 0; - int n = 0; + if (writeall(sockfd, ((void *)&header), sizeof(i3_ipc_header_t)) == -1) + return -1; - /* This first loop is basically unnecessary. No operating system has - * buffers which cannot fit 14 bytes into them, so the write() will only be - * called once. */ - while (sent_bytes < sizeof(i3_ipc_header_t)) { - if ((n = write(sockfd, ((void *)&header) + sent_bytes, sizeof(i3_ipc_header_t) - sent_bytes)) == -1) { - if (errno == EAGAIN) - continue; - return -1; - } - - sent_bytes += n; - } - - sent_bytes = 0; - - while (sent_bytes < message_size) { - if ((n = write(sockfd, payload + sent_bytes, message_size - sent_bytes)) == -1) { - if (errno == EAGAIN) - continue; - return -1; - } - - sent_bytes += n; - } + if (writeall(sockfd, payload, message_size) == -1) + return -1; return 0; } diff --git a/libi3/safewrappers.c b/libi3/safewrappers.c index cf634ad4..6acf3109 100644 --- a/libi3/safewrappers.c +++ b/libi3/safewrappers.c @@ -8,8 +8,10 @@ #include #include #include +#include #include #include +#include #include "libi3.h" @@ -56,3 +58,30 @@ int sasprintf(char **strp, const char *fmt, ...) { va_end(args); return result; } + +ssize_t writeall(int fd, const void *buf, size_t count) { + int written = 0; + ssize_t n = 0; + + while (written < count) { + n = write(fd, buf + written, count - written); + if (n == -1) { + if (errno == EINTR || errno == EAGAIN) + continue; + return n; + } + written += n; + } + + return written; +} + +ssize_t swrite(int fd, const void *buf, size_t count) { + ssize_t n; + + n = writeall(fd, buf, count); + if (n == -1) + err(EXIT_FAILURE, "Failed to write %d", fd); + else + return n; +} diff --git a/src/click.c b/src/click.c index 55e7147c..10abc057 100644 --- a/src/click.c +++ b/src/click.c @@ -46,6 +46,9 @@ static bool tiling_resize_for_border(Con *con, border_t border, xcb_button_press case BORDER_BOTTOM: search_direction = D_DOWN; break; + default: + assert(false); + break; } bool res = resize_find_tiling_participants(&first, &second, search_direction); diff --git a/src/config_parser.c b/src/config_parser.c index b229b445..eef03cae 100644 --- a/src/config_parser.c +++ b/src/config_parser.c @@ -778,14 +778,9 @@ static char *migrate_config(char *input, off_t size) { /* write the whole config file to the pipe, the script will read everything * immediately */ - int written = 0; - int ret; - while (written < size) { - if ((ret = write(writepipe[1], input + written, size - written)) < 0) { - warn("Could not write to pipe"); - return NULL; - } - written += ret; + if (writeall(writepipe[1], input, size) == -1) { + warn("Could not write to pipe"); + return NULL; } close(writepipe[1]); @@ -795,7 +790,7 @@ static char *migrate_config(char *input, off_t size) { /* read the script’s output */ int conv_size = 65535; char *converted = malloc(conv_size); - int read_bytes = 0; + int read_bytes = 0, ret; do { if (read_bytes == conv_size) { conv_size += 65535; diff --git a/src/load_layout.c b/src/load_layout.c index ccd71c37..c4d39fce 100644 --- a/src/load_layout.c +++ b/src/load_layout.c @@ -105,7 +105,7 @@ static int json_end_map(void *ctx) { int cnt = 1; while (workspace != NULL) { FREE(json_node->name); - asprintf(&(json_node->name), "%s_%d", base, cnt++); + sasprintf(&(json_node->name), "%s_%d", base, cnt++); workspace = NULL; TAILQ_FOREACH(output, &(croot->nodes_head), nodes) GREP_FIRST(workspace, output_get_content(output), !strcasecmp(child->name, json_node->name)); diff --git a/src/sighandler.c b/src/sighandler.c index 546b73d9..e971f6bd 100644 --- a/src/sighandler.c +++ b/src/sighandler.c @@ -70,8 +70,14 @@ static int backtrace(void) { int stdin_pipe[2], stdout_pipe[2]; - pipe(stdin_pipe); - pipe(stdout_pipe); + if (pipe(stdin_pipe) == -1) { + ELOG("Failed to init stdin_pipe\n"); + return -1; + } + if (pipe(stdout_pipe) == -1) { + ELOG("Failed to init stdout_pipe\n"); + return -1; + } /* close standard streams in case i3 is started from a terminal; gdb * needs to run without controlling terminal for it to work properly in diff --git a/src/util.c b/src/util.c index c5c22ba8..5760ae72 100644 --- a/src/util.c +++ b/src/util.c @@ -265,25 +265,13 @@ char *store_restart_layout(void) { return NULL; } - size_t written = 0; - while (written < length) { - int n = write(fd, payload + written, length - written); - /* TODO: correct error-handling */ - if (n == -1) { - perror("write()"); - free(filename); - close(fd); - return NULL; - } - if (n == 0) { - DLOG("write == 0?\n"); - free(filename); - close(fd); - return NULL; - } - written += n; - DLOG("written: %zd of %zd\n", written, length); + if (writeall(fd, payload, length) == -1) { + ELOG("Could not write restart layout to \"%s\", layout will be lost: %s\n", filename, strerror(errno)); + free(filename); + close(fd); + return NULL; } + close(fd); if (length > 0) { From ba89fe0a933cdd2d11f93470d3c6afa81f65982f Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 29 Mar 2015 17:11:21 +0200 Subject: [PATCH 91/99] travis: enable more warnings, add -Werror This will ensure that our code stays free of warnings, at least for the warnings that we have enabled. (Using _FORTIFY_SOURCE > 0 leads to more warnings, some of them are harder to address.) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ebabbfaf..279753e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,6 +42,6 @@ install: - sudo /bin/sh -c 'cpanm -n -v X11::XCB || true' - sudo /bin/sh -c 'cpanm -n -v AnyEvent::I3 || true' script: - - make -j + - CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Werror" CPPFLAGS="-D_FORTIFY_SOURCE=0" make -j - (cd testcases && xvfb-run ./complete-run.pl --parallel=1 || (cat latest/complete-run.log; false)) - clang-format-3.5 -i $(find . -name "*.[ch]" | tr '\n' ' ') && git diff --exit-code || (echo 'Code was not formatted using clang-format!'; false) From 6b04f28b4850a32ce1b9b2a5c7bea5b0a7c0a4fe Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 29 Mar 2015 17:12:20 +0200 Subject: [PATCH 92/99] fix remaining warnings --- i3bar/src/xcb.c | 14 +++++++------- libi3/safewrappers.c | 4 ++-- src/handlers.c | 18 +++++++++++------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index d0bc3d6c..e53b9226 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -110,23 +110,23 @@ struct xcb_colors_t { struct xcb_colors_t colors; /* Horizontal offset between a workspace label and button borders */ -const static int ws_hoff_px = 4; +static const int ws_hoff_px = 4; /* Vertical offset between a workspace label and button borders */ -const static int ws_voff_px = 3; +static const int ws_voff_px = 3; /* Offset between two workspace buttons */ -const static int ws_spacing_px = 1; +static const int ws_spacing_px = 1; /* Offset between the statusline and 1) workspace buttons on the left * 2) the tray or screen edge on the right */ -const static int sb_hoff_px = 4; +static const int sb_hoff_px = 4; /* Additional offset between the tray and the statusline, if the tray is not empty */ -const static int tray_loff_px = 2; +static const int tray_loff_px = 2; /* Vertical offset between the bar and a separator */ -const static int sep_voff_px = 4; +static const int sep_voff_px = 4; /* We define xcb_request_failed as a macro to include the relevant line number */ #define xcb_request_failed(cookie, err_msg) _xcb_request_failed(cookie, err_msg, __LINE__) @@ -1941,7 +1941,7 @@ void draw_bars(bool unhide) { DLOG("Printing statusline!\n"); int tray_width = get_tray_width(outputs_walk->trayclients); - int max_statusline_width = outputs_walk->rect.w - workspace_width - tray_width - 2 * logical_px(sb_hoff_px); + uint32_t max_statusline_width = outputs_walk->rect.w - workspace_width - tray_width - 2 * logical_px(sb_hoff_px); /* If the statusline is too long, try to use short texts. */ if (statusline_width > max_statusline_width) diff --git a/libi3/safewrappers.c b/libi3/safewrappers.c index 6acf3109..db9b6b4a 100644 --- a/libi3/safewrappers.c +++ b/libi3/safewrappers.c @@ -60,7 +60,7 @@ int sasprintf(char **strp, const char *fmt, ...) { } ssize_t writeall(int fd, const void *buf, size_t count) { - int written = 0; + size_t written = 0; ssize_t n = 0; while (written < count) { @@ -70,7 +70,7 @@ ssize_t writeall(int fd, const void *buf, size_t count) { continue; return n; } - written += n; + written += (size_t)n; } return written; diff --git a/src/handlers.c b/src/handlers.c index 4b5c87d4..041f7e36 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -874,12 +874,16 @@ static void handle_client_message(xcb_client_message_event_t *event) { .root_y = y_root, .event_x = x_root - (con->rect.x), .event_y = y_root - (con->rect.y)}; - if (direction == _NET_WM_MOVERESIZE_MOVE) { - floating_drag_window(con->parent, &fake); - } else if (direction >= _NET_WM_MOVERESIZE_SIZE_TOPLEFT && direction <= _NET_WM_MOVERESIZE_SIZE_LEFT) { - floating_resize_window(con->parent, FALSE, &fake); - } else { - DLOG("_NET_WM_MOVERESIZE direction %d not implemented\n", direction); + switch (direction) { + case _NET_WM_MOVERESIZE_MOVE: + floating_drag_window(con->parent, &fake); + break; + case _NET_WM_MOVERESIZE_SIZE_TOPLEFT... _NET_WM_MOVERESIZE_SIZE_LEFT: + floating_resize_window(con->parent, FALSE, &fake); + break; + default: + DLOG("_NET_WM_MOVERESIZE direction %d not implemented\n", direction); + break; } } else { DLOG("unhandled clientmessage\n"); @@ -1214,7 +1218,7 @@ static bool handle_strut_partial_change(void *data, xcb_connection_t *conn, uint con->window->dock = W_DOCK_BOTTOM; } else { DLOG("Ignoring invalid reserved edges (_NET_WM_STRUT_PARTIAL), using position as fallback:\n"); - if (con->geometry.y < (int16_t)(search_at->rect.height / 2)) { + if (con->geometry.y < (search_at->rect.height / 2)) { DLOG("geom->y = %d < rect.height / 2 = %d, it is a top dock client\n", con->geometry.y, (search_at->rect.height / 2)); con->window->dock = W_DOCK_TOP; From 909eefb868187fbdd24d7674e6451de9635f679a Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 29 Mar 2015 17:20:11 +0200 Subject: [PATCH 93/99] travis: remove FORTIFY_SOURCE, causes trouble with clang --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 279753e9..733daeac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,6 +42,6 @@ install: - sudo /bin/sh -c 'cpanm -n -v X11::XCB || true' - sudo /bin/sh -c 'cpanm -n -v AnyEvent::I3 || true' script: - - CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Werror" CPPFLAGS="-D_FORTIFY_SOURCE=0" make -j + - CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Werror" make -j - (cd testcases && xvfb-run ./complete-run.pl --parallel=1 || (cat latest/complete-run.log; false)) - clang-format-3.5 -i $(find . -name "*.[ch]" | tr '\n' ' ') && git diff --exit-code || (echo 'Code was not formatted using clang-format!'; false) From b8057392c496cff75c7a62db2d4dafb280ebf502 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 29 Mar 2015 17:45:46 +0200 Subject: [PATCH 94/99] update release.sh for the next version --- release.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release.sh b/release.sh index db5ca09b..06f6dfc0 100755 --- a/release.sh +++ b/release.sh @@ -1,8 +1,8 @@ #!/bin/zsh # This script is used to prepare a new release of i3. -export RELEASE_VERSION="4.9.1" -export PREVIOUS_VERSION="4.9" +export RELEASE_VERSION="4.10" +export PREVIOUS_VERSION="4.9.1" export RELEASE_BRANCH="master" if [ ! -e "../i3.github.io" ] From 71310adaea498d1cb85242b64980295d8662d11f Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 29 Mar 2015 17:46:16 +0200 Subject: [PATCH 95/99] release i3 4.10 --- RELEASE-NOTES-4.10 | 65 +++++++++++++++++++++++++++++++++++++++++++++ RELEASE-NOTES-4.9.1 | 36 ------------------------- man/asciidoc.conf | 2 +- 3 files changed, 66 insertions(+), 37 deletions(-) create mode 100644 RELEASE-NOTES-4.10 delete mode 100644 RELEASE-NOTES-4.9.1 diff --git a/RELEASE-NOTES-4.10 b/RELEASE-NOTES-4.10 new file mode 100644 index 00000000..20e41ac8 --- /dev/null +++ b/RELEASE-NOTES-4.10 @@ -0,0 +1,65 @@ + + ┌──────────────────────────────┐ + │ Release notes for i3 v4.10 │ + └──────────────────────────────┘ + +This is i3 v4.10. This version is considered stable. All users of i3 are +strongly encouraged to upgrade. + +This release contains mostly bugfixes, but we felt it was necessary since there +are two important changes in behavior: we have reverted the pango markup +parsing by default (introduced with i3 v4.9) and the change in how the +“workspace” command behaves (introduced with i3 v4.9). Both of them broke some +user’s setups, which is not acceptable. In order to help us avoid such mistakes +in the future, please consider using the i3 git version — it is typically +stable. + + ┌────────────────────────────┐ + │ Changes in i3 v4.10 │ + └────────────────────────────┘ + + • i3bar: cut long statuslines from the left + • i3bar: add support for the short_text property + • i3-sensible-terminal: launch i3-nagbar when no terminal is found + • i3-config-wizard: switch modifier on key up/down + • docs/layout-saving: added a troubleshooting section + • docs: degender all the terms + • Revert "Workspace command number selection" + • don’t parse blocks as markup by default + • Allow escaping backslashes in commands. + • switch default font from “DejaVu Sans Mono 8” to “monospace 8”, which is + typically a synonym, except for users who prefer a different font. + • When renaming a workspace, look for assignments and move the renamed + workspace to the appropriate output. + • i3-save-tree: make --workspace optional by defaulting to the focused + workspace + • Allow nop command without argument + + ┌────────────────────────────┐ + │ Bugfixes │ + └────────────────────────────┘ + + • i3bar: buffer the statusline to avoid flickering + • i3bar: fix click events for workspace buttons with long statusline + • i3bar: set correct initial position when reconfiguring + • i3bar: reconfigure strut partial on reload + • i3-nagbar: fix sizes/positioning on hi-dpi displays + • i3-config-wizard: fix sizes/positioning on hi-dpi displays + • i3-input: fix sizes/positioning on hi-dpi displays + • Fix scrolling in window decoration with hidden cursor. + • workspace rename focus mismatch + • Don’t overwrite border width when already set (placeholders). + • fix a segfault during config file validation + • Restore placeholder windows after restarting. + • Don’t focus placeholder windows. + + ┌────────────────────────────┐ + │ Thanks! │ + └────────────────────────────┘ + +Thanks for testing, bugfixes, discussions and everything I forgot go out to: + + Chih-Chyuan Hwang, Deiz, Diana Dinosaur, Ingo Bürk, Michael Hofmann, + Michael Tipton, Micha Rosenbaum, shdown, Tony Crisci + +-- Michael Stapelberg, 2015-03-29 diff --git a/RELEASE-NOTES-4.9.1 b/RELEASE-NOTES-4.9.1 deleted file mode 100644 index 5ff6d220..00000000 --- a/RELEASE-NOTES-4.9.1 +++ /dev/null @@ -1,36 +0,0 @@ - - ┌──────────────────────────────┐ - │ Release notes for i3 v4.9.1 │ - └──────────────────────────────┘ - -This is i3 v4.9.1. This version is considered stable. All users of i3 are -strongly encouraged to upgrade. - -This is a bugfix release for i3 v4.9. - - ┌────────────────────────────┐ - │ Bugfixes │ - └────────────────────────────┘ - - • i3bar: fix incorrect y-offset for text - • fix key bindings on big-endian platforms - • fix key bindings using Mode_switch - • fix keyboard layout change detection - • revert "Handle WM_CHANGE_STATE requests for iconic state" (fixes problems - with application windows disappearing, like SDL-based games when switching - workspaces) - • insert id-based match at HEAD, not TAIL (fixes window swallowing not - working when the criteria match the placeholder window) - • improve error messages on failing commands - • replace ~ in filepath when calling append_layout - • properly error out when the layout file cannot be read - - ┌────────────────────────────┐ - │ Thanks! │ - └────────────────────────────┘ - -Thanks for testing, bugfixes, discussions and everything I forgot go out to: - - Steven McDonald, Ton van den Heuvel, Ingo Bürk - --- Michael Stapelberg, 2015-03-07 diff --git a/man/asciidoc.conf b/man/asciidoc.conf index d441e78f..2591938f 100644 --- a/man/asciidoc.conf +++ b/man/asciidoc.conf @@ -7,7 +7,7 @@ template::[header-declarations] {mantitle} {manvolnum} i3 -4.9.1 +4.10 i3 Manual From 8f69ddcb4da37569d78a25f77a5d1e1e1b757e32 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 29 Mar 2015 18:08:59 +0200 Subject: [PATCH 96/99] Update debian/changelog --- debian/changelog | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 1dcfc9f9..cc0e5328 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,14 @@ -i3-wm (4.9.2-1) experimental; urgency=medium +i3-wm (4.10.1-1) experimental; urgency=medium * NOT YET RELEASED. - -- Michael Stapelberg Sat, 07 Mar 2015 20:31:31 +0100 + -- Michael Stapelberg Sun, 29 Mar 2015 18:08:13 +0200 + +i3-wm (4.10-1) experimental; urgency=medium + + * New upstream release. + + -- Michael Stapelberg Sun, 29 Mar 2015 17:46:09 +0200 i3-wm (4.9.1-1) experimental; urgency=medium From 9515cb0713b721948d15adf47b5f2ef92ce513c5 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 29 Mar 2015 18:50:00 +0200 Subject: [PATCH 97/99] =?UTF-8?q?release=20from=20=E2=80=9Cnext=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- release.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release.sh b/release.sh index 06f6dfc0..aaaf5078 100755 --- a/release.sh +++ b/release.sh @@ -3,7 +3,7 @@ export RELEASE_VERSION="4.10" export PREVIOUS_VERSION="4.9.1" -export RELEASE_BRANCH="master" +export RELEASE_BRANCH="next" if [ ! -e "../i3.github.io" ] then From aef495faba3b0cf52902ffbbc048b9b2e9b8b780 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 29 Mar 2015 18:51:04 +0200 Subject: [PATCH 98/99] prepare release.sh for 4.10.1 --- release.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release.sh b/release.sh index aaaf5078..646034a6 100755 --- a/release.sh +++ b/release.sh @@ -1,8 +1,8 @@ #!/bin/zsh # This script is used to prepare a new release of i3. -export RELEASE_VERSION="4.10" -export PREVIOUS_VERSION="4.9.1" +export RELEASE_VERSION="4.10.1" +export PREVIOUS_VERSION="4.10" export RELEASE_BRANCH="next" if [ ! -e "../i3.github.io" ] From 2dea50d469acd03e93b8231ec556e2012510d872 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 29 Mar 2015 19:07:03 +0200 Subject: [PATCH 99/99] release i3 4.10.1 --- RELEASE-NOTES-4.10 => RELEASE-NOTES-4.10.1 | 9 ++++++--- man/asciidoc.conf | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) rename RELEASE-NOTES-4.10 => RELEASE-NOTES-4.10.1 (91%) diff --git a/RELEASE-NOTES-4.10 b/RELEASE-NOTES-4.10.1 similarity index 91% rename from RELEASE-NOTES-4.10 rename to RELEASE-NOTES-4.10.1 index 20e41ac8..61b47705 100644 --- a/RELEASE-NOTES-4.10 +++ b/RELEASE-NOTES-4.10.1 @@ -1,9 +1,9 @@ ┌──────────────────────────────┐ - │ Release notes for i3 v4.10 │ + │ Release notes for i3 v4.10.1 │ └──────────────────────────────┘ -This is i3 v4.10. This version is considered stable. All users of i3 are +This is i3 v4.10.1. This version is considered stable. All users of i3 are strongly encouraged to upgrade. This release contains mostly bugfixes, but we felt it was necessary since there @@ -14,8 +14,11 @@ user’s setups, which is not acceptable. In order to help us avoid such mistake in the future, please consider using the i3 git version — it is typically stable. +PS: The v4.10 release did not contain any of the commits we meant to release +due to a human error in our release automation. Hence the v4.10.1 release. + ┌────────────────────────────┐ - │ Changes in i3 v4.10 │ + │ Changes in i3 v4.10.1 │ └────────────────────────────┘ • i3bar: cut long statuslines from the left diff --git a/man/asciidoc.conf b/man/asciidoc.conf index 2591938f..9a04b75c 100644 --- a/man/asciidoc.conf +++ b/man/asciidoc.conf @@ -7,7 +7,7 @@ template::[header-declarations] {mantitle} {manvolnum} i3 -4.10 +4.10.1 i3 Manual