- 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" 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)
--- /dev/null
+
+ ┌──────────────────────────────┐
+ │ 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
+++ /dev/null
-
- ┌──────────────────────────────┐
- │ 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
-i3-wm (4.9.2-1) experimental; urgency=medium
+i3-wm (4.10.1-1) experimental; urgency=medium
* NOT YET RELEASED.
- -- Michael Stapelberg <stapelberg@debian.org> Sat, 07 Mar 2015 20:31:31 +0100
+ -- Michael Stapelberg <stapelberg@debian.org> Sun, 29 Mar 2015 18:08:13 +0200
+
+i3-wm (4.10-1) experimental; urgency=medium
+
+ * New upstream release.
+
+ -- Michael Stapelberg <stapelberg@debian.org> Sun, 29 Mar 2015 17:46:09 +0200
i3-wm (4.9.1-1) experimental; urgency=medium
* 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;
}
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[]) {
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);
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: ");
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);
+ }
}
}
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);
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__)
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)
*/
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.
.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;
}
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <unistd.h>
#include <stdio.h>
#include <err.h>
+#include <errno.h>
#include "libi3.h"
va_end(args);
return result;
}
+
+ssize_t writeall(int fd, const void *buf, size_t count) {
+ size_t 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 += (size_t)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;
+}
<refentrytitle>{mantitle}</refentrytitle>
<manvolnum>{manvolnum}</manvolnum>
<refmiscinfo class="source">i3</refmiscinfo>
-<refmiscinfo class="version">4.9.1</refmiscinfo>
+<refmiscinfo class="version">4.10</refmiscinfo>
<refmiscinfo class="manual">i3 Manual</refmiscinfo>
</refmeta>
<refnamediv>
#!/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" ]
case BORDER_BOTTOM:
search_direction = D_DOWN;
break;
+ default:
+ assert(false);
+ break;
}
bool res = resize_find_tiling_participants(&first, &second, search_direction);
/* 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]);
/* 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;
.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");
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;
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));
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
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) {