diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index a9cfbd47..f2c55972 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,18 +1,68 @@ -Output of `i3 --moreversion 2>&- || i3 --version`: + -_REPLACE: i3 version output_ +## I'm submitting a… + +
+[ ] Bug
+[ ] Feature Request
+[ ] Documentation Request
+[ ] Other (Please describe in detail)
+
-URL to a logfile as per https://i3wm.org/docs/debugging.html: +## Current Behavior + -_REPLACE: URL to logfile_ +## Expected Behavior + -**What I did:** +## Reproduction Instructions + -**What I saw:** +## Environment + +Output of `i3 --moreversion 2>&-`: +
+i3 version: 
+
-_REPLACE: e.g. "i3 changed focus to the window ABOVE the current window"_ + +
+
+ + +
+Logfile URL:
+
+ + +
+- Linux Distribution & Version:
+- Are you using a compositor (e.g., xcompmgr or compton):
+
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..910b0fca --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,71 @@ +--- +name: Bug report +about: Create a report to help us improve +--- + + + +## I'm submitting a… + +
+[x] Bug
+[ ] Feature Request
+[ ] Documentation Request
+[ ] Other (Please describe in detail)
+
+ +## Current Behavior + + +## Expected Behavior + + +## Reproduction Instructions + + +## Environment + +Output of `i3 --moreversion 2>&-`: +
+i3 version: 
+
+ + +
+
+ + +
+Logfile URL:
+
+ + +
+- Linux Distribution & Version:
+- Are you using a compositor (e.g., xcompmgr or compton):
+
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..e1c169a5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,47 @@ +--- +name: Feature request +about: Suggest an idea for this project +--- + + + +## I'm submitting a… + +
+[ ] Bug
+[x] Feature Request
+[ ] Documentation Request
+[ ] Other (Please describe in detail)
+
+ +## Current Behavior + + +## Desired Behavior + + +## Environment + +Output of `i3 --moreversion 2>&-`: +
+i3 version: 
+
+ + +
+- Linux Distribution & Version:
+- Are you using a compositor (e.g., xcompmgr or compton):
+
diff --git a/.travis.yml b/.travis.yml index 87c996fb..8098035c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,7 @@ install: script: - docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/check-safe-wrappers.sh - docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/check-formatting.sh - - docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 -e CC ${BASENAME} /bin/sh -c 'autoreconf -fi && mkdir -p build && cd build && (../configure || (cat config.log; false)) && make -j CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Werror"' + - docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 -e CC ${BASENAME} /bin/sh -c 'autoreconf -fi && mkdir -p build && cd build && (../configure || (cat config.log; false)) && make -j CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Wstrict-prototypes -Wmissing-prototypes -Werror"' - docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/check-spelling.pl - docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 -e CC ${BASENAME} ./travis/run-tests.sh - ./travis/skip-pkg.sh || docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/debian-build.sh deb/debian-amd64/DIST diff --git a/AnyEvent-I3/lib/AnyEvent/I3.pm b/AnyEvent-I3/lib/AnyEvent/I3.pm index 198c41c9..ae9e5bea 100644 --- a/AnyEvent-I3/lib/AnyEvent/I3.pm +++ b/AnyEvent-I3/lib/AnyEvent/I3.pm @@ -100,11 +100,12 @@ use constant TYPE_GET_VERSION => 7; use constant TYPE_GET_BINDING_MODES => 8; use constant TYPE_GET_CONFIG => 9; use constant TYPE_SEND_TICK => 10; +use constant TYPE_SYNC => 11; our %EXPORT_TAGS = ( 'all' => [ qw(i3 TYPE_RUN_COMMAND TYPE_COMMAND TYPE_GET_WORKSPACES TYPE_SUBSCRIBE TYPE_GET_OUTPUTS TYPE_GET_TREE TYPE_GET_MARKS TYPE_GET_BAR_CONFIG TYPE_GET_VERSION - TYPE_GET_BINDING_MODES TYPE_GET_CONFIG TYPE_SEND_TICK) + TYPE_GET_BINDING_MODES TYPE_GET_CONFIG TYPE_SEND_TICK TYPE_SYNC) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{all} } ); @@ -534,6 +535,19 @@ sub send_tick { $self->message(TYPE_SEND_TICK, $payload); } +=head2 sync + +Sends an i3 sync event. Requires i3 >= 4.16 + +=cut +sub sync { + my ($self, $payload) = @_; + + $self->_ensure_connection; + + $self->message(TYPE_SYNC, $payload); +} + =head2 command($content) Makes i3 execute the given command diff --git a/DEPENDS b/DEPENDS index 1e26afa2..9a92f99e 100644 --- a/DEPENDS +++ b/DEPENDS @@ -4,29 +4,29 @@ "min" means minimum required version "lkgv" means last known good version -┌──────────────┬────────┬────────┬───────────────────────────────────────────────────────────┐ -│ dependency │ min. │ lkgv │ URL │ -├──────────────┼────────┼────────┼───────────────────────────────────────────────────────────┤ -│ pkg-config │ 0.25 │ 0.29 │ https://pkgconfig.freedesktop.org/ │ -│ libxcb │ 1.1.93 │ 1.12 │ https://xcb.freedesktop.org/dist/ │ -│ xcb-util │ 0.3.3 │ 0.4.1 │ https://xcb.freedesktop.org/dist/ │ -│ xkbcommon │ 0.4.0 │ 0.6.1 │ https://xkbcommon.org/ │ -│ xkbcommon-x11│ 0.4.0 │ 0.6.1 │ https://xkbcommon.org/ │ -│ util-cursor³⁴│ 0.0.99 │ 0.1.3 │ https://xcb.freedesktop.org/dist/ │ -│ util-wm⁴ │ 0.3.8 │ 0.3.8 │ https://xcb.freedesktop.org/dist/ │ -│ util-keysyms⁴│ 0.3.8 │ 0.4.0 │ https://xcb.freedesktop.org/dist/ │ -│ util-xrm⁴ │ 1.0.0 │ 1.0.0 │ https://github.com/Airblader/xcb-util-xrm │ -│ libev │ 4.0 │ 4.19 │ http://libev.schmorp.de/ │ -│ yajl │ 2.0.1 │ 2.1.0 │ https://lloyd.github.com/yajl/ │ -│ asciidoc │ 8.3.0 │ 8.6.9 │ http://www.methods.co.nz/asciidoc/ │ -│ xmlto │ 0.0.23 │ 0.0.23 │ http://www.methods.co.nz/asciidoc/ │ -│ Pod::Simple² │ 3.22 │ 3.22 │ http://search.cpan.org/~dwheeler/Pod-Simple-3.23/ │ -│ docbook-xml │ 4.5 │ 4.5 │ http://www.methods.co.nz/asciidoc/ │ -│ PCRE │ 8.12 │ 8.38 │ https://www.pcre.org/ │ -│ libsn¹ │ 0.10 │ 0.12 │ https://freedesktop.org/wiki/Software/startup-notification │ -│ pango │ 1.30.0 | 1.40.1 │ http://www.pango.org/ │ -│ cairo │ 1.14.4 │ 1.14.6 │ https://cairographics.org/ │ -└──────────────┴────────┴────────┴───────────────────────────────────────────────────────────┘ +┌──────────────┬────────┬────────┬─────────────────────────────────────────────────────────────┐ +│ dependency │ min. │ lkgv │ URL │ +├──────────────┼────────┼────────┼─────────────────────────────────────────────────────────────┤ +│ pkg-config │ 0.25 │ 0.29 │ https://pkgconfig.freedesktop.org/ │ +│ libxcb │ 1.1.93 │ 1.12 │ https://xcb.freedesktop.org/dist/ │ +│ xcb-util │ 0.3.3 │ 0.4.1 │ https://xcb.freedesktop.org/dist/ │ +│ xkbcommon │ 0.4.0 │ 0.6.1 │ https://xkbcommon.org/ │ +│ xkbcommon-x11│ 0.4.0 │ 0.6.1 │ https://xkbcommon.org/ │ +│ util-cursor³⁴│ 0.0.99 │ 0.1.3 │ https://xcb.freedesktop.org/dist/ │ +│ util-wm⁴ │ 0.3.8 │ 0.3.8 │ https://xcb.freedesktop.org/dist/ │ +│ util-keysyms⁴│ 0.3.8 │ 0.4.0 │ https://xcb.freedesktop.org/dist/ │ +│ util-xrm⁴ │ 1.0.0 │ 1.0.0 │ https://github.com/Airblader/xcb-util-xrm/ │ +│ libev │ 4.0 │ 4.19 │ http://libev.schmorp.de/ │ +│ yajl │ 2.0.1 │ 2.1.0 │ https://lloyd.github.com/yajl/ │ +│ asciidoc │ 8.3.0 │ 8.6.9 │ http://www.methods.co.nz/asciidoc/ │ +│ xmlto │ 0.0.23 │ 0.0.23 │ http://www.methods.co.nz/asciidoc/ │ +│ Pod::Simple² │ 3.22 │ 3.22 │ http://search.cpan.org/dist/Pod-Simple/ │ +│ docbook-xml │ 4.5 │ 4.5 │ http://www.methods.co.nz/asciidoc/ │ +│ PCRE │ 8.12 │ 8.38 │ https://www.pcre.org/ │ +│ libsn¹ │ 0.10 │ 0.12 │ https://freedesktop.org/wiki/Software/startup-notification/ │ +│ pango │ 1.30.0 │ 1.40.1 │ http://www.pango.org/ │ +│ cairo │ 1.14.4 │ 1.14.6 │ https://cairographics.org/ │ +└──────────────┴────────┴────────┴─────────────────────────────────────────────────────────────┘ ¹ libsn = libstartup-notification ² Pod::Simple is a Perl module required for converting the testsuite documentation to HTML. See https://michael.stapelberg.de/cpan/#Pod::Simple diff --git a/I3_VERSION b/I3_VERSION index 0d5ece58..a39209b2 100644 --- a/I3_VERSION +++ b/I3_VERSION @@ -1 +1 @@ -4.15-non-git +4.16-non-git diff --git a/Makefile.am b/Makefile.am index 184b0734..537fc6a0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -118,7 +118,7 @@ EXTRA_DIST = \ I3_VERSION \ LICENSE \ PACKAGE-MAINTAINER \ - RELEASE-NOTES-4.15 \ + RELEASE-NOTES-4.16 \ generate-command-parser.pl \ parser-specs/commands.spec \ parser-specs/config.spec \ @@ -301,6 +301,7 @@ libi3_a_SOURCES = \ libi3/fake_configure_notify.c \ libi3/font.c \ libi3/format_placeholders.c \ + libi3/g_utf8_make_valid.c \ libi3/get_colorpixel.c \ libi3/get_config_path.c \ libi3/get_exe_path.c \ @@ -357,10 +358,12 @@ i3_msg_i3_msg_SOURCES = \ i3_nagbar_i3_nagbar_CFLAGS = \ $(AM_CFLAGS) \ + $(LIBSN_CFLAGS) \ $(libi3_CFLAGS) i3_nagbar_i3_nagbar_LDADD = \ $(libi3_LIBS) \ + $(LIBSN_LIBS) \ $(XCB_UTIL_CURSOR_LIBS) i3_nagbar_i3_nagbar_SOURCES = \ @@ -414,10 +417,12 @@ i3bar_i3bar_SOURCES = \ i3_config_wizard_i3_config_wizard_CFLAGS = \ $(AM_CFLAGS) \ $(libi3_CFLAGS) \ + $(LIBSN_CFLAGS) \ $(XKBCOMMON_CFLAGS) i3_config_wizard_i3_config_wizard_LDADD = \ $(libi3_LIBS) \ + $(LIBSN_LIBS) \ $(XCB_UTIL_KEYSYMS_LIBS) \ $(XKBCOMMON_LIBS) @@ -521,6 +526,7 @@ i3_SOURCES = \ include/shmlog.h \ include/sighandler.h \ include/startup.h \ + include/sync.h \ include/tree.h \ include/util.h \ include/window.h \ @@ -562,6 +568,7 @@ i3_SOURCES = \ src/sd-daemon.c \ src/sighandler.c \ src/startup.c \ + src/sync.c \ src/tree.c \ src/util.c \ src/version.c \ diff --git a/README.md b/README.md index 21b2e24b..6ac67541 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ ===================================================== [![Build Status](https://travis-ci.org/i3/i3.svg?branch=next)](https://travis-ci.org/i3/i3) -[![Issue Stats](http://www.issuestats.com/github/i3/i3/badge/issue?style=flat)](http://www.issuestats.com/github/i3/i3) -[![Pull Request Stats](http://www.issuestats.com/github/i3/i3/badge/pr?style=flat)](http://www.issuestats.com/github/i3/i3) +[![Issue Stats](https://img.shields.io/github/issues/i3/i3.svg)](https://github.com/i3/i3/issues) +[![Pull Request Stats](https://img.shields.io/github/issues-pr/i3/i3.svg)](https://github.com/i3/i3/pulls) i3 is a tiling window manager for X11. diff --git a/RELEASE-NOTES-4.15 b/RELEASE-NOTES-4.15 deleted file mode 100644 index 0e1f81e4..00000000 --- a/RELEASE-NOTES-4.15 +++ /dev/null @@ -1,113 +0,0 @@ - - ┌────────────────────────────┐ - │ Release notes for i3 v4.15 │ - └────────────────────────────┘ - -This is i3 v4.15. This version is considered stable. All users of i3 are -strongly encouraged to upgrade. - -Aside from a number of fixes and documentation improvements, a number of -commands have been extended to be more complete (e.g. “assign”, “resize”). - - ┌────────────────────────────┐ - │ Changes in i3 v4.15 │ - └────────────────────────────┘ - - • build: AnyEvent::I3 moved to the i3 repository, so that its main consumer, - the i3 testsuite, can use new features immediately (such as the tick event, - in this case). - • docs/hacking-howto: promote “using git / sending patches” and “how to - build?” sections - • docs/i3bar-protocol: document that pango markup only works with pango fonts - • docs/ipc: document focus, nodes, floating_nodes - • docs/ipc: urgent: complete the list of container types - • docs/ipc: document how to detect i3’s byte order in memory-safe languages - • docs/ipc: document the GET_CONFIG request - • docs/userguide: fix formatting issue - • docs/userguide: explain why Mod4 is usually preferred as a modifier - • docs/userguide: use more idiomatic english (full-size, so-called) - • docs/userguide: switch from removed goto command to focus - • docs/userguide: mention in focus - • docs/userguide: remove outdated 2013 last-modified date - • dump-asy: add prerequisite checks - • dump-asy: fix warnings about empty container names - • i3-dump-log: enable shmlog on demand - • i3-sensible-terminal: add “kitty”, “guake”, “tilda” - • i3-sensible-editor: add “gvim” - • i3bar: add --release flag for bindsym in bar blocks - • i3bar: add relative coordinates in JSON for click events - • ipc: rename COMMAND to RUN_COMMAND for consistency - • ipc: implement tick event for less flaky tests - • ipc: add error reply to “focus ” - • ipc: send success response for nop - • default config: add $mod+r to toggle resize mode - • default config: use variables for workspace names to avoid repetition - • introduce “assign [→] [workspace] [number] ” - • introduce “assign [→] output left|right|up|down|primary|” - • introduce a “focus_wrapping” option (subsumes “force_focus_wrapping”) - • introduce percentage point resizing for floating containers: - “resize set [px | ppt] [px | ppt]” - • introduce “resize set ppt ppt” for tiling windows - • rename “new_window” and “new_float” to “default_border” and - “default_floating_border” (the old names keep working) - • output names (e.g. “DP2”) can now be used as synonyms for monitor names - (e.g. “Dell UP2414Q”). - • the “swap” command now works with fullscreen windows - • raise floating windows to top when they are focused programmatically - • _NET_ACTIVE_WINDOW: invalidate focus to force SetInputFocus call - • make focus handling consistent when changing focus between outputs - • round non-integer Xft.dpi values - • tiling resize: remove minimum size - - ┌────────────────────────────┐ - │ Bugfixes │ - └────────────────────────────┘ - - • i3bar: fix various memory leaks - • i3bar: fix crash when no status_command is provided - • fix uninitialized variables in init_dpi_end, tree_restore - • fix incorrectly set up signal handling - • fix “swap” debug log message - • fix crash when specifying invalid con_id for “swap” - • fix crash upon restart with window marks - • fix crash when config file does not end in a newline - • fix crash in append_layout - • fix crash in layout toggle command - • fix crash when switching monitors - • fix use-after-free in randr_init error path - • fix move accidentally moving windows across outputs - • fix crash when floating window is tiled while being resized - • fix out-of-bounds memory read - • fix memory leak when config conversion fails - • fix layout toggle split, which didn’t work until enabling tabbed/stack mode - once - • move XCB event handling into xcb_prepare_cb - • avert endless loop on unexpected EOF in ipc messages - • perform proper cleanup for signals with Term action - • don’t match containers in the scratchpad with criteria - • fix “workspace show” related issues - • fix config file conversion with long variable names - • fix config file conversion memory initialization - • prevent access of freed workspace in _workspace_show - • disable fullscreen when required when programmatically focusing windows - • free last_motion_notify - • don’t raise floating windows when focused because of focus_follows_mouse - • correctly set EWMH atoms when closing a workspace - • don’t raise floating windows when workspace is shown - • keep focus order when encapsulating workspaces - • validate layout files before loading - - ┌────────────────────────────┐ - │ Thanks! │ - └────────────────────────────┘ - -Thanks for testing, bugfixes, discussions and everything I forgot go out to: - - Alex Lu, Ben Creasy, Bennett Piater, Cast, chressie, clonejo, Dan Elkouby, - Daniel Mueller, DebianWall, Diki Ananta, Edward Betts, hwangcc23, Ingo Bürk, - Jan Alexander Steffens, Johannes Lange, Kent Fredric, livanh, Martin - T. H. Sandsmark, Michael Siegel, Orestis Floros, Pallav Agarwal, Pawel - S. Veselov, Pietro Cerutti, Theo Buehler, Thomas Praxl, Tyler Brazier, - Vladimir Panteleev, walker0643, Wes Roberts, xzfc - --- Michael Stapelberg, 2018-03-10 diff --git a/RELEASE-NOTES-4.16 b/RELEASE-NOTES-4.16 new file mode 100644 index 00000000..e5505cbf --- /dev/null +++ b/RELEASE-NOTES-4.16 @@ -0,0 +1,145 @@ + + ┌────────────────────────────┐ + │ Release notes for i3 v4.16 │ + └────────────────────────────┘ + +This is i3 v4.16. This version is considered stable. All users of i3 are +strongly encouraged to upgrade. + +This release contains a number of assorted fixes and improvements across pretty +much all individual components of i3. + + ┌────────────────────────────┐ + │ Changes in i3 v4.16 │ + └────────────────────────────┘ + + • build: add conditionals for building docs/mans + • docs/i3bar-protocol: mention skipping blocks with empty full_text + • docs/ipc: add window_properties to tree node + • docs/layout-saving: clarify JSON non-compliance + • docs/userguide: clarify X resource value format + • docs/userguide: fix move_to_outputs link + • docs/userguide: link workspace_auto_back_and_forth from workspace + command + • docs/userguide: mention known issues for assign + • docs/userguide: use anchor for list_of_commands + • docs/userguide: add the default keybinding for focus parent + • man/*: fix title markers (for asciidoctor) + • man/i3-msg.man: add get_config and send_tick + • ipc: kill misbehaving subscribed clients instead of hanging + • ipc: introduce the sync IPC command for synchronization with i3bar + • ipc: scratchpad show now returns correct success + • ipc: send_tick now sets the already-documented “first” field + • i3bar-protocol: add modifiers to events sent by i3bar + • dump-asy: use Pod::Usage for --help and perldoc + • dump-asy: introduce -gv flag to disable opening ghostview + • dump-asy: introduce -save flag to store the rendered tree in a file + • dump-asy: add marks + • dump-asy: include floating containers + • i3bar: add --verbose flag + • i3bar: make modifier accept combinations (like floating_modifier) + • i3-config-wizard: add --modifier flag to allow for headless config + • i3-config-wizard: support startup notifications + • i3-msg: only print input + error position if they are set + • i3-msg: check replies also in quiet mode (-q) + • i3-msg: add support for the SUBSCRIBE message type + • i3-nagbar: support startup notifications + • i3-nagbar: add option for button that runs commands without a terminal + • i3-save-tree: exclude unsupported transient_for property + • i3-sensible-terminal: add alacritty + • i3-sensible-terminal: add hyper + • introduce strip_workspace_name alongside strip_workspace_numbers + • introduce title_align config directive + • “border toggle” now accepts an optional pixel argument + • “resize set” now interprets 0 as “no change” + • “resize set” now accepts the “width” and “height” keywords + • “resize” with pixel values now works for tiling containers + • the optional “absolute” method is now silently ignored in “move position” + commands, where it did not cause a visible difference anyway + • the _NET_WM_STATE_FOCUSED atom is now supported, resulting in e.g. + GTK applications displaying the correct window decoration + • moving fullscreen containers now moves them across outputs + • floating windows can now be used with a geometry of e.g. +1+1, i.e. + their top-left corner can be outside any output as long as the window + is contained partially by one + • prefer floating fullscreen containers when switching focus + • moving containers to an active workspace no longer changes focus + • the rename workspace command no longer confuses directions (e.g. “left”) + with output names + • prefer $XDG_CONFIG_HOME/i3/config over ~/.i3/config + • allow multiple assignments of workspaces to output + • respect maximum size in WM_NORMAL_HINTS + • reject requests for WM_STATE_ICONIC, which avoids e.g. wine + applications being stuck in paused state + • a number of code refactorings and cleanups, some of which tool-assisted + + ┌────────────────────────────┐ + │ Bugfixes │ + └────────────────────────────┘ + + • build: fix static linking + • i3bar: fix various memory leaks + • i3bar: fix crash when no status_command is provided + • i3bar: fix chopping the first character on the very left when using the + full width of the output + • i3bar: fix relative_x and width properties of click events + • i3bar: fix the tray disappearing in some cases when using "tray_output" + • fix various memory leaks and memory correctness issues + • refocus focused window on FOCUS_IN events for the root window. This + fixes incorrect behavior with steam and some tk apps + • fix focus bugs when moving unfocused containers + • fix incorrect urgent window state edge case + • moving an unfocused container from inside a split container to another + workspace doesn’t focus siblings + • toggling and killing floating windows now maintains focus order + • don’t incorrectly focus siblings when scrolling on window decorations + • fix crash when moving a container to a marked workspace + • fix swap when first is behind a fullscreen window + • fix crash when renaming an existing workspace to a name assigned to the + focused output + • reframe swallowed windows if depth doesn’t match + • use detectable autorepeat so that --release bindings are run only when + the key is actually released (and not when it is repeated) + • fix border artifacts when moving windows + • correctly handle bindings for the same mod key with and without --release + • reset B_UPON_KEYRELEASE_IGNORE_MODS bindings when switching modes + • fix height offset calculation in pango text drawing + • fix detection of libiconv on OpenBSD + • free workspace assignments on reload + • fix mouse position at startup with multiple outputs + • no longer allow dragging global fullscreen floating containers + • fix rendering artifacts with global fullscreen containers + • fix disabling floating for scratchpad windows + • fix a crash when renaming an unfocused empty workspace matching an + assignment + • ensure containers have a size of at least 1px after resize + • permit invalid UTF-8 in layout JSON files (e.g. for window titles) + • correct invalid UTF-8 characters in window and container titles + • fix a crash when moving to a child of a floating container + • fix a crash when matching __focused__ with no window open + • fix no_focus when only using floating windows + • fix max_aspect calculation + • moving an unfocused container from another output now maintains + the correct focus order + • don’t change focus order when swapping containers + • correctly update _NET_CURRENT_DESKTOP when moving containers between outputs + using the directional move command + • don’t produce move events after attempting to directionally move a container + towards a direction it can’t go + • fix sticky focus when switching to workspace on different output + + + ┌────────────────────────────┐ + │ Thanks! │ + └────────────────────────────┘ + +Thanks for testing, bugfixes, discussions and everything I forgot go out to: + + Adrian Cybulski, Aestek, Alan Barr, Andriy Yablonskyy, Cassandra Fox, + Christian Duerr, Dan Elkouby, downzer0, Elouan Martinet, Felix Buehler, + Gravemind, Harry Lawrence, Hritik Vijay, hwangcc23, Ingo Bürk, Joona, Klorax, + lasers, Łukasz Adamczak, Martin, Michael Stapelberg, Oliver Graff, + Orestis Floros, Soumya, Takashi Iwai, Thomas Fischer, Todd Walton, Tony + Crisci, Uli Schlachter, Vivien Didelot + +-- Michael Stapelberg, 2018-11-04 diff --git a/configure.ac b/configure.ac index 8dce4f9f..7ae01422 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Run autoreconf -fi to generate a configure script from this file. AC_PREREQ([2.69]) -AC_INIT([i3], [4.15], [https://github.com/i3/i3/issues]) +AC_INIT([i3], [4.16], [https://github.com/i3/i3/issues]) # For AX_EXTEND_SRCDIR AX_ENABLE_BUILDDIR AM_INIT_AUTOMAKE([foreign subdir-objects -Wall no-dist-gzip dist-bzip2]) @@ -81,9 +81,10 @@ AC_SEARCH_LIBS([floor], [m], , [AC_MSG_FAILURE([cannot find the required floor() # libev does not ship with a pkg-config file :(. AC_SEARCH_LIBS([ev_run], [ev], , [AC_MSG_FAILURE([cannot find the required ev_run() function despite trying to link with -lev])]) -AC_SEARCH_LIBS([shm_open], [rt]) +AC_SEARCH_LIBS([shm_open], [rt], [], [], [-pthread]) -AC_SEARCH_LIBS([iconv_open], [iconv], , [AC_MSG_FAILURE([cannot find the required iconv_open() function despite trying to link with -liconv])]) +AC_SEARCH_LIBS([iconv_open], [iconv], , +AC_SEARCH_LIBS([libiconv_open], [iconv], , [AC_MSG_FAILURE([cannot find the required iconv_open() function despite trying to link with -liconv])])) AX_PTHREAD @@ -109,12 +110,27 @@ AC_PROG_MAKE_SET AC_PROG_RANLIB AC_PROG_LN_S -AC_PATH_PROG([PATH_ASCIIDOC], [asciidoc]) -AC_PATH_PROG([PATH_XMLTO], [xmlto]) -AC_PATH_PROG([PATH_POD2MAN], [pod2man]) - -AM_CONDITIONAL([BUILD_MANS], [test x$PATH_ASCIIDOC != x && test x$PATH_XMLTO != x && test x$PATH_POD2MAN != x]) -AM_CONDITIONAL([BUILD_DOCS], [test x$PATH_ASCIIDOC != x]) +AC_ARG_ENABLE(docs, + AS_HELP_STRING( + [--disable-docs], + [disable building documentation]), + [ax_docs=$enableval], + [ax_docs=yes]) +AC_ARG_ENABLE(mans, + AS_HELP_STRING( + [--disable-mans], + [disable building manual pages]), + [ax_mans=$enableval], + [ax_mans=yes]) +AS_IF([test x$ax_docs = xyes || test x$ax_mans = xyes], [ + AC_PATH_PROG([PATH_ASCIIDOC], [asciidoc]) +]) +AS_IF([test x$ax_mans = xyes], [ + AC_PATH_PROG([PATH_XMLTO], [xmlto]) + AC_PATH_PROG([PATH_POD2MAN], [pod2man]) +]) +AM_CONDITIONAL([BUILD_MANS], [test x$ax_mans = xyes && test x$PATH_ASCIIDOC != x && test x$PATH_XMLTO != x && test x$PATH_POD2MAN != x]) +AM_CONDITIONAL([BUILD_DOCS], [test x$ax_docs = xyes && test x$PATH_ASCIIDOC != x]) AM_PROG_AR diff --git a/contrib/dump-asy.pl b/contrib/dump-asy.pl index 9bb2db3a..5af4c72f 100755 --- a/contrib/dump-asy.pl +++ b/contrib/dump-asy.pl @@ -1,26 +1,35 @@ #!/usr/bin/env perl # vim:ts=4:sw=4:expandtab -# renders the layout tree using asymptote -# -# ./dump-asy.pl -# will render the entire tree -# ./dump-asy.pl 'name' -# will render the tree starting from the node with the specified name, -# e.g. ./dump-asy.pl 2 will render workspace 2 and below use strict; use warnings; use Data::Dumper; +use Getopt::Long; +use Pod::Usage; use AnyEvent::I3; use File::Temp; +use File::Spec; use File::Basename; use v5.10; use IPC::Cmd qw[can_run]; +my %options = ( + gv => 1, + save => undef, + help => 0, +); +my $result = GetOptions( + "gv!" => \$options{gv}, + "save=s" => \$options{save}, + "help|?" => \$options{help}, +); + +pod2usage(-verbose => 2, -exitcode => 0) if $options{help}; + # prerequisites check so we can be specific about failures caused # by not having these tools in the path can_run('asy') or die 'Please install asymptote'; -can_run('gv') or die 'Please install gv'; +can_run('gv') or die 'Please install gv' unless !$options{gv}; my $i3 = i3(); @@ -37,7 +46,7 @@ sub dump_node { my $o = ($n->{orientation} eq 'none' ? "u" : ($n->{orientation} eq 'horizontal' ? "h" : "v")); my $w = (defined($n->{window}) ? $n->{window} : "N"); - my $na = ($n->{name} or "[Empty]"); + my $na = ($n->{name} or ($n->{type} eq "floating_con" ? "[Floating con]" : "[Empty]")); $na =~ s/#/\\#/g; $na =~ s/\$/\\\$/g; $na =~ s/&/\\&/g; @@ -47,14 +56,16 @@ sub dump_node { if (!defined($n->{window})) { $type = $n->{layout}; } - my $name = qq|``$na'' ($type)|; + my $marks = $n->{marks} ? ' [' . join('][', @{$n->{marks}}) . ']' : ''; + my $name = qq|``$na'' ($type)$marks|; print $tmp "TreeNode n" . $n->{id} . " = makeNode("; print $tmp "n" . $parent->{id} . ", " if defined($parent); print $tmp "\"" . $name . "\");\n"; - dump_node($_, $n) for @{$n->{nodes}}; + dump_node($_, $n) for @{$n->{nodes}}; + dump_node($_, $n) for @{$n->{floating_nodes}}; } sub find_node_with_name { @@ -82,5 +93,60 @@ say $tmp "draw(n" . $root->{id} . ", (0, 0));"; close($tmp); my $rep = "$tmp"; $rep =~ s/asy$/eps/; -my $tmp_dir = dirname($rep); -system("cd $tmp_dir && asy $tmp && gv --scale=-1000 --noresize --widgetless $rep && rm $rep"); +if ($options{gv}) { + my $tmp_dir = dirname($rep); + $options{save} = File::Spec->rel2abs($options{save}) if $options{save}; + chdir($tmp_dir); +} else { + $rep = basename($rep); # Output in current dir. +} +system("asy $tmp"); # Create the .eps file. +system("gv --scale=-1000 --noresize --widgetless $rep") if $options{gv}; +if ($options{save}) { + system("mv $rep ${options{save}}"); +} elsif ($options{gv}) { + system("rm $rep"); +} +system("rm $tmp"); + +__END__ + +=head1 NAME + +dump-asy.pl - Render the layout tree using asymptote + +=head1 SYNOPSIS + +dump-asy.pl [workspace] + +=head1 EXAMPLE + +Render the entire tree, run: + + ./dump-asy.pl + +Render the tree starting from the node with the specified name, run: + + ./dump-asy.pl 'name' + +Render the entire tree, save in file 'file.eps' and show using gv, run: + + ./dump-asy.pl --save file.eps + +=head1 OPTIONS + +=over 8 + +=item B<--gv> + +=item B<--no-gv> + +Enable or disable showing the result through gv. If disabled, an .eps file will +be saved in the current working directory. Enabled by default. + +=item B<--save> + +Save result using the specified file-name. If omitted, no file will be saved +when using '--gv' or a random name will be used when using '--no-gv'. + +=back diff --git a/debian/changelog b/debian/changelog index 76fe1577..35b3f9f6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i3-wm (4.15.1-1) unstable; urgency=medium + + * New upstream release. + + -- Michael Stapelberg Sat, 10 Mar 2018 17:27:26 +0100 + i3-wm (4.15-1) unstable; urgency=medium * New upstream release. diff --git a/debian/control b/debian/control index 46e35dfe..71a2599c 100644 --- a/debian/control +++ b/debian/control @@ -40,7 +40,7 @@ Description: metapackage (i3 window manager, screen locker, menu, statusbar) Package: i3-wm Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, x11-utils +Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} Provides: x-window-manager 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 diff --git a/docs/debugging b/docs/debugging index dd26f98d..562a11f2 100644 --- a/docs/debugging +++ b/docs/debugging @@ -160,7 +160,8 @@ flood kicks. == Debugging i3bar -To debug i3bar problems, add +verbose yes+ to all +bar {}+ blocks in your i3 +To debug i3bar problems, use the +--verbose+ commandline parameter, +or add +verbose yes+ to all +bar {}+ blocks in your i3 config, reload your config and then restart all i3bar instances like this: --------------------------------------------------------------------- diff --git a/docs/i3bar-protocol b/docs/i3bar-protocol index cf86531c..826cae53 100644 --- a/docs/i3bar-protocol +++ b/docs/i3bar-protocol @@ -107,7 +107,7 @@ stop_signal:: processing. The default value (if none is specified) is SIGSTOP. cont_signal:: - Specify to i3bar the signal (as an integer)to send to continue your + Specify to i3bar the signal (as an integer) to send to continue your processing. The default value (if none is specified) is SIGCONT. click_events:: @@ -118,7 +118,8 @@ click_events:: full_text:: The +full_text+ will be displayed by i3bar on the status line. This is the - only required key. + only required key. If +full_text+ is an empty string, the block will be + skipped. 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 @@ -242,6 +243,9 @@ relative_x, relative_y:: of the block width, height:: Width and height (in px) of the block +modifiers:: + An array of the modifiers active when the click occurred. The order in which + modifiers are listed is not guaranteed. *Example*: ------------------------------------------ @@ -249,6 +253,7 @@ width, height:: "name": "ethernet", "instance": "eth0", "button": 1, + "modifiers": ["Shift", "Mod1"], "x": 1320, "y": 1400, "relative_x": 12, diff --git a/docs/ipc b/docs/ipc index 8b767ade..bcf8df1a 100644 --- a/docs/ipc +++ b/docs/ipc @@ -65,6 +65,7 @@ to do that). | 8 | +GET_BINDING_MODES+ | <<_binding_modes_reply,BINDING_MODES>> | Gets the names of all currently configured binding modes. | 9 | +GET_CONFIG+ | <<_config_reply,CONFIG>> | Returns the last loaded i3 config. | 10 | +SEND_TICK+ | <<_tick_reply,TICK>> | Sends a tick event with the specified payload. +| 11 | +SYNC+ | <<_sync_reply,SYNC>> | Sends an i3 sync event with the specified random value to the specified window. |====================================================== So, a typical message could look like this: @@ -327,6 +328,8 @@ window (integer):: This field is set to null for split containers or otherwise empty containers. This ID corresponds to what xwininfo(1) and other X11-related tools display (usually in hex). +window_properties (map):: + X11 window properties title, instance, class, window_role and transient_for. urgent (bool):: Whether this container (window, split container, floating container or workspace) has the urgency hint set, directly or indirectly. All parent @@ -422,6 +425,12 @@ JSON dump: "width": 1280, "height": 782 }, + "window_properties": { + "class": "Evince", + "instance": "evince", + "title": "Properties", + "transient_for": 52428808 + }, "floating_nodes": [], "nodes": [ @@ -654,6 +663,18 @@ events generated prior to the +SEND_TICK+ message (happened-before relation). { "success": true } ------------------- +[[_sync_reply]] +=== SYNC reply + +The reply is a map containing the "success" member. After the reply was +received, the https://i3wm.org/docs/testsuite.html#i3_sync[i3 sync message] was +responded to. + +*Example:* +------------------- +{ "success": true } +------------------- + == Events [[events]] @@ -672,6 +693,14 @@ program does not want to cope which such kinds of race conditions (an event based library may not have a problem here), I suggest you create a separate connection to receive events. +If an event message needs to be sent and the socket is not writeable (write +returns EAGAIN, happens when the socket doesn't have enough buffer space for +writing new data) then i3 uses a queue system to store outgoing messages for +each client. This is combined with a timer: if the message queue for a client is +not empty and no data where successfully written in the past 10 seconds, the +connection is killed. Practically, this means that your client should try to +always read events from the socket to avoid having its connection closed. + === Subscribing to events By sending a message of type SUBSCRIBE with a JSON-encoded array as payload diff --git a/docs/layout-saving b/docs/layout-saving index e90ecada..f31b5e21 100644 --- a/docs/layout-saving +++ b/docs/layout-saving @@ -219,13 +219,15 @@ the window which matches any of the criteria. As an example: A layout file as generated by +i3-save-tree(1)+ is not strictly valid JSON: -1. Layout files contain multiple “JSON documents” on the top level, whereas the - JSON standard only allows precisely one “document” (array or hash). +1. Layout files contain multiple “JSON texts” at the top level. The JSON + standard doesn't prohibit this, but in practice most JSON parsers only + allow precisely one “text” per document/file, and will mark multiple texts + as invalid JSON. -2. Layout files contain comments which are not standardized, but understood by - many parsers. +2. Layout files contain comments which are not allowed by the JSON standard, + but are understood by many parsers. -Both deviations from the JSON standard are to make manual editing by humans +Both of these deviations from the norm are to make manual editing by humans easier. In case you are writing a more elaborate tool for manipulating these 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 diff --git a/docs/userguide b/docs/userguide index ba314af1..91060ab2 100644 --- a/docs/userguide +++ b/docs/userguide @@ -245,9 +245,11 @@ you open a new terminal, it will open below the current one. So, how can you open a new terminal window to the *right* of the current one? The solution is to use +focus parent+, which will focus the +Parent Container+ of -the current +Container+. In this case, you would focus the +Vertical Split -Container+ which is *inside* the horizontally oriented workspace. Thus, now new -windows will be opened to the right of the +Vertical Split Container+: +the current +Container+. In default configuration, use +$mod+a+ to navigate one ++Container+ up the tree (you can repeat this multiple times until you get to the ++Workspace Container+). In this case, you would focus the +Vertical Split Container+ +which is *inside* the horizontally oriented workspace. Thus, now new windows will be +opened to the right of the +Vertical Split Container+: image::tree-shot3.png["shot3",title="Focus parent, then open new terminal"] @@ -585,6 +587,16 @@ workspace_layout default|stacking|tabbed workspace_layout tabbed --------------------- +=== Window title alignment + +This option determines the window title's text alignment. +Default is +left+ + +*Syntax*: +--------------------------------------------- +title_align left|center|right +--------------------------------------------- + === Default border style for new windows This option determines which border style new windows will have. The default is @@ -730,7 +742,8 @@ resource database to achieve an easily maintainable, consistent color theme across many X applications. Defining a resource will load this resource from the resource database and -assign its value to the specified variable. A fallback must be specified in +assign its value to the specified variable. This is done verbatim and the value +must therefore be in the format that i3 uses. A fallback must be specified in case the resource cannot be loaded from the database. *Syntax*: @@ -754,14 +767,23 @@ set_from_resource $black i3wm.color0 #000000 To automatically make a specific window show up on a specific workspace, you can use an *assignment*. You can match windows by using any criteria, -see <>. It is recommended that you match on window classes -(and instances, when appropriate) instead of window titles whenever possible -because some applications first create their window, and then worry about -setting the correct title. Firefox with Vimperator comes to mind. The window -starts up being named Firefox, and only when Vimperator is loaded does the -title change. As i3 will get the title as soon as the application maps the -window (mapping means actually displaying it on the screen), you’d need to have -to match on 'Firefox' in this case. +see <>. The difference between +assign+ and ++for_window move to workspace+ is that the former will only be +executed when the application maps the window (mapping means actually displaying +it on the screen) but the latter will be executed whenever a window changes its +properties to something that matches the specified criteria. + +Thus, it is recommended that you match on window classes (and instances, when +appropriate) instead of window titles whenever possible because some +applications first create their window, and then worry about setting the correct +title. Firefox with Vimperator comes to mind. The window starts up being named +Firefox, and only when Vimperator is loaded does the title change. As i3 will +get the title as soon as the application maps the window, you’d need to have to +match on 'Firefox' in this case. +Another known issue is with Spotify, which doesn't set the class hints when +mapping the window, meaning you'll have to use a +for_window+ rule to assign +Spotify to a specific workspace. +Finally, using +assign [tiling]+ and +assign [floating]+ is not supported. You can also assign a window to show up on a specific output. You can use RandR names such as +VGA1+ or names relative to the output with the currently focused @@ -887,7 +909,7 @@ the second screen and so on). *Syntax*: ------------------------------------- -workspace output +workspace output [output2]… ------------------------------------- The 'output' is the name of the RandR output you attach your screen to. On a @@ -906,12 +928,15 @@ monitor name is “Dell UP2414Q”. entire monitor, i3 will still use the entire area of the containing monitor rather than that of just the output's.) +You can specify multiple outputs. The first available will be used. + If you use named workspaces, they must be quoted: *Examples*: --------------------------- workspace 1 output LVDS1 -workspace 5 output VGA1 +workspace 2 output primary +workspace 5 output VGA1 LVDS1 workspace "2: vim" output VGA1 --------------------------- @@ -991,7 +1016,7 @@ ipc-socket ~/.i3/i3-ipc.sock ---------------------------- You can then use the +i3-msg+ application to perform any command listed in -the next section. +<>. === Focus follows mouse @@ -1117,6 +1142,7 @@ force_xinerama yes Also note that your output names are not descriptive (like +HDMI1+) when using Xinerama, instead they are counted up, starting at 0: +xinerama-0+, +xinerama-1+, … +[[workspace_auto_back_and_forth]] === Automatic back-and-forth when switching to the current workspace This configuration directive enables automatic +workspace back_and_forth+ (see @@ -1594,7 +1620,7 @@ bar { } ------------------------ -=== Strip workspace numbers +=== Strip workspace numbers/name Specifies whether workspace numbers should be displayed within the workspace buttons. This is useful if you want to have a named workspace that stays in @@ -1605,11 +1631,15 @@ the form "[n]:[NAME]" will display only the name. You could use this, for instance, to display Roman numerals rather than digits by naming your workspaces to "1:I", "2:II", "3:III", "4:IV", ... +When +strip_workspace_name+ is set to +yes+, any workspace that has a name of +the form "[n]:[NAME]" will display only the number. + The default is to display the full name within the workspace button. *Syntax*: ------------------------------ strip_workspace_numbers yes|no +strip_workspace_name yes|no ------------------------------ *Example*: @@ -1707,6 +1737,7 @@ bar { } -------------------------------------- +[[list_of_commands]] == List of commands Commands are what you bind to specific keypresses. You can also issue commands @@ -2025,10 +2056,13 @@ Use the +move+ command to move a container. # defaults to 10 pixels. move [ px] -# Moves the container either to a specific location -# or to the center of the screen. If 'absolute' is -# used, it is moved to the center of all outputs. -move [absolute] position [px] [px] +# Moves the container to the specified pos_x and pos_y +# coordinates on the screen. +move position [px] [px] + +# Moves the container to the center of the screen. +# If 'absolute' is used, it is moved to the center of +# all outputs. move [absolute] position center # Moves the container to the current position of the @@ -2113,8 +2147,8 @@ for_window [instance=notepad] sticky enable To change to a specific workspace, use the +workspace+ command, followed by the number or name of the workspace. Pass the optional flag -+--no-auto-back-and-forth+ to disable <> for this specific call -only. ++--no-auto-back-and-forth+ to disable <> for this +specific call only. To move containers to specific workspaces, use +move container to workspace+. @@ -2253,8 +2287,7 @@ See <> for how to move a container/workspace to a different RandR output. [[move_to_outputs]] -[[_moving_containers_workspaces_to_randr_outputs]] -=== Moving containers/workspaces to RandR outputs +=== [[_moving_containers_workspaces_to_randr_outputs]]Moving containers/workspaces to RandR outputs To move a container to another RandR output (addressed by names like +LVDS1+ or +VGA1+) or to a RandR output identified by a specific direction (like +left+, @@ -2313,20 +2346,21 @@ If you want to resize containers/windows using your keyboard, you can use the *Syntax*: ------------------------------------------------------- resize grow|shrink [ px [or ppt]] -resize set [px | ppt] [px | ppt] +resize set [width] [px | ppt] +resize set height [px | ppt] +resize set [width] [px | ppt] [height] [px | ppt] ------------------------------------------------------- Direction can either be one of +up+, +down+, +left+ or +right+. Or you can be -less specific and use +width+ or +height+, in which case i3 will take/give -space from all the other containers. The optional pixel argument specifies by -how many pixels a *floating container* should be grown or shrunk (the default -is 10 pixels). The ppt argument means percentage points and specifies by how -many percentage points a *tiling container* should be grown or shrunk (the -default is 10 percentage points). +less specific and use +width+ or +height+, in which case i3 will take/give space +from all the other containers. The optional pixel argument specifies by how many +pixels a container should be grown or shrunk (the default is 10 pixels). The +optional ppt argument means "percentage points", and if specified it indicates +that a *tiling container* should be grown or shrunk by that many points, instead +of by the +px+ value. -Notes about +resize set+: a value of 0 for or means "do -not resize in this direction", and resizing a tiling container by +px+ is not -implemented. +Note about +resize set+: a value of 0 for or means "do not +resize in this direction". It is recommended to define bindings for resizing in a dedicated binding mode. See <> and the example in the i3 @@ -2469,7 +2503,9 @@ To change the border of the current client, you can use +border normal+ to use t border (including window title), +border pixel 1+ to use a 1-pixel border (no window title) and +border none+ to make the client borderless. -There is also +border toggle+ which will toggle the different border styles. +There is also +border toggle+ which will toggle the different border styles. The +optional pixel argument can be used to specify the border width when switching +to the normal and pixel styles. Note that "pixel" refers to logical pixel. On HiDPI displays, a logical pixel may be represented by multiple physical pixels, so +pixel 1+ might not @@ -2477,8 +2513,8 @@ necessarily translate into a single pixel row wide border. *Syntax*: ----------------------------------------------- -border normal|pixel [] -border none|toggle +border normal|pixel|toggle [] +border none # legacy syntax, equivalent to "border pixel 1" border 1pixel diff --git a/etc/config b/etc/config index 3be9831d..da51d570 100644 --- a/etc/config +++ b/etc/config @@ -147,7 +147,7 @@ bindsym Mod1+Shift+c reload # restart i3 inplace (preserves your layout/session, can be used to upgrade i3) bindsym Mod1+Shift+r restart # exit i3 (logs you out of your X session) -bindsym Mod1+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'" +bindsym Mod1+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -B 'Yes, exit i3' 'i3-msg exit'" # resize window (you can also use the mouse for that) mode "resize" { diff --git a/etc/config.keycodes b/etc/config.keycodes index 2d56876c..6fc19426 100644 --- a/etc/config.keycodes +++ b/etc/config.keycodes @@ -133,7 +133,7 @@ bindcode $mod+Shift+54 reload # restart i3 inplace (preserves your layout/session, can be used to upgrade i3) bindcode $mod+Shift+27 restart # exit i3 (logs you out of your X session) -bindcode $mod+Shift+26 exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'" +bindcode $mod+Shift+26 exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -B 'Yes, exit i3' 'i3-msg exit'" # resize window (you can also use the mouse for that) mode "resize" { diff --git a/generate-command-parser.pl b/generate-command-parser.pl index 4c45b6ed..052e4c66 100755 --- a/generate-command-parser.pl +++ b/generate-command-parser.pl @@ -77,7 +77,7 @@ for my $line (@lines) { ($line =~ / ^\s* # skip leading whitespace ([a-z_]+ \s* = \s*|) # optional identifier - (.*?) -> \s* # token + (.*?) -> \s* # token (.*) # optional action /x); diff --git a/i3-config-wizard/main.c b/i3-config-wizard/main.c index b368921f..4b556657 100644 --- a/i3-config-wizard/main.c +++ b/i3-config-wizard/main.c @@ -48,6 +48,9 @@ #include #include +#define SN_API_NOT_YET_FROZEN 1 +#include + #include #include #include @@ -101,7 +104,7 @@ static struct xkb_keymap *xkb_keymap; static uint8_t xkb_base_event; static uint8_t xkb_base_error; -static void finish(); +static void finish(void); #include "GENERATED_config_enums.h" @@ -213,7 +216,7 @@ static const char *get_string(const char *identifier) { static void clear_stack(void) { for (int c = 0; c < 10; c++) { - if (stack[c].type == STACK_STR && stack[c].val.str != NULL) + if (stack[c].type == STACK_STR) free(stack[c].val.str); stack[c].identifier = NULL; stack[c].val.str = NULL; @@ -293,6 +296,7 @@ static char *next_state(const cmdp_token *token) { } sasprintf(&res, "bindsym %s%s%s %s%s\n", (modifiers == NULL ? "" : modrep), (modifiers == NULL ? "" : "+"), str, (release == NULL ? "" : release), get_string("command")); clear_stack(); + free(modrep); return res; } @@ -478,7 +482,7 @@ static void txt(int col, int row, char *text, color_t fg, color_t bg) { * Handles expose events, that is, draws the window contents. * */ -static int handle_expose() { +static int handle_expose(void) { const color_t black = draw_util_hex_to_color("#000000"); const color_t white = draw_util_hex_to_color("#FFFFFF"); const color_t green = draw_util_hex_to_color("#00FF00"); @@ -631,15 +635,13 @@ static void handle_button_press(xcb_button_press_event_t *event) { modifier = MOD_Mod1; handle_expose(); } - - return; } /* * Creates the config file and tells i3 to reload. * */ -static void finish() { +static void finish(void) { printf("creating \"%s\"...\n", config_path); struct xkb_context *xkb_context; @@ -745,10 +747,12 @@ int main(int argc, char *argv[]) { char *pattern = "pango:monospace 8"; char *patternbold = "pango:monospace bold 8"; int o, option_index = 0; + bool headless_run = false; static struct option long_options[] = { {"socket", required_argument, 0, 's'}, {"version", no_argument, 0, 'v'}, + {"modifier", required_argument, 0, 'm'}, {"limit", required_argument, 0, 'l'}, {"prompt", required_argument, 0, 'P'}, {"prefix", required_argument, 0, 'p'}, @@ -756,7 +760,7 @@ int main(int argc, char *argv[]) { {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}}; - char *options_string = "s:vh"; + char *options_string = "sm:vh"; while ((o = getopt_long(argc, argv, options_string, long_options, &option_index)) != -1) { switch (o) { @@ -767,9 +771,18 @@ int main(int argc, char *argv[]) { case 'v': printf("i3-config-wizard " I3_VERSION "\n"); return 0; + case 'm': + headless_run = true; + if (strcmp(optarg, "alt") == 0) + modifier = MOD_Mod1; + else if (strcmp(optarg, "win") == 0) + modifier = MOD_Mod4; + else + err(EXIT_FAILURE, "Invalid modifier key %s", optarg); + break; case 'h': printf("i3-config-wizard " I3_VERSION "\n"); - printf("i3-config-wizard [-s ] [-v]\n"); + printf("i3-config-wizard [-s ] [-m win|alt] [-v] [-h]\n"); return 0; } } @@ -826,12 +839,22 @@ int main(int argc, char *argv[]) { modmap_cookie = xcb_get_modifier_mapping(conn); symbols = xcb_key_symbols_alloc(conn); + if (headless_run) { + finish(); + return 0; + } + /* Place requests for the atoms we need as soon as possible */ #define xmacro(atom) \ xcb_intern_atom_cookie_t atom##_cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom); #include "atoms.xmacro" #undef xmacro + /* Init startup notification. */ + SnDisplay *sndisplay = sn_xcb_display_new(conn, NULL, NULL); + SnLauncheeContext *sncontext = sn_launchee_context_new_from_environment(sndisplay, screen); + sn_display_unref(sndisplay); + root_screen = xcb_aux_get_screen(conn, screen); root = root_screen->root; @@ -864,6 +887,9 @@ int main(int argc, char *argv[]) { 0, /* back pixel: black */ XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS}); + if (sncontext) { + sn_launchee_context_setup_window(sncontext, win); + } /* Map the window (make it visible) */ xcb_map_window(conn, win); @@ -925,6 +951,12 @@ int main(int argc, char *argv[]) { exit(-1); } + /* Startup complete. */ + if (sncontext) { + sn_launchee_context_complete(sncontext); + sn_launchee_context_unref(sncontext); + } + xcb_flush(conn); xcb_generic_event_t *event; @@ -937,13 +969,12 @@ int main(int argc, char *argv[]) { /* Strip off the highest bit (set if the event is generated) */ int type = (event->response_type & 0x7F); + /* TODO: handle mappingnotify */ switch (type) { case XCB_KEY_PRESS: handle_key_press(NULL, conn, (xcb_key_press_event_t *)event); break; - /* TODO: handle mappingnotify */ - case XCB_BUTTON_PRESS: handle_button_press((xcb_button_press_event_t *)event); break; diff --git a/i3-input/main.c b/i3-input/main.c index efb7b20c..d1a2efd7 100644 --- a/i3-input/main.c +++ b/i3-input/main.c @@ -156,7 +156,7 @@ static int handle_key_release(void *ignored, xcb_connection_t *conn, xcb_key_rel return 1; } -static void finish_input() { +static void finish_input(void) { char *command = (char *)concat_strings(glyphs_utf8, input_position); /* count the occurrences of %s in the string */ diff --git a/i3-msg/main.c b/i3-msg/main.c index 91a714e5..fe111416 100644 --- a/i3-msg/main.c +++ b/i3-msg/main.c @@ -95,8 +95,10 @@ static int reply_start_map_cb(void *params) { static int reply_end_map_cb(void *params) { if (!last_reply.success) { - fprintf(stderr, "ERROR: Your command: %s\n", last_reply.input); - fprintf(stderr, "ERROR: %s\n", last_reply.errorposition); + if (last_reply.input) { + fprintf(stderr, "ERROR: Your command: %s\n", last_reply.input); + fprintf(stderr, "ERROR: %s\n", last_reply.errorposition); + } fprintf(stderr, "ERROR: %s\n", last_reply.error); } return 1; @@ -164,16 +166,18 @@ int main(int argc, char *argv[]) { uint32_t message_type = I3_IPC_MESSAGE_TYPE_RUN_COMMAND; char *payload = NULL; bool quiet = false; + bool monitor = false; static struct option long_options[] = { {"socket", required_argument, 0, 's'}, {"type", required_argument, 0, 't'}, {"version", no_argument, 0, 'v'}, {"quiet", no_argument, 0, 'q'}, + {"monitor", no_argument, 0, 'm'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}}; - char *options_string = "s:t:vhq"; + char *options_string = "s:t:vhqm"; while ((o = getopt_long(argc, argv, options_string, long_options, &option_index)) != -1) { if (o == 's') { @@ -202,25 +206,34 @@ int main(int argc, char *argv[]) { message_type = I3_IPC_MESSAGE_TYPE_GET_CONFIG; } else if (strcasecmp(optarg, "send_tick") == 0) { message_type = I3_IPC_MESSAGE_TYPE_SEND_TICK; + } else if (strcasecmp(optarg, "subscribe") == 0) { + message_type = I3_IPC_MESSAGE_TYPE_SUBSCRIBE; } else { printf("Unknown message type\n"); - printf("Known types: run_command, get_workspaces, get_outputs, get_tree, get_marks, get_bar_config, get_binding_modes, get_version, get_config, send_tick\n"); + printf("Known types: run_command, get_workspaces, get_outputs, get_tree, get_marks, get_bar_config, get_binding_modes, get_version, get_config, send_tick, subscribe\n"); exit(EXIT_FAILURE); } } else if (o == 'q') { quiet = true; + } else if (o == 'm') { + monitor = true; } else if (o == 'v') { printf("i3-msg " I3_VERSION "\n"); return 0; } else if (o == 'h') { printf("i3-msg " I3_VERSION "\n"); - printf("i3-msg [-s ] [-t ] \n"); + printf("i3-msg [-s ] [-t ] [-m] \n"); return 0; } else if (o == '?') { exit(EXIT_FAILURE); } } + if (monitor && message_type != I3_IPC_MESSAGE_TYPE_SUBSCRIBE) { + fprintf(stderr, "The monitor option -m is used with -t SUBSCRIBE exclusively.\n"); + exit(EXIT_FAILURE); + } + /* Use all arguments, separated by whitespace, as payload. * This way, you don’t have to do i3-msg 'mark foo', you can use * i3-msg mark foo */ @@ -244,9 +257,6 @@ int main(int argc, char *argv[]) { err(EXIT_FAILURE, "IPC: write()"); free(payload); - if (quiet) - return 0; - uint32_t reply_length; uint32_t reply_type; uint8_t *reply; @@ -273,8 +283,9 @@ int main(int argc, char *argv[]) { errx(EXIT_FAILURE, "IPC: Could not parse JSON reply."); } - /* NB: We still fall-through and print the reply, because even if one - * command failed, that doesn’t mean that all commands failed. */ + if (!quiet) { + printf("%.*s\n", reply_length, reply); + } } else if (reply_type == I3_IPC_REPLY_TYPE_CONFIG) { yajl_handle handle = yajl_alloc(&config_callbacks, NULL, NULL); yajl_status state = yajl_parse(handle, (const unsigned char *)reply, reply_length); @@ -287,12 +298,30 @@ int main(int argc, char *argv[]) { case yajl_status_error: errx(EXIT_FAILURE, "IPC: Could not parse JSON reply."); } + } else if (reply_type == I3_IPC_REPLY_TYPE_SUBSCRIBE) { + do { + free(reply); + if ((ret = ipc_recv_message(sockfd, &reply_type, &reply_length, &reply)) != 0) { + if (ret == -1) + err(EXIT_FAILURE, "IPC: read()"); + exit(1); + } - goto exit; + if (!(reply_type & I3_IPC_EVENT_MASK)) { + errx(EXIT_FAILURE, "IPC: Received reply of type %d but expected an event", reply_type); + } + + if (!quiet) { + fprintf(stdout, "%.*s\n", reply_length, reply); + fflush(stdout); + } + } while (monitor); + } else { + if (!quiet) { + printf("%.*s\n", reply_length, reply); + } } - printf("%.*s\n", reply_length, reply); -exit: free(reply); close(sockfd); diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c index e4628e30..4ce74939 100644 --- a/i3-nagbar/main.c +++ b/i3-nagbar/main.c @@ -32,6 +32,9 @@ #include #include +#define SN_API_NOT_YET_FROZEN 1 +#include + #include "i3-nagbar.h" /** This is the equivalent of XC_left_ptr. I’m not sure why xcb doesn’t have a @@ -52,6 +55,7 @@ typedef struct { char *action; int16_t x; uint16_t width; + bool terminal; } button_t; static xcb_window_t win; @@ -99,10 +103,10 @@ void debuglog(char *fmt, ...) { } /* - * Starts the given application by passing it through a shell. We use double fork - * to avoid zombie processes. As the started application’s parent exits (immediately), - * the application is reparented to init (process-id 1), which correctly handles - * childs, so we don’t have to do it :-). + * Starts the given application by passing it through a shell. We use double + * fork to avoid zombie processes. As the started application’s parent exits + * (immediately), the application is reparented to init (process-id 1), which + * correctly handles children, so we don’t have to do it :-). * * The shell is determined by looking for the SHELL environment variable. If it * does not exist, /bin/sh is used. @@ -115,7 +119,7 @@ static void start_application(const char *command) { setsid(); if (fork() == 0) { /* This is the child */ - execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, (void *)NULL); + execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, NULL); /* not reached */ } exit(0); @@ -184,7 +188,11 @@ static void handle_button_release(xcb_connection_t *conn, xcb_button_release_eve } char *terminal_cmd; - sasprintf(&terminal_cmd, "i3-sensible-terminal -e %s", link_path); + if (button->terminal) { + sasprintf(&terminal_cmd, "i3-sensible-terminal -e %s", link_path); + } else { + terminal_cmd = sstrdup(link_path); + } printf("argv0 = %s\n", argv0); printf("terminal_cmd = %s\n", terminal_cmd); @@ -358,12 +366,13 @@ int main(int argc, char *argv[]) { {"version", no_argument, 0, 'v'}, {"font", required_argument, 0, 'f'}, {"button", required_argument, 0, 'b'}, + {"button-no-terminal", required_argument, 0, 'B'}, {"help", no_argument, 0, 'h'}, {"message", required_argument, 0, 'm'}, {"type", required_argument, 0, 't'}, {0, 0, 0, 0}}; - char *options_string = "b:f:m:t:vh"; + char *options_string = "b:B:f:m:t:vh"; prompt = i3string_from_utf8("Please do not run this program."); @@ -385,12 +394,14 @@ int main(int argc, char *argv[]) { break; case 'h': printf("i3-nagbar " I3_VERSION "\n"); - printf("i3-nagbar [-m ] [-b