From c1b6c946215d0622a4d414fa191623f40f481362 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 25 Apr 2015 20:05:55 -0400 Subject: [PATCH 01/10] Bugfix: serialize con_id with %p in run_binding() %p is equivalent to either %x or %lx, depending on the pointer size of the platform. Before this commit, we always used %d, which has the same behavior on Linux, but is not automatically expanded to %ld on e.g. FreeBSD. fixes #1661 --- src/bindings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings.c b/src/bindings.c index cbac2dfd..9a38ba91 100644 --- a/src/bindings.c +++ b/src/bindings.c @@ -429,7 +429,7 @@ CommandResult *run_binding(Binding *bind, Con *con) { if (con == NULL) command = sstrdup(bind->command); else - sasprintf(&command, "[con_id=\"%d\"] %s", con, bind->command); + sasprintf(&command, "[con_id=\"%p\"] %s", con, bind->command); Binding *bind_cp = binding_copy(bind); CommandResult *result = parse_command(command, NULL); From a0268a38d30ca8a55ca36f570848b581f8ca92e8 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 25 Apr 2015 22:43:46 -0400 Subject: [PATCH 02/10] Ignore InputHint when not in WM_HINTS When InputHint is not in WM_HINTS (i.e., the flag is not set), treat the window as if the InputHint was set (the default behavior). This means that i3 will focus the window when it becomes managed. fixes #1676 --- src/window.c | 6 ++++-- testcases/t/158-wm_take_focus.t | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/window.c b/src/window.c index 5485bcc3..36737943 100644 --- a/src/window.c +++ b/src/window.c @@ -254,8 +254,10 @@ void window_update_hints(i3Window *win, xcb_get_property_reply_t *prop, bool *ur return; } - win->doesnt_accept_focus = !hints.input; - LOG("WM_HINTS.input changed to \"%d\"\n", hints.input); + if (hints.flags & XCB_ICCCM_WM_HINT_INPUT) { + win->doesnt_accept_focus = !hints.input; + LOG("WM_HINTS.input changed to \"%d\"\n", hints.input); + } if (urgency_hint != NULL) *urgency_hint = (xcb_icccm_wm_hints_get_urgency(&hints) != 0); diff --git a/testcases/t/158-wm_take_focus.t b/testcases/t/158-wm_take_focus.t index 050e1162..b8dae3b1 100644 --- a/testcases/t/158-wm_take_focus.t +++ b/testcases/t/158-wm_take_focus.t @@ -50,12 +50,15 @@ sub recv_take_focus { } subtest 'Window without WM_TAKE_FOCUS', sub { - fresh_workspace; + my $ws = fresh_workspace; my $window = open_window; ok(!recv_take_focus($window), 'did not receive ClientMessage'); + my $con = shift get_ws_content($ws); + ok($con->{focused}, 'con is focused'); + done_testing; }; @@ -72,7 +75,7 @@ subtest 'Window without WM_TAKE_FOCUS', sub { # list), the window cannot accept input focus, so we should not try to focus # the window at all. subtest 'Window with WM_TAKE_FOCUS and without InputHint', sub { - fresh_workspace; + my $ws = fresh_workspace; my $take_focus = $x->atom(name => 'WM_TAKE_FOCUS'); @@ -88,6 +91,9 @@ subtest 'Window with WM_TAKE_FOCUS and without InputHint', sub { ok(!recv_take_focus($window), 'did not receive ClientMessage'); + my $con = shift get_ws_content($ws); + ok($con->{focused}, 'con is focused'); + done_testing; }; @@ -97,7 +103,7 @@ subtest 'Window with WM_TAKE_FOCUS and without InputHint', sub { # nearly identical presently, so this is currently used also as a proxy test # for the latter case. subtest 'Window with WM_TAKE_FOCUS and unspecified InputHint', sub { - fresh_workspace; + my $ws = fresh_workspace; my $take_focus = $x->atom(name => 'WM_TAKE_FOCUS'); @@ -105,6 +111,9 @@ subtest 'Window with WM_TAKE_FOCUS and unspecified InputHint', sub { ok(!recv_take_focus($window), 'did not receive ClientMessage'); + my $con = shift get_ws_content($ws); + ok($con->{focused}, 'con is focused'); + done_testing; }; From e71c304444dd3070877887d2bb5407cd64033946 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 23 Apr 2015 18:21:15 -0400 Subject: [PATCH 03/10] Check if output is disabled in handle_output() Check if the `connection` of the randr output is XCB_RANDR_CONNECTION_DISONNECTED and disable the output if it is. This fixes an issue where the output would not be disabled if the output was physically unplugged from the machine. --- src/randr.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/randr.c b/src/randr.c index a4a0f6fd..9549c9d5 100644 --- a/src/randr.c +++ b/src/randr.c @@ -555,6 +555,12 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id, return; } + if (output->connection == XCB_RANDR_CONNECTION_DISCONNECTED) { + DLOG("Disabling output %s: it is disconnected\n", new->name); + new->to_be_disabled = true; + return; + } + bool updated = update_if_necessary(&(new->rect.x), crtc->x) | update_if_necessary(&(new->rect.y), crtc->y) | update_if_necessary(&(new->rect.width), crtc->width) | From d03b96b3698610110faa662deef395d769b2c034 Mon Sep 17 00:00:00 2001 From: Deiz Date: Sun, 26 Apr 2015 14:23:08 -0400 Subject: [PATCH 04/10] Initialize workspace rect to the output's upon creation The comment immediately following implied that this was the intended behaviour. Not doing so means that compound commands that both move a window to a new workspace as well as do something that depends on the workspace's geometry (e.g. 'move position center' or 'floating enable' on a tiled window) would use the workspace's calloc'd 0x0+0x0 geometry. --- src/workspace.c | 1 + ...244-new-workspace-floating-enable-center.t | 53 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 testcases/t/244-new-workspace-floating-enable-center.t diff --git a/src/workspace.c b/src/workspace.c index f55c920e..8bd4b5ea 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -29,6 +29,7 @@ static void _workspace_apply_default_orientation(Con *ws) { if (config.default_orientation == NO_ORIENTATION) { Con *output = con_get_output(ws); ws->layout = (output->rect.height > output->rect.width) ? L_SPLITV : L_SPLITH; + ws->rect = output->rect; DLOG("Auto orientation. Workspace size set to (%d,%d), setting layout to %d.\n", output->rect.width, output->rect.height, ws->layout); } else { diff --git a/testcases/t/244-new-workspace-floating-enable-center.t b/testcases/t/244-new-workspace-floating-enable-center.t new file mode 100644 index 00000000..dbc9a80a --- /dev/null +++ b/testcases/t/244-new-workspace-floating-enable-center.t @@ -0,0 +1,53 @@ +#!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) +# +# Ensures that 'move workspace $new, floating enable' on a marked window +# leaves the window centered on the new workspace. +# Bug still in: 4.10.2-137-ga4f0ed6 +use i3test i3_autostart => 0; + +my $config = <rect; + +is(int($pos->{x} + $pos->{width} / 2), int($x->root->rect->width / 2), + 'x coordinates match'); +is(int($pos->{y} + $pos->{height} / 2), int($x->root->rect->height / 2), + 'y coordinates match'); + +exit_gracefully($pid); + +done_testing; From ee66a8bcde5adc0890b5a8d02705c48dfa1b7cb5 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 3 May 2015 18:57:05 +0200 Subject: [PATCH 05/10] =?UTF-8?q?userguide:=20quoted=20strings=20need=20to?= =?UTF-8?q?=20be=20used,=20escaping=20isn=E2=80=99t=20possible?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes #1678 --- docs/userguide | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/userguide b/docs/userguide index 80de5c88..820f5395 100644 --- a/docs/userguide +++ b/docs/userguide @@ -699,6 +699,10 @@ commands will not run when restarting i3, if you need a command to run also when restarting i3 you should use the +exec_always+ keyword. These commands will be run in order. +See <> for details on the special meaning of +;+ (semicolon) +and +,+ (comma): they chain commands together in i3, so you need to use quoted +strings if they appear in your command. + *Syntax*: ------------------- exec [--no-startup-id] command @@ -1466,7 +1470,11 @@ information on how to use them. What good is a window manager if you can’t actually start any applications? The exec command starts an application by passing the command you specify to a shell. This implies that you can use globbing (wildcards) and programs will be -searched in your $PATH. +searched in your +$PATH+. + +See <> for details on the special meaning of +;+ (semicolon) +and +,+ (comma): they chain commands together in i3, so you need to use quoted +strings if they appear in your command. *Syntax*: ------------------------------ From 7c2842eae4a63668d510196ee6610f816cb32d39 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 12 May 2015 17:04:01 -0400 Subject: [PATCH 06/10] Detect base 16 in cmd criteria Try to detect base 16 numbers given to `con_id` and `id` for command criteria by setting the base of strtol to 0. This should also detect octal. This is necessary because mouse bindings now may be serialized as hex as of 5c32de4. --- src/commands.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands.c b/src/commands.c index fd43a693..9d5275dc 100644 --- a/src/commands.c +++ b/src/commands.c @@ -335,7 +335,7 @@ void cmd_criteria_add(I3_CMD, char *ctype, char *cvalue) { if (strcmp(ctype, "con_id") == 0) { char *end; - long parsed = strtol(cvalue, &end, 10); + long parsed = strtol(cvalue, &end, 0); if (parsed == LONG_MIN || parsed == LONG_MAX || parsed < 0 || @@ -350,7 +350,7 @@ void cmd_criteria_add(I3_CMD, char *ctype, char *cvalue) { if (strcmp(ctype, "id") == 0) { char *end; - long parsed = strtol(cvalue, &end, 10); + long parsed = strtol(cvalue, &end, 0); if (parsed == LONG_MIN || parsed == LONG_MAX || parsed < 0 || From fbcb227537a15d1ef5873500203ae7394a3b3d8f Mon Sep 17 00:00:00 2001 From: Deiz Date: Sun, 29 Mar 2015 17:18:00 -0400 Subject: [PATCH 07/10] Move mkdirp into libi3 --- include/ipc.h | 6 ------ include/libi3.h | 6 ++++++ libi3/mkdirp.c | 38 ++++++++++++++++++++++++++++++++++++++ src/ipc.c | 30 ------------------------------ 4 files changed, 44 insertions(+), 36 deletions(-) create mode 100644 libi3/mkdirp.c diff --git a/include/ipc.h b/include/ipc.h index 96a60a1f..4eed319a 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -50,12 +50,6 @@ typedef void (*handler_t)(int, uint8_t *, int, uint32_t, uint32_t); int size, uint32_t message_size, \ uint32_t message_type) -/** - * Emulates mkdir -p (creates any missing folders) - * - */ -bool mkdirp(const char *path); - /** * Handler for activity on the listening socket, meaning that a new client * has just connected and we should accept() him. Sets up the event handler diff --git a/include/libi3.h b/include/libi3.h index 3a125827..d6a2e980 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -434,3 +434,9 @@ char *get_exe_path(const char *argv0); * */ int logical_px(const int logical); + +/** + * Emulates mkdir -p (creates any missing folders) + * + */ +bool mkdirp(const char *path); diff --git a/libi3/mkdirp.c b/libi3/mkdirp.c new file mode 100644 index 00000000..a0d35f96 --- /dev/null +++ b/libi3/mkdirp.c @@ -0,0 +1,38 @@ +#include "libi3.h" +#include +#include +#include +#include + +/* + * Emulates mkdir -p (creates any missing folders) + * + */ +bool mkdirp(const char *path) { + if (mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0) + return true; + if (errno != ENOENT) { + ELOG("mkdir(%s) failed: %s\n", path, strerror(errno)); + return false; + } + char *copy = sstrdup(path); + /* strip trailing slashes, if any */ + while (copy[strlen(copy) - 1] == '/') + copy[strlen(copy) - 1] = '\0'; + + char *sep = strrchr(copy, '/'); + if (sep == NULL) { + if (copy != NULL) { + free(copy); + copy = NULL; + } + return false; + } + *sep = '\0'; + bool result = false; + if (mkdirp(copy)) + result = mkdirp(path); + free(copy); + + return result; +} diff --git a/src/ipc.c b/src/ipc.c index 52f7db2e..8fed75f1 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -37,36 +37,6 @@ static void set_nonblock(int sockfd) { err(-1, "Could not set O_NONBLOCK"); } -/* - * Emulates mkdir -p (creates any missing folders) - * - */ -bool mkdirp(const char *path) { - if (mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0) - return true; - if (errno != ENOENT) { - ELOG("mkdir(%s) failed: %s\n", path, strerror(errno)); - return false; - } - char *copy = sstrdup(path); - /* strip trailing slashes, if any */ - while (copy[strlen(copy) - 1] == '/') - copy[strlen(copy) - 1] = '\0'; - - char *sep = strrchr(copy, '/'); - if (sep == NULL) { - FREE(copy); - return false; - } - *sep = '\0'; - bool result = false; - if (mkdirp(copy)) - result = mkdirp(path); - free(copy); - - return result; -} - /* * Sends the specified event to all IPC clients which are currently connected * and subscribed to this kind of event. From c0f685e7bc834e8ffd266c79d04451b995804b14 Mon Sep 17 00:00:00 2001 From: Theo Buehler Date: Sat, 23 May 2015 13:12:18 +0200 Subject: [PATCH 08/10] mkdirp: do not throw an error if directory exists If I restart i3 4.10.2 twice, e.g. with $ i3-msg restart; sleep 3; i3-msg restart the second time I get the following two errors: 05/22/15 10:46:03 - ERROR: mkdir(/tmp/i3-theo.toAK7N) failed: File exists 05/22/15 10:46:03 - ERROR: Could not create "/tmp/i3-theo.toAK7N" for storing the restart layout, layout will be lost. The first one is from mkdirp() in src/ipc.c and the second one is from store_restart_layout() in src/util.c. Notice that I do _not_ get the ``open()'' or ``Could not write restart layout to ...'' error messages, so the layout writing code after line 260 in store_restart_layout() succeeded and the layout isn't actually lost. Thus, these error messages are a bit misleading, especially the second one (which is triggered by the failure of mkdirp()). POSIX says about `mkdir -p': ``Each dir operand that names an existing directory shall be ignored without error.'' Therefore, I suggest the following simple patch that makes mkdirp() succeed if the named file exists and actually is a directory. This silences the second error as well. --- libi3/mkdirp.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libi3/mkdirp.c b/libi3/mkdirp.c index a0d35f96..95c31b59 100644 --- a/libi3/mkdirp.c +++ b/libi3/mkdirp.c @@ -11,7 +11,19 @@ bool mkdirp(const char *path) { if (mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0) return true; - if (errno != ENOENT) { + if (errno == EEXIST) { + struct stat st; + /* Check that the named file actually is a directory. */ + if (stat(path, &st)) { + ELOG("stat(%s) failed: %s\n", path, strerror(errno)); + return false; + } + if (!S_ISDIR(st.st_mode)) { + ELOG("mkdir(%s) failed: %s\n", path, strerror(ENOTDIR)); + return false; + } + return true; + } else if (errno != ENOENT) { ELOG("mkdir(%s) failed: %s\n", path, strerror(errno)); return false; } From 4446c4d89064346fd9ab9e00dbb1a544d96bfa24 Mon Sep 17 00:00:00 2001 From: shdown Date: Tue, 2 Jun 2015 23:08:08 +0300 Subject: [PATCH 09/10] i3bar: fix freeing static strings name and color fields of blocks are freed in clear_statusline, so they need to be strdup'ed. --- i3bar/src/child.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 41f8880d..e2638e7b 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -107,14 +107,14 @@ __attribute__((format(printf, 1, 2))) static void set_statusline_error(const cha struct status_block *err_block = scalloc(sizeof(struct status_block)); err_block->full_text = i3string_from_utf8("Error: "); - err_block->name = "error"; - err_block->color = "red"; + err_block->name = sstrdup("error"); + err_block->color = sstrdup("red"); err_block->no_separator = true; struct status_block *message_block = scalloc(sizeof(struct status_block)); message_block->full_text = i3string_from_utf8(message); - message_block->name = "error_message"; - message_block->color = "red"; + message_block->name = sstrdup("error_message"); + message_block->color = sstrdup("red"); message_block->no_separator = true; TAILQ_INSERT_HEAD(&statusline_head, err_block, blocks); From 3cc377166f30d31fd9e9a35a17174c08fe9fb587 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Thu, 30 Jul 2015 22:26:58 +0200 Subject: [PATCH 10/10] release i3 4.10.3 --- RELEASE-NOTES-4.10.2 => RELEASE-NOTES-4.10.3 | 20 ++++++++++++-------- man/asciidoc.conf | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) rename RELEASE-NOTES-4.10.2 => RELEASE-NOTES-4.10.3 (54%) diff --git a/RELEASE-NOTES-4.10.2 b/RELEASE-NOTES-4.10.3 similarity index 54% rename from RELEASE-NOTES-4.10.2 rename to RELEASE-NOTES-4.10.3 index 49c06e50..524f5528 100644 --- a/RELEASE-NOTES-4.10.2 +++ b/RELEASE-NOTES-4.10.3 @@ -1,19 +1,23 @@ ┌──────────────────────────────┐ - │ Release notes for i3 v4.10.2 │ + │ Release notes for i3 v4.10.3 │ └──────────────────────────────┘ -This is i3 v4.10.2. This version is considered stable. All users of i3 are +This is i3 v4.10.3. This version is considered stable. All users of i3 are strongly encouraged to upgrade. ┌────────────────────────────┐ │ Bugfixes │ └────────────────────────────┘ - • Cope with non-null-terminated x class properties. - • Get workspace name when renaming current workspace (fixes crash). - • Use a reasonable default sep_block_width if a separator_symbol is given. - • Remove windows from the save set when unmapping. + • serialize con_id with %p in run_binding() (For FreeBSD) + • ignore InputHint when not in WM_HINTS (fixes e.g. mupdf focus) + • disable physically disconnect RandR outputs + • initialize workspace rect to the output's upon creation + • userguide: quoted strings need to be used, escaping isn’t possible + • mkdirp: do not throw an error if directory exists (fixes layout loss for + in-place restarts) + • i3bar: fix freeing static strings ┌────────────────────────────┐ │ Thanks! │ @@ -21,6 +25,6 @@ strongly encouraged to upgrade. Thanks for testing, bugfixes, discussions and everything I forgot go out to: - Ingo Bürk, Michael Hofmann, + Tony Crisci, Deiz, Theo Buehler, shdown --- Michael Stapelberg, 2015-04-16 +-- Michael Stapelberg, 2015-07-30 diff --git a/man/asciidoc.conf b/man/asciidoc.conf index 9fbce991..eda71d6e 100644 --- a/man/asciidoc.conf +++ b/man/asciidoc.conf @@ -7,7 +7,7 @@ template::[header-declarations] {mantitle} {manvolnum} i3 -4.10.2 +4.10.3 i3 Manual