From 4b1ea08eef8dc5ebde15b21a68a034ba0f71a657 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 15 Nov 2020 19:22:09 +0100 Subject: [PATCH 001/104] release.sh and release notes changes post-release (#4258) --- RELEASE-NOTES-next | 21 +++++++++++++++++++++ release.sh | 45 ++++++++++++++++++--------------------------- 2 files changed, 39 insertions(+), 27 deletions(-) create mode 100644 RELEASE-NOTES-next diff --git a/RELEASE-NOTES-next b/RELEASE-NOTES-next new file mode 100644 index 000000000..e896b54e7 --- /dev/null +++ b/RELEASE-NOTES-next @@ -0,0 +1,21 @@ + + ┌──────────────────────────────┐ + │ Release notes for i3 v4.20 │ + └──────────────────────────────┘ + +This is i3 v4.19. This version is considered stable. All users of i3 are +strongly encouraged to upgrade. + + + ┌────────────────────────────┐ + │ Changes in i3 v4.20 │ + └────────────────────────────┘ + + • placeholder + + ┌────────────────────────────┐ + │ Bugfixes │ + └────────────────────────────┘ + + • placeholder + diff --git a/release.sh b/release.sh index c6b045c0a..4477ebfe2 100755 --- a/release.sh +++ b/release.sh @@ -1,8 +1,10 @@ #!/bin/zsh # This script is used to prepare a new release of i3. +set -eu + export RELEASE_VERSION="4.19" -export PREVIOUS_VERSION="4.18" +export PREVIOUS_VERSION="4.18.3" export RELEASE_BRANCH="next" if [ ! -e "../i3.github.io" ] @@ -24,12 +26,6 @@ then 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 @@ -52,28 +48,32 @@ if [ ! -e "${STARTDIR}/RELEASE-NOTES-${RELEASE_VERSION}" ]; then exit 1 fi git checkout -b release-${RELEASE_VERSION} +git rm RELEASE-NOTES-* 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/^\s*version: '${PREVIOUS_VERSION}'/ version: '${RELEASE_VERSION}'/" meson.build +# Update the release version: +sed -i "s/^\s*version: '4.[^']*'/ version: '${RELEASE_VERSION}'/" meson.build +cp meson.build "${TMPDIR}/meson.build" +# Inject the release date into meson.build for the dist tarball: +sed -i "s/'-non-git'/' ($(date +'%Y-%m-%d'))'/" meson.build git commit -a -m "release i3 ${RELEASE_VERSION}" git tag "${RELEASE_VERSION}" -m "release i3 ${RELEASE_VERSION}" --sign --local-user=0x4AC8EE1D mkdir build (cd build && meson .. && ninja dist) -cp build/meson-build/i3-${RELEASE_VERSION}.tar.xz . +cp build/meson-dist/i3-${RELEASE_VERSION}.tar.xz . echo "Differences in the release tarball file lists:" diff --color -u \ - <(tar tf ../i3-${PREVIOUS_VERSION}.tar.xz | sed "s,i3-${PREVIOUS_VERSION}/,,g" | sort) \ - <(tar tf i3-${RELEASE_VERSION}.tar.xz | sed "s,i3-${RELEASE_VERSION}/,,g" | sort) + <(tar tf ../i3-${PREVIOUS_VERSION}.tar.* | sed "s,i3-${PREVIOUS_VERSION}/,,g" | sort) \ + <(tar tf i3-${RELEASE_VERSION}.tar.xz | sed "s,i3-${RELEASE_VERSION}/,,g" | sort) || true gpg --armor -b i3-${RELEASE_VERSION}.tar.xz -echo "${RELEASE_VERSION}-non-git" > I3_VERSION -git add I3_VERSION -git commit -a -m "Set non-git version to ${RELEASE_VERSION}-non-git." +mv "${TMPDIR}/meson.build" . +git add meson.build +git commit -a -m "Restore non-git version suffix" if [ "${RELEASE_BRANCH}" = "stable" ]; then git checkout stable @@ -94,17 +94,12 @@ git config --add remote.origin.push "+refs/heads/next:refs/heads/next" git config --add remote.origin.push "+refs/heads/stable:refs/heads/stable" ################################################################################ -# Section 2: Debian packaging +# Section 2: Debian packaging (for QA) ################################################################################ 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 -(cd i3 && git add debian/changelog && git commit -m 'Update debian/changelog') - cat > ${TMPDIR}/Dockerfile < Date: Mon, 16 Nov 2020 09:56:49 +0100 Subject: [PATCH 002/104] i3-sensible-terminal: prioritize terminals with good accessibility (#4259) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We never did (and still do not) guarantee any order in which terminal emulators are tried. Quoting from the i3-sensible-terminal man page: > Please don’t complain about the order: If the user has any preference, they > will have $TERMINAL set or modified their i3 configuration file. This commit moves mate-terminal to the beginning of the list, which is considered the most accessible terminal emulator among blind users. fixes https://github.com/i3/i3/issues/4256 --- i3-sensible-terminal | 8 +++++++- man/i3-sensible-terminal.man | 8 ++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/i3-sensible-terminal b/i3-sensible-terminal index c3a2e4e0c..fa1443c40 100755 --- a/i3-sensible-terminal +++ b/i3-sensible-terminal @@ -8,7 +8,13 @@ # We welcome patches that add distribution-specific mechanisms to find the # preferred terminal emulator. On Debian, there is the x-terminal-emulator # symlink for example. -for terminal in "$TERMINAL" x-terminal-emulator urxvt rxvt termit terminator Eterm aterm uxterm xterm gnome-terminal roxterm xfce4-terminal termite lxterminal mate-terminal terminology st qterminal lilyterm tilix terminix konsole kitty guake tilda alacritty hyper; do +# +# Invariants: +# 1. $TERMINAL must come first +# 2. Distribution-specific mechanisms come next, e.g. x-terminal-emulator +# 3. The terminal emulator with best accessibility comes first. +# 4. No order is guaranteed/desired for the remaining terminal emulators. +for terminal in "$TERMINAL" x-terminal-emulator mate-terminal gnome-terminal terminator xfce4-terminal urxvt rxvt termit Eterm aterm uxterm xterm roxterm termite lxterminal terminology st qterminal lilyterm tilix terminix konsole kitty guake tilda alacritty hyper; do if command -v "$terminal" > /dev/null 2>&1; then exec "$terminal" "$@" fi diff --git a/man/i3-sensible-terminal.man b/man/i3-sensible-terminal.man index bda5a7239..1b83e07bf 100644 --- a/man/i3-sensible-terminal.man +++ b/man/i3-sensible-terminal.man @@ -23,20 +23,20 @@ It tries to start one of the following (in that order): * $TERMINAL (this is a non-standard variable) * x-terminal-emulator (only present on Debian and derivatives) +* mate-terminal +* gnome-terminal +* terminator +* xfce4-terminal * urxvt * rxvt * termit -* terminator * Eterm * aterm * uxterm * xterm -* gnome-terminal * roxterm -* xfce4-terminal * termite * lxterminal -* mate-terminal * terminology * st * qterminal From eb83b37936d5356291f49fdc6c1d23ac02fd1c5a Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 16 Nov 2020 11:10:03 +0100 Subject: [PATCH 003/104] userguide: clarify home row / vi navigational key relation (#4260) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this commit, the userguide mentioned “compatibility with most keyboard layouts”, but that seems to not have been the intention of vi author(s). --- docs/userguide | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/docs/userguide b/docs/userguide index bc4afb3f9..37343df90 100644 --- a/docs/userguide +++ b/docs/userguide @@ -53,12 +53,23 @@ existing window (rotated displays). image:two_terminals.png[Two terminals] -To move the focus between the two terminals, you can use the direction keys -which you might know from the editor +vi+. However, in i3, your homerow is used -for these keys (in +vi+, the keys are shifted to the left by one for -compatibility with most keyboard layouts). Therefore, +$mod+j+ is left, +$mod+k+ -is down, +$mod+l+ is up and `$mod+;` is right. So, to switch between the -terminals, use +$mod+k+ or +$mod+l+. Of course, you can also use the arrow keys. +To move the focus between the two terminals, you can use the arrow keys. For +convenience, the arrows are also available directly on the +https://en.wikipedia.org/wiki/Touch_typing[keyboard’s home row] underneath your +right hand: + +|=== +| `$mod+j` | left +| `$mod+k` | down +| `$mod+l` | up +| `$mod+;` | right +|=== + +Note that this differs by one key from the popular text editor `vi`, which was +https://twitter.com/hillelogram/status/1326600125569961991[developed on an +ADM-3A terminal and therefore uses `hjkl` instead of `jkl;`] -- i3’s default is +meant to require minimal finger movement, but some `vi` users change their i3 +config for consistency. At the moment, your workspace is split (it contains two terminals) in a specific direction (horizontal by default). Every window can be split From d0067077ed9ffb013bed0b3c181f36ee726acdb8 Mon Sep 17 00:00:00 2001 From: Dmitri Goutnik Date: Sat, 21 Nov 2020 13:18:24 -0500 Subject: [PATCH 004/104] declare parser generated sources as deps (#4264) --- meson.build | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index 0bf023f2d..70847fc36 100644 --- a/meson.build +++ b/meson.build @@ -514,6 +514,7 @@ executable( 'i3-config-wizard/i3-config-wizard-atoms.xmacro.h', 'i3-config-wizard/main.c', 'i3-config-wizard/xcb.h', + config_parser, ], install: true, include_directories: include_directories('include', 'i3-config-wizard'), @@ -669,7 +670,10 @@ executable( executable( 'test.commands_parser', - 'src/commands_parser.c', + [ + 'src/commands_parser.c', + command_parser, + ], include_directories: inc, c_args: '-DTEST_PARSER', dependencies: common_deps, @@ -678,7 +682,10 @@ executable( executable( 'test.config_parser', - 'src/config_parser.c', + [ + 'src/config_parser.c', + config_parser, + ], include_directories: inc, c_args: '-DTEST_PARSER', dependencies: common_deps, From 68258785acebaa648bacf4ef8b6e44f098f4e396 Mon Sep 17 00:00:00 2001 From: Orestis Floros Date: Tue, 10 Nov 2020 10:24:15 +0100 Subject: [PATCH 005/104] create_workspace_on_output: Prevent duplicate workspace nums MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When going through the `binding_workspace_names` to prioritize user-specified names, we only check if the workspace exists, not the workspace number. If the user specified a `bindsym … workspace number X` directive, then it is appended in `binding_workspace_names` and a workspace is created using that number even though from the POV of a user that uses numbers to change workspaces, that workspace already exists. In similar code here: https://github.com/i3/i3/blob/1d9160f2d247dbaa83fb62f02fd7041dec767fc2/src/workspace.c#L997 we do the check. Fixes #4238 --- RELEASE-NOTES-next | 3 +-- src/workspace.c | 7 +++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/RELEASE-NOTES-next b/RELEASE-NOTES-next index e896b54e7..c24c82a06 100644 --- a/RELEASE-NOTES-next +++ b/RELEASE-NOTES-next @@ -17,5 +17,4 @@ strongly encouraged to upgrade. │ Bugfixes │ └────────────────────────────┘ - • placeholder - + • when initializing new outputs, avoid duplicating workspace numbers diff --git a/src/workspace.c b/src/workspace.c index f3ddf01c8..db3afe4aa 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -254,12 +254,15 @@ Con *create_workspace_on_output(Output *output, Con *content) { continue; } - exists = (get_existing_workspace_by_name(target_name) != NULL); + const int num = ws_name_to_number(target_name); + exists = (num == -1) + ? get_existing_workspace_by_name(target_name) + : get_existing_workspace_by_num(num); if (!exists) { ws->name = sstrdup(target_name); /* Set ->num to the number of the workspace, if the name actually * is a number or starts with a number */ - ws->num = ws_name_to_number(ws->name); + ws->num = num; LOG("Used number %d for workspace with name %s\n", ws->num, ws->name); break; From 13757ac1ca707e0b35105d0c499848bae4460766 Mon Sep 17 00:00:00 2001 From: Orestis Floros Date: Wed, 11 Nov 2020 09:47:25 +0100 Subject: [PATCH 006/104] workspace.c: Make small consistency changes --- src/workspace.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/workspace.c b/src/workspace.c index db3afe4aa..739358a8a 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -134,7 +134,7 @@ Con *workspace_get(const char *num) { /* We set workspace->num to the number if this workspace’s name begins with * a positive number. Otherwise it’s a named ws and num will be 1. */ - const long parsed_num = ws_name_to_number(num); + const int parsed_num = ws_name_to_number(num); Con *output = get_assigned_output(num, parsed_num); /* if an assignment is not found, we create this workspace on the current output */ @@ -238,7 +238,6 @@ void extract_workspace_names_from_bindings(void) { */ Con *create_workspace_on_output(Output *output, Con *content) { /* add a workspace to this output */ - char *name; bool exists = true; Con *ws = con_new(NULL, NULL); ws->type = CT_WORKSPACE; @@ -263,7 +262,7 @@ Con *create_workspace_on_output(Output *output, Con *content) { /* Set ->num to the number of the workspace, if the name actually * is a number or starts with a number */ ws->num = num; - LOG("Used number %d for workspace with name %s\n", ws->num, ws->name); + DLOG("Used number %d for workspace with name %s\n", ws->num, ws->name); break; } @@ -284,6 +283,7 @@ Con *create_workspace_on_output(Output *output, Con *content) { } con_attach(ws, content, false); + char *name; sasprintf(&name, "[i3 con] workspace %s", ws->name); x_set_name(ws, name); free(name); @@ -990,14 +990,14 @@ void workspace_move_to_output(Con *ws, Output *output) { bool used_assignment = false; struct Workspace_Assignment *assignment; TAILQ_FOREACH (assignment, &ws_assignments, ws_assignments) { - bool attached; - int num; if (!output_triggers_assignment(current_output, assignment)) { continue; } /* check if this workspace's name or num is already attached to the tree */ - num = ws_name_to_number(assignment->name); - attached = ((num == -1) ? get_existing_workspace_by_name(assignment->name) : get_existing_workspace_by_num(num)) != NULL; + const int num = ws_name_to_number(assignment->name); + const bool attached = (num == -1) + ? get_existing_workspace_by_name(assignment->name) + : get_existing_workspace_by_num(num); if (attached) { continue; } From b6690045edb24397333f179080a272f9c2d83869 Mon Sep 17 00:00:00 2001 From: ekarpp Date: Mon, 2 Nov 2020 22:16:48 +0200 Subject: [PATCH 007/104] i3-nagbar: add possibility to open bar on focused monitor Closes #3692 i3-nagbar will open by default on the monitor with input focus and using the flag -p on the primary monitor. --- RELEASE-NOTES-next | 3 +- i3-nagbar/main.c | 78 +++++++++++++++++++++++++++++++++++++++------- man/i3-nagbar.man | 6 +++- 3 files changed, 73 insertions(+), 14 deletions(-) diff --git a/RELEASE-NOTES-next b/RELEASE-NOTES-next index c24c82a06..fa7f841b6 100644 --- a/RELEASE-NOTES-next +++ b/RELEASE-NOTES-next @@ -11,7 +11,8 @@ strongly encouraged to upgrade. │ Changes in i3 v4.20 │ └────────────────────────────┘ - • placeholder + • i3-nagbar: position on focused monitor by default + • i3-nagbar: add option to position on primary monitor ┌────────────────────────────┐ │ Bugfixes │ diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c index b13ee1343..7d9c0901f 100644 --- a/i3-nagbar/main.c +++ b/i3-nagbar/main.c @@ -266,13 +266,9 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { } /** - * Return the position and size the i3-nagbar window should use. - * This will be the primary output or a fallback if it cannot be determined. + * Tries to position the rectangle on the primary output. */ -static xcb_rectangle_t get_window_position(void) { - /* Default values if we cannot determine the primary output or its CRTC info. */ - xcb_rectangle_t result = (xcb_rectangle_t){50, 50, 500, font.height + 2 * MSG_PADDING + BAR_BORDER}; - +static void set_window_position_primary(xcb_rectangle_t *result) { xcb_randr_get_screen_resources_current_cookie_t rcookie = xcb_randr_get_screen_resources_current(conn, root); xcb_randr_get_output_primary_cookie_t pcookie = xcb_randr_get_output_primary(conn, root); @@ -314,14 +310,61 @@ static xcb_rectangle_t get_window_position(void) { goto free_resources; } - result.x = crtc->x; - result.y = crtc->y; + result->x = crtc->x; + result->y = crtc->y; goto free_resources; free_resources: free(res); free(primary); - return result; +} + +/** + * Tries to position the rectangle on the output with input focus. + * If unsuccessful, try to position on primary output. + */ +static void set_window_position_focus(xcb_rectangle_t *result) { + bool success = false; + xcb_get_input_focus_reply_t *input_focus = NULL; + xcb_get_geometry_reply_t *geometry = NULL; + xcb_translate_coordinates_reply_t *coordinates = NULL; + + /* To avoid the input window disappearing while determining its position */ + xcb_grab_server(conn); + + input_focus = xcb_get_input_focus_reply(conn, xcb_get_input_focus(conn), NULL); + if (input_focus == NULL || input_focus->focus == XCB_NONE) { + LOG("Failed to receive the current input focus or no window has the input focus right now.\n"); + goto free_resources; + } + + geometry = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, input_focus->focus), NULL); + if (geometry == NULL) { + LOG("Failed to received window geometry.\n"); + goto free_resources; + } + + coordinates = xcb_translate_coordinates_reply( + conn, xcb_translate_coordinates(conn, input_focus->focus, root, geometry->x, geometry->y), NULL); + if (coordinates == NULL) { + LOG("Failed to translate coordinates.\n"); + goto free_resources; + } + + LOG("Found current focus at x = %i / y = %i.\n", coordinates->dst_x, coordinates->dst_y); + result->x = coordinates->dst_x; + result->y = coordinates->dst_y; + success = true; + +free_resources: + xcb_ungrab_server(conn); + free(input_focus); + free(coordinates); + free(geometry); + if (!success) { + LOG("Could not position on focused output, trying to position on primary output.\n"); + set_window_position_primary(result); + } } int main(int argc, char *argv[]) { @@ -360,6 +403,7 @@ int main(int argc, char *argv[]) { argv0 = argv[0]; + bool position_on_primary = false; char *pattern = sstrdup("pango:monospace 8"); int o, option_index = 0; enum { TYPE_ERROR = 0, @@ -373,9 +417,10 @@ int main(int argc, char *argv[]) { {"help", no_argument, 0, 'h'}, {"message", required_argument, 0, 'm'}, {"type", required_argument, 0, 't'}, + {"primary", no_argument, 0, 'p'}, {0, 0, 0, 0}}; - char *options_string = "b:B:f:m:t:vh"; + char *options_string = "b:B:f:m:t:vhp"; prompt = i3string_from_utf8("Please do not run this program."); @@ -399,8 +444,11 @@ int main(int argc, char *argv[]) { case 'h': free(pattern); printf("i3-nagbar " I3_VERSION "\n"); - printf("i3-nagbar [-m ] [-b