summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stapelberg <michael@stapelberg.de>2020-11-15 18:23:15 +0100
committerMichael Stapelberg <michael@stapelberg.de>2020-11-15 18:23:15 +0100
commite6af0a5427296947522a42b30b8a042fd0b68b33 (patch)
tree18268ddc25df141f51fb48e4b1340a3c2f6f879b
parent036903e8b2b9c38dd6e4566638b39e6ca1b6e5b9 (diff)
parent2e59f512e390fc0e9dc79ebd5d9469e905a19cdd (diff)
downloadi3-e6af0a5427296947522a42b30b8a042fd0b68b33.tar.gz
i3-e6af0a5427296947522a42b30b8a042fd0b68b33.zip
Merge branch 'next' into stable
-rw-r--r--.clang-format2
-rw-r--r--.dockerignore1
-rw-r--r--.github/CONTRIBUTING.md8
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.md3
-rw-r--r--.gitignore33
-rw-r--r--.travis.yml3
-rw-r--r--AnyEvent-I3/lib/AnyEvent/I3.pm4
-rw-r--r--I3_VERSION1
-rw-r--r--LICENSE41
-rw-r--r--Makefile.am619
-rw-r--r--PACKAGE-MAINTAINER18
-rw-r--r--README.md3
-rw-r--r--RELEASE-NOTES-4.14.161
-rw-r--r--RELEASE-NOTES-4.16.135
-rw-r--r--RELEASE-NOTES-4.18.325
-rw-r--r--RELEASE-NOTES-4.1981
-rw-r--r--configure.ac202
-rw-r--r--debian/changelog24
-rw-r--r--debian/compat2
-rw-r--r--debian/control4
-rw-r--r--debian/i3-wm.docs32
-rw-r--r--debian/i3-wm.manpages13
-rwxr-xr-xdebian/rules6
-rw-r--r--docs/bigpicture.asy19
-rw-r--r--docs/bigpicture.pngbin9179 -> 338214 bytes
-rw-r--r--docs/bigpicture.xcfbin30613 -> 0 bytes
-rw-r--r--docs/hacking-howto347
-rwxr-xr-xdocs/i3-pod2html16
-rw-r--r--docs/i3bar-protocol14
-rw-r--r--docs/ipc28
-rw-r--r--docs/refcard.html2
-rw-r--r--docs/testsuite12
-rw-r--r--docs/userguide75
-rw-r--r--etc/config9
-rw-r--r--etc/config.keycodes11
-rwxr-xr-xgenerate-command-parser.pl5
-rw-r--r--i3-config-wizard/atoms.xmacro6
-rw-r--r--i3-config-wizard/i3-config-wizard-atoms.xmacro.h8
-rw-r--r--i3-config-wizard/main.c31
-rw-r--r--i3-config-wizard/xcb.h4
-rwxr-xr-xi3-dmenu-desktop15
-rw-r--r--i3-dump-log/main.c31
-rw-r--r--i3-input/keysym2ucs.c3
-rw-r--r--i3-input/main.c52
-rw-r--r--i3-msg/main.c26
-rw-r--r--i3-nagbar/atoms.xmacro6
-rw-r--r--i3-nagbar/i3-nagbar-atoms.xmacro.h8
-rw-r--r--i3-nagbar/i3-nagbar.h18
-rw-r--r--i3-nagbar/main.c79
-rw-r--r--i3bar/include/child.h2
-rw-r--r--i3bar/include/common.h8
-rw-r--r--i3bar/include/configuration.h16
-rw-r--r--i3bar/include/outputs.h3
-rw-r--r--i3bar/include/trayclients.h3
-rw-r--r--i3bar/include/workspaces.h3
-rw-r--r--i3bar/src/child.c53
-rw-r--r--i3bar/src/config.c9
-rw-r--r--i3bar/src/ipc.c15
-rw-r--r--i3bar/src/main.c10
-rw-r--r--i3bar/src/mode.c6
-rw-r--r--i3bar/src/outputs.c22
-rw-r--r--i3bar/src/parse_json_header.c14
-rw-r--r--i3bar/src/workspaces.c12
-rw-r--r--i3bar/src/xcb.c135
-rw-r--r--include/all.h24
-rw-r--r--include/atoms.xmacro2
-rw-r--r--include/atoms_NET_SUPPORTED.xmacro35
-rw-r--r--include/atoms_rest.xmacro20
-rw-r--r--include/click.h2
-rw-r--r--include/commands.h18
-rw-r--r--include/configuration.h30
-rw-r--r--include/data.h87
-rw-r--r--include/floating.h2
-rw-r--r--include/handlers.h19
-rw-r--r--include/i3-atoms_NET_SUPPORTED.xmacro.h37
-rw-r--r--include/i3-atoms_rest.xmacro.h22
-rw-r--r--include/i3.h5
-rw-r--r--include/i3/ipc.h4
-rw-r--r--include/ipc.h10
-rw-r--r--include/libi3.h16
-rw-r--r--include/log.h5
-rw-r--r--include/shmlog.h1
-rw-r--r--include/util.h13
-rw-r--r--include/workspace.h63
-rw-r--r--include/xcb.h25
-rw-r--r--include/xcursor.h1
-rw-r--r--include/xinerama.h2
-rw-r--r--libi3/dpi.c1
-rw-r--r--libi3/draw_util.c3
-rw-r--r--libi3/fake_configure_notify.c1
-rw-r--r--libi3/font.c8
-rw-r--r--libi3/format_placeholders.c1
-rw-r--r--libi3/g_utf8_make_valid.c2
-rw-r--r--libi3/get_colorpixel.c13
-rw-r--r--libi3/get_exe_path.c10
-rw-r--r--libi3/get_mod_mask.c1
-rw-r--r--libi3/get_process_filename.c10
-rw-r--r--libi3/ipc_connect.c10
-rw-r--r--libi3/ipc_recv_message.c11
-rw-r--r--libi3/ipc_send_message.c8
-rw-r--r--libi3/is_debug_build.c11
-rw-r--r--libi3/mkdirp.c2
-rw-r--r--libi3/root_atom_contents.c7
-rw-r--r--libi3/safewrappers.c25
-rw-r--r--libi3/string.c3
-rw-r--r--libi3/strndup.c3
-rw-r--r--libi3/ucs2_conversion.c1
-rw-r--r--m4/ax_append_flag.m471
-rw-r--r--m4/ax_cflags_warn_all.m4122
-rw-r--r--m4/ax_check_compile_flag.m474
-rw-r--r--m4/ax_check_enable_debug.m4124
-rw-r--r--m4/ax_check_gnu_make.m484
-rw-r--r--m4/ax_check_link_flag.m474
-rw-r--r--m4/ax_code_coverage.m4273
-rw-r--r--m4/ax_configure_args.m470
-rw-r--r--m4/ax_enable_builddir.m4302
-rw-r--r--m4/ax_extend_srcdir.m486
-rw-r--r--m4/ax_pthread.m4485
-rw-r--r--m4/ax_require_defined.m437
-rw-r--r--m4/ax_sanitizers.m4130
-rw-r--r--meson.build719
-rwxr-xr-xmeson/meson-dist-script36
-rwxr-xr-xmeson/meson-install-i3-with-shmlog2
-rw-r--r--meson_options.txt10
-rw-r--r--parser-specs/commands.spec47
-rw-r--r--parser-specs/config.spec38
-rwxr-xr-xrelease.sh48
-rw-r--r--src/assignments.c4
-rw-r--r--src/bindings.c45
-rw-r--r--src/click.c127
-rw-r--r--src/commands.c275
-rw-r--r--src/commands_parser.c9
-rw-r--r--src/con.c139
-rw-r--r--src/config.c14
-rw-r--r--src/config_directives.c9
-rw-r--r--src/config_parser.c24
-rw-r--r--src/display_version.c9
-rw-r--r--src/drag.c2
-rw-r--r--src/ewmh.c20
-rw-r--r--src/fake_outputs.c8
-rw-r--r--src/floating.c17
-rw-r--r--src/handlers.c219
-rw-r--r--src/ipc.c86
-rw-r--r--src/load_layout.c15
-rw-r--r--src/log.c21
-rw-r--r--src/main.c54
-rw-r--r--src/manage.c42
-rw-r--r--src/match.c84
-rw-r--r--src/move.c2
-rw-r--r--src/output.c10
-rw-r--r--src/randr.c246
-rw-r--r--src/render.c34
-rw-r--r--src/resize.c4
-rw-r--r--src/restore_layout.c19
-rw-r--r--src/scratchpad.c14
-rw-r--r--src/sd-daemon.c24
-rw-r--r--src/sighandler.c15
-rw-r--r--src/startup.c22
-rw-r--r--src/tree.c10
-rw-r--r--src/util.c83
-rw-r--r--src/window.c4
-rw-r--r--src/workspace.c177
-rw-r--r--src/x.c90
-rw-r--r--src/xcb.c34
-rw-r--r--src/xcursor.c23
-rw-r--r--src/xinerama.c8
-rwxr-xr-xtestcases/complete-run.pl.in20
-rw-r--r--testcases/inject_randr1.5.c16
-rw-r--r--testcases/lib/i3test.pm.in2
-rw-r--r--testcases/lib/i3test/XTEST.pm2
-rw-r--r--testcases/t/116-nestedcons.t1
-rw-r--r--testcases/t/117-workspace.t15
-rw-r--r--testcases/t/119-match.t18
-rw-r--r--testcases/t/124-move.t34
-rw-r--r--testcases/t/132-move-workspace.t47
-rw-r--r--testcases/t/180-fd-leaks.t40
-rw-r--r--testcases/t/193-ipc-version.t1
-rw-r--r--testcases/t/201-config-parser.t35
-rw-r--r--testcases/t/210-mark-unmark.t10
-rw-r--r--testcases/t/271-for_window_tilingfloating.t58
-rw-r--r--testcases/t/297-assign-workspace-to-output.t22
-rw-r--r--testcases/t/310-client-message-sticky.t70
-rw-r--r--testcases/t/311-get-binding-modes.t41
-rw-r--r--testcases/t/542-layout-restore-remanage.t66
-rw-r--r--travis/bintray-autobuild-debian.json4
-rw-r--r--travis/bintray-autobuild-ubuntu.json4
-rwxr-xr-xtravis/check-formatting.sh2
-rwxr-xr-xtravis/check-spelling.pl19
-rwxr-xr-xtravis/debian-build.sh8
-rwxr-xr-xtravis/docker-build-and-push.sh4
-rwxr-xr-xtravis/docs.sh20
-rwxr-xr-xtravis/run-tests.sh4
-rw-r--r--travis/travis-base-386.Dockerfile4
-rw-r--r--travis/travis-base-ubuntu-386.Dockerfile4
-rw-r--r--travis/travis-base-ubuntu.Dockerfile4
-rw-r--r--travis/travis-base.Dockerfile4
196 files changed, 3292 insertions, 5092 deletions
diff --git a/.clang-format b/.clang-format
index 6e49d835..4a15e88e 100644
--- a/.clang-format
+++ b/.clang-format
@@ -9,3 +9,5 @@ PointerBindsToType: false
ColumnLimit: 0
SpaceBeforeParens: ControlStatements
SortIncludes: false
+ForEachMacros: [ TAILQ_FOREACH, TAILQ_FOREACH_REVERSE, SLIST_FOREACH, CIRCLEQ_FOREACH, CIRCLEQ_FOREACH_REVERSE, NODES_FOREACH, NODES_FOREACH_REVERSE, FOREACH_NONINTERNAL]
+TypenameMacros: [ SLIST_HEAD, SLIST_ENTRY, LIST_HEAD, LIST_ENTRY, SIMPLEQ_HEAD, SIMPLEQ_ENTRY, TAILQ_HEAD, TAILQ_ENTRY, CIRCLEQ_HEAD, CIRCLEQ_ENTRY ]
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 00000000..6b8710a7
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1 @@
+.git
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 84644060..40fd8399 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -26,10 +26,16 @@ Note that bug reports and feature requests for related projects should be filed
* Use the `next` branch for developing and sending your pull request.
* Use `clang-format` to format your code.
* Run the [testsuite](https://i3wm.org/docs/testsuite.html)
+* If your changes should be reported on the next release's changelog, also
+ update the [RELEASE-notes-next](../RELEASE-notes-next) file in the root
+ folder. Example of changes that should be reported are bug fixes present in
+ the latest stable version of i3 and new enhancements. Example of changes that
+ should not be reported are minor code improvements, documentation, regression
+ and fixes for bugs that were introduced in the `next` branch.
## Finding something to do
* Find a [reproducible bug](https://github.com/i3/i3/issues?utf8=%E2%9C%93&q=is%3Aopen+label%3Areproducible+label%3Abug+) from the issue tracker. These issues have been reviewed and confirmed by a project contributor.
* Find an [accepted enhancement](https://github.com/i3/i3/issues?utf8=%E2%9C%93&q=is%3Aopen+label%3Aaccepted+label%3Aenhancement) from the issue tracker. These have been approved and are ok to start working on.
-There's a very good [overview of the codebase](https://i3wm.org/docs/hacking-howto.html) available to get you started.
+There's an [overview of the codebase](https://i3wm.org/docs/hacking-howto.html) available to get you started.
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 910b0fca..a6df0a95 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -49,8 +49,9 @@ Please include your (complete) i3 config with which the issue occurs. You can ei
If you would like to help debugging the issue, please try to reduce the config such that it is as close to the default config as possible while still reproducing the issue. This can help us bisect the root cause.
-->
-<pre>
+<details><summary>Config file</summary><pre>
</pre>
+</details>
<!--
Providing a logfile can help us trace the root cause of an issue much quicker. You can learn how to generate the logfile here:
diff --git a/.gitignore b/.gitignore
index b2ebd4aa..6ee317db 100644
--- a/.gitignore
+++ b/.gitignore
@@ -40,31 +40,14 @@ docs/*.html
i3-command-parser.stamp
i3-config-parser.stamp
.clang_complete
+compile_commands.json
+/.ccls-cache
+/.clangd
LAST_VERSION
-################################################################################
-# https://raw.githubusercontent.com/github/gitignore/master/Autotools.gitignore
-################################################################################
+# We recommend building in a subdirectory called build.
+# If you chose a different directory name,
+# it is up to you to arrange for it to be ignored by git,
+# e.g. by listing your directory in .git/info/exclude.
+/build
-# http://www.gnu.org/software/automake
-
-Makefile.in
-/ar-lib
-/test-driver
-
-# http://www.gnu.org/software/autoconf
-
-/autom4te.cache
-/autoscan.log
-/autoscan-*.log
-/aclocal.m4
-/compile
-/config.h.in
-/config.guess
-/config.sub
-/configure
-/configure.scan
-/depcomp
-/install-sh
-/missing
-/stamp-h1
diff --git a/.travis.yml b/.travis.yml
index b56bf684..9935cb63 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -31,9 +31,10 @@ 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 -Wstrict-prototypes -Wmissing-prototypes -Werror -fno-common"'
+ - docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 -e CC ${BASENAME} /bin/sh -c 'rm -rf build; mkdir -p build && cd build && CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Wstrict-prototypes -Wmissing-prototypes -Werror -fno-common" meson .. -Ddocs=true -Dmans=true -Db_sanitize=address && ninja -v'
- 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
+ - docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 -e CC ${BASENAME} /bin/sh -c 'rm -rf distbuild; mkdir distbuild && cd distbuild && meson .. -Ddocs=true -Dmans=true && ninja -v dist'
- ./travis/skip-pkg.sh || docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/debian-build.sh deb/debian-amd64/DIST
- ./travis/skip-pkg.sh || docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME_UBUNTU} ./travis/debian-build.sh deb/ubuntu-amd64/DIST
- ./travis/skip-pkg.sh || docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME_386} linux32 ./travis/debian-build.sh deb/debian-i386/DIST
diff --git a/AnyEvent-I3/lib/AnyEvent/I3.pm b/AnyEvent-I3/lib/AnyEvent/I3.pm
index ae9e5bea..1f4e5bd3 100644
--- a/AnyEvent-I3/lib/AnyEvent/I3.pm
+++ b/AnyEvent-I3/lib/AnyEvent/I3.pm
@@ -101,11 +101,13 @@ use constant TYPE_GET_BINDING_MODES => 8;
use constant TYPE_GET_CONFIG => 9;
use constant TYPE_SEND_TICK => 10;
use constant TYPE_SYNC => 11;
+use constant TYPE_GET_BINDING_STATE => 12;
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_SYNC)
+ TYPE_GET_BINDING_MODES TYPE_GET_CONFIG TYPE_SEND_TICK TYPE_SYNC
+ TYPE_GET_BINDING_STATE)
] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{all} } );
diff --git a/I3_VERSION b/I3_VERSION
deleted file mode 100644
index 784debda..00000000
--- a/I3_VERSION
+++ /dev/null
@@ -1 +0,0 @@
-4.18.3-non-git
diff --git a/LICENSE b/LICENSE
index 6354f065..1f0872c7 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,27 +1,26 @@
Copyright © 2009, Michael Stapelberg and contributors
-All rights reserved.
Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
+modification, are permitted provided that the following conditions
+are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of Michael Stapelberg nor the
- names of contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY Michael Stapelberg ''AS IS'' AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL Michael Stapelberg BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Makefile.am b/Makefile.am
deleted file mode 100644
index ff1c2d32..00000000
--- a/Makefile.am
+++ /dev/null
@@ -1,619 +0,0 @@
-@CODE_COVERAGE_RULES@
-
-echo-version:
- @echo "@I3_VERSION@"
-
-bin_PROGRAMS = \
- i3 \
- i3bar/i3bar \
- i3-config-wizard/i3-config-wizard \
- i3-dump-log/i3-dump-log \
- i3-input/i3-input \
- i3-msg/i3-msg \
- i3-nagbar/i3-nagbar
-
-install-exec-hook:
- $(LN_S) -f i3 $(DESTDIR)$(bindir)/i3-with-shmlog
-
-uninstall-hook:
- rm -f $(DESTDIR)$(bindir)/i3-with-shmlog
-
-i3includedir=$(includedir)/i3
-i3include_HEADERS = \
- include/i3/ipc.h
-
-dist_bin_SCRIPTS = \
- i3-dmenu-desktop \
- i3-migrate-config-to-v4 \
- i3-save-tree \
- i3-sensible-editor \
- i3-sensible-pager \
- i3-sensible-terminal
-
-i3confdir = $(sysconfdir)/i3
-dist_i3conf_DATA = \
- etc/config \
- etc/config.keycodes
-
-applicationsdir = $(datarootdir)/applications
-xsessionsdir = $(datarootdir)/xsessions
-dist_applications_DATA = \
- share/applications/i3.desktop
-dist_xsessions_DATA = \
- share/xsessions/i3.desktop \
- share/xsessions/i3-with-shmlog.desktop
-
-noinst_LIBRARIES = libi3.a
-
-check_PROGRAMS = \
- test.commands_parser \
- test.config_parser \
- test.inject_randr15
-
-check_SCRIPTS = \
- testcases/complete-run.pl
-
-check_DATA = \
- anyevent-i3.stamp
-
-clean-check:
- rm -rf testsuite-* latest i3-cfg-for-* _Inline
-clean-local: clean-check
-
-TESTS = testcases/complete-run.pl
-
-EXTRA_DIST = \
- $(dist_docs_toc_DATA:.html=) \
- $(dist_docs_notoc_DATA:.html=) \
- AnyEvent-I3/Changes \
- AnyEvent-I3/MANIFEST \
- AnyEvent-I3/MANIFEST.SKIP \
- AnyEvent-I3/Makefile.PL \
- AnyEvent-I3/README \
- AnyEvent-I3/lib/AnyEvent/I3.pm \
- AnyEvent-I3/t/00-load.t \
- AnyEvent-I3/t/01-workspaces.t \
- AnyEvent-I3/t/02-sugar.t \
- AnyEvent-I3/t/boilerplate.t \
- AnyEvent-I3/t/manifest.t \
- AnyEvent-I3/t/pod-coverage.t \
- AnyEvent-I3/t/pod.t \
- contrib/dump-asy.pl \
- contrib/gtk-tree-watch.pl \
- contrib/i3-wsbar \
- contrib/per-workspace-layout.pl \
- contrib/trivial-bar-script.sh \
- docs/asciidoc-git.conf \
- docs/bigpicture.png \
- docs/i3-pod2html \
- docs/i3-sync.dia \
- docs/i3-sync.png \
- docs/i3-sync-working.dia \
- docs/i3-sync-working.png \
- docs/keyboard-layer1.png \
- docs/keyboard-layer2.png \
- docs/layout-saving-1.png \
- docs/logo-30.png \
- docs/modes.png \
- docs/refcard.html \
- docs/refcard_style.css \
- docs/single_terminal.png \
- docs/snapping.png \
- docs/tree-layout1.png \
- docs/tree-layout2.png \
- docs/tree-shot1.png \
- docs/tree-shot2.png \
- docs/tree-shot3.png \
- docs/tree-shot4.png \
- docs/two_columns.png \
- docs/two_terminals.png \
- docs/wsbar.dia \
- docs/wsbar.png \
- i3bar/LICENSE \
- libi3/README \
- $(asciidoc_MANS:.1=.man) \
- $(asciidoc_MANS:.1=.man) \
- man/asciidoc.conf.in \
- DEPENDS \
- I3_VERSION \
- LICENSE \
- PACKAGE-MAINTAINER \
- RELEASE-NOTES-4.18.3 \
- generate-command-parser.pl \
- parser-specs/commands.spec \
- parser-specs/config.spec \
- parser-specs/highlighting.vim \
- pseudo-doc.doxygen \
- testcases/complete-run.pl.in \
- testcases/i3-test.config \
- testcases/lib/i3test/Test.pm \
- testcases/lib/i3test/Util.pm \
- testcases/lib/i3test/XTEST.pm \
- testcases/lib/i3test.pm.in \
- testcases/lib/SocketActivation.pm \
- testcases/lib/StartXServer.pm \
- testcases/lib/StatusLine.pm \
- testcases/lib/TestWorker.pm \
- testcases/Makefile.PL \
- testcases/new-test \
- testcases/restart-state.golden \
- testcases/t \
- testcases/valgrind.supp
-
-# dirstamps contains directories which we want to be created in $(top_builddir)
-# so that our custom rules can store files in them.
-dirstamp = .dirstamp
-dirstamps = \
- docs/$(dirstamp) \
- man/$(dirstamp) \
- parser/$(dirstamp)
-DISTCLEANFILES = $(dirstamps)
-
-$(dirstamps):
- @stamp='$@'; $(MKDIR_P) "$${stamp%/*}"
- @: > $@
-
-################################################################################
-# docs generation
-################################################################################
-
-docs_tocdir = ${docdir}
-docs_notocdir = ${docdir}
-docs_poddir = ${docdir}
-if BUILD_DOCS
-dist_docs_toc_DATA = \
- docs/hacking-howto.html \
- docs/userguide.html \
- docs/ipc.html \
- docs/multi-monitor.html \
- docs/wsbar.html \
- docs/testsuite.html \
- docs/i3bar-protocol.html \
- docs/layout-saving.html
-
-dist_docs_notoc_DATA = \
- docs/debugging.html
-
-dist_docs_pod_DATA = \
- docs/lib-i3test.html \
- docs/lib-i3test-test.html
-
-$(dist_docs_toc_DATA): docs/%.html: docs/% docs/$(dirstamp)
- $(AM_V_GEN) @PATH_ASCIIDOC@ -a toc -n -o $@ $<
-
-$(dist_docs_notoc_DATA): docs/%.html: docs/% docs/$(dirstamp)
- $(AM_V_GEN) @PATH_ASCIIDOC@ -n -o $@ $<
-
-docs/lib-i3test.html: testcases/lib/i3test.pm docs/$(dirstamp)
- $(AM_V_GEN) $(top_srcdir)/docs/i3-pod2html $< $@
-
-docs/lib-i3test-test.html: testcases/lib/i3test/Test.pm docs/$(dirstamp)
- $(AM_V_GEN) $(top_srcdir)/docs/i3-pod2html $< $@
-
-else
-dist_docs_toc_DATA =
-dist_docs_notoc_DATA =
-dist_docs_pod_DATA =
-endif
-
-################################################################################
-# manpage generation
-################################################################################
-
-if BUILD_MANS
-dist_man1_MANS = \
- $(asciidoc_MANS) \
- $(pod_MANS)
-
-asciidoc_MANS = \
- man/i3.1 \
- man/i3bar.1 \
- man/i3-msg.1 \
- man/i3-input.1 \
- man/i3-nagbar.1 \
- man/i3-config-wizard.1 \
- man/i3-migrate-config-to-v4.1 \
- man/i3-sensible-editor.1 \
- man/i3-sensible-pager.1 \
- man/i3-sensible-terminal.1 \
- man/i3-dump-log.1
-
-pod_MANS = \
- man/i3-dmenu-desktop.1 \
- man/i3-save-tree.1
-
-$(asciidoc_MANS): man/%.1: man/%.xml man/$(dirstamp)
- $(AM_V_GEN) out='$@'; @PATH_XMLTO@ man -o "$${out%/*}" $<
- @stamp='$@'; $(MKDIR_P) "$${stamp%/*}"
-
-man/%.xml: man/%.man man/asciidoc.conf man/$(dirstamp)
- $(AM_V_GEN) @PATH_ASCIIDOC@ -d manpage -b docbook -f $(top_builddir)/man/asciidoc.conf -o $@ $<
-
-$(pod_MANS): man/%.1: % man/$(dirstamp)
- $(AM_V_GEN) @PATH_POD2MAN@ --utf8 $< > $@
-else
-asciidoc_MANS =
-endif
-
-AM_CPPFLAGS = \
- -DSYSCONFDIR="\"$(sysconfdir)\"" \
- -I$(top_builddir)/parser \
- -I$(top_srcdir)/include \
- @AX_EXTEND_SRCDIR_CPPFLAGS@
-
-i3_CFLAGS = \
- $(AM_CFLAGS) \
- $(libi3_CFLAGS) \
- $(LIBSN_CFLAGS) \
- $(XCB_CFLAGS) \
- $(XCB_UTIL_CURSOR_CFLAGS) \
- $(XCB_UTIL_KEYSYM_CFLAGS) \
- $(XCB_UTIL_WM_CFLAGS) \
- $(XCB_UTIL_XRM_CFLAGS) \
- $(XKBCOMMON_CFLAGS) \
- $(YAJL_CFLAGS) \
- $(LIBPCRE_CFLAGS) \
- $(PTHREAD_CFLAGS) \
- $(CODE_COVERAGE_CFLAGS)
-
-i3_CPPFLAGS = \
- $(AM_CPPFLAGS) \
- $(CODE_COVERAGE_CPPFLAGS)
-
-i3_LDADD = \
- $(libi3_LIBS) \
- $(LIBSN_LIBS) \
- $(XCB_LIBS) \
- $(XCB_UTIL_CURSOR_LIBS) \
- $(XCB_UTIL_KEYSYMS_LIBS) \
- $(XCB_UTIL_WM_LIBS) \
- $(XCB_UTIL_XRM_LIBS) \
- $(XKBCOMMON_LIBS) \
- $(YAJL_LIBS) \
- $(LIBPCRE_LIBS) \
- $(PANGOCAIRO_LIBS) \
- $(PTHREAD_LIBS) \
- $(CODE_COVERAGE_LDFLAGS)
-
-libi3_CFLAGS = \
- $(AM_CFLAGS) \
- $(GLIBGOBJECT_CFLAGS) \
- $(XCB_CFLAGS) \
- $(XCB_UTIL_CFLAGS) \
- $(XCB_UTIL_XRM_CFLAGS) \
- $(YAJL_CFLAGS) \
- $(PANGOCAIRO_CFLAGS)
-
-libi3_LIBS = \
- $(top_builddir)/libi3.a \
- $(GLIBGOBJECT_LIBS) \
- $(XCB_LIBS) \
- $(XCB_UTIL_LIBS) \
- $(XCB_UTIL_XRM_LIBS) \
- $(YAJL_LIBS) \
- $(PANGOCAIRO_LIBS)
-
-libi3_a_CFLAGS = \
- $(libi3_CFLAGS)
-
-libi3_a_SOURCES = \
- include/libi3.h \
- libi3/dpi.c \
- libi3/draw_util.c \
- 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 \
- libi3/get_mod_mask.c \
- libi3/get_process_filename.c \
- libi3/get_visualtype.c \
- libi3/ipc_connect.c \
- libi3/ipc_recv_message.c \
- libi3/ipc_send_message.c \
- libi3/is_debug_build.c \
- libi3/mkdirp.c \
- libi3/resolve_tilde.c \
- libi3/root_atom_contents.c \
- libi3/safewrappers.c \
- libi3/string.c \
- libi3/strndup.c \
- libi3/ucs2_conversion.c
-
-i3_dump_log_i3_dump_log_CFLAGS = \
- $(AM_CFLAGS) \
- $(PTHREAD_CFLAGS) \
- $(libi3_CFLAGS)
-
-i3_dump_log_i3_dump_log_LDADD = \
- $(PTHREAD_LIBS) \
- $(libi3_LIBS)
-
-i3_dump_log_i3_dump_log_SOURCES = \
- i3-dump-log/main.c
-
-i3_input_i3_input_CFLAGS = \
- $(AM_CFLAGS) \
- $(libi3_CFLAGS)
-
-i3_input_i3_input_LDADD = \
- $(libi3_LIBS) \
- $(XCB_UTIL_KEYSYMS_LIBS)
-
-i3_input_i3_input_SOURCES = \
- i3-input/i3-input.h \
- i3-input/keysym2ucs.c \
- i3-input/keysym2ucs.h \
- i3-input/main.c
-
-i3_msg_i3_msg_CFLAGS = \
- $(AM_CFLAGS) \
- $(libi3_CFLAGS)
-
-i3_msg_i3_msg_LDADD = \
- $(libi3_LIBS)
-
-i3_msg_i3_msg_SOURCES = \
- i3-msg/main.c
-
-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 = \
- i3-nagbar/atoms.xmacro \
- i3-nagbar/i3-nagbar.h \
- i3-nagbar/main.c
-
-i3bar_i3bar_CPPFLAGS = \
- $(AM_CPPFLAGS) \
- -I$(top_srcdir)/i3bar/include
-
-i3bar_i3bar_CFLAGS = \
- $(AM_CFLAGS) \
- $(libi3_CFLAGS) \
- $(XCB_CFLAGS) \
- $(XKBCOMMON_CFLAGS) \
- $(PANGOCAIRO_CFLAGS) \
- $(YAJL_CFLAGS)
-
-i3bar_i3bar_LDADD = \
- $(libi3_LIBS) \
- $(XCB_LIBS) \
- $(XCB_UTIL_CURSOR_LIBS) \
- $(XKBCOMMON_LIBS) \
- $(PANGOCAIRO_LIBS) \
- $(YAJL_LIBS)
-
-i3bar_i3bar_SOURCES = \
- i3bar/include/child.h \
- i3bar/include/common.h \
- i3bar/include/configuration.h \
- i3bar/include/ipc.h \
- i3bar/include/mode.h \
- i3bar/include/outputs.h \
- i3bar/include/parse_json_header.h \
- i3bar/include/trayclients.h \
- i3bar/include/util.h \
- i3bar/include/workspaces.h \
- i3bar/include/xcb_atoms.def \
- i3bar/include/xcb.h \
- i3bar/src/child.c \
- i3bar/src/config.c \
- i3bar/src/ipc.c \
- i3bar/src/main.c \
- i3bar/src/mode.c \
- i3bar/src/outputs.c \
- i3bar/src/parse_json_header.c \
- i3bar/src/workspaces.c \
- i3bar/src/xcb.c
-
-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)
-
-i3_config_wizard_i3_config_wizard_SOURCES = \
- i3-config-wizard/atoms.xmacro \
- i3-config-wizard/main.c \
- i3-config-wizard/xcb.h
-
-test_inject_randr15_CPPFLAGS = \
- $(AM_CPPFLAGS)
-
-test_inject_randr15_CFLAGS = \
- $(AM_CFLAGS) \
- $(i3_CFLAGS)
-
-test_inject_randr15_SOURCES = \
- testcases/inject_randr1.5.c
-
-test_inject_randr15_LDADD = \
- $(i3_LDADD)
-
-test_commands_parser_CPPFLAGS = \
- $(AM_CPPFLAGS) \
- -DTEST_PARSER
-
-test_commands_parser_CFLAGS = \
- $(AM_CFLAGS) \
- $(i3_CFLAGS)
-
-test_commands_parser_SOURCES = \
- src/commands_parser.c
-
-test_commands_parser_LDADD = \
- $(i3_LDADD)
-
-test_config_parser_CPPFLAGS = \
- $(AM_CPPFLAGS) \
- -DTEST_PARSER
-
-test_config_parser_CFLAGS = \
- $(AM_CFLAGS) \
- $(i3_CFLAGS)
-
-test_config_parser_SOURCES = \
- src/config_parser.c
-
-test_config_parser_LDADD = \
- $(i3_LDADD)
-
-command_parser_SOURCES = \
- parser/GENERATED_command_enums.h \
- parser/GENERATED_command_tokens.h \
- parser/GENERATED_command_call.h
-
-config_parser_SOURCES = \
- parser/GENERATED_config_enums.h \
- parser/GENERATED_config_tokens.h \
- parser/GENERATED_config_call.h
-
-i3_SOURCES = \
- $(command_parser_SOURCES) \
- $(config_parser_SOURCES) \
- include/all.h \
- include/assignments.h \
- include/atoms_NET_SUPPORTED.xmacro \
- include/atoms_rest.xmacro \
- include/atoms.xmacro \
- include/bindings.h \
- include/click.h \
- include/cmdparse.h \
- include/commands.h \
- include/commands_parser.h \
- include/config_directives.h \
- include/configuration.h \
- include/config_parser.h \
- include/con.h \
- include/data.h \
- include/display_version.h \
- include/drag.h \
- include/ewmh.h \
- include/fake_outputs.h \
- include/floating.h \
- include/handlers.h \
- include/i3.h \
- include/ipc.h \
- include/key_press.h \
- include/load_layout.h \
- include/log.h \
- include/main.h \
- include/manage.h \
- include/match.h \
- include/move.h \
- include/output.h \
- include/queue.h \
- include/randr.h \
- include/regex.h \
- include/render.h \
- include/resize.h \
- include/restore_layout.h \
- include/scratchpad.h \
- include/sd-daemon.h \
- include/shmlog.h \
- include/sighandler.h \
- include/startup.h \
- include/sync.h \
- include/tree.h \
- include/util.h \
- include/window.h \
- include/workspace.h \
- include/xcb.h \
- include/xcursor.h \
- include/x.h \
- include/xinerama.h \
- include/yajl_utils.h \
- src/assignments.c \
- src/bindings.c \
- src/click.c \
- src/commands.c \
- src/commands_parser.c \
- src/con.c \
- src/config.c \
- src/config_directives.c \
- src/config_parser.c \
- src/display_version.c \
- src/drag.c \
- src/ewmh.c \
- src/fake_outputs.c \
- src/floating.c \
- src/handlers.c \
- src/ipc.c \
- src/key_press.c \
- src/load_layout.c \
- src/log.c \
- src/main.c \
- src/manage.c \
- src/match.c \
- src/move.c \
- src/output.c \
- src/randr.c \
- src/regex.c \
- src/render.c \
- src/resize.c \
- src/restore_layout.c \
- src/scratchpad.c \
- src/sd-daemon.c \
- src/sighandler.c \
- src/startup.c \
- src/sync.c \
- src/tree.c \
- src/util.c \
- src/version.c \
- src/window.c \
- src/workspace.c \
- src/x.c \
- src/xcb.c \
- src/xcursor.c \
- src/xinerama.c
-
-################################################################################
-# parser generation
-################################################################################
-
-$(command_parser_SOURCES): %.h: i3-command-parser.stamp
-
-$(config_parser_SOURCES): %.h: i3-config-parser.stamp
-
-src/i3-commands_parser.$(OBJEXT): i3-command-parser.stamp
-
-src/i3-config_parser.$(OBJEXT): i3-config-parser.stamp
-
-i3-command-parser.stamp: parser/$(dirstamp) generate-command-parser.pl parser-specs/commands.spec
- $(AM_V_GEN) $(top_srcdir)/generate-command-parser.pl --input=$(top_srcdir)/parser-specs/commands.spec --prefix=command
- $(AM_V_at) mv GENERATED_command_* $(top_builddir)/parser
- $(AM_V_at) touch $@
-
-i3-config-parser.stamp: parser/$(dirstamp) generate-command-parser.pl parser-specs/config.spec
- $(AM_V_GEN) $(top_srcdir)/generate-command-parser.pl --input=$(top_srcdir)/parser-specs/config.spec --prefix=config
- $(AM_V_at) mv GENERATED_config_* $(top_builddir)/parser
- $(AM_V_at) touch $@
-
-################################################################################
-# AnyEvent-I3 build process
-################################################################################
-
-anyevent-i3.stamp: AnyEvent-I3/lib/AnyEvent/I3.pm
- $(AM_V_BUILD) (cd $(top_srcdir)/AnyEvent-I3 && perl Makefile.PL && make)
- $(AM_V_at) touch $@
-
-CLEANFILES = \
- i3-command-parser.stamp \
- i3-config-parser.stamp \
- anyevent-i3.stamp
diff --git a/PACKAGE-MAINTAINER b/PACKAGE-MAINTAINER
index 953fac53..c5a7bea6 100644
--- a/PACKAGE-MAINTAINER
+++ b/PACKAGE-MAINTAINER
@@ -21,12 +21,14 @@ i3-sensible-terminal is used in the default configuration.
If your distribution has a mechanism to get the preferred terminal, such as the
x-terminal-emulator symlink in Debian, please use it in i3-sensible-terminal.
-On debian, compilation and installing the manpages looks like this:
+You can build i3 like you build any other software package which uses
+https://mesonbuild.com/; see
+https://mesonbuild.com/Quick-guide.html#compiling-a-meson-project
+In case you’re unfamiliar:
- autoreconf -fi
- mkdir -p build && cd build
- ../configure
- make -j8 install
+ $ mkdir -p build && cd build
+ $ meson ..
+ $ ninja
Please make sure that i3-migrate-config-to-v4 and i3-config-wizard are
installed with i3. The Perl script is necessary to (automatically) convert v3
@@ -35,10 +37,8 @@ config with the user’s preferred modifier and should be started on the first
start of i3 (it will automatically exit if it finds a config file).
If you have any questions, ideas, hints, problems or whatever, please do not
-hesitate to contact me. I will help you out. Just drop me an E-Mail (find the
-address at https://michael.stapelberg.de/Impressum/, scroll down to bottom),
-contact me using the same address in jabber or ask on our IRC channel:
-(#i3 on irc.freenode.net).
+hesitate to contact me. I will help you out. Please see
+https://i3wm.org/contact/
Thanks again for your efforts,
Michael
diff --git a/README.md b/README.md
index 6ac67541..a2d8206d 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,9 @@
[![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)
+[![Packages](https://repology.org/badge/latest-versions/i3.svg)](https://repology.org/metapackage/i3/versions)
+[![Packages](https://repology.org/badge/tiny-repos/i3.svg)](https://repology.org/metapackage/i3/versions)
+
i3 is a tiling window manager for X11.
For more information about i3, please see [the project's website](https://i3wm.org/) and [online documentation](https://i3wm.org/docs/).
diff --git a/RELEASE-NOTES-4.14.1 b/RELEASE-NOTES-4.14.1
deleted file mode 100644
index 22c83b2d..00000000
--- a/RELEASE-NOTES-4.14.1
+++ /dev/null
@@ -1,61 +0,0 @@
-
- ┌──────────────────────────────┐
- │ Release notes for i3 v4.14.1 │
- └──────────────────────────────┘
-
-This is i3 v4.14.1. This version is considered stable. All users of i3 are
-strongly encouraged to upgrade.
-
-This is a bugfix release for v4.14.
-
- ┌────────────────────────────┐
- │ Changes in i3 v4.14.1 │
- └────────────────────────────┘
-
- • docs/hacking-howto: promote contributing-related sections
- • docs/ipc: tree reply: document focus, nodes and 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 (existing since v4.14) GET_CONFIG request
- • docs/userguide: document that i3 can accept RandR output names
- • include AnyEvent-I3 in dist tarballs
- • append_layout: validate JSON before loading
- • move: fix erratic behavior with single container child jumping outputs
- • ipc: rename COMMAND to RUN_COMMAND for consistency
- • replace http:// with https:// where applicable
-
- ┌────────────────────────────┐
- │ Bugfixes │
- └────────────────────────────┘
-
- • fix various memory errors
- • fix output and tray_output related issues with RandR 1.5
- • avoid use of uninitialized in init_dpi_end
- • properly initialize sigaction struct
- • swap: invert condition to log debug message in correct situation
- • swap: fix crash on invalid container id
- • fix a crash when restarting with marks
- • i3bar: fix a memory leak
- • test workers: re-seed random number generator after fork
- • tests: run environment-modifying 533-randr15.t at the very end
- • tests: unflake t/257-keypress-group1-fallback.t
- • tests: unflake t/263-edge-borders.t
- • tests: unflake tests by not starting i3bar
- • fix a crash with configfiles which do not end in a newline.
- • append_layout: free incomplete containers when JSON parsing fails
- • layout toggle: fix crash with invalid parameters
- • outputs: avert crash by fixing focus when creating output containers
- • correctly raise floating videos to the top when switching between windows
- programmatically
- • fix crash when a floating window is tiled while being resized via mouse
-
- ┌────────────────────────────┐
- │ Thanks! │
- └────────────────────────────┘
-
-Thanks for testing, bugfixes, discussions and everything I forgot go out to:
-
- hwangcc23, Ingo Bürk, Kent Fredric, Martin T. H. Sandsmark, Orestis Floros,
- Theo Buehler, Vladimir Panteleev
-
--- Michael Stapelberg, 2017-09-24
diff --git a/RELEASE-NOTES-4.16.1 b/RELEASE-NOTES-4.16.1
deleted file mode 100644
index 88bddb42..00000000
--- a/RELEASE-NOTES-4.16.1
+++ /dev/null
@@ -1,35 +0,0 @@
-
- ┌──────────────────────────────┐
- │ Release notes for i3 v4.16.1 │
- └──────────────────────────────┘
-
-This is i3 v4.16.1. This version is considered stable. All users of i3 are
-strongly encouraged to upgrade.
-
-This is a bugfix release for v4.16.
-
- ┌────────────────────────────┐
- │ Bugfixes │
- └────────────────────────────┘
-
- • Truncate wm_name utf8 strings to first zero byte
- (fixes window title corruption)
- • Apply title_align to non-leaf containers
- Additionally, marks will now display for non-leaf containers.
- • attach_to_workspace: set new parent before tree_render
- (fixes a heap-use-after-free)
- • Use ipc queue for all messages
- (fixes an i3bar crash)
- • Fix crash with popups when fullscreen is non-leaf
- • Fix: render_con shows floating containers on wrong workspace
-
-
- ┌────────────────────────────┐
- │ Thanks! │
- └────────────────────────────┘
-
-Thanks for testing, bugfixes, discussions and everything I forgot go out to:
-
- Orestis Floros
-
--- Michael Stapelberg, 2019-01-27
diff --git a/RELEASE-NOTES-4.18.3 b/RELEASE-NOTES-4.18.3
deleted file mode 100644
index 5c14a398..00000000
--- a/RELEASE-NOTES-4.18.3
+++ /dev/null
@@ -1,25 +0,0 @@
-
- ┌──────────────────────────────┐
- │ Release notes for i3 v4.18.3 │
- └──────────────────────────────┘
-
-This is i3 v4.18.3. This version is considered stable. All users of i3 are
-strongly encouraged to upgrade.
-
-This is a bugfix release for v4.18.
-
- ┌────────────────────────────┐
- │ Bugfixes │
- └────────────────────────────┘
-
- • Bugfix: kick tray clients before destroying the bar
-
- ┌────────────────────────────┐
- │ Thanks! │
- └────────────────────────────┘
-
-Thanks for testing, bugfixes, discussions and everything I forgot go out to:
-
- Mark Guptill, Orestis Floros
-
--- Michael Stapelberg, 2020-10-19
diff --git a/RELEASE-NOTES-4.19 b/RELEASE-NOTES-4.19
new file mode 100644
index 00000000..cd5bf2c6
--- /dev/null
+++ b/RELEASE-NOTES-4.19
@@ -0,0 +1,81 @@
+
+ ┌──────────────────────────────┐
+ │ Release notes for i3 v4.19 │
+ └──────────────────────────────┘
+
+This is i3 v4.19. This version is considered stable. All users of i3 are
+strongly encouraged to upgrade.
+
+In this release, we switched from the autotools build system to the meson build
+system (https://mesonbuild.com/). Check https://github.com/i3/i3/issues/4086 for
+details. If this causes problems for you, you can revert the commit which
+removed autotools from the tree: we tried our best to keep both build systems
+working. Please reach out to us in that case!
+
+ ┌────────────────────────────┐
+ │ Changes in i3 v4.19 │
+ └────────────────────────────┘
+
+ • userguide: explain button6 and button7 (scroll wheel right/left)
+ • ipc: always include the marks property (even if empty)
+ • ipc: introduce GET_BINDING_STATE command
+ • ipc: clarify workspace name field semantics
+ • ipc: document parse_error COMMAND reply field
+ • i3bar: launch using exec to avoid leaving useless shell process
+ • i3bar: make dock client order deterministic (sorted by class/instance) as a
+ side effect, i3bars without an explicit bar-id will be sorted according
+ to their definition order in the config file
+ • i3bar: update config when necessary (reduces redraws on bar mode changes)
+ • i3bar: add coordinates relative to the current output in i3bar click events
+ • i3bar: add “nonprimary” output option
+ • i3bar: set WM_CLASS instance to bar id
+ • i3-input: add different exit codes for when i3-input fails
+ • i3-dmenu-desktop: Support symlinks in search path
+ • pod2html: render without stylesheet by default
+ • introduce “tiling_from” and ”floating_from” criteria
+ • mention rofi in default config file
+ • allow ppt values in move direction and move position commands
+ • allow matching on empty properties like class, title, etc.
+
+ ┌────────────────────────────┐
+ │ Bugfixes │
+ └────────────────────────────┘
+
+ • i3-nagbar: Use _PATH_BSHELL to ensure using a bourne shell
+ • i3bar: fix Xorg memory leak
+ • i3bar: fix hang when pausing/resuming bar program
+ • i3bar: fix crash on invalid JSON input
+ • i3bar: kick tray clients before destroying the bar
+ • ensure client windows have a size of at least 1px after resize
+ • correctly handle overlapping decorations
+ • limit workspace numbers within 0..INT32_MAX
+ • fix a bug with tiling resize inside floating container
+ • correctly handle mouse resize in fullscreen containers by
+ not propagating $mod+right click to fullscreen clients
+ • do not try to resize fullscreen and non-fullscreen windows
+ • do not focus floating windows changing workspace with ConfigureNotify
+ • set _NET_DESKTOP_VIEWPORT after randr changes
+ • fix a bug with i3-nagbar not starting after it has already started once
+ • fix conflict when moving parent of fullscreen window to workspace
+ • fix named workspace assignments on output changes
+ • fix named workspace assignment precedence on workspace renames
+ • fix windows getting swallowed more than once
+ • erase i3 --moreversion progress line before overwriting
+ • fix test case 180-fd-leaks when running on Fedora
+ • fix crash in `focus next sibling`
+ • fix moving tiling windows out of the scratchpad
+ • floating_maybe_reassign_ws: only re-focus if previously focused
+ (fixes a focus issue with KDE notifications)
+ • fix crash on invalid JSON input in stored layouts
+ • fix monitor change during/with i3 restart by moving
+ content for non-existing output containers
+
+Thanks for testing, bugfixes, discussions and everything I forgot go out to:
+
+ 6144, acheronfail, Albert Safin, Alessandro Vinciguerra, Andrey Burov,
+ Francesc Hervada-Sala, Heman Gandhi, Ian Fan, Ingo Bürk, izzel, Jason, Jason
+ Nader, Jorg Heymans, Joseph, Konstantin Kharlamov, Lukas Kern, Mark Guptill,
+ Martin T. H. Sandsmark, Matthew Martin, Maxim Schuwalow, Mike Sharov, Orestis
+ Floros, Vasily Fomin, Wilhelm Schuster, xzfc, zero77
+
+-- Michael Stapelberg, 2020-11-15
diff --git a/configure.ac b/configure.ac
deleted file mode 100644
index 8149464a..00000000
--- a/configure.ac
+++ /dev/null
@@ -1,202 +0,0 @@
-# -*- Autoconf -*-
-# Run autoreconf -fi to generate a configure script from this file.
-
-AC_PREREQ([2.69])
-AC_INIT([i3], [4.18.3], [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])
-# Default to silent rules, use V=1 to get verbose compilation output.
-AM_SILENT_RULES([yes])
-# Make it possible to disable maintainer mode to disable re-generation of build
-# system files.
-AM_MAINTAINER_MODE([enable])
-AC_CONFIG_SRCDIR([libi3/ipc_recv_message.c])
-AC_CONFIG_HEADERS([config.h])
-AC_CONFIG_MACRO_DIR([m4])
-
-dnl Verify macros defined in m4/ such as AX_SANITIZERS are not present in the
-dnl output, i.e. are replaced as expected. This line results in a better error
-dnl message when using aclocal < 1.13 (which does not understand
-dnl AC_CONFIG_MACRO_DIR) without passing the -I m4 parameter.
-m4_pattern_forbid([AX_SANITIZERS])
-
-# Verify we are using GNU make because we use '%'-style pattern rules in
-# Makefile.am, which are a GNU make extension. Pull requests to replace
-# '%'-style pattern rules with a more portable alternative are welcome.
-AX_CHECK_GNU_MAKE
-AS_VAR_IF([_cv_gnu_make_command], [""], [AC_MSG_ERROR([the i3 Makefile.am requires GNU make])])
-
-AX_EXTEND_SRCDIR
-
-AS_IF([test -e ${srcdir}/.git],
- [
- VERSION="$(git -C ${srcdir} describe --tags --abbrev=0)"
- I3_VERSION="$(git -C ${srcdir} describe --tags --always) ($(git -C ${srcdir} rev-list --format=%cd --date=short -n1 $(git rev-parse HEAD) | tail -n1), branch \\\"$(git -C ${srcdir} describe --tags --always --all | sed s:heads/::)\\\")"
- # Mirrors what libi3/is_debug_build.c does:
- is_release=$(test $(echo "${I3_VERSION}" | cut -d '(' -f 1 | wc -m) -lt 10 && echo yes || echo no)
- ],
- [
- VERSION="$(cut -d '-' -f 1 ${srcdir}/I3_VERSION | cut -d ' ' -f 1)"
- I3_VERSION="$(sed -e 's/@<:@\"?\\@:>@/\\&/g' ${srcdir}/I3_VERSION)"
- is_release="$(grep -q non-git ${srcdir}/I3_VERSION && echo no || echo yes)"
- ])
-AC_SUBST([I3_VERSION], [$I3_VERSION])
-MAJOR_VERSION="$(echo ${VERSION} | cut -d '.' -f 1)"
-MINOR_VERSION="$(echo ${VERSION} | cut -d '.' -f 2)"
-PATCH_VERSION="$(echo ${VERSION} | cut -d '.' -f 3)"
-AS_IF([test "x${PATCH_VERSION}" = x], [PATCH_VERSION=0])
-AC_DEFINE_UNQUOTED([I3_VERSION], ["${I3_VERSION}"], [i3 version])
-AC_DEFINE_UNQUOTED([MAJOR_VERSION], [${MAJOR_VERSION}], [i3 major version])
-AC_DEFINE_UNQUOTED([MINOR_VERSION], [${MINOR_VERSION}], [i3 minor version])
-AC_DEFINE_UNQUOTED([PATCH_VERSION], [${PATCH_VERSION}], [i3 patch version])
-
-AX_CODE_COVERAGE
-
-dnl is_release must be lowercase because AX_CHECK_ENABLE_DEBUG calls m4_tolower
-dnl on its fourth argument.
-AX_CHECK_ENABLE_DEBUG([yes], , [UNUSED_NDEBUG], [$is_release])
-
-AC_PROG_CC_C99
-
-# For strnlen() and vasprintf().
-AC_USE_SYSTEM_EXTENSIONS
-
-# Checks for typedefs, structures, and compiler characteristics.
-AC_CHECK_HEADER_STDBOOL
-dnl The error message should include the specific type which could not be
-dnl found, but I do not see a way to achieve that.
-AC_CHECK_TYPES([mode_t, off_t, pid_t, size_t, ssize_t], , [AC_MSG_FAILURE([cannot find required type])])
-
-# Checks for library functions.
-AC_FUNC_FORK
-AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
-AC_FUNC_STRNLEN
-AC_CHECK_FUNCS([atexit dup2 ftruncate getcwd gettimeofday localtime_r memchr memset mkdir rmdir setlocale socket strcasecmp strchr strdup strerror strncasecmp strrchr strspn strstr strtol strtoul], , [AC_MSG_FAILURE([cannot find the $ac_func function, which i3 requires])])
-AC_REPLACE_FUNCS([mkdirp strndup])
-
-# Checks for libraries.
-
-AC_SEARCH_LIBS([floor], [m], , [AC_MSG_FAILURE([cannot find the required floor() function despite trying to link with -lm])])
-
-# 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], [], [], [-pthread])
-
-AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <iconv.h>], [iconv_open(0, 0)])], ,
- [LIBS="-liconv $LIBS"
- AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <iconv.h>], [iconv_open(0, 0)])], ,
- [AC_MSG_FAILURE([cannot find the required iconv_open() function despite trying to link with -liconv])])]
-)
-
-AX_PTHREAD
-
-dnl Each prefix corresponds to a source tarball which users might have
-dnl downloaded in a newer version and would like to overwrite.
-PKG_CHECK_MODULES([LIBSN], [libstartup-notification-1.0])
-PKG_CHECK_MODULES([XCB], [xcb xcb-xkb xcb-xinerama xcb-randr xcb-shape])
-PKG_CHECK_MODULES([XCB_UTIL], [xcb-event xcb-util])
-PKG_CHECK_MODULES([XCB_UTIL_CURSOR], [xcb-cursor])
-PKG_CHECK_MODULES([XCB_UTIL_KEYSYMS], [xcb-keysyms])
-PKG_CHECK_MODULES([XCB_UTIL_WM], [xcb-icccm])
-PKG_CHECK_MODULES([XCB_UTIL_XRM], [xcb-xrm])
-PKG_CHECK_MODULES([XKBCOMMON], [xkbcommon xkbcommon-x11])
-PKG_CHECK_MODULES([YAJL], [yajl])
-PKG_CHECK_MODULES([LIBPCRE], [libpcre >= 8.10])
-PKG_CHECK_MODULES([PANGOCAIRO], [cairo >= 1.14.4 pangocairo])
-PKG_CHECK_MODULES([GLIBGOBJECT], [glib-2.0 gobject-2.0])
-
-# Checks for programs.
-AC_PROG_AWK
-AC_PROG_CPP
-AC_PROG_INSTALL
-AC_PROG_MAKE_SET
-AC_PROG_RANLIB
-AC_PROG_LN_S
-
-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
-
-AX_FLAGS_WARN_ALL
-AX_CHECK_COMPILE_FLAG([-Wunused-value], [AX_APPEND_FLAG([-Wunused-value], [AM_CFLAGS])])
-AC_SUBST(AM_CFLAGS)
-
-# Checks for header files.
-AC_CHECK_HEADERS([fcntl.h float.h inttypes.h limits.h locale.h netinet/in.h paths.h stddef.h stdint.h stdlib.h string.h sys/param.h sys/socket.h sys/time.h unistd.h], , [AC_MSG_FAILURE([cannot find the $ac_header header, which i3 requires])])
-
-AC_CONFIG_FILES([Makefile testcases/lib/i3test.pm man/asciidoc.conf])
-AC_CONFIG_FILES([testcases/complete-run.pl], [chmod +x testcases/complete-run.pl])
-
-# Enable address sanitizer for non-release builds. The performance hit is a
-# 50% increase of wallclock time for the testsuite on my machine.
-if test x$is_release = xyes; then
- default_sanitizers=
-else
- default_sanitizers=address
-fi
-AX_SANITIZERS(, [$default_sanitizers], [AC_DEFINE([I3_ASAN_ENABLED], [], [Enable ASAN])])
-
-AC_OUTPUT
-
-if test -z "${BUILD_DOCS_TRUE}"; then
- print_BUILD_DOCS=yes
-else
- print_BUILD_DOCS=no
-fi
-
-
-if test -z "${BUILD_MANS_TRUE}"; then
- print_BUILD_MANS=yes
-else
- print_BUILD_MANS=no
-fi
-
-in_git_worktree=`git rev-parse --is-inside-work-tree 2>/dev/null`
-if [[ "$in_git_worktree" = "true" ]]; then
- git_dir=`git rev-parse --git-dir 2>/dev/null`
- srcdir=`dirname "$git_dir"`
- exclude_dir=`pwd | sed "s,^$srcdir,,g"`
- if ! grep -q "^$exclude_dir" "$git_dir/info/exclude"; then
- echo "$exclude_dir" >> "$git_dir/info/exclude"
- fi
-fi
-
-echo \
-"--------------------------------------------------------------------------------
-build configured:
-
-AS_HELP_STRING([i3 version:], [`echo ${I3_VERSION} | sed 's,\\\\,,g'`])
-AS_HELP_STRING([is release version:], [${is_release}])
-
-AS_HELP_STRING([build manpages:], [${print_BUILD_MANS}])
-AS_HELP_STRING([build docs:], [${print_BUILD_DOCS}])
-AS_HELP_STRING([enable debug flags:], [${ax_enable_debug}])
-AS_HELP_STRING([code coverage:], [${CODE_COVERAGE_ENABLED}])
-AS_HELP_STRING([enabled sanitizers:], [${ax_enabled_sanitizers}])
-
-To compile, run:
-
- cd `pwd` && make -j8
---------------------------------------------------------------------------------"
diff --git a/debian/changelog b/debian/changelog
index 5e9d740a..3fddbe34 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,27 @@
+i3-wm (4.19-1) unstable; urgency=medium
+
+ * New upstream release.
+
+ -- Michael Stapelberg <stapelberg@debian.org> Mon, 19 Oct 2020 22:48:30 +0200
+
+i3-wm (4.18.3-1) unstable; urgency=medium
+
+ * New upstream release.
+
+ -- Michael Stapelberg <stapelberg@debian.org> Mon, 19 Oct 2020 22:48:30 +0200
+
+i3-wm (4.18.2-1) unstable; urgency=medium
+
+ * New upstream release.
+
+ -- Michael Stapelberg <stapelberg@debian.org> Sun, 26 Jul 2020 10:24:46 +0200
+
+i3-wm (4.18.1-1) unstable; urgency=medium
+
+ * New upstream release.
+
+ -- Michael Stapelberg <stapelberg@debian.org> Wed, 22 Apr 2020 09:04:42 +0200
+
i3-wm (4.18-1) unstable; urgency=medium
* New upstream release.
diff --git a/debian/compat b/debian/compat
index ec635144..f599e28b 100644
--- a/debian/compat
+++ b/debian/compat
@@ -1 +1 @@
-9
+10
diff --git a/debian/control b/debian/control
index 843e6557..5cd27cd6 100644
--- a/debian/control
+++ b/debian/control
@@ -2,8 +2,8 @@ Source: i3-wm
Section: x11
Priority: extra
Maintainer: Michael Stapelberg <stapelberg@debian.org>
-Build-Depends: debhelper (>= 9),
- dh-autoreconf,
+Build-Depends: debhelper (>= 10),
+ meson,
libx11-dev,
libxcb-util0-dev (>= 0.3.8),
libxcb-keysyms1-dev,
diff --git a/debian/i3-wm.docs b/debian/i3-wm.docs
deleted file mode 100644
index 437175b3..00000000
--- a/debian/i3-wm.docs
+++ /dev/null
@@ -1,32 +0,0 @@
-docs/debugging.html
-docs/hacking-howto.html
-docs/i3bar-protocol.html
-docs/userguide.html
-docs/bigpicture.png
-docs/single_terminal.png
-docs/snapping.png
-docs/two_columns.png
-docs/two_terminals.png
-docs/modes.png
-docs/ipc.html
-docs/multi-monitor.html
-docs/wsbar.html
-docs/wsbar.png
-docs/keyboard-layer1.png
-docs/keyboard-layer2.png
-docs/testsuite.html
-docs/i3-sync-working.png
-docs/i3-sync.png
-docs/tree-layout1.png
-docs/tree-layout2.png
-docs/tree-shot1.png
-docs/tree-shot2.png
-docs/tree-shot3.png
-docs/tree-shot4.png
-docs/refcard.html
-docs/refcard_style.css
-docs/logo-30.png
-docs/lib-i3test.html
-docs/lib-i3test-test.html
-docs/layout-saving.html
-docs/layout-saving-1.png
diff --git a/debian/i3-wm.manpages b/debian/i3-wm.manpages
deleted file mode 100644
index 1953b6a8..00000000
--- a/debian/i3-wm.manpages
+++ /dev/null
@@ -1,13 +0,0 @@
-man/i3.1
-man/i3-msg.1
-man/i3-input.1
-man/i3-nagbar.1
-man/i3-config-wizard.1
-man/i3-dump-log.1
-man/i3-migrate-config-to-v4.1
-man/i3-sensible-pager.1
-man/i3-sensible-editor.1
-man/i3-sensible-terminal.1
-man/i3-dmenu-desktop.1
-man/i3-save-tree.1
-man/i3bar.1
diff --git a/debian/rules b/debian/rules
index d5c30686..26e303e6 100755
--- a/debian/rules
+++ b/debian/rules
@@ -14,12 +14,12 @@ override_dh_auto_test:
# TODO: enable tests
override_dh_auto_configure:
- # The default is /usr/share/doc/i3
- dh_auto_configure -- --docdir=/usr/share/doc/i3-wm
+ # Set -Ddocdir; the default is /usr/share/doc/i3
+ dh_auto_configure -- -Ddocdir=/usr/share/doc/i3-wm -Dmans=true
override_dh_builddeb:
# bintray does not support xz currently.
dh_builddeb -- -Zgzip
%:
- dh $@ --parallel --builddirectory=build --with=autoreconf
+ dh $@ --buildsystem=meson
diff --git a/docs/bigpicture.asy b/docs/bigpicture.asy
new file mode 100644
index 00000000..4b3656c6
--- /dev/null
+++ b/docs/bigpicture.asy
@@ -0,0 +1,19 @@
+import drawtree;
+treeLevelStep = 2cm;
+TreeNode n94457831379296 = makeNode("``root'' (splith) []");
+TreeNode n94457831380944 = makeNode(n94457831379296, "``\_\_i3'' (output) []");
+TreeNode n94457831384048 = makeNode(n94457831380944, "``content'' (splith) []");
+TreeNode n94457831387184 = makeNode(n94457831384048, "``\_\_i3\_scratch'' (splith) []");
+TreeNode n94457831390576 = makeNode(n94457831379296, "``eDP-1'' (output) []");
+TreeNode n94457831393744 = makeNode(n94457831390576, "``topdock'' (dockarea) []");
+TreeNode n94457831396992 = makeNode(n94457831390576, "``content'' (splith) []");
+TreeNode n94457831628304 = makeNode(n94457831396992, "``1'' (splith) []");
+TreeNode n94457831571040 = makeNode(n94457831628304, "``Hacking i3: How To - Mozilla Firefox'' (leaf) []");
+TreeNode n94457831246384 = makeNode(n94457831628304, "``vim'' (leaf) []");
+TreeNode n94457831461088 = makeNode(n94457831396992, "``Named workspace'' (splith) []");
+TreeNode n94457831471424 = makeNode(n94457831461088, "``[Empty]'' (tabbed) []");
+TreeNode n94457831570576 = makeNode(n94457831471424, "``contrib/dump-asy.pl --no-gv'' (leaf) [Marks go here]");
+TreeNode n94457831645488 = makeNode(n94457831471424, "``ipython'' (leaf) []");
+TreeNode n94457831400192 = makeNode(n94457831390576, "``bottomdock'' (dockarea) []");
+TreeNode n94457831424848 = makeNode(n94457831400192, "``i3bar for output eDP-1'' (leaf) []");
+draw(n94457831379296, (0, 0));
diff --git a/docs/bigpicture.png b/docs/bigpicture.png
index fc3c8db7..031673b8 100644
--- a/docs/bigpicture.png
+++ b/docs/bigpicture.png
Binary files differ
diff --git a/docs/bigpicture.xcf b/docs/bigpicture.xcf
deleted file mode 100644
index ead00719..00000000
--- a/docs/bigpicture.xcf
+++ /dev/null
Binary files differ
diff --git a/docs/hacking-howto b/docs/hacking-howto
index 2ca44a5f..cc08cd1f 100644
--- a/docs/hacking-howto
+++ b/docs/hacking-howto
@@ -8,83 +8,82 @@ touching i3’s source code. It should contain all important information to help
you understand why things are like they are. If it does not mention something
you find necessary, please do not hesitate to contact me.
+++++
+<div style="background-color:red; color:white; padding:20px;">
+<strong style="color:white;">WARNING!</strong>
+<p>
+++++
+This document is not 100% up to date. Specifically, everything up to and
+including <<data_structures>> has been updated recently. The rest might contain
+outdated information.
+++++
+</p>
+</div>
+++++
+
== Building i3
-You can build i3 like you build any other software package which uses autotools.
-Here’s a memory refresher:
+You can build i3 like you build any other software package which uses
+https://mesonbuild.com/[The Meson Build system]; see
+https://mesonbuild.com/Quick-guide.html#compiling-a-meson-project[Quickstart
+Guide → Compiling a Meson project]. In case you’re unfamiliar:
- $ autoreconf -fi
$ mkdir -p build && cd build
- $ ../configure
- $ make -j8
-
-(The autoreconf -fi step is unnecessary if you are building from a release tarball,
- but shouldn’t hurt either.)
+ $ meson ..
+ $ ninja
=== Build system features
-* We use the AX_ENABLE_BUILDDIR macro to enforce builds happening in a separate
- directory. This is a prerequisite for the AX_EXTEND_SRCDIR macro and building
+* We use the +AX_ENABLE_BUILDDIR+ macro to enforce builds happening in a separate
+ directory. This is a prerequisite for the +AX_EXTEND_SRCDIR+ macro and building
in a separate directory is common practice anyway. In case this causes any
trouble when packaging i3 for your distribution, please open an issue.
-* “make check” runs the i3 testsuite. See docs/testsuite for details.
+* +make check+ runs the i3 testsuite. See docs/testsuite for details.
-* “make distcheck” (runs testsuite on “make dist” result, tiny bit quicker
+* +make distcheck+ (runs testsuite on +make dist+ result, tiny bit quicker
feedback cycle than waiting for the travis build to catch the issue).
-* “make uninstall” (occasionally requested by users who compile from source)
+* +make uninstall+ (occasionally requested by users who compile from source)
-* “make” will build manpages/docs by default if the tools are installed.
+* +make+ will build manpages/docs by default if the tools are installed.
Conversely, manpages/docs are not tried to be built for users who don’t want
- to install all these dependencies to get started hacking on i3.
+ to install all these dependencies to get started hacking on i3. Manpages and
+ docs can be disabled with the +--disable-mans++ and ++--disable-docs++
+ configure options respectively.
* non-release builds will enable address sanitizer by default. Use the
- --disable-sanitizers configure option to turn off all sanitizers, and see
- --help for available sanitizers.
-
-* Support for pre-compiled headers (PCH) has been dropped for now in the
- interest of simplicity. If you need support for PCH, please open an issue.
+ +--disable-sanitizers+ configure option to turn off all sanitizers, and see
+ +--help+ for available sanitizers.
-* Coverage reports are now generated using “make check-code-coverage”, which
- requires specifying --enable-code-coverage when calling configure.
+* Coverage reports are now generated using +make check-code-coverage+, which
+ requires specifying +--enable-code-coverage+ when calling configure.
-== Using git / sending patches
-
-For a short introduction into using git, see
-https://web.archive.org/web/20121024222556/http://www.spheredev.org/wiki/Git_for_the_lazy
-or, for more documentation, see https://git-scm.com/documentation
+== Pull requests
Please talk to us before working on new features to see whether they will be
accepted. A good way for this is to open an issue and asking for opinions on it.
-Even for accepted features, this can be a good way to refine an idea upfront. However,
-we don't want to see certain features in i3, e.g., switching window focus in an
-Alt+Tab like way.
+Even for accepted features, this can be a good way to refine an idea upfront.
+However, we don't want to see certain features in i3, e.g., switching window
+focus in an Alt+Tab like way.
-When working on bugfixes, please make sure you mention that you are working on
-it in the corresponding bug report at https://github.com/i3/i3/issues. In case
-there is no bug report yet, please create one.
+When working on bugfixes, please make sure you mention that you are working on it
+in the corresponding bug report at https://github.com/i3/i3/issues. In case there
+is no bug report yet, please create one.
After you are done, please submit your work for review as a pull request at
-https://github.com/i3/i3.
-
-Do not send emails to the mailing list or any author directly, and don’t submit
-them in the bugtracker, since all reviews should be done in public at
-https://github.com/i3/i3. In order to make your review go as fast as possible, you
-could have a look at previous reviews and see what the common mistakes are.
+https://github.com/i3/i3. In order to make your review go as fast as possible,
+you could have a look at previous reviews and see what the common mistakes are.
=== Which branch to use?
-Work on i3 generally happens in two branches: “master” and “next” (the latter
-being the default branch, the one that people get when they check out the git
-repository).
+Work on i3 generally happens in two branches: “next” (default) and “stable”.
-The contents of “master” are always stable. That is, it contains the source code
+The contents of “stable” are always stable. That is, it contains the source code
of the latest release, plus any bugfixes that were applied since that release.
-New features are only found in the “next” branch. Therefore, if you are working
-on a new feature, use the “next” branch. If you are working on a bugfix, use the
-“next” branch, too, but make sure your code also works on “master”.
+New features are only found in the “next” branch. Always use this branch when
+writing new code (both bugfixes and features).
== Window Managers
@@ -106,9 +105,9 @@ In the case of i3, the tasks (and order of them) are the following:
the first client of X) and manage them (reparent them, create window
decorations, etc.)
. When new windows are created, manage them
-. Handle the client’s `_WM_STATE` property, but only `_WM_STATE_FULLSCREEN` and
- `_NET_WM_STATE_DEMANDS_ATTENTION`
-. Handle the client’s `WM_NAME` property
+. Handle the client’s +_WM_STATE+ property, but only +_WM_STATE_FULLSCREEN+ and
+ +_NET_WM_STATE_DEMANDS_ATTENTION+
+. Handle the client’s +WM_NAME+ property
. Handle the client’s size hints to display them proportionally
. Handle the client’s urgency hint
. Handle enter notifications (focus follows mouse)
@@ -123,11 +122,11 @@ will be discussed.
=== Tiling window managers
-Traditionally, there are two approaches to managing windows: The most common
-one nowadays is floating, which means the user can freely move/resize the
-windows. The other approach is called tiling, which means that your window
-manager distributes windows to use as much space as possible while not
-overlapping each other.
+Traditionally, there are two approaches to managing windows: The most common one
+nowadays is stacking (or floating, using i3's terminology), which means the user
+can freely move/resize the windows, potentially overlapping them. The other
+approach is called tiling, which means that the window manager distributes
+windows to use as much space as possible while not overlapping each other.
The idea behind tiling is that you should not need to waste your time
moving/resizing windows while you usually want to get some work done. After
@@ -161,63 +160,67 @@ example.
== Files
-include/atoms.xmacro::
-A file containing all X11 atoms which i3 uses. This file will be included
-various times (for defining, requesting and receiving the atoms), each time
-with a different definition of xmacro().
+i3's source code is in the +src+ folder while header files reside in +include+.
+Other tools such as i3bar and i3-nagbar have their own folders. i3 and its tools
+share an internal library called ``libi3'' which also has its own folder.
+
+The following list gives an overview of the codebase, explaining the
+functionality of the most important, core source code files. Other files in the
+tree that are not mentioned here implement specific functionalities: for example,
++src/scratchpad.c+ is obviously about the scratchpad functionality.
include/data.h::
-Contains data definitions used by nearly all files. You really need to read
-this first.
+Contains data definitions used by nearly all files.
include/*.h::
Contains forward definitions for all public functions, as well as
doxygen-compatible comments (so if you want to get a bit more of the big
picture, either browse all header files or use doxygen if you prefer that).
-src/config_parser.c::
-Contains a custom configuration parser. See src/command_parser.c for rationale
- on why we use a custom parser.
-
-src/click.c::
-Contains all functions which handle mouse button clicks (right mouse button
-clicks initiate resizing and thus are relatively complex).
-
-src/command_parser.c::
-Contains a hand-written parser to parse commands (commands are what
-you bind on keys and what you can send to i3 using the IPC interface, like
-'move left' or 'workspace 4').
+src/config_directives.c::
+src/commands.c::
+Contain the definitions for all high-level config and command directives. These
+are excellent places to start with a top-to-bottom approach to understand
+specific i3 behavior. For example, if you want to investigate a bug that happens
+for the +move to mark+ command, you can use gdb to pause in
++cmd_move_con_to_mark+ and then work your way from there, stepping into
+lower-level functions.
src/con.c::
-Contains all functions which deal with containers directly (creating
-containers, searching containers, getting specific properties from containers,
-…).
-
-src/config.c::
-Contains all functions handling the configuration file (calling the parser
-src/config_parser.c) with the correct path, switching key bindings mode).
+Contains all functions which deal with containers directly (creating containers,
+searching containers, getting specific properties from containers, …). Contains
+abstractions and auxiliary functions necessary to work with the container
+structure which is used in almost all parts of the codebase.
-src/ewmh.c::
-Functions to get/set certain EWMH properties easily.
+src/tree.c::
+Contains functions which deal with the tree abstraction. However, be aware that
++src/con.c+ also contains functions that heavily interact with the tree
+structure. Some functions that are included in +str/tree.c+ are those that handle
+opening and closing containers in the tree, finding the container that should be
+focused next and flattening the tree. See also +src/move.c+ for other
+move-specific functions that interact with the tree, which were moved into their
+own file because they are so long.
-src/floating.c::
-Contains functions for floating mode (mostly resizing/dragging).
+src/workspace.c::
+Contains functions which deal with workspaces. Includes code that creates new
+workspaces, shows existing ones and deals with workspace assignments.
src/handlers.c::
Contains all handlers for all kinds of X events (new window title, new hints,
-unmapping, key presses, button presses, …).
-
-src/ipc.c::
-Contains code for the IPC interface.
-
-src/load_layout.c::
-Contains code for loading layouts from JSON files.
+unmapping, key presses, button presses, …). This is a very important file to
+understand how i3 interacts with changes to its environment.
-src/log.c::
-Contains the logging functions.
+src/command_parser.c::
+src/config_parser.c::
+Contain a hand-written parser to parse commands and configuration (commands are what
+you bind on keys and what you can send to i3 using the IPC interface, like
++move left+ or +workspace 4+). +src/config.c+ is responsible for calling the
+configuration parser.
-src/main.c::
-Initializes the window manager.
+src/click.c::
+src/resize.c::
+Contain functions which handle mouse button clicks (right mouse button
+clicks initiate resizing and thus are relatively complex).
src/manage.c::
Looks at existing or new windows and decides whether to manage them. If so, it
@@ -226,93 +229,66 @@ reparents the window and inserts it into our data structures.
src/match.c::
A "match" is a data structure which acts like a mask or expression to match
certain windows or not. For example, when using commands, you can specify a
-command like this: [title="*Firefox*"] kill. The title member of the match
+command like this: +[title="*Firefox*"] kill+. The title member of the match
data structure will then be filled and i3 will check each window using
-match_matches_window() to find the windows affected by this command.
-
-src/move.c::
-Contains code to move a container in a specific direction.
-
-src/output.c::
-Functions to handle CT_OUTPUT cons.
++match_matches_window()+ to find the windows affected by this command.
src/randr.c::
The RandR API is used to get (and re-query) the configured outputs (monitors,
-…).
+…). Legacy Xinerama support resides in +src/xinerama.c+.
src/render.c::
Renders the tree data structure by assigning coordinates to every node. These
values will later be pushed to X11 in +src/x.c+.
-src/resize.c::
-Contains the functions to resize containers.
-
-src/restore_layout.c::
-Everything for restored containers that is not pure state parsing (which can be
-found in load_layout.c).
-
src/sighandler.c::
Handles +SIGSEGV+, +SIGABRT+ and +SIGFPE+ by showing a dialog that i3 crashed.
-You can chose to let it dump core, to restart it in-place or to restart it
-in-place but forget about the layout.
-
-src/tree.c::
-Contains functions which open or close containers in the tree, change focus or
-cleanup ("flatten") the tree. See also +src/move.c+ for another similar
-function, which was moved into its own file because it is so long.
-
-src/util.c::
-Contains useful functions which are not really dependent on anything.
+You can choose to let it dump core and restart i3 in-place (either trying to
+preserve layout or forget about it).
src/window.c::
Handlers to update X11 window properties like +WM_CLASS+, +_NET_WM_NAME+,
+CLIENT_LEADER+, etc.
-src/workspace.c::
-Contains all functions related to workspaces (displaying, hiding, renaming…)
-
-src/x.c::
-Transfers our in-memory tree (see +src/render.c+) to X11.
-
-src/xcb.c::
-Contains wrappers to use xcb more easily.
-
-src/xcursor.c::
-XCursor functions (for cursor themes).
-
-src/xinerama.c::
-Legacy support for Xinerama. See +src/randr.c+ for the preferred API.
+include/*.xmacro.*::
+A file containing all X11 atoms which i3 uses. This file will be included
+various times (for defining, requesting and receiving the atoms), each time
+with a different definition of xmacro().
+[[data_structures]]
== Data structures
+See +include/data.h+ for documented data structures. The most important ones are
+explained here.
-See include/data.h for documented data structures. The most important ones are
-explained right here.
-
-/////////////////////////////////////////////////////////////////////////////////
-// TODO: update image
-
-image:bigpicture.png[The Big Picture]
+The following picture is generated by the +contrib/dump-asy.pl+ script.
-/////////////////////////////////////////////////////////////////////////////////
+image:bigpicture.png["The Big Picture",width=1000,link="bigpicture.png"]
-So, the hierarchy is:
+The hierarchy is:
-. *X11 root window*, the root container
-. *Output container* (LVDS1 in this example)
-. *Content container* (there are also containers for dock windows)
-. *Workspaces* (Workspace 1 in this example, with horizontal orientation)
-. *Split container* (vertically split)
-. *X11 window containers*
+. *Root container*
+. *Output containers*: +eDP-1+ in this example and the internal +__i3++ output
+. *Content and 2 dockarea containers*
+. *Workspaces*: Numbered workspace ``1'' and a ``Named workspace''
+. *Split containers*: One horizontal in the first workspace and a tabbed one in
+ the named one.
+. *Leaf containers*: Windows like vim and an i3bar dock.
The data type is +Con+, in all cases.
-=== X11 root window
+=== Root container
+
+The root container (global variable +croot+) is the up-most ascendant of every i3
+container. It can be used to iterate over the whole tree structure. E.g., it is
+used to reply to the +GET_WORKSPACES+ request, iterating over it's children to
+find all workspaces. This is different from the X11 root window.
-The X11 root window is a single window per X11 display (a display is identified
-by +:0+ or +:1+ etc.). The root window is what you draw your background image
-on. It spans all the available outputs, e.g. +VGA1+ is a specific part of the
-root window and +LVDS1+ is a specific part of the root window.
+The X11 root window (global variable +root+) is a single window per X11 display
+(a display is identified by +:0+ or +:1+ etc.). The root window is what you draw
+your background image on. It spans all the available outputs, e.g. +VGA1+ is a
+specific part of the root window and +LVDS1+ is a specific part of the root
+window.
=== Output container
@@ -334,8 +310,8 @@ currently on.
=== Content container
Each output has multiple children. Two of them are dock containers which hold
-dock clients. The other one is the content container, which holds the actual
-content (workspaces) of this output.
+the top and bottom dock clients. The other one is the content container, which
+holds the actual content (workspaces) of this output.
=== Workspace
@@ -354,21 +330,20 @@ vertical) and a layout.
Split containers (and X11 window containers, which are a subtype of split
containers) can have different border styles.
-=== X11 window container
+=== Leaf containers
-An X11 window container holds exactly one X11 window. These are the leaf nodes
-of the layout tree, they cannot have any children.
+A leaf container holds exactly one X11 window. They can't have any children.
== List/queue macros
i3 makes heavy use of the list macros defined in BSD operating systems. To
ensure that the operating system on which i3 is compiled has all the expected
-features, i3 comes with `include/queue.h`. On BSD systems, you can use man
-`queue(3)`. On Linux, you have to use google (or read the source).
+features, i3 comes with +include/queue.h+. On BSD systems, you can use +man
+queue(3)+. On Linux, you have to use google (or read the source).
The lists used are +SLIST+ (single linked lists), +CIRCLEQ+ (circular
queues) and +TAILQ+ (tail queues). Usually, only forward traversal is necessary,
-so an `SLIST` works fine. If inserting elements at arbitrary positions or at
+so an +SLIST+ works fine. If inserting elements at arbitrary positions or at
the end of a list is necessary, a +TAILQ+ is used instead. However, for the
windows inside a container, a +CIRCLEQ+ is necessary to go from the currently
selected window to the window above/below.
@@ -378,10 +353,10 @@ selected window to the window above/below.
There is a row of standard variables used in many events. The following names
should be chosen for those:
- * ``conn'' is the xcb_connection_t
- * ``event'' is the event of the particular type
- * ``con'' names a container
- * ``current'' is a loop variable when using +TAILQ_FOREACH+ etc.
+ * +conn+ is the xcb_connection_t
+ * +event+ is the event of the particular type
+ * +con+ names a container
+ * +current+ is a loop variable when using +TAILQ_FOREACH+ etc.
== Startup (src/mainx.c, main())
@@ -430,7 +405,7 @@ The bound command is parsed by the cmdparse lexer/parser, see +parse_cmd+ in
== Manage windows (src/main.c, manage_window() and reparent_window())
-`manage_window()` does some checks to decide whether the window should be
++manage_window()+ does some checks to decide whether the window should be
managed at all:
* Windows have to be mapped, that is, visible on screen
@@ -438,18 +413,18 @@ managed at all:
not be managed by a window manager
Afterwards, i3 gets the initial geometry and reparents the window (see
-`reparent_window()`) if it wasn’t already managed.
++reparent_window()+) if it wasn’t already managed.
Reparenting means that for each window which is reparented, a new window,
slightly larger than the original one, is created. The original window is then
reparented to the bigger one (called "frame").
-After reparenting, the window type (`_NET_WM_WINDOW_TYPE`) is checked to see
-whether this window is a dock (`_NET_WM_WINDOW_TYPE_DOCK`), like dzen2 for
+After reparenting, the window type (+_NET_WM_WINDOW_TYPE+) is checked to see
+whether this window is a dock (+_NET_WM_WINDOW_TYPE_DOCK+), like dzen2 for
example. Docks are handled differently, they don’t have decorations and are not
assigned to a specific container. Instead, they are positioned at the bottom
or top of the screen (in the appropriate dock area containers). To get the
-height which needs to be reserved for the window, the `_NET_WM_STRUT_PARTIAL`
+height which needs to be reserved for the window, the +_NET_WM_STRUT_PARTIAL+
property is used.
Furthermore, the list of assignments (to other workspaces, which may be on
@@ -460,10 +435,10 @@ target workspace is not visible, the window will not be mapped.
== What happens when an application is started?
i3 does not care about applications. All it notices is when new windows are
-mapped (see `src/handlers.c`, `handle_map_request()`). The window is then
+mapped (see +src/handlers.c+, +handle_map_request()+). The window is then
reparented (see section "Manage windows").
-After reparenting the window, `render_tree()` is called which renders the
+After reparenting the window, +render_tree()+ is called which renders the
internal layout table. The new window has been placed in the currently focused
container and therefore the new window and the old windows (if any) need to be
moved/resized so that the currently active layout (default/stacking/tabbed mode)
@@ -482,7 +457,7 @@ can reconfigure themselves).
Only the _NET_WM_STATE_FULLSCREEN and _NET_WM_STATE_DEMANDS_ATTENTION atoms
are handled.
-The former calls ``toggle_fullscreen()'' for the specific client which just
+The former calls +toggle_fullscreen()+ for the specific client which just
configures the client to use the whole screen on which it currently is.
Also, it is set as fullscreen_client for the i3Screen.
@@ -539,7 +514,7 @@ container) to the bottom.
=== Rendering the root container
-The i3 root container (`con->type == CT_ROOT`) represents the X11 root window.
+The i3 root container (+con->type == CT_ROOT+) represents the X11 root window.
It contains one child container for every output (like LVDS1, VGA1, …), which
is available on your computer.
@@ -558,7 +533,7 @@ only called for the global fullscreen window.
=== Rendering an output
-Output containers (`con->layout == L_OUTPUT`) represent a hardware output like
+Output containers (+con->layout == L_OUTPUT+) represent a hardware output like
LVDS1, VGA1, etc. An output container has three children (at the moment): One
content container (having workspaces as children) and the top/bottom dock area
containers.
@@ -566,7 +541,7 @@ containers.
The rendering happens in the function +render_l_output()+ in the following
steps:
-1. Find the content container (`con->type == CT_CON`)
+1. Find the content container (+con->type == CT_CON+)
2. Get the currently visible workspace (+con_get_fullscreen_con(content,
CF_OUTPUT)+).
3. If there is a fullscreened window on that workspace, directly render it and
@@ -574,22 +549,22 @@ steps:
4. Sum up the space used by all the dock windows (they have a variable height
only).
5. Set the workspace rects (x/y/width/height) based on the position of the
- output (stored in `con->rect`) and the usable space
- (`con->rect.{width,height}` without the space used for dock windows).
+ output (stored in +con->rect+) and the usable space
+ (+con->rect.{width,height}+ without the space used for dock windows).
6. Recursively raise and render the output’s child containers (meaning dock
area containers and the content container).
=== Rendering a workspace or split container
From here on, there really is no difference anymore. All containers are of
-`con->type == CT_CON` (whether workspace or split container) and some of them
-have a `con->window`, meaning they represent an actual window instead of a
++con->type == CT_CON+ (whether workspace or split container) and some of them
+have a +con->window+, meaning they represent an actual window instead of a
split container.
==== Default layout
In default layout, containers are placed horizontally or vertically next to
-each other (depending on the `con->orientation`). If a child is a leaf node (as
+each other (depending on the +con->orientation+). If a child is a leaf node (as
opposed to a split container) and has border style "normal", appropriate space
will be reserved for its window decoration.
@@ -835,8 +810,8 @@ workspace <direction>::
the beginning. +
NOTE: Note that you can specify multiple literals in the same line. This has
- exactly the same effect as if you specified `direction =
- 'next_on_output' -> call cmd_workspace($direction)` and so forth. +
+ exactly the same effect as if you specified +direction =
+ 'next_on_output' -> call cmd_workspace($direction)+ and so forth. +
NOTE: Also note that the order of literals is important here: If 'next' were
ordered before 'next_on_output', then 'next_on_output' would never
@@ -1020,11 +995,11 @@ Without much ado, here is the list of cases which need to be considered:
== Gotchas
-* Forgetting to call `xcb_flush(conn);` after sending a request. This usually
+* Forgetting to call +xcb_flush(conn);+ after sending a request. This usually
leads to code which looks like it works fine but which does not work under
certain conditions.
-* Forgetting to call `floating_fix_coordinates(con, old_rect, new_rect)` after
+* Forgetting to call +floating_fix_coordinates(con, old_rect, new_rect)+ after
moving workspaces across outputs. Coordinates for floating containers are
not relative to workspace boundaries, so you must correct their coordinates
or those containers will show up in the wrong workspace or not at all.
diff --git a/docs/i3-pod2html b/docs/i3-pod2html
index bd797fcb..e2de51b3 100755
--- a/docs/i3-pod2html
+++ b/docs/i3-pod2html
@@ -4,8 +4,14 @@
use strict;
use warnings;
use Pod::Simple::HTML;
+use Getopt::Long;
use v5.10;
+my $stylesurl = '';
+
+GetOptions("stylesurl=s" => \$stylesurl)
+ or die "parsing flags";
+
$Pod::Simple::HTML::Tagmap{'Verbatim'} = '<pre><tt>';
$Pod::Simple::HTML::Tagmap{'VerbatimFormatted'} = '<pre><tt>';
$Pod::Simple::HTML::Tagmap{'/Verbatim'} = '</tt></pre>';
@@ -22,8 +28,9 @@ open(my $out, '>', $ARGV[1]) or die "Couldn’t open $ARGV[1] for writing: $!\n"
my $parser = Pod::Simple::HTML->new();
$parser->index(1);
-$parser->html_header_before_title(
-<<'EOF'
+if ($stylesurl ne '') {
+ $parser->html_header_before_title(
+<<EOF
<!doctype html>
<html lang="en">
<head>
@@ -31,7 +38,7 @@ $parser->html_header_before_title(
<meta charset="utf-8">
<meta name="generator" content="Pod::Simple::HTML">
<meta name="description" content="i3 Perl documentation">
-<link rel="stylesheet" href="https://i3wm.org/css/style.css" type="text/css" />
+<link rel="stylesheet" href="$stylesurl/style.css" type="text/css" />
<style type="text/css">
.pod pre {
background: #333;
@@ -63,7 +70,8 @@ tt {
</style>
<title>
EOF
-);
+ );
+}
$parser->html_header_after_title(
<<'EOF'
</title>
diff --git a/docs/i3bar-protocol b/docs/i3bar-protocol
index cadcd8a8..c1bf8f80 100644
--- a/docs/i3bar-protocol
+++ b/docs/i3bar-protocol
@@ -103,9 +103,11 @@ https://github.com/i3/i3/blob/next/contrib/trivial-bar-script.sh
version::
The version number (as an integer) of the i3bar protocol you will use.
stop_signal::
- Specify to i3bar the signal (as an integer) to send to stop your
- processing.
- The default value (if none is specified) is SIGSTOP.
+ Specify the signal (as an integer) that i3bar should send to request that you
+ pause your output. This is used to conserve battery power when the bar is
+ hidden by not unnecessarily computing bar updates. The default value is SIGSTOP,
+ which will unconditionally stop your process. If this is an issue, this feature
+ can be disabled by setting the value to 0.
cont_signal::
Specify to i3bar the signal (as an integer) to send to continue your
processing.
@@ -258,6 +260,8 @@ button::
relative_x, relative_y::
Coordinates where the click occurred, with respect to the top left corner
of the block
+output_x, output_y::
+ Coordinates relative to the current output where the click occurred
width, height::
Width and height (in px) of the block
modifiers::
@@ -271,10 +275,12 @@ modifiers::
"instance": "eth0",
"button": 1,
"modifiers": ["Shift", "Mod1"],
- "x": 1320,
+ "x": 1925,
"y": 1400,
"relative_x": 12,
"relative_y": 8,
+ "output_x": 5,
+ "output_y": 1400,
"width": 50,
"height": 22
}
diff --git a/docs/ipc b/docs/ipc
index 5bc40e26..bb8719cb 100644
--- a/docs/ipc
+++ b/docs/ipc
@@ -1,7 +1,7 @@
IPC interface (interprocess communication)
==========================================
Michael Stapelberg <michael@i3wm.org>
-September 2017
+June 2020
This document describes how to interface with i3 from a separate process. This
is useful for example to remote-control i3 (to write test cases for example) or
@@ -66,6 +66,7 @@ to do that).
| 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.
+| 12 | +GET_BINDING_STATE+ | <<_binding_state_reply,BINDING_STATE>> | Request the current binding state, i.e. the currently active binding mode name.
|======================================================
So, a typical message could look like this:
@@ -131,6 +132,8 @@ GET_CONFIG (9)::
Reply to the GET_CONFIG message.
TICK (10)::
Reply to the SEND_TICK message.
+GET_BINDING_STATE (12)::
+ Reply to the GET_BINDING_STATE message.
[[_command_reply]]
=== COMMAND reply
@@ -158,6 +161,14 @@ sending a reply. Expect the socket to be shut down.
[{ "success": true }]
-------------------
+When the specified command cannot be parsed, `success` will be false and
+`parse_error` will be true:
+
+*Example:*
+-------------------
+[{ "success": false, "parse_error": true }]
+-------------------
+
[[_workspaces_reply]]
=== WORKSPACES reply
@@ -172,8 +183,8 @@ num (integer)::
The logical number of the workspace. Corresponds to the command
to switch to this workspace. For named workspaces, this will be -1.
name (string)::
- The name of this workspace (by default num+1), as changed by the
- user. Encoded in UTF-8.
+ The name of this workspace if changed by the user, otherwise defaults
+ to the string representation of the +num+ field). Encoded in UTF-8.
visible (boolean)::
Whether this workspace is currently visible on an output (multiple
workspaces can be visible at the same time).
@@ -709,6 +720,17 @@ responded to.
{ "success": true }
-------------------
+[[_binding_state_reply]]
+=== GET_BINDING_STATE reply
+
+The binding_state reply is a map which currently only contains the "name"
+member, which is the name of the currently active binding mode as a string.
+
+*Example:*
+-------------------
+{ "name": "default" }
+-------------------
+
== Events
[[events]]
diff --git a/docs/refcard.html b/docs/refcard.html
index 6d71c98d..0e3a4121 100644
--- a/docs/refcard.html
+++ b/docs/refcard.html
@@ -15,7 +15,7 @@
h1 { font-size: 1.1em; }
header a { font-size: 0.7em; }
header p { margin: 5px 0; font-size: 0.8em; text-align: left; }
- kbd { font-family: LinuxBiolinumKeyboard, Linux Biolinum Keyboard O, Linux Biolinum Keyboard, DejaVu Sans Mono, monospace; font-size: 0.9em; }
+ kbd { font-family: LinuxBiolinumKeyboard, Linux Biolinum Keyboard O, Linux Biolinum Keyboard, DejaVu Sans Mono, monospace; font-size: 1.2em; }
code { font-family: DejaVu Sans Mono, monospace; font-size: 0.8em; }
section { break-inside: avoid-column; -moz-break-inside: -moz-avoid-column; -webkit-break-inside: avoid-column; }
h2 { margin: 7px 0 2px; padding: 2px 4px; font-size: 1.1em; font-family: LinuxBiolinum, Linux Biolinum O, Linux Biolinum, sans; background-color: #b3b3b3; }
diff --git a/docs/testsuite b/docs/testsuite
index b535e7c1..145da158 100644
--- a/docs/testsuite
+++ b/docs/testsuite
@@ -120,13 +120,11 @@ tests are run under Xvfb.
---------------------------------------
$ cd ~/i3
-$ autoreconf -fi
-
$ mkdir -p build && cd build
-$ ../configure
+$ meson ..
-$ make -j8
+$ ninja
# output omitted because it is very long
$ cd testcases
@@ -183,13 +181,11 @@ You can still use ./testcases/complete-run.pl to get the interactive progress ou
---------------------------------------
$ cd ~/i3
-$ autoreconf -fi
-
$ mkdir -p build && cd build
-$ ../configure
+$ meson ..
-$ make -j8
+$ ninja
# output omitted because it is very long
$ make check
diff --git a/docs/userguide b/docs/userguide
index 36c7abb7..bc4afb3f 100644
--- a/docs/userguide
+++ b/docs/userguide
@@ -54,7 +54,7 @@ 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 may know from the editor +vi+. However, in i3, your homerow is used
+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
@@ -245,7 +245,7 @@ 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 default configuration, use +$mod+a+ to navigate one
+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
@@ -263,7 +263,7 @@ single workspace on which you open three terminal windows. All these terminal
windows are directly attached to one node inside i3’s layout tree, the
workspace node. By default, the workspace node’s orientation is +horizontal+.
-Now you move one of these terminals down (+$mod+Shift+k+ by default). The
+Now you move one of these terminals down (+$mod+Shift+j+ by default). The
workspace node’s orientation will be changed to +vertical+. The terminal window
you moved down is directly attached to the workspace and appears on the bottom
of the screen. A new (horizontal) container was created to accommodate the
@@ -924,7 +924,7 @@ available outputs by running +xrandr --current+.
If your X server supports RandR 1.5 or newer, i3 will use RandR monitor objects
instead of output objects. Run +xrandr --listmonitors+ to see a list. Usually,
a monitor object contains exactly one output, and has the same name as the
-output; but should that not be the case, you may specify the name of either the
+output; but should that not be the case, you can specify the name of either the
monitor or the output in i3's configuration. For example, the Dell UP2414Q uses
two scalers internally, so its output names might be “DP1” and “DP2”, but the
monitor name is “Dell UP2414Q”.
@@ -1066,7 +1066,7 @@ mouse_warping none
=== Popups during fullscreen mode
When you are in fullscreen mode, some applications still open popup windows
-(take Xpdf for example). This is because these applications may not be aware
+(take Xpdf for example). This is because these applications might not be aware
that they are in fullscreen mode (they do not check the corresponding hint).
There are three things which are possible to do in this situation:
@@ -1176,9 +1176,9 @@ workspace_auto_back_and_forth yes
=== Delaying urgency hint reset on workspace change
If an application on another workspace sets an urgency hint, switching to this
-workspace may lead to immediate focus of the application, which also means the
+workspace might lead to immediate focus of the application, which also means the
window decoration color would be immediately reset to +client.focused+. This
-may make it unnecessarily hard to tell which window originally raised the
+might make it unnecessarily hard to tell which window originally raised the
event.
In order to prevent this, you can tell i3 to delay resetting the urgency state
@@ -1201,9 +1201,9 @@ force_display_urgency_hint 500 ms
=== Focus on window activation
If a window is activated, e.g., via +google-chrome www.google.com+, it may request
-to take focus. Since this may not preferable, different reactions can be configured.
+to take focus. Since this might not be preferable, different reactions can be configured.
-Note that this may not affect windows that are being opened. To prevent new windows
+Note that this might not affect windows that are being opened. To prevent new windows
from being focused, see <<no_focus>>.
*Syntax*:
@@ -1350,9 +1350,11 @@ mode). The modifier key can be configured using the +modifier+ option.
The mode option can be changed during runtime through the +bar mode+ command.
On reload the mode will be reverted to its configured value.
-The hide mode maximizes screen space that can be used for actual windows. Also,
-i3bar sends the +SIGSTOP+ and +SIGCONT+ signals to the statusline process to
-save battery power.
+The hide mode maximizes screen space that can be used for actual windows. When
+the bar is hidden, i3bar sends the +SIGSTOP+ and +SIGCONT+ signals to the
++status_command+ process in order to conserve battery power. This feature can
+be disabled by the +status_command+ process by setting the appropriate values
+in its JSON header message.
Invisible mode allows to permanently maximize screen space, as the bar is never
shown. Thus, you can configure i3bar to not disturb you by popping up because
@@ -1409,6 +1411,11 @@ button4::
Scroll wheel up.
button5::
Scroll wheel down.
+button6::
+ Scroll wheel right.
+button7::
+ Scroll wheel left.
+
Please note that the old +wheel_up_cmd+ and +wheel_down_cmd+ commands are deprecated
and will be removed in a future release. We strongly recommend using the more general
@@ -1477,9 +1484,16 @@ options for different outputs by using multiple 'bar' blocks.
To make a particular i3bar instance handle multiple outputs, specify the output
directive multiple times.
+These output names have a special meaning:
+
+primary::
+ Selects the output that is configured as primary in the X server.
+nonprimary::
+ Selects every output that is not configured as primary in the X server.
+
*Syntax*:
---------------
-output primary|<output>
+output primary|nonprimary|<output>
---------------
*Example*:
@@ -1635,7 +1649,7 @@ bar {
By default, the width a workspace button is determined by the width of the text
showing the workspace name. If the name is too short (say, one letter), then the
-workspace button may look too small.
+workspace button might look too small.
This option specifies the minimum width for workspace buttons. If the name of
a workspace is too short to cover the button, an additional padding is added on
@@ -1645,7 +1659,7 @@ The default value of zero means that no additional padding is added.
The setting also applies to the current binding mode indicator.
-Note that the specified pixels refer to logical pixels, which may translate
+Note that the specified pixels refer to logical pixels, which might translate
into more pixels on HiDPI displays.
*Syntax*:
@@ -1675,8 +1689,8 @@ 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. Be aware
-that the colon in the workspace name is optional, so `[n][NAME]` will also
-have the the workspace name and number stripped correctly.
+that the colon in the workspace name is optional, so `[n][NAME]` will also
+have the workspace name and number stripped correctly.
*Syntax*:
------------------------------
@@ -1895,8 +1909,18 @@ con_id::
to match only the currently focused window.
floating::
Only matches floating windows. This criterion requires no value.
+floating_from::
+ Like +floating+ but this criterion takes two possible values: "auto"
+ and "user". With "auto", only windows that were automatically opened as
+ floating are matched. With "user", only windows that the user made
+ floating are matched.
tiling::
Only matches tiling windows. This criterion requires no value.
+tiling_from::
+ Like +tiling+ but this criterion takes two possible values: "auto" and
+ "user". With "auto", only windows that were automatically opened as
+ tiling are matched. With "user", only windows that the user made tiling
+ are matched.
The criteria +class+, +instance+, +role+, +title+, +workspace+ and +mark+ are
actually regular expressions (PCRE). See +pcresyntax(3)+ or +perldoc perlre+ for
@@ -2123,12 +2147,15 @@ Use the +move+ command to move a container.
# Moves the container into the given direction.
# The optional pixel argument specifies how far the
# container should be moved if it is floating and
-# defaults to 10 pixels.
-move <left|right|down|up> [<px> px]
+# defaults to 10 pixels. The optional ppt argument
+# means "percentage points", and if specified it indicates
+# how many points the container should be moved if it is
+# floating rather than by a pixel value.
+move <left|right|down|up> [<amount> [px|ppt]]
# Moves the container to the specified pos_x and pos_y
# coordinates on the screen.
-move position <pos_x> [px] <pos_y> [px]
+move position <pos_x> [px|ppt] <pos_y> [px|ppt]
# Moves the container to the center of the screen.
# If 'absolute' is used, it is moved to the center of
@@ -2444,7 +2471,7 @@ for_window [class="urxvt"] resize set 640 480
=== Jumping to specific windows
Often when in a multi-monitor environment, you want to quickly jump to a
-specific window. For example, while working on workspace 3 you may want to
+specific window. For example, while working on workspace 3 you might want to
jump to your mail client to email your boss that you’ve achieved some
important goal. Instead of figuring out how to navigate to your mail client,
it would be more convenient to have a shortcut. You can use the +focus+ command
@@ -2479,7 +2506,7 @@ for this purpose: It lets you input a command and sends the command to i3. It
can also prefix this command and display a custom prompt for the input dialog.
The additional +--toggle+ option will remove the mark if the window already has
-this mark or add it otherwise. Note that you may need to use this in
+this mark or add it otherwise. Note that you might need to use this in
combination with +--add+ (see below) as any other marks will otherwise be
removed.
@@ -2578,7 +2605,7 @@ 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
+is represented by multiple physical pixels, so +pixel 1+ might not
necessarily translate into a single pixel row wide border.
*Syntax*:
@@ -2841,7 +2868,7 @@ See also <<presentations>> for more examples of multi-monitor setups.
=== Interesting configuration for multi-monitor environments
-There are several things to configure in i3 which may be interesting if you
+There are several things to configure in i3 which might be interesting if you
have more than one monitor:
1. You can specify which workspace should be put on which screen. This
diff --git a/etc/config b/etc/config
index 2591c187..19cb8c48 100644
--- a/etc/config
+++ b/etc/config
@@ -52,10 +52,11 @@ bindsym Mod1+Return exec i3-sensible-terminal
bindsym Mod1+Shift+q kill
# start dmenu (a program launcher)
-bindsym Mod1+d exec dmenu_run
-# There also is the (new) i3-dmenu-desktop which only displays applications
-# shipping a .desktop file. It is a wrapper around dmenu, so you need that
-# installed.
+bindsym Mod1+d exec --no-startup-id dmenu_run
+# A more modern dmenu replacement is rofi:
+# bindsym Mod1+d exec rofi -modi drun,run -show drun
+# There also is i3-dmenu-desktop which only displays applications shipping a
+# .desktop file. It is a wrapper around dmenu, so you need that installed.
# bindsym Mod1+d exec --no-startup-id i3-dmenu-desktop
# change focus
diff --git a/etc/config.keycodes b/etc/config.keycodes
index 951c0a23..aa79901b 100644
--- a/etc/config.keycodes
+++ b/etc/config.keycodes
@@ -46,11 +46,12 @@ bindcode $mod+36 exec i3-sensible-terminal
bindcode $mod+Shift+24 kill
# start dmenu (a program launcher)
-bindcode $mod+40 exec dmenu_run
-# There also is the (new) i3-dmenu-desktop which only displays applications
-# shipping a .desktop file. It is a wrapper around dmenu, so you need that
-# installed.
-# bindsym $mod+d exec --no-startup-id i3-dmenu-desktop
+bindcode $mod+40 exec --no-startup-id dmenu_run
+# A more modern dmenu replacement is rofi:
+# bindcode $mod+40 exec rofi -modi drun,run -show drun
+# There also is i3-dmenu-desktop which only displays applications shipping a
+# .desktop file. It is a wrapper around dmenu, so you need that installed.
+bindcode $mod+40 exec --no-startup-id i3-dmenu-desktop
# change focus
bindcode $mod+44 focus left
diff --git a/generate-command-parser.pl b/generate-command-parser.pl
index 052e4c66..77502db7 100755
--- a/generate-command-parser.pl
+++ b/generate-command-parser.pl
@@ -117,6 +117,7 @@ my @keys = sort { (length($b) <=> length($a)) or ($a cmp $b) } keys %states;
open(my $enumfh, '>', "GENERATED_${prefix}_enums.h");
my %statenum;
+say $enumfh '#pragma once';
say $enumfh 'typedef enum {';
my $cnt = 0;
for my $state (@keys, '__CALL') {
@@ -131,6 +132,7 @@ close($enumfh);
# Third step: Generate the call function.
open(my $callfh, '>', "GENERATED_${prefix}_call.h");
my $resultname = uc(substr($prefix, 0, 1)) . substr($prefix, 1) . 'ResultIR';
+say $callfh '#pragma once';
say $callfh "static void GENERATED_call(const int call_identifier, struct $resultname *result) {";
say $callfh ' switch (call_identifier) {';
my $call_id = 0;
@@ -206,6 +208,7 @@ close($callfh);
# Fourth step: Generate the token datastructures.
open(my $tokfh, '>', "GENERATED_${prefix}_tokens.h");
+say $tokfh '#pragma once';
for my $state (@keys) {
my $tokens = $states{$state};
@@ -218,6 +221,8 @@ for my $state (@keys) {
# quote of the literal. We can do strdup(literal + 1); then :).
$token_name =~ s/'$//;
}
+ # Escape double quotes:
+ $token_name =~ s,",\\",g;
my $next_state = $token->{next_state};
if ($next_state =~ /^call /) {
($call_identifier) = ($next_state =~ /^call ([0-9]+)$/);
diff --git a/i3-config-wizard/atoms.xmacro b/i3-config-wizard/atoms.xmacro
deleted file mode 100644
index 8f94ceaa..00000000
--- a/i3-config-wizard/atoms.xmacro
+++ /dev/null
@@ -1,6 +0,0 @@
-xmacro(_NET_WM_NAME)
-xmacro(_NET_WM_WINDOW_TYPE)
-xmacro(_NET_WM_WINDOW_TYPE_DIALOG)
-xmacro(ATOM)
-xmacro(CARDINAL)
-xmacro(UTF8_STRING)
diff --git a/i3-config-wizard/i3-config-wizard-atoms.xmacro.h b/i3-config-wizard/i3-config-wizard-atoms.xmacro.h
new file mode 100644
index 00000000..2d504678
--- /dev/null
+++ b/i3-config-wizard/i3-config-wizard-atoms.xmacro.h
@@ -0,0 +1,8 @@
+// clang-format off
+#define CONFIG_WIZARD_ATOMS_XMACRO \
+xmacro(_NET_WM_NAME) \
+xmacro(_NET_WM_WINDOW_TYPE) \
+xmacro(_NET_WM_WINDOW_TYPE_DIALOG) \
+xmacro(ATOM) \
+xmacro(CARDINAL) \
+xmacro(UTF8_STRING)
diff --git a/i3-config-wizard/main.c b/i3-config-wizard/main.c
index f999de30..25117f2b 100644
--- a/i3-config-wizard/main.c
+++ b/i3-config-wizard/main.c
@@ -10,6 +10,8 @@
*/
#include <config.h>
+#include "libi3.h"
+
#if defined(__FreeBSD__)
#include <sys/param.h>
#endif
@@ -23,37 +25,33 @@
#define _WITH_GETLINE
#endif
-#include <stdio.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <string.h>
#include <ctype.h>
-#include <errno.h>
#include <err.h>
-#include <stdint.h>
+#include <errno.h>
+#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/stat.h>
-#include <fcntl.h>
-#include <glob.h>
-#include <assert.h>
+#include <sys/types.h>
+#include <unistd.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
#include <xcb/xcb_event.h>
#include <xcb/xcb_keysyms.h>
-
-#include <xkbcommon/xkbcommon.h>
#include <xkbcommon/xkbcommon-x11.h>
+#include <xkbcommon/xkbcommon.h>
#define SN_API_NOT_YET_FROZEN 1
#include <libsn/sn-launchee.h>
+#include <X11/XKBlib.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
-#include <X11/XKBlib.h>
+
+#include "i3-config-wizard-atoms.xmacro.h"
/* We need SYSCONFDIR for the path to the keycode config template, so raise an
* error if it’s not defined for whatever reason */
@@ -69,7 +67,6 @@
#include "xcb.h"
xcb_visualtype_t *visual_type = NULL;
-#include "libi3.h"
#define TEXT_PADDING logical_px(4)
#define WIN_POS_X logical_px(490)
@@ -848,7 +845,7 @@ int main(int argc, char *argv[]) {
/* 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"
+ CONFIG_WIZARD_ATOMS_XMACRO
#undef xmacro
/* Init startup notification. */
@@ -905,7 +902,7 @@ int main(int argc, char *argv[]) {
A_##name = reply->atom; \
free(reply); \
} while (0);
-#include "atoms.xmacro"
+ CONFIG_WIZARD_ATOMS_XMACRO
#undef xmacro
/* Set dock mode */
diff --git a/i3-config-wizard/xcb.h b/i3-config-wizard/xcb.h
index f3e204e8..dc8568a7 100644
--- a/i3-config-wizard/xcb.h
+++ b/i3-config-wizard/xcb.h
@@ -3,6 +3,8 @@
/* from X11/keysymdef.h */
#define XCB_NUM_LOCK 0xff7f
+#include "i3-config-wizard-atoms.xmacro.h"
+
#define xmacro(atom) xcb_atom_t A_##atom;
-#include "atoms.xmacro"
+CONFIG_WIZARD_ATOMS_XMACRO
#undef xmacro
diff --git a/i3-dmenu-desktop b/i3-dmenu-desktop
index d57e9a38..07fe8336 100755
--- a/i3-dmenu-desktop
+++ b/i3-dmenu-desktop
@@ -13,6 +13,7 @@ use POSIX qw(locale_h);
use File::Find;
use File::Basename qw(basename);
use File::Temp qw(tempfile);
+use List::Util 'first';
use Getopt::Long;
use Pod::Usage;
use v5.10;
@@ -123,6 +124,8 @@ for my $dir (split(':', $xdg_data_dirs)) {
# Cleanup the paths, maybe some application does not cope with double slashes
# (the field code %k is replaced with the .desktop file location).
@searchdirs = map { s,//,/,g; $_ } @searchdirs;
+# Also remove any trailing slashes.
+@searchdirs = map { s,/*$,,g; $_ } @searchdirs;
# To avoid errors by File::Find’s find(), only pass existing directories.
@searchdirs = grep { -d $_ } @searchdirs;
@@ -133,8 +136,15 @@ find(
return unless substr($_, -1 * length('.desktop')) eq '.desktop';
my $relative = $File::Find::name;
- # + 1 for the trailing /, which is missing in ::topdir.
- substr($relative, 0, length($File::Find::topdir) + 1) = '';
+ # Find and then replace the directory in @searchdirs in which the
+ # current file is located. We used to do this with
+ # $File::Find::topdir but it is not supported when using the
+ # 'follow' or 'follow_fast' options.
+ # See #3973, #4031.
+ my $topdir = first { substr($relative, 0, length($_)) eq $_ } @searchdirs;
+
+ # + 1 for the trailing /, which is missing in $topdir.
+ substr($relative, 0, length($topdir) + 1) = '';
# Don’t overwrite files with the same relative path, we search in
# descending order of importance.
@@ -143,6 +153,7 @@ find(
$desktops{$relative} = $File::Find::name;
},
no_chdir => 1,
+ follow_fast => 1,
},
@searchdirs
);
diff --git a/i3-dump-log/main.c b/i3-dump-log/main.c
index 4f15f26f..e58b0c37 100644
--- a/i3-dump-log/main.c
+++ b/i3-dump-log/main.c
@@ -9,27 +9,22 @@
*/
#include <config.h>
-#include <stdio.h>
+#include "libi3.h"
+#include "shmlog.h"
+
+#include <err.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <i3/ipc.h>
+#include <signal.h>
#include <stdbool.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
+#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
#include <string.h>
-#include <errno.h>
-#include <err.h>
-#include <stdint.h>
-#include <getopt.h>
-#include <limits.h>
-#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
-#include <signal.h>
-
-#include "libi3.h"
-#include "shmlog.h"
-#include <i3/ipc.h>
+#include <unistd.h>
#if !defined(__OpenBSD__)
static uint32_t offset_next_write;
@@ -246,8 +241,8 @@ int main(int argc, char *argv[]) {
sigaction(SIGINT, &action, NULL);
/* Since pthread_cond_wait() expects a mutex, we need to provide one.
- * To not lock i3 (that’s bad, mhkay?) we just define one outside of
- * the shared memory. */
+ * To not lock i3 (that’s bad, mhkay?) we just define one outside of
+ * the shared memory. */
pthread_mutex_t dummy_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&dummy_mutex);
while (!interrupted) {
diff --git a/i3-input/keysym2ucs.c b/i3-input/keysym2ucs.c
index 52bdc044..80375099 100644
--- a/i3-input/keysym2ucs.c
+++ b/i3-input/keysym2ucs.c
@@ -31,9 +31,10 @@
* This software is in the public domain. Share and enjoy!
*/
-#include <xcb/xcb.h>
#include "keysym2ucs.h"
+#include <xcb/xcb.h>
+
struct codepair {
unsigned short keysym;
unsigned short ucs;
diff --git a/i3-input/main.c b/i3-input/main.c
index e495fe10..ef9e0701 100644
--- a/i3-input/main.c
+++ b/i3-input/main.c
@@ -8,36 +8,38 @@
* to i3.
*
*/
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
-#include <sys/types.h>
#include <stdlib.h>
-#include <stdbool.h>
-#include <unistd.h>
#include <string.h>
-#include <errno.h>
-#include <err.h>
-#include <stdint.h>
-#include <getopt.h>
-#include <limits.h>
+#include <sys/types.h>
+#include <unistd.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
-#include <xcb/xcb_event.h>
#include <xcb/xcb_keysyms.h>
xcb_visualtype_t *visual_type = NULL;
+#include "i3-input.h"
+#include "keysym2ucs.h"
#include "libi3.h"
#include <X11/keysym.h>
-#include "keysym2ucs.h"
-
-#include "i3-input.h"
-
#define MAX_WIDTH logical_px(500)
#define BORDER logical_px(2)
#define PADDING logical_px(2)
+/* Exit codes for i3-input:
+ * 0 if i3-input exited successfully and the command was run
+ * 1 if the user canceled input
+ * 2 if i3-input fails for any other reason */
+const int EXIT_OK = 0;
+const int EXIT_CANCEL = 1;
+const int EXIT_ERROR = 2;
+
/* IPC format string. %s will be replaced with what the user entered, then
* the command will be sent to i3 */
static char *format;
@@ -192,11 +194,11 @@ static void finish_input(void) {
/* prefix the command if a prefix was specified on commandline */
printf("command = %s\n", full);
- ipc_send_message(sockfd, strlen(full), 0, (uint8_t *)full);
+ int ret = ipc_send_message(sockfd, strlen(full), 0, (uint8_t *)full);
free(full);
- exit(0);
+ exit(ret == 0 ? EXIT_OK : EXIT_ERROR);
}
/*
@@ -245,7 +247,7 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press
return 1;
}
if (sym == XK_Escape) {
- exit(0);
+ exit(EXIT_CANCEL);
}
/* TODO: handle all of these? */
@@ -303,7 +305,7 @@ static xcb_rectangle_t get_window_position(void) {
xcb_intern_atom_reply_t *nswc_reply = xcb_intern_atom_reply(conn, nswc_cookie, NULL);
if (nswc_reply == NULL) {
ELOG("Could not intern atom _NET_SUPPORTING_WM_CHECK\n");
- exit(-1);
+ exit(EXIT_ERROR);
}
A__NET_SUPPORTING_WM_CHECK = nswc_reply->atom;
free(nswc_reply);
@@ -373,9 +375,8 @@ free_resources:
}
int main(int argc, char *argv[]) {
- format = sstrdup("%s");
char *socket_path = NULL;
- char *pattern = sstrdup("pango:monospace 8");
+ char *pattern = NULL;
int o, option_index = 0;
static struct option long_options[] = {
@@ -399,7 +400,7 @@ int main(int argc, char *argv[]) {
break;
case 'v':
printf("i3-input " I3_VERSION);
- return 0;
+ return EXIT_OK;
case 'p':
/* This option is deprecated, but will still work in i3 v4.1, 4.2 and 4.3 */
fprintf(stderr, "i3-input: WARNING: the -p option is DEPRECATED in favor of the -F (format) option\n");
@@ -427,9 +428,12 @@ int main(int argc, char *argv[]) {
printf("\n");
printf("Example:\n");
printf(" i3-input -F 'workspace \"%%s\"' -P 'Switch to workspace: '\n");
- return 0;
+ return EXIT_OK;
}
}
+ if (!format) {
+ format = "%s";
+ }
printf("using format \"%s\"\n", format);
@@ -446,7 +450,7 @@ int main(int argc, char *argv[]) {
symbols = xcb_key_symbols_alloc(conn);
init_dpi();
- font = load_font(pattern, true);
+ font = load_font(pattern ? pattern : "pango:monospace 8", true);
set_font(&font);
if (prompt != NULL)
@@ -495,7 +499,7 @@ int main(int argc, char *argv[]) {
if (reply->status != XCB_GRAB_STATUS_SUCCESS) {
fprintf(stderr, "Could not grab keyboard, status = %d\n", reply->status);
- exit(-1);
+ exit(EXIT_ERROR);
}
xcb_flush(conn);
@@ -531,5 +535,5 @@ int main(int argc, char *argv[]) {
}
draw_util_surface_free(conn, &surface);
- return 0;
+ return EXIT_OK;
}
diff --git a/i3-msg/main.c b/i3-msg/main.c
index 3a897416..c1c8bb81 100644
--- a/i3-msg/main.c
+++ b/i3-msg/main.c
@@ -16,27 +16,17 @@
*/
#include "libi3.h"
-#include <stdio.h>
+#include <err.h>
+#include <getopt.h>
+#include <i3/ipc.h>
#include <stdbool.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
+#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
#include <string.h>
-#include <errno.h>
-#include <err.h>
-#include <stdint.h>
-#include <getopt.h>
-#include <limits.h>
+#include <unistd.h>
#include <yajl/yajl_parse.h>
-#include <yajl/yajl_version.h>
-
-#include <xcb/xcb.h>
-#include <xcb/xcb_aux.h>
-
-#include <i3/ipc.h>
/*
* Having verboselog() and errorlog() is necessary when using libi3.
@@ -199,6 +189,8 @@ int main(int argc, char *argv[]) {
message_type = I3_IPC_MESSAGE_TYPE_GET_BAR_CONFIG;
} else if (strcasecmp(optarg, "get_binding_modes") == 0) {
message_type = I3_IPC_MESSAGE_TYPE_GET_BINDING_MODES;
+ } else if (strcasecmp(optarg, "get_binding_state") == 0) {
+ message_type = I3_IPC_MESSAGE_TYPE_GET_BINDING_STATE;
} else if (strcasecmp(optarg, "get_version") == 0) {
message_type = I3_IPC_MESSAGE_TYPE_GET_VERSION;
} else if (strcasecmp(optarg, "get_config") == 0) {
@@ -209,7 +201,7 @@ int main(int argc, char *argv[]) {
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, subscribe\n");
+ printf("Known types: run_command, get_workspaces, get_outputs, get_tree, get_marks, get_bar_config, get_binding_modes, get_binding_state, get_version, get_config, send_tick, subscribe\n");
exit(EXIT_FAILURE);
}
} else if (o == 'q') {
diff --git a/i3-nagbar/atoms.xmacro b/i3-nagbar/atoms.xmacro
deleted file mode 100644
index 333ba2d6..00000000
--- a/i3-nagbar/atoms.xmacro
+++ /dev/null
@@ -1,6 +0,0 @@
-xmacro(_NET_WM_WINDOW_TYPE)
-xmacro(_NET_WM_WINDOW_TYPE_DOCK)
-xmacro(_NET_WM_STRUT_PARTIAL)
-xmacro(I3_SOCKET_PATH)
-xmacro(ATOM)
-xmacro(CARDINAL)
diff --git a/i3-nagbar/i3-nagbar-atoms.xmacro.h b/i3-nagbar/i3-nagbar-atoms.xmacro.h
new file mode 100644
index 00000000..c430b59a
--- /dev/null
+++ b/i3-nagbar/i3-nagbar-atoms.xmacro.h
@@ -0,0 +1,8 @@
+// clang-format off
+#define NAGBAR_ATOMS_XMACRO \
+xmacro(_NET_WM_WINDOW_TYPE) \
+xmacro(_NET_WM_WINDOW_TYPE_DOCK) \
+xmacro(_NET_WM_STRUT_PARTIAL) \
+xmacro(I3_SOCKET_PATH) \
+xmacro(ATOM) \
+xmacro(CARDINAL)
diff --git a/i3-nagbar/i3-nagbar.h b/i3-nagbar/i3-nagbar.h
deleted file mode 100644
index cb672bea..00000000
--- a/i3-nagbar/i3-nagbar.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma once
-
-#include <config.h>
-
-#include <err.h>
-
-#define die(...) errx(EXIT_FAILURE, __VA_ARGS__);
-#define FREE(pointer) \
- do { \
- free(pointer); \
- pointer = NULL; \
- } while (0)
-
-#define xmacro(atom) xcb_atom_t A_##atom;
-#include "atoms.xmacro"
-#undef xmacro
-
-extern xcb_window_t root;
diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c
index 5099cf54..b13ee134 100644
--- a/i3-nagbar/main.c
+++ b/i3-nagbar/main.c
@@ -8,39 +8,34 @@
* when the user has an error in their configuration file.
*
*/
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
+#include <config.h>
+
+#include "libi3.h"
+
#include <err.h>
-#include <stdint.h>
+#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
-#include <fcntl.h>
#include <paths.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <xcb/randr.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
-#include <xcb/xcb_event.h>
-#include <xcb/randr.h>
#include <xcb/xcb_cursor.h>
xcb_visualtype_t *visual_type = NULL;
-#include "libi3.h"
#define SN_API_NOT_YET_FROZEN 1
#include <libsn/sn-launchee.h>
-#include "i3-nagbar.h"
-
-/** This is the equivalent of XC_left_ptr. I’m not sure why xcb doesn’t have a
- * constant for that. */
-#define XCB_CURSOR_LEFT_PTR 68
+#include "i3-nagbar-atoms.xmacro.h"
#define MSG_PADDING logical_px(8)
#define BTN_PADDING logical_px(3)
@@ -49,6 +44,12 @@ xcb_visualtype_t *visual_type = NULL;
#define CLOSE_BTN_GAP logical_px(15)
#define BAR_BORDER logical_px(2)
+#define xmacro(atom) xcb_atom_t A_##atom;
+NAGBAR_ATOMS_XMACRO
+#undef xmacro
+
+#define die(...) errx(EXIT_FAILURE, __VA_ARGS__);
+
static char *argv0 = NULL;
typedef struct {
@@ -108,10 +109,6 @@ void debuglog(char *fmt, ...) {
* 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.
- *
*/
static void start_application(const char *command) {
printf("executing: %s\n", command);
@@ -177,7 +174,7 @@ static void handle_button_release(xcb_connection_t *conn, xcb_button_release_eve
warn("Could not fdopen() temporary script to store the nagbar command");
return;
}
- fprintf(script, "#!/bin/sh\nrm %s\n%s", script_path, button->action);
+ fprintf(script, "#!%s\nrm %s\n%s", _PATH_BSHELL, script_path, button->action);
/* Also closes fd */
fclose(script);
@@ -322,8 +319,8 @@ static xcb_rectangle_t get_window_position(void) {
goto free_resources;
free_resources:
- FREE(res);
- FREE(primary);
+ free(res);
+ free(primary);
return result;
}
@@ -357,8 +354,8 @@ int main(int argc, char *argv[]) {
unlink(argv[0]);
cmd = sstrdup(argv[0]);
*(cmd + argv0_len - strlen(".nagbar_cmd")) = '\0';
- execl("/bin/sh", "/bin/sh", cmd, NULL);
- err(EXIT_FAILURE, "execv(/bin/sh, /bin/sh, %s)", cmd);
+ execl(_PATH_BSHELL, _PATH_BSHELL, cmd, NULL);
+ err(EXIT_FAILURE, "execl(%s, %s, %s)", _PATH_BSHELL, _PATH_BSHELL, cmd);
}
argv0 = argv[0];
@@ -431,7 +428,7 @@ int main(int argc, char *argv[]) {
/* 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"
+ NAGBAR_ATOMS_XMACRO
#undef xmacro
/* Init startup notification. */
@@ -469,24 +466,12 @@ int main(int argc, char *argv[]) {
xcb_rectangle_t win_pos = get_window_position();
- xcb_cursor_t cursor;
xcb_cursor_context_t *cursor_ctx;
- if (xcb_cursor_context_new(conn, root_screen, &cursor_ctx) == 0) {
- cursor = xcb_cursor_load_cursor(cursor_ctx, "left_ptr");
- xcb_cursor_context_free(cursor_ctx);
- } else {
- cursor = xcb_generate_id(conn);
- i3Font cursor_font = load_font("cursor", false);
- xcb_create_glyph_cursor(
- conn,
- cursor,
- cursor_font.specific.xcb.id,
- cursor_font.specific.xcb.id,
- XCB_CURSOR_LEFT_PTR,
- XCB_CURSOR_LEFT_PTR + 1,
- 0, 0, 0,
- 65535, 65535, 65535);
+ if (xcb_cursor_context_new(conn, root_screen, &cursor_ctx) < 0) {
+ errx(EXIT_FAILURE, "Cannot allocate xcursor context");
}
+ xcb_cursor_t cursor = xcb_cursor_load_cursor(cursor_ctx, "left_ptr");
+ xcb_cursor_context_free(cursor_ctx);
/* Open an input window */
win = xcb_generate_id(conn);
@@ -525,7 +510,7 @@ int main(int argc, char *argv[]) {
A_##name = reply->atom; \
free(reply); \
} while (0);
-#include "atoms.xmacro"
+ NAGBAR_ATOMS_XMACRO
#undef xmacro
/* Set dock mode */
@@ -618,7 +603,7 @@ int main(int argc, char *argv[]) {
free(event);
}
- FREE(pattern);
+ free(pattern);
draw_util_surface_free(conn, &bar);
return 0;
diff --git a/i3bar/include/child.h b/i3bar/include/child.h
index 3afed819..adc638be 100644
--- a/i3bar/include/child.h
+++ b/i3bar/include/child.h
@@ -85,4 +85,4 @@ bool child_want_click_events(void);
* Generates a click event, if enabled.
*
*/
-void send_block_clicked(int button, const char *name, const char *instance, int x, int y, int x_rel, int y_rel, int width, int height, int mods);
+void send_block_clicked(int button, const char *name, const char *instance, int x, int y, int x_rel, int y_rel, int out_x, int out_y, int width, int height, int mods);
diff --git a/i3bar/include/common.h b/i3bar/include/common.h
index 222f42dd..52f77b0e 100644
--- a/i3bar/include/common.h
+++ b/i3bar/include/common.h
@@ -9,7 +9,6 @@
#include <config.h>
-#include <stdbool.h>
#include <xcb/xcb.h>
#include <xcb/xproto.h>
#include "libi3.h"
@@ -78,12 +77,10 @@ struct status_block {
char *name;
char *instance;
- TAILQ_ENTRY(status_block)
- blocks;
+ TAILQ_ENTRY(status_block) blocks;
};
-extern TAILQ_HEAD(statusline_head, status_block)
- statusline_head;
+extern TAILQ_HEAD(statusline_head, status_block) statusline_head;
#include "child.h"
#include "ipc.h"
@@ -94,5 +91,4 @@ extern TAILQ_HEAD(statusline_head, status_block)
#include "trayclients.h"
#include "xcb.h"
#include "configuration.h"
-#include "libi3.h"
#include "parse_json_header.h"
diff --git a/i3bar/include/configuration.h b/i3bar/include/configuration.h
index 70167247..f39d24c9 100644
--- a/i3bar/include/configuration.h
+++ b/i3bar/include/configuration.h
@@ -29,23 +29,18 @@ typedef struct binding_t {
char *command;
bool release;
- TAILQ_ENTRY(binding_t)
- bindings;
+ TAILQ_ENTRY(binding_t) bindings;
} binding_t;
typedef struct tray_output_t {
char *output;
- TAILQ_ENTRY(tray_output_t)
- tray_outputs;
+ TAILQ_ENTRY(tray_output_t) tray_outputs;
} tray_output_t;
typedef struct config_t {
uint32_t modifier;
-
- TAILQ_HEAD(bindings_head, binding_t)
- bindings;
-
+ TAILQ_HEAD(bindings_head, binding_t) bindings;
position_t position;
bool verbose;
bool transparency;
@@ -59,10 +54,7 @@ typedef struct config_t {
char *command;
char *fontname;
i3String *separator_symbol;
-
- TAILQ_HEAD(tray_outputs_head, tray_output_t)
- tray_outputs;
-
+ TAILQ_HEAD(tray_outputs_head, tray_output_t) tray_outputs;
int tray_padding;
int num_outputs;
char **outputs;
diff --git a/i3bar/include/outputs.h b/i3bar/include/outputs.h
index 5bb19c40..4685e51e 100644
--- a/i3bar/include/outputs.h
+++ b/i3bar/include/outputs.h
@@ -73,6 +73,5 @@ struct i3_output {
struct ws_head* workspaces; /* The workspaces on this output */
struct tc_head* trayclients; /* The tray clients on this output */
- SLIST_ENTRY(i3_output)
- slist; /* Pointer for the SLIST-Macro */
+ SLIST_ENTRY(i3_output) slist; /* Pointer for the SLIST-Macro */
};
diff --git a/i3bar/include/trayclients.h b/i3bar/include/trayclients.h
index 3f215ce4..bcf55959 100644
--- a/i3bar/include/trayclients.h
+++ b/i3bar/include/trayclients.h
@@ -21,6 +21,5 @@ struct trayclient {
char *class_class;
char *class_instance;
- TAILQ_ENTRY(trayclient)
- tailq; /* Pointer for the TAILQ-Macro */
+ TAILQ_ENTRY(trayclient) tailq; /* Pointer for the TAILQ-Macro */
};
diff --git a/i3bar/include/workspaces.h b/i3bar/include/workspaces.h
index 0ef5c0a9..ff61450c 100644
--- a/i3bar/include/workspaces.h
+++ b/i3bar/include/workspaces.h
@@ -41,6 +41,5 @@ struct i3_ws {
rect rect; /* The rect of the ws (not used (yet)) */
struct i3_output *output; /* The current output of the ws */
- TAILQ_ENTRY(i3_ws)
- tailq; /* Pointer for the TAILQ-Macro */
+ TAILQ_ENTRY(i3_ws) tailq; /* Pointer for the TAILQ-Macro */
};
diff --git a/i3bar/src/child.c b/i3bar/src/child.c
index 85206ac3..bece314f 100644
--- a/i3bar/src/child.c
+++ b/i3bar/src/child.c
@@ -10,28 +10,26 @@
#include "common.h"
#include "yajl_utils.h"
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
#include <err.h>
+#include <errno.h>
#include <ev.h>
-#include <yajl/yajl_common.h>
-#include <yajl/yajl_parse.h>
-#include <yajl/yajl_version.h>
-#include <yajl/yajl_gen.h>
+#include <fcntl.h>
#include <paths.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
-#include <xcb/xcb_keysyms.h>
+#include <yajl/yajl_gen.h>
+#include <yajl/yajl_parse.h>
/* Global variables for child_*() */
i3bar_child child;
+#define DLOG_CHILD DLOG("%s: pid=%ld stopped=%d stop_signal=%d cont_signal=%d click_events=%d click_events_init=%d\n", \
+ __func__, (long)child.pid, child.stopped, child.stop_signal, child.cont_signal, child.click_events, child.click_events_init)
/* stdin- and SIGCHLD-watchers */
ev_io *stdin_io;
@@ -90,7 +88,7 @@ static void clear_statusline(struct statusline_head *head, bool free_resources)
static void copy_statusline(struct statusline_head *from, struct statusline_head *to) {
struct status_block *current;
- TAILQ_FOREACH(current, from, blocks) {
+ TAILQ_FOREACH (current, from, blocks) {
struct status_block *new_block = smalloc(sizeof(struct status_block));
memcpy(new_block, current, sizeof(struct status_block));
TAILQ_INSERT_TAIL(to, new_block, blocks);
@@ -345,7 +343,7 @@ static int stdin_end_array(void *context) {
DLOG("dumping statusline:\n");
struct status_block *current;
- TAILQ_FOREACH(current, &statusline_head, blocks) {
+ TAILQ_FOREACH (current, &statusline_head, blocks) {
DLOG("full_text = %s\n", i3string_as_utf8(current->full_text));
DLOG("short_text = %s\n", (current->short_text == NULL ? NULL : i3string_as_utf8(current->short_text)));
DLOG("color = %s\n", current->color);
@@ -543,7 +541,7 @@ static void child_write_output(void) {
/*
* Start a child process with the specified command and reroute stdin.
- * We actually start a $SHELL to execute the command so we don't have to care
+ * We actually start a shell to execute the command so we don't have to care
* about arguments and such.
*
* If `command' is NULL, such as in the case when no `status_command' is given
@@ -619,9 +617,12 @@ void start_child(char *command) {
ev_child_start(main_loop, child_sig);
atexit(kill_child_at_exit);
+ DLOG_CHILD;
}
static void child_click_events_initialize(void) {
+ DLOG_CHILD;
+
if (!child.click_events_init) {
yajl_gen_array_open(gen);
child_write_output();
@@ -633,7 +634,7 @@ static void child_click_events_initialize(void) {
* Generates a click event, if enabled.
*
*/
-void send_block_clicked(int button, const char *name, const char *instance, int x, int y, int x_rel, int y_rel, int width, int height, int mods) {
+void send_block_clicked(int button, const char *name, const char *instance, int x, int y, int x_rel, int y_rel, int out_x, int out_y, int width, int height, int mods) {
if (!child.click_events) {
return;
}
@@ -685,6 +686,12 @@ void send_block_clicked(int button, const char *name, const char *instance, int
ystr("relative_y");
yajl_gen_integer(gen, y_rel);
+ ystr("output_x");
+ yajl_gen_integer(gen, out_x);
+
+ ystr("output_y");
+ yajl_gen_integer(gen, out_y);
+
ystr("width");
yajl_gen_integer(gen, width);
@@ -700,6 +707,8 @@ void send_block_clicked(int button, const char *name, const char *instance, int
*
*/
void kill_child_at_exit(void) {
+ DLOG_CHILD;
+
if (child.pid > 0) {
if (child.cont_signal > 0 && child.stopped)
killpg(child.pid, child.cont_signal);
@@ -713,6 +722,8 @@ void kill_child_at_exit(void) {
*
*/
void kill_child(void) {
+ DLOG_CHILD;
+
if (child.pid > 0) {
if (child.cont_signal > 0 && child.stopped)
killpg(child.pid, child.cont_signal);
@@ -728,6 +739,8 @@ void kill_child(void) {
*
*/
void stop_child(void) {
+ DLOG_CHILD;
+
if (child.stop_signal > 0 && !child.stopped) {
child.stopped = true;
killpg(child.pid, child.stop_signal);
@@ -739,6 +752,8 @@ void stop_child(void) {
*
*/
void cont_child(void) {
+ DLOG_CHILD;
+
if (child.cont_signal > 0 && child.stopped) {
child.stopped = false;
killpg(child.pid, child.cont_signal);
diff --git a/i3bar/src/config.c b/i3bar/src/config.c
index 29b0908b..5d4bf88a 100644
--- a/i3bar/src/config.c
+++ b/i3bar/src/config.c
@@ -9,15 +9,12 @@
*/
#include "common.h"
-#include <string.h>
-#include <stdlib.h>
#include <stdio.h>
-#include <errno.h>
-#include <i3/ipc.h>
-#include <yajl/yajl_parse.h>
-#include <yajl/yajl_version.h>
+#include <stdlib.h>
+#include <string.h>
#include <X11/Xlib.h>
+#include <yajl/yajl_parse.h>
config_t config;
static char *cur_key;
diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c
index df5a12cf..f2c105ac 100644
--- a/i3bar/src/ipc.c
+++ b/i3bar/src/ipc.c
@@ -9,16 +9,13 @@
*/
#include "common.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <string.h>
#include <errno.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <i3/ipc.h>
#include <ev.h>
+#include <i3/ipc.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#ifdef I3_ASAN_ENABLED
#include <sanitizer/lsan_interface.h>
#endif
@@ -72,7 +69,7 @@ static void got_output_reply(char *reply) {
reconfig_windows(false);
i3_output *o_walk;
- SLIST_FOREACH(o_walk, outputs, slist) {
+ SLIST_FOREACH (o_walk, outputs, slist) {
kick_tray_clients(o_walk);
}
diff --git a/i3bar/src/main.c b/i3bar/src/main.c
index 65cb00ff..4e729341 100644
--- a/i3bar/src/main.c
+++ b/i3bar/src/main.c
@@ -7,15 +7,13 @@
*/
#include "common.h"
-#include <stdio.h>
-#include <i3/ipc.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
#include <ev.h>
#include <getopt.h>
#include <glob.h>
+#include <i3/ipc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
struct ev_loop *main_loop;
diff --git a/i3bar/src/mode.c b/i3bar/src/mode.c
index 97087ce0..13d02110 100644
--- a/i3bar/src/mode.c
+++ b/i3bar/src/mode.c
@@ -9,12 +9,10 @@
*/
#include "common.h"
-#include <string.h>
#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
+#include <string.h>
+
#include <yajl/yajl_parse.h>
-#include <yajl/yajl_version.h>
/* A datatype to pass through the callbacks to save the state */
struct mode_json_params {
diff --git a/i3bar/src/outputs.c b/i3bar/src/outputs.c
index 2fa3195c..168f3eef 100644
--- a/i3bar/src/outputs.c
+++ b/i3bar/src/outputs.c
@@ -9,13 +9,12 @@
*/
#include "common.h"
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
#include <errno.h>
-#include <i3/ipc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
#include <yajl/yajl_parse.h>
-#include <yajl/yajl_version.h>
/* A datatype to pass through the callbacks to save the state */
struct outputs_json_params {
@@ -193,11 +192,12 @@ static int outputs_end_map_cb(void *params_) {
/* See if we actually handle that output */
if (config.num_outputs > 0) {
+ const bool is_primary = params->outputs_walk->primary;
bool handle_output = false;
for (int c = 0; c < config.num_outputs; c++) {
- if (strcasecmp(params->outputs_walk->name, config.outputs[c]) == 0 ||
- (strcasecmp(config.outputs[c], "primary") == 0 &&
- params->outputs_walk->primary)) {
+ if ((strcasecmp(params->outputs_walk->name, config.outputs[c]) == 0) ||
+ (strcasecmp(config.outputs[c], "primary") == 0 && is_primary) ||
+ (strcasecmp(config.outputs[c], "nonprimary") == 0 && !is_primary)) {
handle_output = true;
break;
}
@@ -304,7 +304,7 @@ void free_outputs(void) {
if (outputs == NULL) {
return;
}
- SLIST_FOREACH(outputs_walk, outputs, slist) {
+ SLIST_FOREACH (outputs_walk, outputs, slist) {
destroy_window(outputs_walk);
if (outputs_walk->trayclients != NULL && !TAILQ_EMPTY(outputs_walk->trayclients)) {
FREE_TAILQ(outputs_walk->trayclients, trayclient);
@@ -323,7 +323,7 @@ i3_output *get_output_by_name(char *name) {
if (name == NULL) {
return NULL;
}
- SLIST_FOREACH(walk, outputs, slist) {
+ SLIST_FOREACH (walk, outputs, slist) {
if (!strcmp(walk->name, name)) {
break;
}
@@ -338,7 +338,7 @@ i3_output *get_output_by_name(char *name) {
*/
bool output_has_focus(i3_output *output) {
i3_ws *ws_walk;
- TAILQ_FOREACH(ws_walk, output->workspaces, tailq) {
+ TAILQ_FOREACH (ws_walk, output->workspaces, tailq) {
if (ws_walk->focused) {
return true;
}
diff --git a/i3bar/src/parse_json_header.c b/i3bar/src/parse_json_header.c
index 3d4c2a67..c74a62fe 100644
--- a/i3bar/src/parse_json_header.c
+++ b/i3bar/src/parse_json_header.c
@@ -10,22 +10,10 @@
*/
#include "common.h"
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
#include <signal.h>
-#include <stdio.h>
-#include <fcntl.h>
#include <string.h>
-#include <errno.h>
-#include <err.h>
-#include <ev.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <yajl/yajl_common.h>
+
#include <yajl/yajl_parse.h>
-#include <yajl/yajl_version.h>
static enum {
KEY_VERSION,
diff --git a/i3bar/src/workspaces.c b/i3bar/src/workspaces.c
index 9a0b950e..bd56f5d0 100644
--- a/i3bar/src/workspaces.c
+++ b/i3bar/src/workspaces.c
@@ -9,12 +9,10 @@
*/
#include "common.h"
-#include <string.h>
#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
+#include <string.h>
+
#include <yajl/yajl_parse.h>
-#include <yajl/yajl_version.h>
/* A datatype to pass through the callbacks to save the state */
struct workspaces_json_params {
@@ -114,7 +112,7 @@ static int workspaces_string_cb(void *params_, const unsigned char *val, size_t
if ((config.strip_ws_numbers || config.strip_ws_name) && params->workspaces_walk->num >= 0) {
/* Special case: strip off the workspace number/name */
- static char ws_num[10];
+ static char ws_num[32];
snprintf(ws_num, sizeof(ws_num), "%d", params->workspaces_walk->num);
@@ -269,9 +267,9 @@ void free_workspaces(void) {
}
i3_ws *ws_walk;
- SLIST_FOREACH(outputs_walk, outputs, slist) {
+ SLIST_FOREACH (outputs_walk, outputs, slist) {
if (outputs_walk->workspaces != NULL && !TAILQ_EMPTY(outputs_walk->workspaces)) {
- TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) {
+ TAILQ_FOREACH (ws_walk, outputs_walk->workspaces, tailq) {
I3STRING_FREE(ws_walk->name);
FREE(ws_walk->canonical_name);
}
diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c
index a01e31ea..ab59209d 100644
--- a/i3bar/src/xcb.c
+++ b/i3bar/src/xcb.c
@@ -9,26 +9,15 @@
*/
#include "common.h"
-#include <xcb/xcb.h>
-#include <xcb/xkb.h>
-#include <xcb/xproto.h>
-#include <xcb/xcb_aux.h>
-#include <xcb/xcb_cursor.h>
-
-#include <stdio.h>
+#include <err.h>
+#include <ev.h>
+#include <i3/ipc.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
#include <string.h>
-#include <i3/ipc.h>
-#include <ev.h>
-#include <errno.h>
-#include <limits.h>
-#include <err.h>
-#include <X11/Xlib.h>
-#include <X11/XKBlib.h>
-#include <X11/extensions/XKB.h>
+#include <xcb/xcb_aux.h>
+#include <xcb/xcb_cursor.h>
+#include <xcb/xkb.h>
#ifdef I3_ASAN_ENABLED
#include <sanitizer/lsan_interface.h>
@@ -36,10 +25,6 @@
#include "libi3.h"
-/** This is the equivalent of XC_left_ptr. I’m not sure why xcb doesn’t have a
- * constant for that. */
-#define XCB_CURSOR_LEFT_PTR 68
-
/* We save the atoms in an easy to access array, indexed by an enum */
enum {
#define ATOM_DO(name) name,
@@ -161,7 +146,7 @@ static uint32_t get_sep_offset(struct status_block *block) {
static int get_tray_width(struct tc_head *trayclients) {
trayclient *trayclient;
int tray_width = 0;
- TAILQ_FOREACH_REVERSE(trayclient, trayclients, tc_head, tailq) {
+ TAILQ_FOREACH_REVERSE (trayclient, trayclients, tc_head, tailq) {
if (!trayclient->mapped)
continue;
tray_width += icon_size + logical_px(config.tray_padding);
@@ -203,7 +188,7 @@ static uint32_t predict_statusline_length(bool use_short_text) {
uint32_t width = 0;
struct status_block *block;
- TAILQ_FOREACH(block, &statusline_head, blocks) {
+ TAILQ_FOREACH (block, &statusline_head, blocks) {
i3String *text = block->full_text;
struct status_block_render_desc *render = &block->full_render;
if (use_short_text && block->short_text != NULL) {
@@ -266,7 +251,7 @@ static void draw_statusline(i3_output *output, uint32_t clip_left, bool use_focu
uint32_t x = 0 - clip_left;
/* Draw the text of each block */
- TAILQ_FOREACH(block, &statusline_head, blocks) {
+ TAILQ_FOREACH (block, &statusline_head, blocks) {
i3String *text = block->full_text;
struct status_block_render_desc *render = &block->full_render;
if (use_short_text && block->short_text != NULL) {
@@ -343,7 +328,7 @@ static void hide_bars(void) {
}
i3_output *walk;
- SLIST_FOREACH(walk, outputs, slist) {
+ SLIST_FOREACH (walk, outputs, slist) {
if (!walk->active) {
continue;
}
@@ -368,7 +353,7 @@ static void unhide_bars(void) {
cont_child();
- SLIST_FOREACH(walk, outputs, slist) {
+ SLIST_FOREACH (walk, outputs, slist) {
if (walk->bar.id == XCB_NONE) {
continue;
}
@@ -448,7 +433,7 @@ void init_colors(const struct xcb_color_strings_t *new_colors) {
static bool execute_custom_command(xcb_keycode_t input_code, bool event_is_release) {
binding_t *binding;
- TAILQ_FOREACH(binding, &(config.bindings), bindings) {
+ TAILQ_FOREACH (binding, &(config.bindings), bindings) {
if ((binding->input_code != input_code) || (binding->release != event_is_release))
continue;
@@ -458,7 +443,7 @@ static bool execute_custom_command(xcb_keycode_t input_code, bool event_is_relea
return false;
}
-static void child_handle_button(xcb_button_press_event_t *event, i3_output *output, uint32_t statusline_x) {
+static void child_handle_button(xcb_button_press_event_t *event, i3_output *output, uint32_t statusline_x, uint32_t statusline_y) {
if (statusline_x > (uint32_t)output->statusline_width) {
return;
}
@@ -466,7 +451,7 @@ static void child_handle_button(xcb_button_press_event_t *event, i3_output *outp
/* x of the start of the current block relative to the statusline. */
uint32_t last_block_x = 0;
struct status_block *block;
- TAILQ_FOREACH(block, &statusline_head, blocks) {
+ TAILQ_FOREACH (block, &statusline_head, blocks) {
i3String *text;
struct status_block_render_desc *render;
if (output->statusline_short_text && block->short_text != NULL) {
@@ -487,9 +472,13 @@ static void child_handle_button(xcb_button_press_event_t *event, i3_output *outp
/* x of the click event relative to the current block. */
const uint32_t relative_x = statusline_x - last_block_x;
if (relative_x <= full_render_width) {
+ const uint32_t output_x = event->event_x;
+ const uint32_t output_y = statusline_y + event->event_y;
+
send_block_clicked(event->detail, block->name, block->instance,
event->root_x, event->root_y, relative_x,
- event->event_y, full_render_width, bar_height,
+ event->event_y, output_x, output_y,
+ full_render_width, bar_height,
event->state);
return;
}
@@ -521,7 +510,7 @@ static void handle_button(xcb_button_press_event_t *event) {
/* Determine, which bar was clicked */
i3_output *walk;
xcb_window_t bar = event->event;
- SLIST_FOREACH(walk, outputs, slist) {
+ SLIST_FOREACH (walk, outputs, slist) {
if (walk->bar.id == bar) {
break;
}
@@ -541,7 +530,7 @@ static void handle_button(xcb_button_press_event_t *event) {
int workspace_width = 0;
i3_ws *cur_ws = NULL, *clicked_ws = NULL, *ws_walk;
- TAILQ_FOREACH(ws_walk, walk->workspaces, tailq) {
+ TAILQ_FOREACH (ws_walk, walk->workspaces, tailq) {
int w = predict_button_width(ws_walk->name_width);
if (x >= workspace_width && x <= workspace_width + w)
clicked_ws = ws_walk;
@@ -557,9 +546,9 @@ static void handle_button(xcb_button_press_event_t *event) {
/* Calculate the horizontal coordinate (x) of the start of the
* statusline by subtracting its width and the width of the tray from
* the bar width. */
- const int offset = walk->rect.w - walk->statusline_width -
- tray_width - logical_px((tray_width > 0) * sb_hoff_px);
- if (x >= offset) {
+ const int offset_x = walk->rect.w - walk->statusline_width -
+ tray_width - logical_px((tray_width > 0) * sb_hoff_px);
+ if (x >= offset_x) {
/* Click was after the start of the statusline, return to avoid
* executing any other actions even if a click event is not
* produced eventually. */
@@ -567,8 +556,10 @@ static void handle_button(xcb_button_press_event_t *event) {
if (!event_is_release) {
/* x of the click event relative to the start of the
* statusline. */
- const uint32_t statusline_x = x - offset;
- child_handle_button(event, walk, statusline_x);
+ const uint32_t statusline_x = x - offset_x;
+ const uint32_t statusline_y = event->root_y - walk->rect.y - event->event_y;
+
+ child_handle_button(event, walk, statusline_x, statusline_y);
}
return;
@@ -614,7 +605,7 @@ static void handle_button(xcb_button_press_event_t *event) {
/* if no workspace was clicked, focus our currently visible
* workspace if it is not already focused */
if (cur_ws == NULL) {
- TAILQ_FOREACH(cur_ws, walk->workspaces, tailq) {
+ TAILQ_FOREACH (cur_ws, walk->workspaces, tailq) {
if (cur_ws->visible && !cur_ws->focused)
break;
}
@@ -672,7 +663,7 @@ static void handle_visibility_notify(xcb_visibility_notify_event_t *event) {
int num_visible = 0;
i3_output *output;
- SLIST_FOREACH(output, outputs, slist) {
+ SLIST_FOREACH (output, outputs, slist) {
if (!output->active) {
continue;
}
@@ -689,19 +680,6 @@ static void handle_visibility_notify(xcb_visibility_notify_event_t *event) {
}
}
-static int strcasecmp_nullable(const char *a, const char *b) {
- if (a == b) {
- return 0;
- }
- if (a == NULL) {
- return -1;
- }
- if (b == NULL) {
- return 1;
- }
- return strcasecmp(a, b);
-}
-
/*
* Comparison function to sort trayclients in ascending alphanumeric order
* according to their class.
@@ -723,14 +701,14 @@ static int reorder_trayclients_cmp(const void *_a, const void *_b) {
*/
static void configure_trayclients(void) {
i3_output *output;
- SLIST_FOREACH(output, outputs, slist) {
+ SLIST_FOREACH (output, outputs, slist) {
if (!output->active) {
continue;
}
int count = 0;
trayclient *client;
- TAILQ_FOREACH(client, output->trayclients, tailq) {
+ TAILQ_FOREACH (client, output->trayclients, tailq) {
if (client->mapped) {
count++;
}
@@ -738,7 +716,7 @@ static void configure_trayclients(void) {
int idx = 0;
trayclient **trayclients = smalloc(count * sizeof(trayclient *));
- TAILQ_FOREACH(client, output->trayclients, tailq) {
+ TAILQ_FOREACH (client, output->trayclients, tailq) {
if (client->mapped) {
trayclients[idx++] = client;
}
@@ -763,13 +741,13 @@ static void configure_trayclients(void) {
static trayclient *trayclient_and_output_from_window(xcb_window_t win, i3_output **output) {
i3_output *o_walk;
- SLIST_FOREACH(o_walk, outputs, slist) {
+ SLIST_FOREACH (o_walk, outputs, slist) {
if (!o_walk->active) {
continue;
}
trayclient *client;
- TAILQ_FOREACH(client, o_walk->trayclients, tailq) {
+ TAILQ_FOREACH (client, o_walk->trayclients, tailq) {
if (client->win == win) {
if (output) {
*output = o_walk;
@@ -1112,12 +1090,12 @@ static void handle_property_notify(xcb_property_notify_event_t *event) {
static void handle_configuration_change(xcb_window_t window) {
trayclient *trayclient;
i3_output *output;
- SLIST_FOREACH(output, outputs, slist) {
+ SLIST_FOREACH (output, outputs, slist) {
if (!output->active)
continue;
int clients = 0;
- TAILQ_FOREACH_REVERSE(trayclient, output->trayclients, tc_head, tailq) {
+ TAILQ_FOREACH_REVERSE (trayclient, output->trayclients, tc_head, tailq) {
if (!trayclient->mapped)
continue;
clients++;
@@ -1299,22 +1277,11 @@ char *init_xcb_early(void) {
}
xcb_cursor_context_t *cursor_ctx;
- if (xcb_cursor_context_new(conn, root_screen, &cursor_ctx) == 0) {
- cursor = xcb_cursor_load_cursor(cursor_ctx, "left_ptr");
- xcb_cursor_context_free(cursor_ctx);
- } else {
- cursor = xcb_generate_id(xcb_connection);
- i3Font cursor_font = load_font("cursor", false);
- xcb_create_glyph_cursor(
- xcb_connection,
- cursor,
- cursor_font.specific.xcb.id,
- cursor_font.specific.xcb.id,
- XCB_CURSOR_LEFT_PTR,
- XCB_CURSOR_LEFT_PTR + 1,
- 0, 0, 0,
- 65535, 65535, 65535);
+ if (xcb_cursor_context_new(conn, root_screen, &cursor_ctx) < 0) {
+ errx(EXIT_FAILURE, "Cannot allocate xcursor context");
}
+ cursor = xcb_cursor_load_cursor(cursor_ctx, "left_ptr");
+ xcb_cursor_context_free(cursor_ctx);
/* The various watchers to communicate with xcb */
xcb_io = smalloc(sizeof(ev_io));
@@ -1730,7 +1697,7 @@ static i3_output *get_tray_output(void) {
i3_output *output = NULL;
if (TAILQ_EMPTY(&(config.tray_outputs))) {
/* No tray_output specified, use first active output. */
- SLIST_FOREACH(output, outputs, slist) {
+ SLIST_FOREACH (output, outputs, slist) {
if (output->active) {
return output;
}
@@ -1744,8 +1711,8 @@ static i3_output *get_tray_output(void) {
/* If one or more tray_output assignments were specified, we ensure that at
* least one of them is actually an output managed by this instance. */
tray_output_t *tray_output;
- TAILQ_FOREACH(tray_output, &(config.tray_outputs), tray_outputs) {
- SLIST_FOREACH(output, outputs, slist) {
+ TAILQ_FOREACH (tray_output, &(config.tray_outputs), tray_outputs) {
+ SLIST_FOREACH (output, outputs, slist) {
if (output->active &&
(strcasecmp(output->name, tray_output->output) == 0 ||
(strcasecmp(tray_output->output, "primary") == 0 && output->primary))) {
@@ -1766,7 +1733,7 @@ void reconfig_windows(bool redraw_bars) {
uint32_t values[6];
i3_output *walk;
- SLIST_FOREACH(walk, outputs, slist) {
+ SLIST_FOREACH (walk, outputs, slist) {
if (!walk->active) {
/* If an output is not active, we destroy its bar */
/* FIXME: Maybe we rather want to unmap? */
@@ -1834,6 +1801,8 @@ void reconfig_windows(bool redraw_bars) {
bar_height);
/* Set the WM_CLASS and WM_NAME (we don't need UTF-8) atoms */
+ char *class;
+ int len = sasprintf(&class, "%s%ci3bar%c", config.bar_id, 0, 0);
xcb_void_cookie_t class_cookie;
class_cookie = xcb_change_property(xcb_connection,
XCB_PROP_MODE_REPLACE,
@@ -1841,8 +1810,8 @@ void reconfig_windows(bool redraw_bars) {
XCB_ATOM_WM_CLASS,
XCB_ATOM_STRING,
8,
- (strlen("i3bar") + 1) * 2,
- "i3bar\0i3bar\0");
+ len,
+ class);
char *name;
sasprintf(&name, "i3bar for output %s", walk->name);
@@ -2029,7 +1998,7 @@ void draw_bars(bool unhide) {
uint32_t short_statusline_width = predict_statusline_length(true);
i3_output *outputs_walk;
- SLIST_FOREACH(outputs_walk, outputs, slist) {
+ SLIST_FOREACH (outputs_walk, outputs, slist) {
int workspace_width = 0;
if (!outputs_walk->active) {
@@ -2048,7 +2017,7 @@ void draw_bars(bool unhide) {
if (!config.disable_ws) {
i3_ws *ws_walk;
- TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) {
+ TAILQ_FOREACH (ws_walk, outputs_walk->workspaces, tailq) {
DLOG("Drawing button for WS %s at x = %d, len = %d\n",
i3string_as_utf8(ws_walk->name), workspace_width, ws_walk->name_width);
color_t fg_color = colors.inactive_ws_fg;
@@ -2142,7 +2111,7 @@ void draw_bars(bool unhide) {
*/
void redraw_bars(void) {
i3_output *outputs_walk;
- SLIST_FOREACH(outputs_walk, outputs, slist) {
+ SLIST_FOREACH (outputs_walk, outputs, slist) {
if (!outputs_walk->active) {
continue;
}
diff --git a/include/all.h b/include/all.h
index aa2b5b25..55111944 100644
--- a/include/all.h
+++ b/include/all.h
@@ -15,31 +15,24 @@
#include <config.h>
#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
#include <stdbool.h>
-#include <stdlib.h>
+#include <stdint.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include <locale.h>
-#include <getopt.h>
-#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <glob.h>
-#include <errno.h>
-#include <err.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <math.h>
-#include <limits.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
-#include <xcb/xcb_keysyms.h>
#include <xcb/xcb_icccm.h>
+#include <xcb/xcb_keysyms.h>
-#include <yajl/yajl_gen.h>
-#include <yajl/yajl_version.h>
-
+#include "libi3.h"
#include "data.h"
#include "util.h"
#include "ipc.h"
@@ -72,7 +65,6 @@
#include "ewmh.h"
#include "assignments.h"
#include "regex.h"
-#include "libi3.h"
#include "startup.h"
#include "scratchpad.h"
#include "commands.h"
diff --git a/include/atoms.xmacro b/include/atoms.xmacro
deleted file mode 100644
index 730e569a..00000000
--- a/include/atoms.xmacro
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "atoms_NET_SUPPORTED.xmacro"
-#include "atoms_rest.xmacro"
diff --git a/include/atoms_NET_SUPPORTED.xmacro b/include/atoms_NET_SUPPORTED.xmacro
deleted file mode 100644
index a81948a9..00000000
--- a/include/atoms_NET_SUPPORTED.xmacro
+++ /dev/null
@@ -1,35 +0,0 @@
-xmacro(_NET_SUPPORTED)
-xmacro(_NET_SUPPORTING_WM_CHECK)
-xmacro(_NET_WM_NAME)
-xmacro(_NET_WM_VISIBLE_NAME)
-xmacro(_NET_WM_MOVERESIZE)
-xmacro(_NET_WM_STATE_STICKY)
-xmacro(_NET_WM_STATE_FULLSCREEN)
-xmacro(_NET_WM_STATE_DEMANDS_ATTENTION)
-xmacro(_NET_WM_STATE_MODAL)
-xmacro(_NET_WM_STATE_HIDDEN)
-xmacro(_NET_WM_STATE_FOCUSED)
-xmacro(_NET_WM_STATE)
-xmacro(_NET_WM_WINDOW_TYPE)
-xmacro(_NET_WM_WINDOW_TYPE_NORMAL)
-xmacro(_NET_WM_WINDOW_TYPE_DOCK)
-xmacro(_NET_WM_WINDOW_TYPE_DIALOG)
-xmacro(_NET_WM_WINDOW_TYPE_UTILITY)
-xmacro(_NET_WM_WINDOW_TYPE_TOOLBAR)
-xmacro(_NET_WM_WINDOW_TYPE_SPLASH)
-xmacro(_NET_WM_WINDOW_TYPE_MENU)
-xmacro(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU)
-xmacro(_NET_WM_WINDOW_TYPE_POPUP_MENU)
-xmacro(_NET_WM_WINDOW_TYPE_TOOLTIP)
-xmacro(_NET_WM_WINDOW_TYPE_NOTIFICATION)
-xmacro(_NET_WM_DESKTOP)
-xmacro(_NET_WM_STRUT_PARTIAL)
-xmacro(_NET_CLIENT_LIST)
-xmacro(_NET_CLIENT_LIST_STACKING)
-xmacro(_NET_CURRENT_DESKTOP)
-xmacro(_NET_NUMBER_OF_DESKTOPS)
-xmacro(_NET_DESKTOP_NAMES)
-xmacro(_NET_DESKTOP_VIEWPORT)
-xmacro(_NET_ACTIVE_WINDOW)
-xmacro(_NET_CLOSE_WINDOW)
-xmacro(_NET_MOVERESIZE_WINDOW)
diff --git a/include/atoms_rest.xmacro b/include/atoms_rest.xmacro
deleted file mode 100644
index b65a81d8..00000000
--- a/include/atoms_rest.xmacro
+++ /dev/null
@@ -1,20 +0,0 @@
-xmacro(_NET_WM_USER_TIME)
-xmacro(_NET_STARTUP_ID)
-xmacro(_NET_WORKAREA)
-xmacro(WM_PROTOCOLS)
-xmacro(WM_DELETE_WINDOW)
-xmacro(UTF8_STRING)
-xmacro(WM_STATE)
-xmacro(WM_CLIENT_LEADER)
-xmacro(WM_TAKE_FOCUS)
-xmacro(WM_WINDOW_ROLE)
-xmacro(I3_SOCKET_PATH)
-xmacro(I3_CONFIG_PATH)
-xmacro(I3_SYNC)
-xmacro(I3_SHMLOG_PATH)
-xmacro(I3_PID)
-xmacro(I3_FLOATING_WINDOW)
-xmacro(_NET_REQUEST_FRAME_EXTENTS)
-xmacro(_NET_FRAME_EXTENTS)
-xmacro(_MOTIF_WM_HINTS)
-xmacro(WM_CHANGE_STATE)
diff --git a/include/click.h b/include/click.h
index 0d57abf7..898f1870 100644
--- a/include/click.h
+++ b/include/click.h
@@ -19,4 +19,4 @@
* Then, route_click is called on the appropriate con.
*
*/
-int handle_button_press(xcb_button_press_event_t *event);
+void handle_button_press(xcb_button_press_event_t *event);
diff --git a/include/commands.h b/include/commands.h
index 27d631a2..7a1877a1 100644
--- a/include/commands.h
+++ b/include/commands.h
@@ -219,10 +219,10 @@ void cmd_fullscreen(I3_CMD, const char *action, const char *fullscreen_mode);
void cmd_sticky(I3_CMD, const char *action);
/**
- * Implementation of 'move <direction> [<pixels> [px]]'.
+ * Implementation of 'move <direction> [<amount> [px|ppt]]'.
*
*/
-void cmd_move_direction(I3_CMD, const char *direction_str, long move_px);
+void cmd_move_direction(I3_CMD, const char *direction_str, long amount, const char *mode);
/**
* Implementation of 'layout default|stacked|stacking|tabbed|splitv|splith'.
@@ -267,10 +267,10 @@ void cmd_open(I3_CMD);
void cmd_focus_output(I3_CMD, const char *name);
/**
- * Implementation of 'move [window|container] [to] [absolute] position <px> [px] <px> [px]
+ * Implementation of 'move [window|container] [to] [absolute] position [<pos_x> [px|ppt] <pos_y> [px|ppt]]
*
*/
-void cmd_move_window_to_position(I3_CMD, long x, long y);
+void cmd_move_window_to_position(I3_CMD, long x, const char *mode_x, long y, const char *mode_y);
/**
* Implementation of 'move [window|container] [to] [absolute] position center
@@ -315,10 +315,16 @@ void cmd_title_format(I3_CMD, const char *format);
void cmd_rename_workspace(I3_CMD, const char *old_name, const char *new_name);
/**
- * Implementation of 'bar (hidden_state hide|show|toggle)|(mode dock|hide|invisible|toggle) [<bar_id>]'
+ * Implementation of 'bar mode dock|hide|invisible|toggle [<bar_id>]'
*
*/
-void cmd_bar(I3_CMD, const char *bar_type, const char *bar_value, const char *bar_id);
+void cmd_bar_mode(I3_CMD, const char *bar_mode, const char *bar_id);
+
+/**
+ * Implementation of 'bar hidden_state hide|show|toggle [<bar_id>]'
+ *
+ */
+void cmd_bar_hidden_state(I3_CMD, const char *bar_hidden_state, const char *bar_id);
/**
* Implementation of 'shmlog <size>|toggle|on|off'
diff --git a/include/configuration.h b/include/configuration.h
index d7c2ab8b..11cdde0d 100644
--- a/include/configuration.h
+++ b/include/configuration.h
@@ -12,9 +12,6 @@
*/
#pragma once
-#include "libi3.h"
-
-#include <stdbool.h>
#include "queue.h"
#include "i3.h"
@@ -69,8 +66,7 @@ struct Variable {
char *value;
char *next_match;
- SLIST_ENTRY(Variable)
- variables;
+ SLIST_ENTRY(Variable) variables;
};
/**
@@ -84,8 +80,7 @@ struct Mode {
bool pango_markup;
struct bindings_head *bindings;
- SLIST_ENTRY(Mode)
- modes;
+ SLIST_ENTRY(Mode) modes;
};
/**
@@ -275,8 +270,7 @@ struct Barconfig {
/* List of outputs on which the tray is allowed to be shown, in order.
* The special value "none" disables it (per default, it will be shown) and
* the special value "primary" enabled it on the primary output. */
- TAILQ_HEAD(tray_outputs_head, tray_output_t)
- tray_outputs;
+ TAILQ_HEAD(tray_outputs_head, tray_output_t) tray_outputs;
/* Padding around the tray icons. */
int tray_padding;
@@ -298,8 +292,7 @@ struct Barconfig {
/** Bar modifier (to show bar when in hide mode). */
uint32_t modifier;
- TAILQ_HEAD(bar_bindings_head, Barbinding)
- bar_bindings;
+ TAILQ_HEAD(bar_bindings_head, Barbinding) bar_bindings;
/** Bar position (bottom by default). */
enum { P_BOTTOM = 0,
@@ -373,8 +366,7 @@ struct Barconfig {
char *binding_mode_text;
} colors;
- TAILQ_ENTRY(Barconfig)
- configs;
+ TAILQ_ENTRY(Barconfig) configs;
};
/**
@@ -392,15 +384,13 @@ struct Barbinding {
/** If true, the command will be executed after the button is released. */
bool release;
- TAILQ_ENTRY(Barbinding)
- bindings;
+ TAILQ_ENTRY(Barbinding) bindings;
};
struct tray_output_t {
char *output;
- TAILQ_ENTRY(tray_output_t)
- tray_outputs;
+ TAILQ_ENTRY(tray_output_t) tray_outputs;
};
typedef enum {
@@ -428,9 +418,3 @@ bool load_configuration(const char *override_configfile, config_load_t load_type
*
*/
void ungrab_all_keys(xcb_connection_t *conn);
-
-/**
- * Sends the current bar configuration as an event to all barconfig_update listeners.
- *
- */
-void update_barconfig(void);
diff --git a/include/data.h b/include/data.h
index c0e34b41..e411129f 100644
--- a/include/data.h
+++ b/include/data.h
@@ -9,13 +9,10 @@
*/
#pragma once
-#include "libi3.h"
-
#define SN_API_NOT_YET_FROZEN 1
#include <libsn/sn-launcher.h>
#include <xcb/randr.h>
-#include <stdbool.h>
#include <pcre.h>
#include <sys/time.h>
@@ -209,8 +206,7 @@ struct Workspace_Assignment {
char *name;
char *output;
- TAILQ_ENTRY(Workspace_Assignment)
- ws_assignments;
+ TAILQ_ENTRY(Workspace_Assignment) ws_assignments;
};
struct Ignore_Event {
@@ -218,8 +214,7 @@ struct Ignore_Event {
int response_type;
time_t added;
- SLIST_ENTRY(Ignore_Event)
- ignore_events;
+ SLIST_ENTRY(Ignore_Event) ignore_events;
};
/**
@@ -238,8 +233,7 @@ struct Startup_Sequence {
* completed) */
time_t delete_at;
- TAILQ_ENTRY(Startup_Sequence)
- sequences;
+ TAILQ_ENTRY(Startup_Sequence) sequences;
};
/**
@@ -265,9 +259,7 @@ struct regex {
struct Binding_Keycode {
xcb_keycode_t keycode;
i3_event_state_mask_t modifiers;
-
- TAILQ_ENTRY(Binding_Keycode)
- keycodes;
+ TAILQ_ENTRY(Binding_Keycode) keycodes;
};
/******************************************************************************
@@ -328,14 +320,12 @@ struct Binding {
/** Only in use if symbol != NULL. Contains keycodes which generate the
* specified symbol. Useful for unbinding and checking which binding was
* used when a key press event comes in. */
- TAILQ_HEAD(keycodes_head, Binding_Keycode)
- keycodes_head;
+ TAILQ_HEAD(keycodes_head, Binding_Keycode) keycodes_head;
/** Command, like in command mode */
char *command;
- TAILQ_ENTRY(Binding)
- bindings;
+ TAILQ_ENTRY(Binding) bindings;
};
/**
@@ -351,19 +341,13 @@ struct Autostart {
/** no_startup_id flag for start_application(). Determines whether a
* startup notification context/ID should be created. */
bool no_startup_id;
-
- TAILQ_ENTRY(Autostart)
- autostarts;
-
- TAILQ_ENTRY(Autostart)
- autostarts_always;
+ TAILQ_ENTRY(Autostart) autostarts;
+ TAILQ_ENTRY(Autostart) autostarts_always;
};
struct output_name {
char *name;
-
- SLIST_ENTRY(output_name)
- names;
+ SLIST_ENTRY(output_name) names;
};
/**
@@ -390,8 +374,7 @@ struct xoutput {
/** List of names for the output.
* An output always has at least one name; the first name is
* considered the primary one. */
- SLIST_HEAD(names_head, output_name)
- names_head;
+ SLIST_HEAD(names_head, output_name) names_head;
/** Pointer to the Con which represents this output */
Con *con;
@@ -399,8 +382,7 @@ struct xoutput {
/** x, y, width, height */
Rect rect;
- TAILQ_ENTRY(xoutput)
- outputs;
+ TAILQ_ENTRY(xoutput) outputs;
};
/**
@@ -494,6 +476,9 @@ struct Window {
/* Time when the window became managed. Used to determine whether a window
* should be swallowed after initial management. */
time_t managed_since;
+
+ /* The window has been swallowed. */
+ bool swallowed;
};
/**
@@ -530,7 +515,11 @@ struct Match {
} dock;
xcb_window_t id;
enum { WM_ANY = 0,
+ WM_TILING_AUTO,
+ WM_TILING_USER,
WM_TILING,
+ WM_FLOATING_AUTO,
+ WM_FLOATING_USER,
WM_FLOATING } window_mode;
Con *con_id;
@@ -547,8 +536,7 @@ struct Match {
M_ASSIGN_WS,
M_BELOW } insert_where;
- TAILQ_ENTRY(Match)
- matches;
+ TAILQ_ENTRY(Match) matches;
/* Whether this match was generated when restarting i3 inplace.
* Leads to not setting focus when managing a new window, because the old
@@ -595,8 +583,7 @@ struct Assignment {
char *output;
} dest;
- TAILQ_ENTRY(Assignment)
- assignments;
+ TAILQ_ENTRY(Assignment) assignments;
};
/** Fullscreen modes. Used by Con.fullscreen_mode. */
@@ -607,8 +594,7 @@ typedef enum { CF_NONE = 0,
struct mark_t {
char *name;
- TAILQ_ENTRY(mark_t)
- marks;
+ TAILQ_ENTRY(mark_t) marks;
};
/**
@@ -672,8 +658,7 @@ struct Con {
char *sticky_group;
/* user-definable marks to jump to this container later */
- TAILQ_HEAD(marks_head, mark_t)
- marks_head;
+ TAILQ_HEAD(marks_head, mark_t) marks_head;
/* cached to decide whether a redraw is needed */
bool mark_changed;
@@ -692,17 +677,12 @@ struct Con {
struct deco_render_params *deco_render_params;
/* Only workspace-containers can have floating clients */
- TAILQ_HEAD(floating_head, Con)
- floating_head;
-
- TAILQ_HEAD(nodes_head, Con)
- nodes_head;
+ TAILQ_HEAD(floating_head, Con) floating_head;
- TAILQ_HEAD(focus_head, Con)
- focus_head;
+ TAILQ_HEAD(nodes_head, Con) nodes_head;
+ TAILQ_HEAD(focus_head, Con) focus_head;
- TAILQ_HEAD(swallow_head, Match)
- swallow_head;
+ TAILQ_HEAD(swallow_head, Match) swallow_head;
fullscreen_mode_t fullscreen_mode;
@@ -740,17 +720,10 @@ struct Con {
FLOATING_USER_ON = 3
} floating;
- TAILQ_ENTRY(Con)
- nodes;
-
- TAILQ_ENTRY(Con)
- focused;
-
- TAILQ_ENTRY(Con)
- all_cons;
-
- TAILQ_ENTRY(Con)
- floating_windows;
+ TAILQ_ENTRY(Con) nodes;
+ TAILQ_ENTRY(Con) focused;
+ TAILQ_ENTRY(Con) all_cons;
+ TAILQ_ENTRY(Con) floating_windows;
/** callbacks */
void (*on_remove_child)(Con *);
diff --git a/include/floating.h b/include/floating.h
index 8e60f78c..612874fc 100644
--- a/include/floating.h
+++ b/include/floating.h
@@ -25,7 +25,7 @@ typedef enum { BORDER_LEFT = (1 << 0),
* floating_windows list of the workspace.
*
*/
-void floating_enable(Con *con, bool automatic);
+bool floating_enable(Con *con, bool automatic);
/**
* Disables floating mode for the given container by re-attaching the container
diff --git a/include/handlers.h b/include/handlers.h
index d2c79c59..81012e7b 100644
--- a/include/handlers.h
+++ b/include/handlers.h
@@ -47,22 +47,3 @@ void handle_event(int type, xcb_generic_event_t *event);
*
*/
void property_handlers_init(void);
-
-#if 0
-/**
- * Configuration notifies are only handled because we need to set up ignore
- * for the following enter notify events
- *
- */
-int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_notify_event_t *event);
-#endif
-
-#if 0
-/**
- * Handles _NET_WM_WINDOW_TYPE changes
- *
- */
-int handle_window_type(void *data, xcb_connection_t *conn, uint8_t state,
- xcb_window_t window, xcb_atom_t atom,
- xcb_get_property_reply_t *property);
-#endif
diff --git a/include/i3-atoms_NET_SUPPORTED.xmacro.h b/include/i3-atoms_NET_SUPPORTED.xmacro.h
new file mode 100644
index 00000000..b491da98
--- /dev/null
+++ b/include/i3-atoms_NET_SUPPORTED.xmacro.h
@@ -0,0 +1,37 @@
+// clang-format off
+#define I3_NET_SUPPORTED_ATOMS_XMACRO \
+xmacro(_NET_SUPPORTED) \
+xmacro(_NET_SUPPORTING_WM_CHECK) \
+xmacro(_NET_WM_NAME) \
+xmacro(_NET_WM_VISIBLE_NAME) \
+xmacro(_NET_WM_MOVERESIZE) \
+xmacro(_NET_WM_STATE_STICKY) \
+xmacro(_NET_WM_STATE_FULLSCREEN) \
+xmacro(_NET_WM_STATE_DEMANDS_ATTENTION) \
+xmacro(_NET_WM_STATE_MODAL) \
+xmacro(_NET_WM_STATE_HIDDEN) \
+xmacro(_NET_WM_STATE_FOCUSED) \
+xmacro(_NET_WM_STATE) \
+xmacro(_NET_WM_WINDOW_TYPE) \
+xmacro(_NET_WM_WINDOW_TYPE_NORMAL) \
+xmacro(_NET_WM_WINDOW_TYPE_DOCK) \
+xmacro(_NET_WM_WINDOW_TYPE_DIALOG) \
+xmacro(_NET_WM_WINDOW_TYPE_UTILITY) \
+xmacro(_NET_WM_WINDOW_TYPE_TOOLBAR) \
+xmacro(_NET_WM_WINDOW_TYPE_SPLASH) \
+xmacro(_NET_WM_WINDOW_TYPE_MENU) \
+xmacro(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU) \
+xmacro(_NET_WM_WINDOW_TYPE_POPUP_MENU) \
+xmacro(_NET_WM_WINDOW_TYPE_TOOLTIP) \
+xmacro(_NET_WM_WINDOW_TYPE_NOTIFICATION) \
+xmacro(_NET_WM_DESKTOP) \
+xmacro(_NET_WM_STRUT_PARTIAL) \
+xmacro(_NET_CLIENT_LIST) \
+xmacro(_NET_CLIENT_LIST_STACKING) \
+xmacro(_NET_CURRENT_DESKTOP) \
+xmacro(_NET_NUMBER_OF_DESKTOPS) \
+xmacro(_NET_DESKTOP_NAMES) \
+xmacro(_NET_DESKTOP_VIEWPORT) \
+xmacro(_NET_ACTIVE_WINDOW) \
+xmacro(_NET_CLOSE_WINDOW) \
+xmacro(_NET_MOVERESIZE_WINDOW)
diff --git a/include/i3-atoms_rest.xmacro.h b/include/i3-atoms_rest.xmacro.h
new file mode 100644
index 00000000..75a5f230
--- /dev/null
+++ b/include/i3-atoms_rest.xmacro.h
@@ -0,0 +1,22 @@
+// clang-format off
+#define I3_REST_ATOMS_XMACRO \
+xmacro(_NET_WM_USER_TIME) \
+xmacro(_NET_STARTUP_ID) \
+xmacro(_NET_WORKAREA) \
+xmacro(WM_PROTOCOLS) \
+xmacro(WM_DELETE_WINDOW) \
+xmacro(UTF8_STRING) \
+xmacro(WM_STATE) \
+xmacro(WM_CLIENT_LEADER) \
+xmacro(WM_TAKE_FOCUS) \
+xmacro(WM_WINDOW_ROLE) \
+xmacro(I3_SOCKET_PATH) \
+xmacro(I3_CONFIG_PATH) \
+xmacro(I3_SYNC) \
+xmacro(I3_SHMLOG_PATH) \
+xmacro(I3_PID) \
+xmacro(I3_FLOATING_WINDOW) \
+xmacro(_NET_REQUEST_FRAME_EXTENTS) \
+xmacro(_NET_FRAME_EXTENTS) \
+xmacro(_MOTIF_WM_HINTS) \
+xmacro(WM_CHANGE_STATE)
diff --git a/include/i3.h b/include/i3.h
index e7afe7e5..2c550fa9 100644
--- a/include/i3.h
+++ b/include/i3.h
@@ -57,7 +57,8 @@ extern xcb_key_symbols_t *keysyms;
extern char **start_argv;
extern Display *xlibdpy, *xkbdpy;
extern int xkb_current_group;
-extern TAILQ_HEAD(bindings_head, Binding) * bindings;
+extern TAILQ_HEAD(bindings_head, Binding) *bindings;
+extern const char *current_binding_mode;
extern TAILQ_HEAD(autostarts_head, Autostart) autostarts;
extern TAILQ_HEAD(autostarts_always_head, Autostart) autostarts_always;
extern TAILQ_HEAD(ws_assignments_head, Workspace_Assignment) ws_assignments;
@@ -71,7 +72,7 @@ extern uint8_t root_depth;
extern xcb_visualid_t visual_id;
extern xcb_colormap_t colormap;
-extern bool xcursor_supported, xkb_supported, shape_supported;
+extern bool xkb_supported, shape_supported;
extern xcb_window_t root;
extern struct ev_loop *main_loop;
extern bool only_check_config;
diff --git a/include/i3/ipc.h b/include/i3/ipc.h
index 884a0cf6..187640cd 100644
--- a/include/i3/ipc.h
+++ b/include/i3/ipc.h
@@ -66,6 +66,9 @@ typedef struct i3_ipc_header {
/** Trigger an i3 sync protocol message via IPC. */
#define I3_IPC_MESSAGE_TYPE_SYNC 11
+/** Request the current binding state. */
+#define I3_IPC_MESSAGE_TYPE_GET_BINDING_STATE 12
+
/*
* Messages from i3 to clients
*
@@ -82,6 +85,7 @@ typedef struct i3_ipc_header {
#define I3_IPC_REPLY_TYPE_CONFIG 9
#define I3_IPC_REPLY_TYPE_TICK 10
#define I3_IPC_REPLY_TYPE_SYNC 11
+#define I3_IPC_REPLY_TYPE_GET_BINDING_STATE 12
/*
* Events from i3 to clients. Events have the first bit set high.
diff --git a/include/ipc.h b/include/ipc.h
index a608ef56..0d19daf4 100644
--- a/include/ipc.h
+++ b/include/ipc.h
@@ -12,7 +12,6 @@
#include <config.h>
#include <ev.h>
-#include <stdbool.h>
#include <yajl/yajl_gen.h>
#include <yajl/yajl_parse.h>
@@ -41,8 +40,7 @@ typedef struct ipc_client {
uint8_t *buffer;
size_t buffer_size;
- TAILQ_ENTRY(ipc_client)
- clients;
+ TAILQ_ENTRY(ipc_client) clients;
} ipc_client;
/*
@@ -145,9 +143,9 @@ void ipc_send_barconfig_update_event(Barconfig *barconfig);
void ipc_send_binding_event(const char *event_type, Binding *bind);
/**
- * Set the maximum duration that we allow for a connection with an unwriteable
- * socket.
- */
+ * Set the maximum duration that we allow for a connection with an unwriteable
+ * socket.
+ */
void ipc_set_kill_timeout(ev_tstamp new);
/**
diff --git a/include/libi3.h b/include/libi3.h
index 15d1bc76..c0b9ddbd 100644
--- a/include/libi3.h
+++ b/include/libi3.h
@@ -101,7 +101,7 @@ void errorlog(char *fmt, ...)
#if !defined(DLOG)
void debuglog(char *fmt, ...)
__attribute__((format(printf, 1, 2)));
-#define DLOG(fmt, ...) debuglog("%s:%s:%d - " fmt, STRIPPED__FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define DLOG(fmt, ...) debuglog("%s:%s:%d - " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#endif
/**
@@ -182,6 +182,12 @@ ssize_t writeall_nonblock(int fd, const void *buf, size_t count);
ssize_t swrite(int fd, const void *buf, size_t count);
/**
+ * Like strcasecmp but considers the case where either string is NULL.
+ *
+ */
+int strcasecmp_nullable(const char *a, const char *b);
+
+/**
* Build an i3String from an UTF-8 encoded string.
* Returns the newly-allocated i3String.
*
@@ -341,7 +347,7 @@ gchar *g_utf8_make_valid(const gchar *str, gssize len);
*/
uint32_t get_colorpixel(const char *hex) __attribute__((const));
-#ifndef HAVE_strndup
+#ifndef HAVE_STRNDUP
/**
* Taken from FreeBSD
* Returns a pointer to a new string which is a duplicate of the
@@ -526,7 +532,7 @@ char *resolve_tilde(const char *path);
*/
char *get_config_path(const char *override_configpath, bool use_system_paths);
-#ifndef HAVE_mkdirp
+#ifndef HAVE_MKDIRP
/**
* Emulates mkdir -p (creates any missing folders)
*
@@ -537,9 +543,9 @@ int mkdirp(const char *path, mode_t mode);
/** Helper structure for usage in format_placeholders(). */
typedef struct placeholder_t {
/* The placeholder to be replaced, e.g., "%title". */
- char *name;
+ const char *name;
/* The value this placeholder should be replaced with. */
- char *value;
+ const char *value;
} placeholder_t;
/**
diff --git a/include/log.h b/include/log.h
index 5c530231..c2758443 100644
--- a/include/log.h
+++ b/include/log.h
@@ -11,9 +11,6 @@
#include <config.h>
-#include <stdarg.h>
-#include <stdbool.h>
-
/* We will include libi3.h which define its own version of LOG, ELOG.
* We want *our* version, so we undef the libi3 one. */
#if defined(LOG)
@@ -29,7 +26,7 @@
is, delete the preceding comma */
#define LOG(fmt, ...) verboselog(fmt, ##__VA_ARGS__)
#define ELOG(fmt, ...) errorlog("ERROR: " fmt, ##__VA_ARGS__)
-#define DLOG(fmt, ...) debuglog("%s:%s:%d - " fmt, STRIPPED__FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define DLOG(fmt, ...) debuglog("%s:%s:%d - " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
extern char *errorfilename;
extern char *shmlogname;
diff --git a/include/shmlog.h b/include/shmlog.h
index dc8081f1..7b7e133a 100644
--- a/include/shmlog.h
+++ b/include/shmlog.h
@@ -12,7 +12,6 @@
#include <config.h>
-#include <stdint.h>
#if !defined(__OpenBSD__)
#include <pthread.h>
#endif
diff --git a/include/util.h b/include/util.h
index 6d525626..09ad941f 100644
--- a/include/util.h
+++ b/include/util.h
@@ -28,15 +28,15 @@
#define NODES_FOREACH(head) \
for (Con *child = (Con *)-1; (child == (Con *)-1) && ((child = 0), true);) \
- TAILQ_FOREACH(child, &((head)->nodes_head), nodes)
+ TAILQ_FOREACH (child, &((head)->nodes_head), nodes)
#define NODES_FOREACH_REVERSE(head) \
for (Con *child = (Con *)-1; (child == (Con *)-1) && ((child = 0), true);) \
- TAILQ_FOREACH_REVERSE(child, &((head)->nodes_head), nodes_head, nodes)
+ TAILQ_FOREACH_REVERSE (child, &((head)->nodes_head), nodes_head, nodes)
/* greps the ->nodes of the given head and returns the first node that matches the given condition */
#define GREP_FIRST(dest, head, condition) \
- NODES_FOREACH(head) { \
+ NODES_FOREACH (head) { \
if (!(condition)) \
continue; \
\
@@ -65,6 +65,7 @@ bool rect_contains(Rect rect, uint32_t x, uint32_t y);
Rect rect_add(Rect a, Rect b);
Rect rect_sub(Rect a, Rect b);
bool rect_equals(Rect a, Rect b);
+Rect rect_sanitize_dimensions(Rect rect);
/**
* Returns true if the name consists of only digits.
@@ -85,7 +86,7 @@ bool layout_from_name(const char *layout_str, layout_t *out);
* interpreted as a "named workspace".
*
*/
-long ws_name_to_number(const char *name);
+int ws_name_to_number(const char *name);
/**
* Updates *destination with new_value and returns true if it was changed or false
@@ -142,13 +143,13 @@ char *pango_escape_markup(char *input);
void start_nagbar(pid_t *nagbar_pid, char *argv[]);
/**
- * Kills the i3-nagbar process, if *nagbar_pid != -1.
+ * Kills the i3-nagbar process, if nagbar_pid != -1.
*
* If wait_for_it is set (restarting i3), this function will waitpid(),
* otherwise, ev is assumed to handle it (reloading).
*
*/
-void kill_nagbar(pid_t *nagbar_pid, bool wait_for_it);
+void kill_nagbar(pid_t nagbar_pid, bool wait_for_it);
/**
* Converts a string into a long using strtol().
diff --git a/include/workspace.h b/include/workspace.h
index 69974a2e..2193ed0b 100644
--- a/include/workspace.h
+++ b/include/workspace.h
@@ -46,6 +46,19 @@ Con *get_existing_workspace_by_name(const char *name);
Con *get_existing_workspace_by_num(int num);
/**
+ * Returns the first output that is assigned to a workspace specified by the
+ * given name or number. Returns NULL if no such output exists.
+ *
+ * If an assignment matches by number but there is an assignment later that
+ * matches by name, the second one is preferred.
+ * The order of the 'ws_assignments' queue is respected: if multiple
+ * assignments match the criteria, the first one is returned.
+ * 'name' is ignored when NULL, 'parsed_num' is ignored when it is -1.
+ *
+ */
+Con *get_assigned_output(const char *name, long parsed_num);
+
+/**
* Returns true if the first output assigned to a workspace with the given
* workspace assignment is the same as the given output.
*
@@ -57,11 +70,8 @@ bool output_triggers_assignment(Output *output, struct Workspace_Assignment *ass
* creating the workspace if necessary (by allocating the necessary amount of
* memory and initializing the data structures correctly).
*
- * If created is not NULL, *created will be set to whether or not the
- * workspace has just been created.
- *
*/
-Con *workspace_get(const char *num, bool *created);
+Con *workspace_get(const char *num);
/**
* Extracts workspace names from keybindings (e.g. “web” from “bindsym $mod+1
@@ -136,51 +146,6 @@ void workspace_back_and_forth(void);
*/
Con *workspace_back_and_forth_get(void);
-#if 0
-/**
- * Assigns the given workspace to the given screen by correctly updating its
- * state and reconfiguring all the clients on this workspace.
- *
- * This is called when initializing a screen and when re-assigning it to a
- * different screen which just got available (if you configured it to be on
- * screen 1 and you just plugged in screen 1).
- *
- */
-void workspace_assign_to(Workspace *ws, Output *screen, bool hide_it);
-
-/**
- * Initializes the given workspace if it is not already initialized. The given
- * screen is to be understood as a fallback, if the workspace itself either
- * was not assigned to a particular screen or cannot be placed there because
- * the screen is not attached at the moment.
- *
- */
-void workspace_initialize(Workspace *ws, Output *screen, bool recheck);
-
-/**
- * Gets the first unused workspace for the given screen, taking into account
- * the preferred_screen setting of every workspace (workspace assignments).
- *
- */
-Workspace *get_first_workspace_for_output(Output *screen);
-
-/**
- * Unmaps all clients (and stack windows) of the given workspace.
- *
- * This needs to be called separately when temporarily rendering a workspace
- * which is not the active workspace to force reconfiguration of all clients,
- * like in src/xinerama.c when re-assigning a workspace to another screen.
- *
- */
-void workspace_unmap_clients(xcb_connection_t *conn, Workspace *u_ws);
-
-/**
- * Maps all clients (and stack windows) of the given workspace.
- *
- */
-void workspace_map_clients(xcb_connection_t *conn, Workspace *ws);
-#endif
-
/**
* Goes through all clients on the given workspace and updates the workspace’s
* urgent flag accordingly.
diff --git a/include/xcb.h b/include/xcb.h
index 32110c7d..ba4ff2f3 100644
--- a/include/xcb.h
+++ b/include/xcb.h
@@ -18,13 +18,6 @@
#define _NET_WM_STATE_ADD 1
#define _NET_WM_STATE_TOGGLE 2
-/** This is the equivalent of XC_left_ptr. I’m not sure why xcb doesn’t have a
- * constant for that. */
-#define XCB_CURSOR_LEFT_PTR 68
-#define XCB_CURSOR_SB_H_DOUBLE_ARROW 108
-#define XCB_CURSOR_SB_V_DOUBLE_ARROW 116
-#define XCB_CURSOR_WATCH 150
-
/* from X11/keysymdef.h */
#define XCB_NUM_LOCK 0xff7f
@@ -49,15 +42,19 @@
#define ROOT_EVENT_MASK (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \
XCB_EVENT_MASK_BUTTON_PRESS | \
XCB_EVENT_MASK_STRUCTURE_NOTIFY | /* when the user adds a screen (e.g. video \
- projector), the root window gets a \
- ConfigureNotify */ \
+ * projector), the root window gets a \
+ * ConfigureNotify */ \
XCB_EVENT_MASK_POINTER_MOTION | \
XCB_EVENT_MASK_PROPERTY_CHANGE | \
XCB_EVENT_MASK_FOCUS_CHANGE | \
XCB_EVENT_MASK_ENTER_WINDOW)
+#include "i3-atoms_rest.xmacro.h"
+#include "i3-atoms_NET_SUPPORTED.xmacro.h"
+
#define xmacro(atom) extern xcb_atom_t A_##atom;
-#include "atoms.xmacro"
+I3_NET_SUPPORTED_ATOMS_XMACRO
+I3_REST_ATOMS_XMACRO
#undef xmacro
extern unsigned int xcb_numlock_mask;
@@ -102,14 +99,6 @@ xcb_atom_t xcb_get_preferred_window_type(xcb_get_property_reply_t *reply);
bool xcb_reply_contains_atom(xcb_get_property_reply_t *prop, xcb_atom_t atom);
/**
- * Set the cursor of the root window to the given cursor id.
- * This function should only be used if xcursor_supported == false.
- * Otherwise, use xcursor_set_root_cursor().
- *
- */
-void xcb_set_root_cursor(int cursor);
-
-/**
* Get depth of visual specified by visualid
*
*/
diff --git a/include/xcursor.h b/include/xcursor.h
index 804e1f84..ad33d506 100644
--- a/include/xcursor.h
+++ b/include/xcursor.h
@@ -28,7 +28,6 @@ enum xcursor_cursor_t {
void xcursor_load_cursors(void);
xcb_cursor_t xcursor_get_cursor(enum xcursor_cursor_t c);
-int xcursor_get_xcb_cursor(enum xcursor_cursor_t c);
/**
* Sets the cursor of the root window to the 'pointer' cursor.
diff --git a/include/xinerama.h b/include/xinerama.h
index f01ee568..52a5db33 100644
--- a/include/xinerama.h
+++ b/include/xinerama.h
@@ -13,8 +13,6 @@
#include <config.h>
-#include "data.h"
-
/**
* We have just established a connection to the X server and need the initial
* Xinerama information to setup workspaces for each screen.
diff --git a/libi3/dpi.c b/libi3/dpi.c
index d15e35be..dec38bc8 100644
--- a/libi3/dpi.c
+++ b/libi3/dpi.c
@@ -9,6 +9,7 @@
#include <math.h>
#include <stdlib.h>
+
#include <xcb/xcb_xrm.h>
static long dpi;
diff --git a/libi3/draw_util.c b/libi3/draw_util.c
index 092ac967..313dc29a 100644
--- a/libi3/draw_util.c
+++ b/libi3/draw_util.c
@@ -9,11 +9,10 @@
#include "libi3.h"
#include <stdlib.h>
-#include <err.h>
#include <string.h>
+
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
-#include <cairo/cairo-xcb.h>
/* The default visual_type to use if none is specified when creating the surface. Must be defined globally. */
extern xcb_visualtype_t *visual_type;
diff --git a/libi3/fake_configure_notify.c b/libi3/fake_configure_notify.c
index 145f4512..5d87c3da 100644
--- a/libi3/fake_configure_notify.c
+++ b/libi3/fake_configure_notify.c
@@ -8,7 +8,6 @@
#include "libi3.h"
#include <stdlib.h>
-#include <stdbool.h>
#include <xcb/xcb.h>
#include <xcb/xproto.h>
diff --git a/libi3/font.c b/libi3/font.c
index 7b10edf0..5ed58b8d 100644
--- a/libi3/font.c
+++ b/libi3/font.c
@@ -8,14 +8,12 @@
#include "libi3.h"
#include <assert.h>
+#include <cairo/cairo-xcb.h>
+#include <err.h>
+#include <pango/pangocairo.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
-#include <stdbool.h>
-#include <err.h>
-
-#include <cairo/cairo-xcb.h>
-#include <pango/pangocairo.h>
static const i3Font *savedFont = NULL;
diff --git a/libi3/format_placeholders.c b/libi3/format_placeholders.c
index 770e383d..71870a7b 100644
--- a/libi3/format_placeholders.c
+++ b/libi3/format_placeholders.c
@@ -8,7 +8,6 @@
#include "libi3.h"
#include <stdlib.h>
-#include <stdint.h>
#include <string.h>
#ifndef CS_STARTS_WITH
diff --git a/libi3/g_utf8_make_valid.c b/libi3/g_utf8_make_valid.c
index b15873b3..71beafd3 100644
--- a/libi3/g_utf8_make_valid.c
+++ b/libi3/g_utf8_make_valid.c
@@ -19,8 +19,8 @@
#include "libi3.h"
-#include <string.h>
#include <glib.h>
+#include <string.h>
/* Copied from:
* https://gitlab.gnome.org/GNOME/glib/blob/f928dfdf57bf92c883b53b16d7a9d49add504f52/glib/gutf8.c#L1752-1815 */
diff --git a/libi3/get_colorpixel.c b/libi3/get_colorpixel.c
index 49a9e3b4..32ef34cd 100644
--- a/libi3/get_colorpixel.c
+++ b/libi3/get_colorpixel.c
@@ -6,22 +6,19 @@
*
*/
#include "libi3.h"
+#include "queue.h"
-#include <stdlib.h>
#include <stdint.h>
+#include <stdlib.h>
#include <string.h>
-
-#include "queue.h"
struct Colorpixel {
char hex[8];
uint32_t pixel;
- SLIST_ENTRY(Colorpixel)
- colorpixels;
+ SLIST_ENTRY(Colorpixel) colorpixels;
};
-SLIST_HEAD(colorpixel_head, Colorpixel)
-colorpixels;
+SLIST_HEAD(colorpixel_head, Colorpixel) colorpixels;
/*
* Returns the colorpixel to use for the given hex color (think of HTML).
@@ -48,7 +45,7 @@ uint32_t get_colorpixel(const char *hex) {
/* Lookup this colorpixel in the cache */
struct Colorpixel *colorpixel;
- SLIST_FOREACH(colorpixel, &(colorpixels), colorpixels) {
+ SLIST_FOREACH (colorpixel, &(colorpixels), colorpixels) {
if (strcmp(colorpixel->hex, hex) == 0)
return colorpixel->pixel;
}
diff --git a/libi3/get_exe_path.c b/libi3/get_exe_path.c
index e933f5b6..3b46ef82 100644
--- a/libi3/get_exe_path.c
+++ b/libi3/get_exe_path.c
@@ -7,12 +7,10 @@
*/
#include "libi3.h"
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-#include <limits.h>
-#include <stdlib.h>
#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
/*
* This function returns the absolute path to the executable it is running in.
@@ -91,7 +89,7 @@ char *get_exe_path(const char *argv0) {
free(destpath);
sasprintf(&destpath, "%s/%s", component, argv0);
/* Of course this is not 100% equivalent to actually exec()ing the
- * binary, but meh. */
+ * binary, but meh. */
if (access(destpath, X_OK) == 0) {
free(path);
free(tmp);
diff --git a/libi3/get_mod_mask.c b/libi3/get_mod_mask.c
index 98031d4c..92af456d 100644
--- a/libi3/get_mod_mask.c
+++ b/libi3/get_mod_mask.c
@@ -9,6 +9,7 @@
#include <stdint.h>
#include <stdlib.h>
+
#include <xcb/xcb.h>
#include <xcb/xcb_keysyms.h>
diff --git a/libi3/get_process_filename.c b/libi3/get_process_filename.c
index 7e2ecbd2..21429ec3 100644
--- a/libi3/get_process_filename.c
+++ b/libi3/get_process_filename.c
@@ -7,17 +7,11 @@
*/
#include "libi3.h"
-#include <assert.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdbool.h>
#include <err.h>
-#include <sys/stat.h>
-#include <sys/types.h>
#include <pwd.h>
+#include <stdlib.h>
+#include <sys/stat.h>
#include <unistd.h>
-#include <err.h>
/*
* Returns the name of a temporary file with the specified prefix.
diff --git a/libi3/ipc_connect.c b/libi3/ipc_connect.c
index f659a1a4..871fe083 100644
--- a/libi3/ipc_connect.c
+++ b/libi3/ipc_connect.c
@@ -7,14 +7,12 @@
*/
#include "libi3.h"
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <string.h>
#include <err.h>
-#include <stdlib.h>
-#include <unistd.h>
#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
/*
* Connects to the i3 IPC socket and returns the file descriptor for the
diff --git a/libi3/ipc_recv_message.c b/libi3/ipc_recv_message.c
index 84da5aa3..516405b0 100644
--- a/libi3/ipc_recv_message.c
+++ b/libi3/ipc_recv_message.c
@@ -7,15 +7,12 @@
*/
#include "libi3.h"
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <unistd.h>
#include <errno.h>
-#include <inttypes.h>
-
#include <i3/ipc.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
/*
* Reads a message from the given socket file descriptor and stores its length
diff --git a/libi3/ipc_send_message.c b/libi3/ipc_send_message.c
index c2cc0127..4faeea7f 100644
--- a/libi3/ipc_send_message.c
+++ b/libi3/ipc_send_message.c
@@ -7,14 +7,8 @@
*/
#include "libi3.h"
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <err.h>
-#include <errno.h>
-
#include <i3/ipc.h>
+#include <stdint.h>
/*
* Formats a message (payload) of the given size and type and sends it to i3 via
diff --git a/libi3/is_debug_build.c b/libi3/is_debug_build.c
index 52187bda..9458f75b 100644
--- a/libi3/is_debug_build.c
+++ b/libi3/is_debug_build.c
@@ -8,7 +8,6 @@
#include "libi3.h"
#include <string.h>
-#include <stdbool.h>
/*
* Returns true if this version of i3 is a debug build (anything which is not a
@@ -17,10 +16,16 @@
*/
bool is_debug_build(void) {
/* i3_version contains either something like this:
- * "4.0.2 (2011-11-11, branch "release")".
- * or: "4.0.2-123-gCOFFEEBABE (2011-11-11, branch "next")".
+ * "4.0.2 (2011-11-11)" (release version)
+ * or: "4.0.2-123-gC0FFEE" (debug version)
*
* So we check for the offset of the first opening round bracket to
* determine whether this is a git version or a release version. */
+ if (strchr(I3_VERSION, '(') == NULL) {
+ return true; // e.g. 4.0.2-123-gC0FFEE
+ }
+ /* In practice, debug versions do not contain parentheses at all,
+ * but leave the logic as it was before so that we can re-add
+ * parentheses if we chose to. */
return ((strchr(I3_VERSION, '(') - I3_VERSION) > 10);
}
diff --git a/libi3/mkdirp.c b/libi3/mkdirp.c
index 35a30475..d29bb95b 100644
--- a/libi3/mkdirp.c
+++ b/libi3/mkdirp.c
@@ -12,7 +12,7 @@
#include <string.h>
#include <sys/stat.h>
-#ifndef HAVE_mkdirp
+#ifndef HAVE_MKDIRP
/*
* Emulates mkdir -p (creates any missing folders)
*
diff --git a/libi3/root_atom_contents.c b/libi3/root_atom_contents.c
index d6394d4b..6feb31bc 100644
--- a/libi3/root_atom_contents.c
+++ b/libi3/root_atom_contents.c
@@ -7,12 +7,9 @@
*/
#include "libi3.h"
-#include <stdio.h>
-#include <string.h>
-#include <stdbool.h>
-#include <limits.h>
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
+#include <string.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
diff --git a/libi3/safewrappers.c b/libi3/safewrappers.c
index 1802b327..767a0f05 100644
--- a/libi3/safewrappers.c
+++ b/libi3/safewrappers.c
@@ -7,13 +7,11 @@
*/
#include "libi3.h"
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <stdio.h>
#include <err.h>
#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
/*
* The s* functions (safe) are wrappers around malloc, strdup, …, which exits if one of
@@ -110,3 +108,20 @@ ssize_t swrite(int fd, const void *buf, size_t count) {
else
return n;
}
+
+/*
+ * Like strcasecmp but considers the case where either string is NULL.
+ *
+ */
+int strcasecmp_nullable(const char *a, const char *b) {
+ if (a == b) {
+ return 0;
+ }
+ if (a == NULL) {
+ return -1;
+ }
+ if (b == NULL) {
+ return 1;
+ }
+ return strcasecmp(a, b);
+}
diff --git a/libi3/string.c b/libi3/string.c
index 9efa3690..da18c550 100644
--- a/libi3/string.c
+++ b/libi3/string.c
@@ -11,11 +11,10 @@
*/
#include "libi3.h"
+#include <glib.h>
#include <stdlib.h>
#include <string.h>
-#include <glib.h>
-
struct _i3String {
char *utf8;
xcb_char2b_t *ucs2;
diff --git a/libi3/strndup.c b/libi3/strndup.c
index e215a76f..8911732c 100644
--- a/libi3/strndup.c
+++ b/libi3/strndup.c
@@ -7,10 +7,9 @@
*/
#include "libi3.h"
-#include <sys/types.h>
#include <string.h>
-#ifndef HAVE_strndup
+#ifndef HAVE_STRNDUP
/*
* Taken from FreeBSD
* Returns a pointer to a new string which is a duplicate of the
diff --git a/libi3/ucs2_conversion.c b/libi3/ucs2_conversion.c
index c651cdb3..c7467239 100644
--- a/libi3/ucs2_conversion.c
+++ b/libi3/ucs2_conversion.c
@@ -8,7 +8,6 @@
#include "libi3.h"
#include <err.h>
-#include <errno.h>
#include <iconv.h>
#include <stdlib.h>
#include <string.h>
diff --git a/m4/ax_append_flag.m4 b/m4/ax_append_flag.m4
deleted file mode 100644
index 08f2e07e..00000000
--- a/m4/ax_append_flag.m4
+++ /dev/null
@@ -1,71 +0,0 @@
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_append_flag.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE])
-#
-# DESCRIPTION
-#
-# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space
-# added in between.
-#
-# If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
-# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains
-# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly
-# FLAG.
-#
-# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION.
-#
-# LICENSE
-#
-# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
-# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
-#
-# This program is free software: you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-# Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-# As a special exception, the respective Autoconf Macro's copyright owner
-# gives unlimited permission to copy, distribute and modify the configure
-# scripts that are the output of Autoconf when processing the Macro. You
-# need not follow the terms of the GNU General Public License when using
-# or distributing such scripts, even though portions of the text of the
-# Macro appear in them. The GNU General Public License (GPL) does govern
-# all other use of the material that constitutes the Autoconf Macro.
-#
-# This special exception to the GPL applies to versions of the Autoconf
-# Macro released by the Autoconf Archive. When you make and distribute a
-# modified version of the Autoconf Macro, you may extend this special
-# exception to the GPL to apply to your modified version as well.
-
-#serial 6
-
-AC_DEFUN([AX_APPEND_FLAG],
-[dnl
-AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF
-AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])
-AS_VAR_SET_IF(FLAGS,[
- AS_CASE([" AS_VAR_GET(FLAGS) "],
- [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])],
- [
- AS_VAR_APPEND(FLAGS,[" $1"])
- AC_RUN_LOG([: FLAGS="$FLAGS"])
- ])
- ],
- [
- AS_VAR_SET(FLAGS,[$1])
- AC_RUN_LOG([: FLAGS="$FLAGS"])
- ])
-AS_VAR_POPDEF([FLAGS])dnl
-])dnl AX_APPEND_FLAG
diff --git a/m4/ax_cflags_warn_all.m4 b/m4/ax_cflags_warn_all.m4
deleted file mode 100644
index 1f077992..00000000
--- a/m4/ax_cflags_warn_all.m4
+++ /dev/null
@@ -1,122 +0,0 @@
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_cflags_warn_all.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_CFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
-# AX_CXXFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
-# AX_FCFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
-#
-# DESCRIPTION
-#
-# Try to find a compiler option that enables most reasonable warnings.
-#
-# For the GNU compiler it will be -Wall (and -ansi -pedantic) The result
-# is added to the shellvar being CFLAGS, CXXFLAGS, or FCFLAGS by default.
-#
-# Currently this macro knows about the GCC, Solaris, Digital Unix, AIX,
-# HP-UX, IRIX, NEC SX-5 (Super-UX 10), Cray J90 (Unicos 10.0.0.8), and
-# Intel compilers. For a given compiler, the Fortran flags are much more
-# experimental than their C equivalents.
-#
-# - $1 shell-variable-to-add-to : CFLAGS, CXXFLAGS, or FCFLAGS
-# - $2 add-value-if-not-found : nothing
-# - $3 action-if-found : add value to shellvariable
-# - $4 action-if-not-found : nothing
-#
-# NOTE: These macros depend on AX_APPEND_FLAG.
-#
-# LICENSE
-#
-# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
-# Copyright (c) 2010 Rhys Ulerich <rhys.ulerich@gmail.com>
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3 of the License, or (at your
-# option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-# Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-# As a special exception, the respective Autoconf Macro's copyright owner
-# gives unlimited permission to copy, distribute and modify the configure
-# scripts that are the output of Autoconf when processing the Macro. You
-# need not follow the terms of the GNU General Public License when using
-# or distributing such scripts, even though portions of the text of the
-# Macro appear in them. The GNU General Public License (GPL) does govern
-# all other use of the material that constitutes the Autoconf Macro.
-#
-# This special exception to the GPL applies to versions of the Autoconf
-# Macro released by the Autoconf Archive. When you make and distribute a
-# modified version of the Autoconf Macro, you may extend this special
-# exception to the GPL to apply to your modified version as well.
-
-#serial 15
-
-AC_DEFUN([AX_FLAGS_WARN_ALL],[dnl
-AS_VAR_PUSHDEF([FLAGS],[_AC_LANG_PREFIX[]FLAGS])dnl
-AS_VAR_PUSHDEF([VAR],[ac_cv_[]_AC_LANG_ABBREV[]flags_warn_all])dnl
-AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum warnings],
-VAR,[VAR="no, unknown"
-ac_save_[]FLAGS="$[]FLAGS"
-for ac_arg dnl
-in "-warn all % -warn all" dnl Intel
- "-pedantic % -Wall" dnl GCC
- "-xstrconst % -v" dnl Solaris C
- "-std1 % -verbose -w0 -warnprotos" dnl Digital Unix
- "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX
- "-ansi -ansiE % -fullwarn" dnl IRIX
- "+ESlit % +w1" dnl HP-UX C
- "-Xc % -pvctl[,]fullmsg" dnl NEC SX-5 (Super-UX 10)
- "-h conform % -h msglevel 2" dnl Cray C (Unicos)
- #
-do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
- [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
-done
-FLAGS="$ac_save_[]FLAGS"
-])
-AS_VAR_POPDEF([FLAGS])dnl
-AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
-case ".$VAR" in
- .ok|.ok,*) m4_ifvaln($3,$3) ;;
- .|.no|.no,*) m4_default($4,[m4_ifval($2,[AX_APPEND_FLAG([$2], [$1])])]) ;;
- *) m4_default($3,[AX_APPEND_FLAG([$VAR], [$1])]) ;;
-esac
-AS_VAR_POPDEF([VAR])dnl
-])dnl AX_FLAGS_WARN_ALL
-dnl implementation tactics:
-dnl the for-argument contains a list of options. The first part of
-dnl these does only exist to detect the compiler - usually it is
-dnl a global option to enable -ansi or -extrawarnings. All other
-dnl compilers will fail about it. That was needed since a lot of
-dnl compilers will give false positives for some option-syntax
-dnl like -Woption or -Xoption as they think of it is a pass-through
-dnl to later compile stages or something. The "%" is used as a
-dnl delimiter. A non-option comment can be given after "%%" marks
-dnl which will be shown but not added to the respective C/CXXFLAGS.
-
-AC_DEFUN([AX_CFLAGS_WARN_ALL],[dnl
-AC_LANG_PUSH([C])
-AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
-AC_LANG_POP([C])
-])
-
-AC_DEFUN([AX_CXXFLAGS_WARN_ALL],[dnl
-AC_LANG_PUSH([C++])
-AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
-AC_LANG_POP([C++])
-])
-
-AC_DEFUN([AX_FCFLAGS_WARN_ALL],[dnl
-AC_LANG_PUSH([Fortran])
-AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
-AC_LANG_POP([Fortran])
-])
diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4
deleted file mode 100644
index ca363971..00000000
--- a/m4/ax_check_compile_flag.m4
+++ /dev/null
@@ -1,74 +0,0 @@
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
-#
-# DESCRIPTION
-#
-# Check whether the given FLAG works with the current language's compiler
-# or gives an error. (Warnings, however, are ignored)
-#
-# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
-# success/failure.
-#
-# If EXTRA-FLAGS is defined, it is added to the current language's default
-# flags (e.g. CFLAGS) when the check is done. The check is thus made with
-# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
-# force the compiler to issue an error when a bad flag is given.
-#
-# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
-#
-# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
-# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
-#
-# LICENSE
-#
-# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
-# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
-#
-# This program is free software: you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-# Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-# As a special exception, the respective Autoconf Macro's copyright owner
-# gives unlimited permission to copy, distribute and modify the configure
-# scripts that are the output of Autoconf when processing the Macro. You
-# need not follow the terms of the GNU General Public License when using
-# or distributing such scripts, even though portions of the text of the
-# Macro appear in them. The GNU General Public License (GPL) does govern
-# all other use of the material that constitutes the Autoconf Macro.
-#
-# This special exception to the GPL applies to versions of the Autoconf
-# Macro released by the Autoconf Archive. When you make and distribute a
-# modified version of the Autoconf Macro, you may extend this special
-# exception to the GPL to apply to your modified version as well.
-
-#serial 4
-
-AC_DEFUN([AX_CHECK_COMPILE_FLAG],
-[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
-AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
-AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
- ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
- _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
- AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
- [AS_VAR_SET(CACHEVAR,[yes])],
- [AS_VAR_SET(CACHEVAR,[no])])
- _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
-AS_VAR_IF(CACHEVAR,yes,
- [m4_default([$2], :)],
- [m4_default([$3], :)])
-AS_VAR_POPDEF([CACHEVAR])dnl
-])dnl AX_CHECK_COMPILE_FLAGS
diff --git a/m4/ax_check_enable_debug.m4 b/m4/ax_check_enable_debug.m4
deleted file mode 100644
index f99d75fe..00000000
--- a/m4/ax_check_enable_debug.m4
+++ /dev/null
@@ -1,124 +0,0 @@
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_check_enable_debug.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_CHECK_ENABLE_DEBUG([enable by default=yes/info/profile/no], [ENABLE DEBUG VARIABLES ...], [DISABLE DEBUG VARIABLES NDEBUG ...], [IS-RELEASE])
-#
-# DESCRIPTION
-#
-# Check for the presence of an --enable-debug option to configure, with
-# the specified default value used when the option is not present. Return
-# the value in the variable $ax_enable_debug.
-#
-# Specifying 'yes' adds '-g -O0' to the compilation flags for all
-# languages. Specifying 'info' adds '-g' to the compilation flags.
-# Specifying 'profile' adds '-g -pg' to the compilation flags and '-pg' to
-# the linking flags. Otherwise, nothing is added.
-#
-# Define the variables listed in the second argument if debug is enabled,
-# defaulting to no variables. Defines the variables listed in the third
-# argument if debug is disabled, defaulting to NDEBUG. All lists of
-# variables should be space-separated.
-#
-# If debug is not enabled, ensure AC_PROG_* will not add debugging flags.
-# Should be invoked prior to any AC_PROG_* compiler checks.
-#
-# IS-RELEASE can be used to change the default to 'no' when making a
-# release. Set IS-RELEASE to 'yes' or 'no' as appropriate. By default, it
-# uses the value of $ax_is_release, so if you are using the AX_IS_RELEASE
-# macro, there is no need to pass this parameter.
-#
-# AX_IS_RELEASE([git-directory])
-# AX_CHECK_ENABLE_DEBUG()
-#
-# LICENSE
-#
-# Copyright (c) 2011 Rhys Ulerich <rhys.ulerich@gmail.com>
-# Copyright (c) 2014, 2015 Philip Withnall <philip@tecnocode.co.uk>
-#
-# Copying and distribution of this file, with or without modification, are
-# permitted in any medium without royalty provided the copyright notice
-# and this notice are preserved.
-
-#serial 5
-
-AC_DEFUN([AX_CHECK_ENABLE_DEBUG],[
- AC_BEFORE([$0],[AC_PROG_CC])dnl
- AC_BEFORE([$0],[AC_PROG_CXX])dnl
- AC_BEFORE([$0],[AC_PROG_F77])dnl
- AC_BEFORE([$0],[AC_PROG_FC])dnl
-
- AC_MSG_CHECKING(whether to enable debugging)
-
- ax_enable_debug_default=m4_tolower(m4_normalize(ifelse([$1],,[no],[$1])))
- ax_enable_debug_is_release=m4_tolower(m4_normalize(ifelse([$4],,
- [$ax_is_release],
- [$4])))
-
- # If this is a release, override the default.
- AS_IF([test "$ax_enable_debug_is_release" = "yes"],
- [ax_enable_debug_default="no"])
-
- m4_define(ax_enable_debug_vars,[m4_normalize(ifelse([$2],,,[$2]))])
- m4_define(ax_disable_debug_vars,[m4_normalize(ifelse([$3],,[NDEBUG],[$3]))])
-
- AC_ARG_ENABLE(debug,
- [AS_HELP_STRING([--enable-debug=]@<:@yes/info/profile/no@:>@,[compile with debugging])],
- [],enable_debug=$ax_enable_debug_default)
-
- # empty mean debug yes
- AS_IF([test "x$enable_debug" = "x"],
- [enable_debug="yes"])
-
- # case of debug
- AS_CASE([$enable_debug],
- [yes],[
- AC_MSG_RESULT(yes)
- CFLAGS="${CFLAGS} -g -O0"
- CXXFLAGS="${CXXFLAGS} -g -O0"
- FFLAGS="${FFLAGS} -g -O0"
- FCFLAGS="${FCFLAGS} -g -O0"
- OBJCFLAGS="${OBJCFLAGS} -g -O0"
- ],
- [info],[
- AC_MSG_RESULT(info)
- CFLAGS="${CFLAGS} -g"
- CXXFLAGS="${CXXFLAGS} -g"
- FFLAGS="${FFLAGS} -g"
- FCFLAGS="${FCFLAGS} -g"
- OBJCFLAGS="${OBJCFLAGS} -g"
- ],
- [profile],[
- AC_MSG_RESULT(profile)
- CFLAGS="${CFLAGS} -g -pg"
- CXXFLAGS="${CXXFLAGS} -g -pg"
- FFLAGS="${FFLAGS} -g -pg"
- FCFLAGS="${FCFLAGS} -g -pg"
- OBJCFLAGS="${OBJCFLAGS} -g -pg"
- LDFLAGS="${LDFLAGS} -pg"
- ],
- [
- AC_MSG_RESULT(no)
- dnl Ensure AC_PROG_CC/CXX/F77/FC/OBJC will not enable debug flags
- dnl by setting any unset environment flag variables
- AS_IF([test "x${CFLAGS+set}" != "xset"],
- [CFLAGS=""])
- AS_IF([test "x${CXXFLAGS+set}" != "xset"],
- [CXXFLAGS=""])
- AS_IF([test "x${FFLAGS+set}" != "xset"],
- [FFLAGS=""])
- AS_IF([test "x${FCFLAGS+set}" != "xset"],
- [FCFLAGS=""])
- AS_IF([test "x${OBJCFLAGS+set}" != "xset"],
- [OBJCFLAGS=""])
- ])
-
- dnl Define various variables if debugging is disabled.
- dnl assert.h is a NOP if NDEBUG is defined, so define it by default.
- AS_IF([test "x$enable_debug" = "xyes"],
- [m4_map_args_w(ax_enable_debug_vars, [AC_DEFINE(], [,,[Define if debugging is enabled])])],
- [m4_map_args_w(ax_disable_debug_vars, [AC_DEFINE(], [,,[Define if debugging is disabled])])])
- ax_enable_debug=$enable_debug
-])
diff --git a/m4/ax_check_gnu_make.m4 b/m4/ax_check_gnu_make.m4
deleted file mode 100644
index 6762e9ed..00000000
--- a/m4/ax_check_gnu_make.m4
+++ /dev/null
@@ -1,84 +0,0 @@
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_check_gnu_make.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_CHECK_GNU_MAKE()
-#
-# DESCRIPTION
-#
-# This macro searches for a GNU version of make. If a match is found:
-#
-# * The makefile variable `ifGNUmake' is set to the empty string, otherwise
-# it is set to "#". This is useful for including a special features in a
-# Makefile, which cannot be handled by other versions of make.
-# * The variable `_cv_gnu_make_command` is set to the command to invoke
-# GNU make if it exists, the empty string otherwise.
-# * The variable `ax_cv_gnu_make_command` is set to the command to invoke
-# GNU make by copying `_cv_gnu_make_command`, otherwise it is unset.
-# * If GNU Make is found, its version is extracted from the output of
-# `make --version` as the last field of a record of space-separated
-# columns and saved into the variable `ax_check_gnu_make_version`.
-#
-# Here is an example of its use:
-#
-# Makefile.in might contain:
-#
-# # A failsafe way of putting a dependency rule into a makefile
-# $(DEPEND):
-# $(CC) -MM $(srcdir)/*.c > $(DEPEND)
-#
-# @ifGNUmake@ ifeq ($(DEPEND),$(wildcard $(DEPEND)))
-# @ifGNUmake@ include $(DEPEND)
-# @ifGNUmake@ endif
-#
-# Then configure.in would normally contain:
-#
-# AX_CHECK_GNU_MAKE()
-# AC_OUTPUT(Makefile)
-#
-# Then perhaps to cause gnu make to override any other make, we could do
-# something like this (note that GNU make always looks for GNUmakefile
-# first):
-#
-# if ! test x$_cv_gnu_make_command = x ; then
-# mv Makefile GNUmakefile
-# echo .DEFAULT: > Makefile ;
-# echo \ $_cv_gnu_make_command \$@ >> Makefile;
-# fi
-#
-# Then, if any (well almost any) other make is called, and GNU make also
-# exists, then the other make wraps the GNU make.
-#
-# LICENSE
-#
-# Copyright (c) 2008 John Darrington <j.darrington@elvis.murdoch.edu.au>
-# Copyright (c) 2015 Enrico M. Crisostomo <enrico.m.crisostomo@gmail.com>
-#
-# Copying and distribution of this file, with or without modification, are
-# permitted in any medium without royalty provided the copyright notice
-# and this notice are preserved. This file is offered as-is, without any
-# warranty.
-
-#serial 8
-
-AC_DEFUN([AX_CHECK_GNU_MAKE],dnl
- [AC_PROG_AWK
- AC_CACHE_CHECK([for GNU make],[_cv_gnu_make_command],[dnl
- _cv_gnu_make_command="" ;
-dnl Search all the common names for GNU make
- for a in "$MAKE" make gmake gnumake ; do
- if test -z "$a" ; then continue ; fi ;
- if "$a" --version 2> /dev/null | grep GNU 2>&1 > /dev/null ; then
- _cv_gnu_make_command=$a ;
- AX_CHECK_GNU_MAKE_HEADLINE=$("$a" --version 2> /dev/null | grep "GNU Make")
- ax_check_gnu_make_version=$(echo ${AX_CHECK_GNU_MAKE_HEADLINE} | ${AWK} -F " " '{ print $(NF); }')
- break ;
- fi
- done ;])
-dnl If there was a GNU version, then set @ifGNUmake@ to the empty string, '#' otherwise
- AS_VAR_IF([_cv_gnu_make_command], [""], [AS_VAR_SET([ifGNUmake], ["#"])], [AS_VAR_SET([ifGNUmake], [""])])
- AS_VAR_IF([_cv_gnu_make_command], [""], [AS_UNSET(ax_cv_gnu_make_command)], [AS_VAR_SET([ax_cv_gnu_make_command], [${_cv_gnu_make_command}])])
- AC_SUBST([ifGNUmake])
-])
diff --git a/m4/ax_check_link_flag.m4 b/m4/ax_check_link_flag.m4
deleted file mode 100644
index eb01a6ce..00000000
--- a/m4/ax_check_link_flag.m4
+++ /dev/null
@@ -1,74 +0,0 @@
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
-#
-# DESCRIPTION
-#
-# Check whether the given FLAG works with the linker or gives an error.
-# (Warnings, however, are ignored)
-#
-# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
-# success/failure.
-#
-# If EXTRA-FLAGS is defined, it is added to the linker's default flags
-# when the check is done. The check is thus made with the flags: "LDFLAGS
-# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
-# issue an error when a bad flag is given.
-#
-# INPUT gives an alternative input source to AC_LINK_IFELSE.
-#
-# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
-# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG.
-#
-# LICENSE
-#
-# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
-# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
-#
-# This program is free software: you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-# Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-# As a special exception, the respective Autoconf Macro's copyright owner
-# gives unlimited permission to copy, distribute and modify the configure
-# scripts that are the output of Autoconf when processing the Macro. You
-# need not follow the terms of the GNU General Public License when using
-# or distributing such scripts, even though portions of the text of the
-# Macro appear in them. The GNU General Public License (GPL) does govern
-# all other use of the material that constitutes the Autoconf Macro.
-#
-# This special exception to the GPL applies to versions of the Autoconf
-# Macro released by the Autoconf Archive. When you make and distribute a
-# modified version of the Autoconf Macro, you may extend this special
-# exception to the GPL to apply to your modified version as well.
-
-#serial 4
-
-AC_DEFUN([AX_CHECK_LINK_FLAG],
-[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
-AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
-AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
- ax_check_save_flags=$LDFLAGS
- LDFLAGS="$LDFLAGS $4 $1"
- AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
- [AS_VAR_SET(CACHEVAR,[yes])],
- [AS_VAR_SET(CACHEVAR,[no])])
- LDFLAGS=$ax_check_save_flags])
-AS_VAR_IF(CACHEVAR,yes,
- [m4_default([$2], :)],
- [m4_default([$3], :)])
-AS_VAR_POPDEF([CACHEVAR])dnl
-])dnl AX_CHECK_LINK_FLAGS
diff --git a/m4/ax_code_coverage.m4 b/m4/ax_code_coverage.m4
deleted file mode 100644
index 1f1bc702..00000000
--- a/m4/ax_code_coverage.m4
+++ /dev/null
@@ -1,273 +0,0 @@
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_code_coverage.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_CODE_COVERAGE()
-#
-# DESCRIPTION
-#
-# Defines CODE_COVERAGE_CPPFLAGS, CODE_COVERAGE_CFLAGS,
-# CODE_COVERAGE_CXXFLAGS and CODE_COVERAGE_LDFLAGS which should be
-# included in the CPPFLAGS, CFLAGS CXXFLAGS and LIBS/LDFLAGS variables of
-# every build target (program or library) which should be built with code
-# coverage support. Also defines CODE_COVERAGE_RULES which should be
-# substituted in your Makefile; and $enable_code_coverage which can be
-# used in subsequent configure output. CODE_COVERAGE_ENABLED is defined
-# and substituted, and corresponds to the value of the
-# --enable-code-coverage option, which defaults to being disabled.
-#
-# Test also for gcov program and create GCOV variable that could be
-# substituted.
-#
-# Note that all optimisation flags in CFLAGS must be disabled when code
-# coverage is enabled.
-#
-# Usage example:
-#
-# configure.ac:
-#
-# AX_CODE_COVERAGE
-#
-# Makefile.am:
-#
-# @CODE_COVERAGE_RULES@
-# my_program_LIBS = ... $(CODE_COVERAGE_LDFLAGS) ...
-# my_program_CPPFLAGS = ... $(CODE_COVERAGE_CPPFLAGS) ...
-# my_program_CFLAGS = ... $(CODE_COVERAGE_CFLAGS) ...
-# my_program_CXXFLAGS = ... $(CODE_COVERAGE_CXXFLAGS) ...
-#
-# This results in a "check-code-coverage" rule being added to any
-# Makefile.am which includes "@CODE_COVERAGE_RULES@" (assuming the module
-# has been configured with --enable-code-coverage). Running `make
-# check-code-coverage` in that directory will run the module's test suite
-# (`make check`) and build a code coverage report detailing the code which
-# was touched, then print the URI for the report.
-#
-# This code was derived from Makefile.decl in GLib, originally licenced
-# under LGPLv2.1+.
-#
-# LICENSE
-#
-# Copyright (c) 2012, 2016 Philip Withnall
-# Copyright (c) 2012 Xan Lopez
-# Copyright (c) 2012 Christian Persch
-# Copyright (c) 2012 Paolo Borelli
-# Copyright (c) 2012 Dan Winship
-# Copyright (c) 2015 Bastien ROUCARIES
-#
-# This library is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or (at
-# your option) any later version.
-#
-# This library is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
-# General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-#serial 15
-
-AC_DEFUN([AX_CODE_COVERAGE],[
- dnl Check for --enable-code-coverage
- AC_REQUIRE([AC_PROG_SED])
-
- # allow to override gcov location
- AC_ARG_WITH([gcov],
- [AS_HELP_STRING([--with-gcov[=GCOV]], [use given GCOV for coverage (GCOV=gcov).])],
- [_AX_CODE_COVERAGE_GCOV_PROG_WITH=$with_gcov],
- [_AX_CODE_COVERAGE_GCOV_PROG_WITH=gcov])
-
- AC_MSG_CHECKING([whether to build with code coverage support])
- AC_ARG_ENABLE([code-coverage],
- AS_HELP_STRING([--enable-code-coverage],
- [Whether to enable code coverage support]),,
- enable_code_coverage=no)
-
- AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test x$enable_code_coverage = xyes])
- AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage])
- AC_MSG_RESULT($enable_code_coverage)
-
- AS_IF([ test "$enable_code_coverage" = "yes" ], [
- # check for gcov
- AC_CHECK_TOOL([GCOV],
- [$_AX_CODE_COVERAGE_GCOV_PROG_WITH],
- [:])
- AS_IF([test "X$GCOV" = "X:"],
- [AC_MSG_ERROR([gcov is needed to do coverage])])
- AC_SUBST([GCOV])
-
- dnl Check if gcc is being used
- AS_IF([ test "$GCC" = "no" ], [
- AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage])
- ])
-
- # List of supported lcov versions.
- lcov_version_list="1.6 1.7 1.8 1.9 1.10 1.11 1.12 1.13"
-
- AC_CHECK_PROG([LCOV], [lcov], [lcov])
- AC_CHECK_PROG([GENHTML], [genhtml], [genhtml])
-
- AS_IF([ test "$LCOV" ], [
- AC_CACHE_CHECK([for lcov version], ax_cv_lcov_version, [
- ax_cv_lcov_version=invalid
- lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'`
- for lcov_check_version in $lcov_version_list; do
- if test "$lcov_version" = "$lcov_check_version"; then
- ax_cv_lcov_version="$lcov_check_version (ok)"
- fi
- done
- ])
- ], [
- lcov_msg="To enable code coverage reporting you must have one of the following lcov versions installed: $lcov_version_list"
- AC_MSG_ERROR([$lcov_msg])
- ])
-
- case $ax_cv_lcov_version in
- ""|invalid[)]
- lcov_msg="You must have one of the following versions of lcov: $lcov_version_list (found: $lcov_version)."
- AC_MSG_ERROR([$lcov_msg])
- LCOV="exit 0;"
- ;;
- esac
-
- AS_IF([ test -z "$GENHTML" ], [
- AC_MSG_ERROR([Could not find genhtml from the lcov package])
- ])
-
- dnl Build the code coverage flags
- CODE_COVERAGE_CPPFLAGS="-DNDEBUG"
- CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage"
- CODE_COVERAGE_CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage"
- CODE_COVERAGE_LDFLAGS="-lgcov"
-
- AC_SUBST([CODE_COVERAGE_CPPFLAGS])
- AC_SUBST([CODE_COVERAGE_CFLAGS])
- AC_SUBST([CODE_COVERAGE_CXXFLAGS])
- AC_SUBST([CODE_COVERAGE_LDFLAGS])
- ])
-
-[CODE_COVERAGE_RULES='
-# Code coverage
-#
-# Optional:
-# - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting.
-# Multiple directories may be specified, separated by whitespace.
-# (Default: $(top_builddir))
-# - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated
-# by lcov for code coverage. (Default:
-# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info)
-# - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage
-# reports to be created. (Default:
-# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage)
-# - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage,
-# set to 0 to disable it and leave empty to stay with the default.
-# (Default: empty)
-# - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov
-# instances. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE)
-# - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov
-# instances. (Default: $CODE_COVERAGE_LCOV_SHOPTS_DEFAULT)
-# - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov
-# - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the
-# collecting lcov instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH)
-# - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov
-# instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_DEFAULT)
-# - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering
-# lcov instance. (Default: empty)
-# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov
-# instance. (Default: $CODE_COVERAGE_LCOV_RMOPTS_DEFAULT)
-# - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the
-# genhtml instance. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE)
-# - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml
-# instance. (Default: $CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT)
-# - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore
-#
-# The generated report will be titled using the $(PACKAGE_NAME) and
-# $(PACKAGE_VERSION). In order to add the current git hash to the title,
-# use the git-version-gen script, available online.
-
-# Optional variables
-CODE_COVERAGE_DIRECTORY ?= $(top_builddir)
-CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info
-CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage
-CODE_COVERAGE_BRANCH_COVERAGE ?=
-CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= $(if $(CODE_COVERAGE_BRANCH_COVERAGE),\
---rc lcov_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE))
-CODE_COVERAGE_LCOV_SHOPTS ?= $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT)
-CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool "$(GCOV)"
-CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= $(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH)
-CODE_COVERAGE_LCOV_OPTIONS ?= $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT)
-CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?=
-CODE_COVERAGE_LCOV_RMOPTS ?= $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT)
-CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=\
-$(if $(CODE_COVERAGE_BRANCH_COVERAGE),\
---rc genhtml_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE))
-CODE_COVERAGE_GENHTML_OPTIONS ?= $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULTS)
-CODE_COVERAGE_IGNORE_PATTERN ?=
-
-code_coverage_v_lcov_cap = $(code_coverage_v_lcov_cap_$(V))
-code_coverage_v_lcov_cap_ = $(code_coverage_v_lcov_cap_$(AM_DEFAULT_VERBOSITY))
-code_coverage_v_lcov_cap_0 = @echo " LCOV --capture"\
- $(CODE_COVERAGE_OUTPUT_FILE);
-code_coverage_v_lcov_ign = $(code_coverage_v_lcov_ign_$(V))
-code_coverage_v_lcov_ign_ = $(code_coverage_v_lcov_ign_$(AM_DEFAULT_VERBOSITY))
-code_coverage_v_lcov_ign_0 = @echo " LCOV --remove /tmp/*"\
- $(CODE_COVERAGE_IGNORE_PATTERN);
-code_coverage_v_genhtml = $(code_coverage_v_genhtml_$(V))
-code_coverage_v_genhtml_ = $(code_coverage_v_genhtml_$(AM_DEFAULT_VERBOSITY))
-code_coverage_v_genhtml_0 = @echo " GEN " $(CODE_COVERAGE_OUTPUT_DIRECTORY);
-code_coverage_quiet = $(code_coverage_quiet_$(V))
-code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY))
-code_coverage_quiet_0 = --quiet
-
-# sanitizes the test-name: replaces with underscores: dashes and dots
-code_coverage_sanitize = $(subst -,_,$(subst .,_,$(1)))
-
-# Use recursive makes in order to ignore errors during check
-check-code-coverage:
-ifeq ($(CODE_COVERAGE_ENABLED),yes)
- -$(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check
- $(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture
-else
- @echo "Need to reconfigure with --enable-code-coverage"
-endif
-
-# Capture code coverage data
-code-coverage-capture: code-coverage-capture-hook
-ifeq ($(CODE_COVERAGE_ENABLED),yes)
- $(code_coverage_v_lcov_cap)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(call code_coverage_sanitize,$(PACKAGE_NAME)-$(PACKAGE_VERSION))" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_OPTIONS)
- $(code_coverage_v_lcov_ign)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_RMOPTS)
- -@rm -f $(CODE_COVERAGE_OUTPUT_FILE).tmp
- $(code_coverage_v_genhtml)LANG=C $(GENHTML) $(code_coverage_quiet) $(addprefix --prefix ,$(CODE_COVERAGE_DIRECTORY)) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS)
- @echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html"
-else
- @echo "Need to reconfigure with --enable-code-coverage"
-endif
-
-# Hook rule executed before code-coverage-capture, overridable by the user
-code-coverage-capture-hook:
-
-ifeq ($(CODE_COVERAGE_ENABLED),yes)
-clean: code-coverage-clean
-code-coverage-clean:
- -$(LCOV) --directory $(top_builddir) -z
- -rm -rf $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_FILE).tmp $(CODE_COVERAGE_OUTPUT_DIRECTORY)
- -find . -name "*.gcda" -o -name "*.gcov" -delete
-endif
-
-GITIGNOREFILES ?=
-GITIGNOREFILES += $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY)
-
-A''M_DISTCHECK_CONFIGURE_FLAGS ?=
-A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-code-coverage
-
-.PHONY: check-code-coverage code-coverage-capture code-coverage-capture-hook code-coverage-clean
-']
-
- AC_SUBST([CODE_COVERAGE_RULES])
- m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([CODE_COVERAGE_RULES])])
-])
diff --git a/m4/ax_configure_args.m4 b/m4/ax_configure_args.m4
deleted file mode 100644
index 0726b1bc..00000000
--- a/m4/ax_configure_args.m4
+++ /dev/null
@@ -1,70 +0,0 @@
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_configure_args.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_CONFIGURE_ARGS
-#
-# DESCRIPTION
-#
-# Helper macro for AX_ENABLE_BUILDDIR.
-#
-# The traditional way of starting a subdir-configure is running the script
-# with ${1+"$@"} but since autoconf 2.60 this is broken. Instead we have
-# to rely on eval'ing $ac_configure_args however some old autoconf
-# versions do not provide that. To ensure maximum portability of autoconf
-# extension macros this helper can be AC_REQUIRE'd so that
-# $ac_configure_args will alsways be present.
-#
-# Sadly, the traditional "exec $SHELL" of the enable_builddir macros is
-# spoiled now and must be replaced by "eval + exit $?".
-#
-# Example:
-#
-# AC_DEFUN([AX_ENABLE_SUBDIR],[dnl
-# AC_REQUIRE([AX_CONFIGURE_ARGS])dnl
-# eval $SHELL $ac_configure_args || exit $?
-# ...])
-#
-# LICENSE
-#
-# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3 of the License, or (at your
-# option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-# Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-# As a special exception, the respective Autoconf Macro's copyright owner
-# gives unlimited permission to copy, distribute and modify the configure
-# scripts that are the output of Autoconf when processing the Macro. You
-# need not follow the terms of the GNU General Public License when using
-# or distributing such scripts, even though portions of the text of the
-# Macro appear in them. The GNU General Public License (GPL) does govern
-# all other use of the material that constitutes the Autoconf Macro.
-#
-# This special exception to the GPL applies to versions of the Autoconf
-# Macro released by the Autoconf Archive. When you make and distribute a
-# modified version of the Autoconf Macro, you may extend this special
-# exception to the GPL to apply to your modified version as well.
-
-#serial 9
-
-AC_DEFUN([AX_CONFIGURE_ARGS],[
- # [$]@ is unsable in 2.60+ but earlier autoconf had no ac_configure_args
- if test "${ac_configure_args+set}" != "set" ; then
- ac_configure_args=
- for ac_arg in ${1+"[$]@"}; do
- ac_configure_args="$ac_configure_args '$ac_arg'"
- done
- fi
-])
diff --git a/m4/ax_enable_builddir.m4 b/m4/ax_enable_builddir.m4
deleted file mode 100644
index 5f4ba327..00000000
--- a/m4/ax_enable_builddir.m4
+++ /dev/null
@@ -1,302 +0,0 @@
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_enable_builddir.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_ENABLE_BUILDDIR [(dirstring-or-command [,Makefile.mk [,-all]])]
-#
-# DESCRIPTION
-#
-# If the current configure was run within the srcdir then we move all
-# configure-files into a subdir and let the configure steps continue
-# there. We provide an option --disable-builddir to suppress the move into
-# a separate builddir.
-#
-# Defaults:
-#
-# $1 = $host (overridden with $HOST)
-# $2 = Makefile.mk
-# $3 = -all
-#
-# This macro must be called before AM_INIT_AUTOMAKE. It creates a default
-# toplevel srcdir Makefile from the information found in the created
-# toplevel builddir Makefile. It just copies the variables and
-# rule-targets, each extended with a default rule-execution that recurses
-# into the build directory of the current "HOST". You can override the
-# auto-dection through `config.guess` and build-time of course, as in
-#
-# make HOST=i386-mingw-cross
-#
-# which can of course set at configure time as well using
-#
-# configure --host=i386-mingw-cross
-#
-# After the default has been created, additional rules can be appended
-# that will not just recurse into the subdirectories and only ever exist
-# in the srcdir toplevel makefile - these parts are read from the $2 =
-# Makefile.mk file
-#
-# The automatic rules are usually scanning the toplevel Makefile for lines
-# like '#### $host |$builddir' to recognize the place where to recurse
-# into. Usually, the last one is the only one used. However, almost all
-# targets have an additional "*-all" rule which makes the script to
-# recurse into _all_ variants of the current HOST (!!) setting. The "-all"
-# suffix can be overriden for the macro as well.
-#
-# a special rule is only given for things like "dist" that will copy the
-# tarball from the builddir to the sourcedir (or $(PUB)) for reason of
-# convenience.
-#
-# LICENSE
-#
-# Copyright (c) 2009 Guido U. Draheim <guidod@gmx.de>
-# Copyright (c) 2009 Alan Jenkins <alan-jenkins@tuffmail.co.uk>
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3 of the License, or (at your
-# option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-# Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-# As a special exception, the respective Autoconf Macro's copyright owner
-# gives unlimited permission to copy, distribute and modify the configure
-# scripts that are the output of Autoconf when processing the Macro. You
-# need not follow the terms of the GNU General Public License when using
-# or distributing such scripts, even though portions of the text of the
-# Macro appear in them. The GNU General Public License (GPL) does govern
-# all other use of the material that constitutes the Autoconf Macro.
-#
-# This special exception to the GPL applies to versions of the Autoconf
-# Macro released by the Autoconf Archive. When you make and distribute a
-# modified version of the Autoconf Macro, you may extend this special
-# exception to the GPL to apply to your modified version as well.
-
-#serial 25
-
-AC_DEFUN([AX_ENABLE_BUILDDIR],[
-AC_REQUIRE([AC_CANONICAL_HOST])[]dnl
-AC_REQUIRE([AC_CANONICAL_TARGET])[]dnl
-AC_REQUIRE([AX_CONFIGURE_ARGS])[]dnl
-AC_REQUIRE([AM_AUX_DIR_EXPAND])[]dnl
-AC_BEFORE([$0],[AM_INIT_AUTOMAKE])dnl
-AS_VAR_PUSHDEF([SUB],[ax_enable_builddir])dnl
-AS_VAR_PUSHDEF([AUX],[ax_enable_builddir_auxdir])dnl
-AS_VAR_PUSHDEF([SED],[ax_enable_builddir_sed])dnl
-SUB="."
-AC_ARG_ENABLE([builddir], AS_HELP_STRING(
- [--disable-builddir],[disable automatic build in subdir of sources])
- ,[SUB="$enableval"], [SUB="auto"])
-if test ".$ac_srcdir_defaulted" != ".no" ; then
-if test ".$srcdir" = ".." ; then
- if test -f config.status ; then
- AC_MSG_NOTICE(toplevel srcdir already configured... skipping subdir build)
- else
- test ".$SUB" = "." && SUB="."
- test ".$SUB" = ".no" && SUB="."
- test ".$TARGET" = "." && TARGET="$target"
- test ".$SUB" = ".auto" && SUB="m4_ifval([$1], [$1],[$TARGET])"
- if test ".$SUB" != ".." ; then # we know where to go and
- AS_MKDIR_P([$SUB])
- echo __.$SUB.__ > $SUB/conftest.tmp
- cd $SUB
- if grep __.$SUB.__ conftest.tmp >/dev/null 2>/dev/null ; then
- rm conftest.tmp
- AC_MSG_RESULT([continue configure in default builddir "./$SUB"])
- else
- AC_MSG_ERROR([could not change to default builddir "./$SUB"])
- fi
- srcdir=`echo "$SUB" |
- sed -e 's,^\./,,;s,[[^/]]$,&/,;s,[[^/]]*/,../,g;s,[[/]]$,,;'`
- # going to restart from subdirectory location
- test -f $srcdir/config.log && mv $srcdir/config.log .
- test -f $srcdir/confdefs.h && mv $srcdir/confdefs.h .
- test -f $srcdir/conftest.log && mv $srcdir/conftest.log .
- test -f $srcdir/$cache_file && mv $srcdir/$cache_file .
- AC_MSG_RESULT(....exec $SHELL $srcdir/[$]0 "--srcdir=$srcdir" "--enable-builddir=$SUB" ${1+"[$]@"})
- case "[$]0" in # restart
- [[\\/]]* | ?:[[\\/]]*) # Asbolute name
- eval $SHELL "'[$]0'" "'--srcdir=$srcdir'" "'--enable-builddir=$SUB'" $ac_configure_args ;;
- *) eval $SHELL "'$srcdir/[$]0'" "'--srcdir=$srcdir'" "'--enable-builddir=$SUB'" $ac_configure_args ;;
- esac ; exit $?
- fi
- fi
-fi fi
-test ".$SUB" = ".auto" && SUB="."
-dnl ac_path_prog uses "set dummy" to override $@ which would defeat the "exec"
-AC_PATH_PROG(SED,gsed sed, sed)
-AUX="$am_aux_dir"
-AS_VAR_POPDEF([SED])dnl
-AS_VAR_POPDEF([AUX])dnl
-AS_VAR_POPDEF([SUB])dnl
-AC_CONFIG_COMMANDS([buildir],[dnl .............. config.status ..............
-AS_VAR_PUSHDEF([SUB],[ax_enable_builddir])dnl
-AS_VAR_PUSHDEF([TOP],[top_srcdir])dnl
-AS_VAR_PUSHDEF([SRC],[ac_top_srcdir])dnl
-AS_VAR_PUSHDEF([AUX],[ax_enable_builddir_auxdir])dnl
-AS_VAR_PUSHDEF([SED],[ax_enable_builddir_sed])dnl
-pushdef([END],[Makefile.mk])dnl
-pushdef([_ALL],[ifelse([$3],,[-all],[$3])])dnl
- SRC="$ax_enable_builddir_srcdir"
- if test ".$SUB" = ".." ; then
- if test -f "$TOP/Makefile" ; then
- AC_MSG_NOTICE([skipping TOP/Makefile - left untouched])
- else
- AC_MSG_NOTICE([skipping TOP/Makefile - not created])
- fi
- else
- if test -f "$SRC/Makefile" ; then
- a=`grep "^VERSION " "$SRC/Makefile"` ; b=`grep "^VERSION " Makefile`
- test "$a" != "$b" && rm "$SRC/Makefile"
- fi
- if test -f "$SRC/Makefile" ; then
- echo "$SRC/Makefile : $SRC/Makefile.in" > $tmp/conftemp.mk
- echo " []@ echo 'REMOVED,,,' >\$[]@" >> $tmp/conftemp.mk
- eval "${MAKE-make} -f $tmp/conftemp.mk 2>/dev/null >/dev/null"
- if grep '^REMOVED,,,' "$SRC/Makefile" >/dev/null
- then rm $SRC/Makefile ; fi
- cp $tmp/conftemp.mk $SRC/makefiles.mk~ ## DEBUGGING
- fi
- if test ! -f "$SRC/Makefile" ; then
- AC_MSG_NOTICE([create TOP/Makefile guessed from local Makefile])
- x='`' ; cat >$tmp/conftemp.sed <<_EOF
-/^\$/n
-x
-/^\$/bS
-x
-/\\\\\$/{H;d;}
-{H;s/.*//;x;}
-bM
-:S
-x
-/\\\\\$/{h;d;}
-{h;s/.*//;x;}
-:M
-s/\\(\\n\\) /\\1 /g
-/^ /d
-/^[[ ]]*[[\\#]]/d
-/^VPATH *=/d
-s/^srcdir *=.*/srcdir = ./
-s/^top_srcdir *=.*/top_srcdir = ./
-/[[:=]]/!d
-/^\\./d
-dnl Now handle rules (i.e. lines containing ":" but not " = ").
-/ = /b
-/ .= /b
-/:/!b
-s/:.*/:/
-s/ / /g
-s/ \\([[a-z]][[a-z-]]*[[a-zA-Z0-9]]\\)\\([[ :]]\\)/ \\1 \\1[]_ALL\\2/g
-s/^\\([[a-z]][[a-z-]]*[[a-zA-Z0-9]]\\)\\([[ :]]\\)/\\1 \\1[]_ALL\\2/
-s/ / /g
-/^all all[]_ALL[[ :]]/i\\
-all-configured : all[]_ALL
-dnl dist-all exists... and would make for dist-all-all
-s/ [[a-zA-Z0-9-]]*[]_ALL [[a-zA-Z0-9-]]*[]_ALL[]_ALL//g
-/[]_ALL[]_ALL/d
-a\\
- @ HOST="\$(HOST)\" \\\\\\
- ; test ".\$\$HOST" = "." && HOST=$x sh $AUX/config.guess $x \\\\\\
- ; BUILD=$x grep "^#### \$\$HOST " Makefile | sed -e 's/.*|//' $x \\\\\\
- ; use=$x basename "\$\@" _ALL $x; n=$x echo \$\$BUILD | wc -w $x \\\\\\
- ; echo "MAKE \$\$HOST : \$\$n * \$\@"; if test "\$\$n" -eq "0" ; then : \\\\\\
- ; BUILD=$x grep "^####.*|" Makefile |tail -1| sed -e 's/.*|//' $x ; fi \\\\\\
- ; test ".\$\$BUILD" = "." && BUILD="." \\\\\\
- ; test "\$\$use" = "\$\@" && BUILD=$x echo "\$\$BUILD" | tail -1 $x \\\\\\
- ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\
- ; (cd "\$\$i" && test ! -f configure && \$(MAKE) \$\$use) || exit; done
-dnl special rule add-on: "dist" copies the tarball to $(PUB). (source tree)
-/dist[]_ALL *:/a\\
- @ HOST="\$(HOST)\" \\\\\\
- ; test ".\$\$HOST" = "." && HOST=$x sh $AUX/config.guess $x \\\\\\
- ; BUILD=$x grep "^#### \$\$HOST " Makefile | sed -e 's/.*|//' $x \\\\\\
- ; found=$x echo \$\$BUILD | wc -w $x \\\\\\
- ; echo "MAKE \$\$HOST : \$\$found \$(PACKAGE)-\$(VERSION).tar.*" \\\\\\
- ; if test "\$\$found" -eq "0" ; then : \\\\\\
- ; BUILD=$x grep "^#### .*|" Makefile |tail -1| sed -e 's/.*|//' $x \\\\\\
- ; fi ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\
- ; for f in \$\$i/\$(PACKAGE)-\$(VERSION).tar.* \\\\\\
- ; do test -f "\$\$f" && mv "\$\$f" \$(PUB). ; done ; break ; done
-dnl special rule add-on: "dist-foo" copies all the archives to $(PUB). (source tree)
-/dist-[[a-zA-Z0-9]]*[]_ALL *:/a\\
- @ HOST="\$(HOST)\" \\\\\\
- ; test ".\$\$HOST" = "." && HOST=$x sh ./config.guess $x \\\\\\
- ; BUILD=$x grep "^#### \$\$HOST " Makefile | sed -e 's/.*|//' $x \\\\\\
- ; found=$x echo \$\$BUILD | wc -w $x \\\\\\
- ; echo "MAKE \$\$HOST : \$\$found \$(PACKAGE)-\$(VERSION).*" \\\\\\
- ; if test "\$\$found" -eq "0" ; then : \\\\\\
- ; BUILD=$x grep "^#### .*|" Makefile |tail -1| sed -e 's/.*|//' $x \\\\\\
- ; fi ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\
- ; for f in \$\$i/\$(PACKAGE)-\$(VERSION).* \\\\\\
- ; do test -f "\$\$f" && mv "\$\$f" \$(PUB). ; done ; break ; done
-dnl special rule add-on: "distclean" removes all local builddirs completely
-/distclean[]_ALL *:/a\\
- @ HOST="\$(HOST)\" \\\\\\
- ; test ".\$\$HOST" = "." && HOST=$x sh $AUX/config.guess $x \\\\\\
- ; BUILD=$x grep "^#### .*|" Makefile | sed -e 's/.*|//' $x \\\\\\
- ; use=$x basename "\$\@" _ALL $x; n=$x echo \$\$BUILD | wc -w $x \\\\\\
- ; echo "MAKE \$\$HOST : \$\$n * \$\@ (all local builds)" \\\\\\
- ; test ".\$\$BUILD" = "." && BUILD="." \\\\\\
- ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\
- ; echo "# rm -r \$\$i"; done ; echo "# (sleep 3)" ; sleep 3 \\\\\\
- ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\
- ; echo "\$\$i" | grep "^/" > /dev/null && continue \\\\\\
- ; echo "\$\$i" | grep "^../" > /dev/null && continue \\\\\\
- ; echo "rm -r \$\$i"; (rm -r "\$\$i") ; done ; rm Makefile
-_EOF
- cp "$tmp/conftemp.sed" "$SRC/makefile.sed~" ## DEBUGGING
- $SED -f $tmp/conftemp.sed Makefile >$SRC/Makefile
- if test -f "$SRC/m4_ifval([$2],[$2],[END])" ; then
- AC_MSG_NOTICE([extend TOP/Makefile with TOP/m4_ifval([$2],[$2],[END])])
- cat $SRC/END >>$SRC/Makefile
- fi ; xxxx="####"
- echo "$xxxx CONFIGURATIONS FOR TOPLEVEL MAKEFILE: " >>$SRC/Makefile
- # sanity check
- if grep '^; echo "MAKE ' $SRC/Makefile >/dev/null ; then
- AC_MSG_NOTICE([buggy sed found - it deletes tab in "a" text parts])
- $SED -e '/^@ HOST=/s/^/ /' -e '/^; /s/^/ /' $SRC/Makefile \
- >$SRC/Makefile~
- (test -s $SRC/Makefile~ && mv $SRC/Makefile~ $SRC/Makefile) 2>/dev/null
- fi
- else
- xxxx="\\#\\#\\#\\#"
- # echo "/^$xxxx *$ax_enable_builddir_host /d" >$tmp/conftemp.sed
- echo "s!^$xxxx [[^|]]* | *$SUB *\$!$xxxx ...... $SUB!" >$tmp/conftemp.sed
- $SED -f "$tmp/conftemp.sed" "$SRC/Makefile" >$tmp/mkfile.tmp
- cp "$tmp/conftemp.sed" "$SRC/makefiles.sed~" ## DEBUGGING
- cp "$tmp/mkfile.tmp" "$SRC/makefiles.out~" ## DEBUGGING
- if cmp -s "$SRC/Makefile" "$tmp/mkfile.tmp" 2>/dev/null ; then
- AC_MSG_NOTICE([keeping TOP/Makefile from earlier configure])
- rm "$tmp/mkfile.tmp"
- else
- AC_MSG_NOTICE([reusing TOP/Makefile from earlier configure])
- mv "$tmp/mkfile.tmp" "$SRC/Makefile"
- fi
- fi
- AC_MSG_NOTICE([build in $SUB (HOST=$ax_enable_builddir_host)])
- xxxx="####"
- echo "$xxxx" "$ax_enable_builddir_host" "|$SUB" >>$SRC/Makefile
- fi
-popdef([END])dnl
-AS_VAR_POPDEF([SED])dnl
-AS_VAR_POPDEF([AUX])dnl
-AS_VAR_POPDEF([SRC])dnl
-AS_VAR_POPDEF([TOP])dnl
-AS_VAR_POPDEF([SUB])dnl
-],[dnl
-ax_enable_builddir_srcdir="$srcdir" # $srcdir
-ax_enable_builddir_host="$HOST" # $HOST / $host
-ax_enable_builddir_version="$VERSION" # $VERSION
-ax_enable_builddir_package="$PACKAGE" # $PACKAGE
-ax_enable_builddir_auxdir="$ax_enable_builddir_auxdir" # $AUX
-ax_enable_builddir_sed="$ax_enable_builddir_sed" # $SED
-ax_enable_builddir="$ax_enable_builddir" # $SUB
-])dnl
-])
diff --git a/m4/ax_extend_srcdir.m4 b/m4/ax_extend_srcdir.m4
deleted file mode 100644
index 40f37878..00000000
--- a/m4/ax_extend_srcdir.m4
+++ /dev/null
@@ -1,86 +0,0 @@
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_extend_srcdir.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_EXTEND_SRCDIR
-#
-# DESCRIPTION
-#
-# The AX_EXTEND_SRCDIR macro extends $srcdir by one path component.
-#
-# As an example, when working in /home/michael/i3-4.12/build and calling
-# ../configure, your $srcdir is "..". After calling AX_EXTEND_SRCDIR,
-# $srcdir will be set to "../../i3-4.12".
-#
-# The result of extending $srcdir is that filenames (e.g. in the output of
-# the "backtrace" gdb command) will include one more path component of the
-# absolute source path. The additional path component makes it easy for
-# users to recognize which files belong to the PACKAGE, and -- provided a
-# dist tarball was unpacked -- which version of PACKAGE was used.
-#
-# As an example, in "backtrace", you will see:
-#
-# #0 main (argc=1, argv=0x7fffffff1fc8) at ../../i3-4.12/src/main.c:187
-#
-# instead of:
-#
-# #0 main (argc=1, argv=0x7fffffff1fc8) at ../src/main.c:187
-#
-# In case your code uses the __FILE__ preprocessor directive to refer to
-# the filename of the current source file (e.g. in debug messages), using
-# the extended path might be undesirable. For this purpose,
-# AX_EXTEND_SRCDIR defines the output variable AX_EXTEND_SRCDIR_CPPFLAGS,
-# which can be added to AM_CPPFLAGS in Makefile.am in order to define the
-# preprocessor directive STRIPPED__FILE__. As an example, when compiling
-# the file "../../i3-4.12/src/main.c", STRIPPED__FILE__ evaluates to
-# "main.c".
-#
-# There are some caveats: When $srcdir is "." (i.e. when ./configure was
-# called instead of ../configure in a separate build directory),
-# AX_EXTEND_SRCDIR will still extend $srcdir, but the intended effect will
-# not be achieved because of the way automake specifies file paths:
-# automake defines COMPILE to use "`test -f '$source' || echo
-# '\$(srcdir)/'`$source" in order to prefer files in the current directory
-# over specifying $srcdir explicitly.
-#
-# The AX_EXTEND_SRCDIR author is not aware of any way to influence this
-# automake behavior. Patches very welcome.
-#
-# To work around this issue, you can use AX_ENABLE_BUILDDIR i.e. by adding
-# the following code to configure.ac:
-#
-# AX_ENABLE_BUILDDIR
-# dnl ...
-# AX_EXTEND_SRCDIR
-#
-# Then also add this bit to Makefile.am (if you wish to use
-# STRIPPED__FILE__ in your code):
-#
-# AM_CPPFLAGS = @AX_EXTEND_SRCDIR_CPPFLAGS@
-#
-# LICENSE
-#
-# Copyright (c) 2016 Michael Stapelberg <michael@i3wm.org>
-#
-# Copying and distribution of this file, with or without modification, are
-# permitted in any medium without royalty provided the copyright notice
-# and this notice are preserved. This file is offered as-is, without any
-# warranty.
-
-#serial 3
-
-AC_DEFUN([AX_EXTEND_SRCDIR],
-[dnl
-AS_CASE([$srcdir],
- [.|.*|/*],
- [
- # pwd -P is specified in IEEE 1003.1 from 2004
- as_dir=`cd "$srcdir" && pwd -P`
- as_base=`AS_BASENAME([$as_dir])`
- srcdir=${srcdir}/../${as_base}
-
- AC_SUBST([AX_EXTEND_SRCDIR_CPPFLAGS], ["-DSTRIPPED__FILE__=AS_ESCAPE([\"$$(basename $<)\"])"])
- ])
-])dnl AX_EXTEND_SRCDIR
diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4
deleted file mode 100644
index 4c4051ea..00000000
--- a/m4/ax_pthread.m4
+++ /dev/null
@@ -1,485 +0,0 @@
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
-#
-# DESCRIPTION
-#
-# This macro figures out how to build C programs using POSIX threads. It
-# sets the PTHREAD_LIBS output variable to the threads library and linker
-# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
-# flags that are needed. (The user can also force certain compiler
-# flags/libs to be tested by setting these environment variables.)
-#
-# Also sets PTHREAD_CC to any special C compiler that is needed for
-# multi-threaded programs (defaults to the value of CC otherwise). (This
-# is necessary on AIX to use the special cc_r compiler alias.)
-#
-# NOTE: You are assumed to not only compile your program with these flags,
-# but also to link with them as well. For example, you might link with
-# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
-#
-# If you are only building threaded programs, you may wish to use these
-# variables in your default LIBS, CFLAGS, and CC:
-#
-# LIBS="$PTHREAD_LIBS $LIBS"
-# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
-# CC="$PTHREAD_CC"
-#
-# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
-# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
-# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
-#
-# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
-# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
-# PTHREAD_CFLAGS.
-#
-# ACTION-IF-FOUND is a list of shell commands to run if a threads library
-# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
-# is not found. If ACTION-IF-FOUND is not specified, the default action
-# will define HAVE_PTHREAD.
-#
-# Please let the authors know if this macro fails on any platform, or if
-# you have any other suggestions or comments. This macro was based on work
-# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
-# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
-# Alejandro Forero Cuervo to the autoconf macro repository. We are also
-# grateful for the helpful feedback of numerous users.
-#
-# Updated for Autoconf 2.68 by Daniel Richard G.
-#
-# LICENSE
-#
-# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
-# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
-#
-# This program is free software: you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-# Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-# As a special exception, the respective Autoconf Macro's copyright owner
-# gives unlimited permission to copy, distribute and modify the configure
-# scripts that are the output of Autoconf when processing the Macro. You
-# need not follow the terms of the GNU General Public License when using
-# or distributing such scripts, even though portions of the text of the
-# Macro appear in them. The GNU General Public License (GPL) does govern
-# all other use of the material that constitutes the Autoconf Macro.
-#
-# This special exception to the GPL applies to versions of the Autoconf
-# Macro released by the Autoconf Archive. When you make and distribute a
-# modified version of the Autoconf Macro, you may extend this special
-# exception to the GPL to apply to your modified version as well.
-
-#serial 23
-
-AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
-AC_DEFUN([AX_PTHREAD], [
-AC_REQUIRE([AC_CANONICAL_HOST])
-AC_REQUIRE([AC_PROG_CC])
-AC_REQUIRE([AC_PROG_SED])
-AC_LANG_PUSH([C])
-ax_pthread_ok=no
-
-# We used to check for pthread.h first, but this fails if pthread.h
-# requires special compiler flags (e.g. on Tru64 or Sequent).
-# It gets checked for in the link test anyway.
-
-# First of all, check if the user has set any of the PTHREAD_LIBS,
-# etcetera environment variables, and if threads linking works using
-# them:
-if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
- ax_pthread_save_CC="$CC"
- ax_pthread_save_CFLAGS="$CFLAGS"
- ax_pthread_save_LIBS="$LIBS"
- AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
- CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
- LIBS="$PTHREAD_LIBS $LIBS"
- AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
- AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
- AC_MSG_RESULT([$ax_pthread_ok])
- if test "x$ax_pthread_ok" = "xno"; then
- PTHREAD_LIBS=""
- PTHREAD_CFLAGS=""
- fi
- CC="$ax_pthread_save_CC"
- CFLAGS="$ax_pthread_save_CFLAGS"
- LIBS="$ax_pthread_save_LIBS"
-fi
-
-# We must check for the threads library under a number of different
-# names; the ordering is very important because some systems
-# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
-# libraries is broken (non-POSIX).
-
-# Create a list of thread flags to try. Items starting with a "-" are
-# C compiler flags, and other items are library names, except for "none"
-# which indicates that we try without any flags at all, and "pthread-config"
-# which is a program returning the flags for the Pth emulation library.
-
-ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
-
-# The ordering *is* (sometimes) important. Some notes on the
-# individual items follow:
-
-# pthreads: AIX (must check this before -lpthread)
-# none: in case threads are in libc; should be tried before -Kthread and
-# other compiler flags to prevent continual compiler warnings
-# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
-# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
-# (Note: HP C rejects this with "bad form for `-t' option")
-# -pthreads: Solaris/gcc (Note: HP C also rejects)
-# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
-# doesn't hurt to check since this sometimes defines pthreads and
-# -D_REENTRANT too), HP C (must be checked before -lpthread, which
-# is present but should not be used directly; and before -mthreads,
-# because the compiler interprets this as "-mt" + "-hreads")
-# -mthreads: Mingw32/gcc, Lynx/gcc
-# pthread: Linux, etcetera
-# --thread-safe: KAI C++
-# pthread-config: use pthread-config program (for GNU Pth library)
-
-case $host_os in
-
- freebsd*)
-
- # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
- # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
-
- ax_pthread_flags="-kthread lthread $ax_pthread_flags"
- ;;
-
- hpux*)
-
- # From the cc(1) man page: "[-mt] Sets various -D flags to enable
- # multi-threading and also sets -lpthread."
-
- ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
- ;;
-
- openedition*)
-
- # IBM z/OS requires a feature-test macro to be defined in order to
- # enable POSIX threads at all, so give the user a hint if this is
- # not set. (We don't define these ourselves, as they can affect
- # other portions of the system API in unpredictable ways.)
-
- AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
- [
-# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
- AX_PTHREAD_ZOS_MISSING
-# endif
- ],
- [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
- ;;
-
- solaris*)
-
- # On Solaris (at least, for some versions), libc contains stubbed
- # (non-functional) versions of the pthreads routines, so link-based
- # tests will erroneously succeed. (N.B.: The stubs are missing
- # pthread_cleanup_push, or rather a function called by this macro,
- # so we could check for that, but who knows whether they'll stub
- # that too in a future libc.) So we'll check first for the
- # standard Solaris way of linking pthreads (-mt -lpthread).
-
- ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags"
- ;;
-esac
-
-# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
-
-AS_IF([test "x$GCC" = "xyes"],
- [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"])
-
-# The presence of a feature test macro requesting re-entrant function
-# definitions is, on some systems, a strong hint that pthreads support is
-# correctly enabled
-
-case $host_os in
- darwin* | hpux* | linux* | osf* | solaris*)
- ax_pthread_check_macro="_REENTRANT"
- ;;
-
- aix*)
- ax_pthread_check_macro="_THREAD_SAFE"
- ;;
-
- *)
- ax_pthread_check_macro="--"
- ;;
-esac
-AS_IF([test "x$ax_pthread_check_macro" = "x--"],
- [ax_pthread_check_cond=0],
- [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
-
-# Are we compiling with Clang?
-
-AC_CACHE_CHECK([whether $CC is Clang],
- [ax_cv_PTHREAD_CLANG],
- [ax_cv_PTHREAD_CLANG=no
- # Note that Autoconf sets GCC=yes for Clang as well as GCC
- if test "x$GCC" = "xyes"; then
- AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
- [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
-# if defined(__clang__) && defined(__llvm__)
- AX_PTHREAD_CC_IS_CLANG
-# endif
- ],
- [ax_cv_PTHREAD_CLANG=yes])
- fi
- ])
-ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
-
-ax_pthread_clang_warning=no
-
-# Clang needs special handling, because older versions handle the -pthread
-# option in a rather... idiosyncratic way
-
-if test "x$ax_pthread_clang" = "xyes"; then
-
- # Clang takes -pthread; it has never supported any other flag
-
- # (Note 1: This will need to be revisited if a system that Clang
- # supports has POSIX threads in a separate library. This tends not
- # to be the way of modern systems, but it's conceivable.)
-
- # (Note 2: On some systems, notably Darwin, -pthread is not needed
- # to get POSIX threads support; the API is always present and
- # active. We could reasonably leave PTHREAD_CFLAGS empty. But
- # -pthread does define _REENTRANT, and while the Darwin headers
- # ignore this macro, third-party headers might not.)
-
- PTHREAD_CFLAGS="-pthread"
- PTHREAD_LIBS=
-
- ax_pthread_ok=yes
-
- # However, older versions of Clang make a point of warning the user
- # that, in an invocation where only linking and no compilation is
- # taking place, the -pthread option has no effect ("argument unused
- # during compilation"). They expect -pthread to be passed in only
- # when source code is being compiled.
- #
- # Problem is, this is at odds with the way Automake and most other
- # C build frameworks function, which is that the same flags used in
- # compilation (CFLAGS) are also used in linking. Many systems
- # supported by AX_PTHREAD require exactly this for POSIX threads
- # support, and in fact it is often not straightforward to specify a
- # flag that is used only in the compilation phase and not in
- # linking. Such a scenario is extremely rare in practice.
- #
- # Even though use of the -pthread flag in linking would only print
- # a warning, this can be a nuisance for well-run software projects
- # that build with -Werror. So if the active version of Clang has
- # this misfeature, we search for an option to squash it.
-
- AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
- [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
- [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
- # Create an alternate version of $ac_link that compiles and
- # links in two steps (.c -> .o, .o -> exe) instead of one
- # (.c -> exe), because the warning occurs only in the second
- # step
- ax_pthread_save_ac_link="$ac_link"
- ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
- ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"`
- ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
- ax_pthread_save_CFLAGS="$CFLAGS"
- for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
- AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
- CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
- ac_link="$ax_pthread_save_ac_link"
- AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
- [ac_link="$ax_pthread_2step_ac_link"
- AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
- [break])
- ])
- done
- ac_link="$ax_pthread_save_ac_link"
- CFLAGS="$ax_pthread_save_CFLAGS"
- AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
- ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
- ])
-
- case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
- no | unknown) ;;
- *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
- esac
-
-fi # $ax_pthread_clang = yes
-
-if test "x$ax_pthread_ok" = "xno"; then
-for ax_pthread_try_flag in $ax_pthread_flags; do
-
- case $ax_pthread_try_flag in
- none)
- AC_MSG_CHECKING([whether pthreads work without any flags])
- ;;
-
- -mt,pthread)
- AC_MSG_CHECKING([whether pthreads work with -mt -lpthread])
- PTHREAD_CFLAGS="-mt"
- PTHREAD_LIBS="-lpthread"
- ;;
-
- -*)
- AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
- PTHREAD_CFLAGS="$ax_pthread_try_flag"
- ;;
-
- pthread-config)
- AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
- AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
- PTHREAD_CFLAGS="`pthread-config --cflags`"
- PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
- ;;
-
- *)
- AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
- PTHREAD_LIBS="-l$ax_pthread_try_flag"
- ;;
- esac
-
- ax_pthread_save_CFLAGS="$CFLAGS"
- ax_pthread_save_LIBS="$LIBS"
- CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
- LIBS="$PTHREAD_LIBS $LIBS"
-
- # Check for various functions. We must include pthread.h,
- # since some functions may be macros. (On the Sequent, we
- # need a special flag -Kthread to make this header compile.)
- # We check for pthread_join because it is in -lpthread on IRIX
- # while pthread_create is in libc. We check for pthread_attr_init
- # due to DEC craziness with -lpthreads. We check for
- # pthread_cleanup_push because it is one of the few pthread
- # functions on Solaris that doesn't have a non-functional libc stub.
- # We try pthread_create on general principles.
-
- AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
-# if $ax_pthread_check_cond
-# error "$ax_pthread_check_macro must be defined"
-# endif
- static void routine(void *a) { a = 0; }
- static void *start_routine(void *a) { return a; }],
- [pthread_t th; pthread_attr_t attr;
- pthread_create(&th, 0, start_routine, 0);
- pthread_join(th, 0);
- pthread_attr_init(&attr);
- pthread_cleanup_push(routine, 0);
- pthread_cleanup_pop(0) /* ; */])],
- [ax_pthread_ok=yes],
- [])
-
- CFLAGS="$ax_pthread_save_CFLAGS"
- LIBS="$ax_pthread_save_LIBS"
-
- AC_MSG_RESULT([$ax_pthread_ok])
- AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
-
- PTHREAD_LIBS=""
- PTHREAD_CFLAGS=""
-done
-fi
-
-# Various other checks:
-if test "x$ax_pthread_ok" = "xyes"; then
- ax_pthread_save_CFLAGS="$CFLAGS"
- ax_pthread_save_LIBS="$LIBS"
- CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
- LIBS="$PTHREAD_LIBS $LIBS"
-
- # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
- AC_CACHE_CHECK([for joinable pthread attribute],
- [ax_cv_PTHREAD_JOINABLE_ATTR],
- [ax_cv_PTHREAD_JOINABLE_ATTR=unknown
- for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
- AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
- [int attr = $ax_pthread_attr; return attr /* ; */])],
- [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
- [])
- done
- ])
- AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
- test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
- test "x$ax_pthread_joinable_attr_defined" != "xyes"],
- [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
- [$ax_cv_PTHREAD_JOINABLE_ATTR],
- [Define to necessary symbol if this constant
- uses a non-standard name on your system.])
- ax_pthread_joinable_attr_defined=yes
- ])
-
- AC_CACHE_CHECK([whether more special flags are required for pthreads],
- [ax_cv_PTHREAD_SPECIAL_FLAGS],
- [ax_cv_PTHREAD_SPECIAL_FLAGS=no
- case $host_os in
- solaris*)
- ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
- ;;
- esac
- ])
- AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
- test "x$ax_pthread_special_flags_added" != "xyes"],
- [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
- ax_pthread_special_flags_added=yes])
-
- AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
- [ax_cv_PTHREAD_PRIO_INHERIT],
- [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
- [[int i = PTHREAD_PRIO_INHERIT;]])],
- [ax_cv_PTHREAD_PRIO_INHERIT=yes],
- [ax_cv_PTHREAD_PRIO_INHERIT=no])
- ])
- AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
- test "x$ax_pthread_prio_inherit_defined" != "xyes"],
- [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
- ax_pthread_prio_inherit_defined=yes
- ])
-
- CFLAGS="$ax_pthread_save_CFLAGS"
- LIBS="$ax_pthread_save_LIBS"
-
- # More AIX lossage: compile with *_r variant
- if test "x$GCC" != "xyes"; then
- case $host_os in
- aix*)
- AS_CASE(["x/$CC"],
- [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
- [#handle absolute path differently from PATH based program lookup
- AS_CASE(["x$CC"],
- [x/*],
- [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
- [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
- ;;
- esac
- fi
-fi
-
-test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
-
-AC_SUBST([PTHREAD_LIBS])
-AC_SUBST([PTHREAD_CFLAGS])
-AC_SUBST([PTHREAD_CC])
-
-# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
-if test "x$ax_pthread_ok" = "xyes"; then
- ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
- :
-else
- ax_pthread_ok=no
- $2
-fi
-AC_LANG_POP
-])dnl AX_PTHREAD
diff --git a/m4/ax_require_defined.m4 b/m4/ax_require_defined.m4
deleted file mode 100644
index cae11112..00000000
--- a/m4/ax_require_defined.m4
+++ /dev/null
@@ -1,37 +0,0 @@
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_require_defined.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_REQUIRE_DEFINED(MACRO)
-#
-# DESCRIPTION
-#
-# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have
-# been defined and thus are available for use. This avoids random issues
-# where a macro isn't expanded. Instead the configure script emits a
-# non-fatal:
-#
-# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found
-#
-# It's like AC_REQUIRE except it doesn't expand the required macro.
-#
-# Here's an example:
-#
-# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
-#
-# LICENSE
-#
-# Copyright (c) 2014 Mike Frysinger <vapier@gentoo.org>
-#
-# Copying and distribution of this file, with or without modification, are
-# permitted in any medium without royalty provided the copyright notice
-# and this notice are preserved. This file is offered as-is, without any
-# warranty.
-
-#serial 1
-
-AC_DEFUN([AX_REQUIRE_DEFINED], [dnl
- m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
-])dnl AX_REQUIRE_DEFINED
diff --git a/m4/ax_sanitizers.m4 b/m4/ax_sanitizers.m4
deleted file mode 100644
index 836d4afd..00000000
--- a/m4/ax_sanitizers.m4
+++ /dev/null
@@ -1,130 +0,0 @@
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_sanitizers.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_SANITIZERS([SANITIZERS], [ENABLED-BY-DEFAULT], [ACTION-SUCCESS])
-#
-# DESCRIPTION
-#
-# Offers users to enable one or more sanitizers (see
-# https://github.com/google/sanitizers) with the corresponding
-# --enable-<sanitizer>-sanitizer option.
-#
-# SANITIZERS is a whitespace-separated list of sanitizers to offer via
-# --enable-<sanitizer>-sanitizer options, e.g. "address memory" for the
-# address sanitizer and the memory sanitizer. If SANITIZERS is not specified,
-# all known sanitizers to AX_SANITIZERS will be offered, which at the time of
-# writing are "address memory undefined".
-# NOTE that SANITIZERS is expanded at autoconf time, not at configure time,
-# i.e. you cannot use shell variables in SANITIZERS.
-#
-# ENABLED-BY-DEFAULT is a whitespace-separated list of sanitizers which
-# should be enabled by default, e.g. "memory undefined". Note that not all
-# sanitizers can be combined, e.g. memory sanitizer cannot be enabled when
-# address sanitizer is already enabled.
-# Set ENABLED-BY-DEFAULT to a single whitespace in order to disable all
-# sanitizers by default.
-# ENABLED-BY-DEFAULT is expanded at configure time, so you can use shell
-# variables.
-#
-# ACTION-SUCCESS allows to specify shell commands to execute on success, i.e.
-# when one of the sanitizers was successfully enabled. This is a good place
-# to call AC_DEFINE for any precompiler constants you might need to make your
-# code play nice with sanitizers.
-#
-# The variable ax_enabled_sanitizers contains a whitespace-separated list of
-# all enabled sanitizers, so that you can print them at the end of configure,
-# if you wish.
-#
-# The additional --enable-sanitizers option allows users to enable/disable
-# all sanitizers, effectively overriding ENABLED-BY-DEFAULT.
-#
-# EXAMPLES
-#
-# AX_SANITIZERS([address])
-# dnl offer users to enable address sanitizer via --enable-address-sanitizer
-#
-# is_debug_build=…
-# if test "x$is_debug_build" = "xyes"; then
-# default_sanitizers="address memory"
-# else
-# default_sanitizers=
-# fi
-# AX_SANITIZERS([address memory], [$default_sanitizers])
-# dnl enable address sanitizer and memory sanitizer by default for debug
-# dnl builds, e.g. when building from git instead of a dist tarball.
-#
-# AX_SANITIZERS(, , [
-# AC_DEFINE([SANITIZERS_ENABLED],
-# [],
-# [At least one sanitizer was enabled])])
-# dnl enable all sanitizers known to AX_SANITIZERS by default and set the
-# dnl SANITIZERS_ENABLED precompiler constant.
-#
-# AX_SANITIZERS(, [ ])
-# dnl provide all sanitizers, but enable none by default.
-#
-# LICENSE
-#
-# Copyright (c) 2016 Michael Stapelberg <michael@i3wm.org>
-#
-# Copying and distribution of this file, with or without modification,
-# are permitted in any medium without royalty provided the copyright
-# notice and this notice are preserved. This file is offered as-is,
-# without any warranty.
-
-AC_DEFUN([AX_SANITIZERS],
-[AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG])
-AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
-AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
-AC_ARG_ENABLE(sanitizers,
- AS_HELP_STRING(
- [--enable-sanitizers],
- [enable all known sanitizers]),
- [ax_sanitizers_default=$enableval],
- [ax_sanitizers_default=])
-ax_enabled_sanitizers=
-m4_foreach_w([mysan], m4_default($1, [address memory undefined]), [
- dnl If ax_sanitizers_default is unset, i.e. the user neither explicitly
- dnl enabled nor explicitly disabled all sanitizers, we get the default value
- dnl for this sanitizer based on whether it is listed in ENABLED-BY-DEFAULT.
- AS_IF([test "x$ax_sanitizers_default" = "x"], [dnl
- ax_sanitizer_default=
- for mycheck in m4_default([$2], [address memory undefined]); do
- AS_IF([test "x$mycheck" = "x[]mysan"], [ax_sanitizer_default=yes])
- done
- AS_IF([test "x$ax_sanitizer_default" = "x"], [ax_sanitizer_default=no])
- ],
- [ax_sanitizer_default=$ax_sanitizers_default])
- AC_ARG_ENABLE(mysan[]-sanitizer,
- AS_HELP_STRING(
- [--enable-[]mysan[]-sanitizer],
- [enable -fsanitize=mysan]),
- [ax_sanitizer_enabled=$enableval],
- [ax_sanitizer_enabled=$ax_sanitizer_default])
-
-AS_IF([test "x$ax_sanitizer_enabled" = "xyes"], [
-dnl Not using AX_APPEND_COMPILE_FLAGS and AX_APPEND_LINK_FLAGS because they
-dnl lack the ability to specify ACTION-SUCCESS.
- AX_CHECK_COMPILE_FLAG([-fsanitize=[]mysan], [
- AX_CHECK_LINK_FLAG([-fsanitize=[]mysan], [
- AX_APPEND_FLAG([-fsanitize=[]mysan], [])
-dnl If and only if libtool is being used, LDFLAGS needs to contain -Wc,-fsanitize=….
-dnl See e.g. https://sources.debian.net/src/systemd/231-7/configure.ac/?hl=128#L135
-dnl TODO: how can recognize that situation and add -Wc,?
- AX_APPEND_FLAG([-fsanitize=[]mysan], [LDFLAGS])
-dnl TODO: add -fPIE -pie for memory
- # -fno-omit-frame-pointer results in nicer stack traces in error
- # messages, see http://clang.llvm.org/docs/AddressSanitizer.html#usage
- AX_CHECK_COMPILE_FLAG([-fno-omit-frame-pointer], [
- AX_APPEND_FLAG([-fno-omit-frame-pointer], [])])
-dnl TODO: at least for clang, we should specify exactly -O1, not -O2 or -O0, so that performance is reasonable but stacktraces are not tampered with (due to inlining), see http://clang.llvm.org/docs/AddressSanitizer.html#usage
- m4_default([$3], :)
- ax_enabled_sanitizers="[]mysan $ax_enabled_sanitizers"
- ])
- ])
-])
-])dnl
-])dnl AX_SANITIZERS
diff --git a/meson.build b/meson.build
new file mode 100644
index 00000000..0bf023f2
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,719 @@
+# -*- mode: meson -*-
+
+# Style objective: be consistent with what mesonbuild.com documents/uses, and/or
+# the meson book: https://meson-manual.com/
+
+project(
+ 'i3',
+ 'c',
+ version: '4.19',
+ default_options: [
+ 'c_std=c11',
+ 'warning_level=1', # enable all warnings (-Wall)
+ # TODO(https://github.com/i3/i3/issues/4087): switch to
+ # 'buildtype=debugoptimized',
+ ],
+ # Ubuntu 18.04 (supported until 2023) has meson 0.45.
+ # We can revisit our minimum supported meson version
+ # if it turns out to be too hard to maintain.
+ meson_version: '>=0.45.0',
+)
+
+cc = meson.get_compiler('c')
+add_project_arguments(cc.get_supported_arguments(['-Wunused-value']), language: 'c')
+
+if meson.version().version_compare('>=0.48.0')
+ # https://github.com/mesonbuild/meson/issues/2166#issuecomment-629696911
+ meson.add_dist_script('meson/meson-dist-script')
+else
+ message('meson <0.48.0 detected, dist tarballs will not be filtered')
+endif
+
+################################################################################
+# Version handling
+################################################################################
+
+cdata = configuration_data()
+
+version_array = meson.project_version().split('.')
+cdata.set('MAJOR_VERSION', version_array[0].to_int())
+cdata.set('MINOR_VERSION', version_array[1].to_int())
+if version_array.length() > 2
+ cdata.set('PATCH_VERSION', version_array[2].to_int())
+else
+ cdata.set('PATCH_VERSION', 0)
+endif
+cdata.set_quoted('I3_VERSION', '@VCS_TAG@')
+cdata.set_quoted('SYSCONFDIR', join_paths(get_option('prefix'), get_option('sysconfdir')))
+
+if get_option('b_sanitize').split(',').contains('address')
+ cdata.set('I3_ASAN_ENABLED', 1)
+endif
+
+cdata.set('HAVE_STRNDUP', cc.has_function('strndup'))
+cdata.set('HAVE_MKDIRP', cc.has_function('mkdirp'))
+
+# Instead of generating config.h directly, make vcs_tag generate it so that
+# @VCS_TAG@ is replaced.
+config_h_in = configure_file(
+ output: 'config.h.in',
+ configuration: cdata,
+)
+config_h = declare_dependency(
+ sources: vcs_tag(
+ input: config_h_in,
+ output: 'config.h',
+ fallback: meson.project_version() + '-non-git',
+ )
+)
+
+################################################################################
+# docs generation
+################################################################################
+
+docdir = get_option('docdir')
+if docdir == ''
+ docdir = join_paths(get_option('datadir'), 'doc', 'i3')
+endif
+
+if get_option('docs')
+ asciidoc = find_program('asciidoc')
+ doc_toc_inputs = [
+ 'docs/hacking-howto',
+ 'docs/userguide',
+ 'docs/ipc',
+ 'docs/multi-monitor',
+ 'docs/wsbar',
+ 'docs/testsuite',
+ 'docs/i3bar-protocol',
+ 'docs/layout-saving',
+ ]
+ foreach m : doc_toc_inputs
+ custom_target(
+ m.underscorify()+'_asciidoc',
+ input: m,
+ output: '@BASENAME@.html',
+ command: [
+ asciidoc,
+ '-a', 'toc',
+ '-n',
+ '-o', '@OUTPUT@',
+ '@INPUT@',
+ ],
+ install: true,
+ install_dir: docdir,
+ )
+ endforeach
+
+ doc_notoc_inputs = [
+ 'docs/debugging',
+ ]
+ foreach m : doc_notoc_inputs
+ custom_target(
+ m.underscorify()+'_asciidoc',
+ input: m,
+ output: '@BASENAME@.html',
+ command: [
+ asciidoc,
+ '-n',
+ '-o', '@OUTPUT@',
+ '@INPUT@',
+ ],
+ install: true,
+ install_dir: docdir,
+ )
+ endforeach
+
+else
+ if run_command('[', '-f', 'docs/hacking-howto.html', ']').returncode() == 0
+ install_data(
+ [
+ 'docs/hacking-howto.html',
+ 'docs/userguide.html',
+ 'docs/ipc.html',
+ 'docs/multi-monitor.html',
+ 'docs/wsbar.html',
+ 'docs/testsuite.html',
+ 'docs/i3bar-protocol.html',
+ 'docs/layout-saving.html',
+ 'docs/debugging.html',
+ ],
+ install_dir: docdir,
+ )
+ endif
+endif
+
+install_data(
+ [
+ 'docs/bigpicture.png',
+ 'docs/single_terminal.png',
+ 'docs/snapping.png',
+ 'docs/two_columns.png',
+ 'docs/two_terminals.png',
+ 'docs/modes.png',
+ 'docs/wsbar.png',
+ 'docs/keyboard-layer1.png',
+ 'docs/keyboard-layer2.png',
+ 'docs/i3-sync-working.png',
+ 'docs/i3-sync.png',
+ 'docs/tree-layout1.png',
+ 'docs/tree-layout2.png',
+ 'docs/tree-shot1.png',
+ 'docs/tree-shot2.png',
+ 'docs/tree-shot3.png',
+ 'docs/tree-shot4.png',
+ 'docs/refcard.html',
+ 'docs/refcard_style.css',
+ 'docs/logo-30.png',
+ 'docs/layout-saving-1.png',
+ ],
+ install_dir: docdir,
+)
+
+if meson.version().version_compare('>=0.53')
+ summary('build docs (-Ddocs)', get_option('docs'))
+endif
+
+################################################################################
+# manpages
+################################################################################
+
+man1 = join_paths(get_option('mandir'), 'man1')
+
+if get_option('mans')
+ asciidoc = find_program('asciidoc')
+ asciidoc_cdata = configuration_data()
+ asciidoc_cdata.set('PACKAGE_VERSION', meson.project_version())
+ asciidoc_conf = configure_file(
+ input: 'man/asciidoc.conf.in',
+ output: 'asciidoc.conf',
+ configuration: asciidoc_cdata,
+ )
+
+ xmlto = find_program('xmlto')
+
+ pod2man = find_program('pod2man')
+
+ man_inputs = [
+ 'man/i3.man',
+ 'man/i3bar.man',
+ 'man/i3-msg.man',
+ 'man/i3-input.man',
+ 'man/i3-nagbar.man',
+ 'man/i3-config-wizard.man',
+ 'man/i3-migrate-config-to-v4.man',
+ 'man/i3-sensible-editor.man',
+ 'man/i3-sensible-pager.man',
+ 'man/i3-sensible-terminal.man',
+ 'man/i3-dump-log.man',
+ ]
+
+ foreach m : man_inputs
+ xml = custom_target(
+ m.underscorify()+'_asciidoc',
+ input: m,
+ output: '@BASENAME@.xml',
+ command: [
+ asciidoc,
+ '-d', 'manpage',
+ '-b', 'docbook',
+ '-f', asciidoc_conf,
+ '-o', '@OUTPUT@',
+ '@INPUT@',
+ ],
+ )
+
+ custom_target(
+ m.underscorify()+'_xmlto',
+ input: xml,
+ output: '@BASENAME@.1',
+ command: [
+ xmlto,
+ 'man',
+ '-o',
+ '@OUTDIR@',
+ '@INPUT@',
+ ],
+ # We should use install and install_dir instead of install_man as per:
+ # https://github.com/mesonbuild/meson/issues/4981#issuecomment-467084867
+ # https://github.com/mesonbuild/meson/issues/1550#issuecomment-370164307
+ install: true,
+ install_dir: man1,
+ )
+ endforeach
+
+ pod2man_inputs = [
+ 'i3-dmenu-desktop',
+ 'i3-save-tree',
+ ]
+ foreach m : pod2man_inputs
+ custom_target(
+ m.underscorify()+'_pod2man',
+ input: m,
+ output: '@BASENAME@.1',
+ command: [
+ pod2man,
+ '--utf8',
+ '@INPUT@',
+ '@OUTPUT@',
+ ],
+ # We should use install and install_dir instead of install_man as per:
+ # https://github.com/mesonbuild/meson/issues/4981#issuecomment-467084867
+ # https://github.com/mesonbuild/meson/issues/1550#issuecomment-370164307
+ install: true,
+ install_dir: man1,
+ )
+ endforeach
+
+else
+ if run_command('[', '-f', 'man/i3.1', ']').returncode() == 0
+ install_data(
+ [
+ 'man/i3.1',
+ 'man/i3bar.1',
+ 'man/i3-msg.1',
+ 'man/i3-input.1',
+ 'man/i3-nagbar.1',
+ 'man/i3-config-wizard.1',
+ 'man/i3-migrate-config-to-v4.1',
+ 'man/i3-sensible-editor.1',
+ 'man/i3-sensible-pager.1',
+ 'man/i3-sensible-terminal.1',
+ 'man/i3-dump-log.1',
+ 'man/i3-dmenu-desktop.1',
+ 'man/i3-save-tree.1',
+ ],
+ install_dir: man1,
+ )
+ endif
+endif
+
+if meson.version().version_compare('>=0.53')
+ summary('build manpages (-Dmans)', get_option('mans'))
+endif
+
+# Required for e.g. struct ucred to be defined as per unix(7).
+add_project_arguments('-D_GNU_SOURCE', language: 'c')
+
+# https://mesonbuild.com/howtox.html#add-math-library-lm-portably
+m_dep = cc.find_library('m', required: false)
+rt_dep = cc.find_library('rt', required: false)
+iconv_dep = cc.find_library('iconv', required: false)
+
+libsn_dep = dependency('libstartup-notification-1.0', method: 'pkg-config')
+xcb_dep = dependency('xcb', method: 'pkg-config')
+xcb_xkb_dep = dependency('xcb-xkb', method: 'pkg-config')
+xcb_xinerama_dep = dependency('xcb-xinerama', method: 'pkg-config')
+xcb_randr_dep = dependency('xcb-randr', method: 'pkg-config')
+xcb_shape_dep = dependency('xcb-shape', method: 'pkg-config')
+xcb_util_dep = dependency('xcb-util', method: 'pkg-config')
+xcb_util_cursor_dep = dependency('xcb-cursor', method: 'pkg-config')
+xcb_util_keysyms_dep = dependency('xcb-keysyms', method: 'pkg-config')
+xcb_util_wm_dep = dependency('xcb-icccm', method: 'pkg-config')
+xcb_util_xrm_dep = dependency('xcb-xrm', method: 'pkg-config')
+xkbcommon_dep = dependency('xkbcommon', method: 'pkg-config')
+xkbcommon_x11_dep = dependency('xkbcommon-x11', method: 'pkg-config')
+yajl_dep = dependency('yajl', method: 'pkg-config')
+libpcre_dep = dependency('libpcre', version: '>=8.10', method: 'pkg-config')
+cairo_dep = dependency('cairo', version: '>=1.14.4', method: 'pkg-config')
+pangocairo_dep = dependency('pangocairo', method: 'pkg-config')
+glib_dep = dependency('glib-2.0', method: 'pkg-config')
+gobject_dep = dependency('gobject-2.0', method: 'pkg-config')
+
+ev_dep = cc.find_library('ev')
+
+inc = include_directories('include')
+
+libi3srcs = [
+ 'libi3/dpi.c',
+ 'libi3/draw_util.c',
+ 'libi3/fake_configure_notify.c',
+ 'libi3/font.c',
+ 'libi3/format_placeholders.c',
+ 'libi3/get_colorpixel.c',
+ 'libi3/get_config_path.c',
+ 'libi3/get_exe_path.c',
+ 'libi3/get_mod_mask.c',
+ 'libi3/get_process_filename.c',
+ 'libi3/get_visualtype.c',
+ 'libi3/g_utf8_make_valid.c',
+ 'libi3/ipc_connect.c',
+ 'libi3/ipc_recv_message.c',
+ 'libi3/ipc_send_message.c',
+ 'libi3/is_debug_build.c',
+ 'libi3/resolve_tilde.c',
+ 'libi3/root_atom_contents.c',
+ 'libi3/safewrappers.c',
+ 'libi3/string.c',
+ 'libi3/ucs2_conversion.c',
+]
+
+if not cdata.get('HAVE_STRNDUP')
+ libi3srcs += 'libi3/strndup.c'
+endif
+
+if not cdata.get('HAVE_MKDIRP')
+ libi3srcs += 'libi3/mkdirp.c'
+endif
+
+libi3 = static_library(
+ 'i3',
+ libi3srcs,
+ include_directories: inc,
+ dependencies: [
+ pangocairo_dep,
+ config_h,
+ ],
+)
+
+i3srcs = [
+ 'src/assignments.c',
+ 'src/bindings.c',
+ 'src/click.c',
+ 'src/commands.c',
+ 'src/commands_parser.c',
+ 'src/con.c',
+ 'src/config.c',
+ 'src/config_directives.c',
+ 'src/config_parser.c',
+ 'src/display_version.c',
+ 'src/drag.c',
+ 'src/ewmh.c',
+ 'src/fake_outputs.c',
+ 'src/floating.c',
+ 'src/handlers.c',
+ 'src/ipc.c',
+ 'src/key_press.c',
+ 'src/load_layout.c',
+ 'src/log.c',
+ 'src/main.c',
+ 'src/manage.c',
+ 'src/match.c',
+ 'src/move.c',
+ 'src/output.c',
+ 'src/randr.c',
+ 'src/regex.c',
+ 'src/render.c',
+ 'src/resize.c',
+ 'src/restore_layout.c',
+ 'src/scratchpad.c',
+ 'src/sd-daemon.c',
+ 'src/sighandler.c',
+ 'src/startup.c',
+ 'src/sync.c',
+ 'src/tree.c',
+ 'src/util.c',
+ 'src/version.c',
+ 'src/window.c',
+ 'src/workspace.c',
+ 'src/x.c',
+ 'src/xcb.c',
+ 'src/xcursor.c',
+ 'src/xinerama.c',
+]
+
+# Verify the perl interpreter is present for running parser_gen,
+# ensuring a good error message when it isn’t:
+perl = find_program('perl')
+parser_gen = find_program('generate-command-parser.pl')
+
+command_parser = custom_target(
+ 'command_parser',
+ input: 'parser-specs/commands.spec',
+ output: [
+ 'GENERATED_command_enums.h',
+ 'GENERATED_command_tokens.h',
+ 'GENERATED_command_call.h',
+ ],
+ command: [perl, parser_gen, '--input=@INPUT@', '--prefix=command'],
+)
+
+i3srcs += command_parser
+
+config_parser = custom_target(
+ 'config_parser',
+ input: 'parser-specs/config.spec',
+ output: [
+ 'GENERATED_config_enums.h',
+ 'GENERATED_config_tokens.h',
+ 'GENERATED_config_call.h',
+ ],
+ command: [parser_gen, '--input=@INPUT@', '--prefix=config'],
+)
+
+i3srcs += config_parser
+
+# src/log.c uses threading primitives for synchronization
+thread_dep = dependency('threads')
+
+common_deps = [
+ thread_dep,
+ m_dep,
+ iconv_dep,
+ rt_dep,
+ libsn_dep,
+ xcb_dep,
+ xcb_xkb_dep,
+ xcb_xinerama_dep,
+ xcb_randr_dep,
+ xcb_shape_dep,
+ xcb_util_dep,
+ xcb_util_cursor_dep,
+ xcb_util_keysyms_dep,
+ xcb_util_wm_dep,
+ xcb_util_xrm_dep,
+ xkbcommon_dep,
+ xkbcommon_x11_dep,
+ yajl_dep,
+ libpcre_dep,
+ cairo_dep,
+ pangocairo_dep,
+ glib_dep,
+ gobject_dep,
+ ev_dep,
+ config_h,
+]
+
+executable(
+ 'i3',
+ i3srcs,
+ install: true,
+ include_directories: inc,
+ dependencies: common_deps,
+ link_with: libi3,
+)
+
+# This is the only currently working way of installing a symbolic link:
+meson.add_install_script(
+ 'meson/meson-install-i3-with-shmlog',
+ get_option('bindir'),
+)
+
+executable(
+ 'i3bar',
+ [
+ 'i3bar/src/child.c',
+ 'i3bar/src/config.c',
+ 'i3bar/src/ipc.c',
+ 'i3bar/src/main.c',
+ 'i3bar/src/mode.c',
+ 'i3bar/src/outputs.c',
+ 'i3bar/src/parse_json_header.c',
+ 'i3bar/src/workspaces.c',
+ 'i3bar/src/xcb.c',
+ ],
+ install: true,
+ include_directories: include_directories('include', 'i3bar/include'),
+ dependencies: common_deps,
+ link_with: libi3,
+)
+
+executable(
+ 'i3-config-wizard',
+ [
+ 'i3-config-wizard/i3-config-wizard-atoms.xmacro.h',
+ 'i3-config-wizard/main.c',
+ 'i3-config-wizard/xcb.h',
+ ],
+ install: true,
+ include_directories: include_directories('include', 'i3-config-wizard'),
+ dependencies: common_deps,
+ link_with: libi3,
+)
+
+executable(
+ 'i3-dump-log',
+ 'i3-dump-log/main.c',
+ install: true,
+ include_directories: inc,
+ dependencies: common_deps,
+ link_with: libi3,
+)
+
+executable(
+ 'i3-input',
+ [
+ 'i3-input/i3-input.h',
+ 'i3-input/keysym2ucs.h',
+ 'i3-input/keysym2ucs.c',
+ 'i3-input/main.c',
+ ],
+ install: true,
+ include_directories: inc,
+ dependencies: common_deps,
+ link_with: libi3,
+)
+
+executable(
+ 'i3-msg',
+ 'i3-msg/main.c',
+ install: true,
+ include_directories: inc,
+ dependencies: common_deps,
+ link_with: libi3,
+)
+
+executable(
+ 'i3-nagbar',
+ [
+ 'i3-nagbar/i3-nagbar-atoms.xmacro.h',
+ 'i3-nagbar/main.c',
+ ],
+ install: true,
+ include_directories: include_directories('include', 'i3-nagbar'),
+ dependencies: common_deps,
+ link_with: libi3,
+)
+
+install_data(
+ [
+ 'i3-dmenu-desktop',
+ 'i3-migrate-config-to-v4',
+ 'i3-save-tree',
+ 'i3-sensible-editor',
+ 'i3-sensible-pager',
+ 'i3-sensible-terminal',
+ ],
+ install_dir: 'bin',
+)
+
+install_subdir(
+ 'etc',
+ strip_directory: true,
+ install_dir: join_paths(get_option('sysconfdir'), 'i3'),
+)
+
+install_subdir(
+ 'share/',
+ strip_directory: true,
+ install_dir: get_option('datadir'),
+)
+
+install_headers(
+ 'include/i3/ipc.h',
+ subdir: 'i3',
+)
+
+# We cannot use configure_file for complete-run.pl.in and i3test.pm.in
+# because configure_file strips the backslash in e.g. \@display,
+# resulting in @display, breaking our Perl code:
+# https://github.com/mesonbuild/meson/issues/7165
+bash = find_program('bash')
+replace_dirs = [
+ bash, '-c', # Use bash to capture output and mark as executable
+ 'sed -e \'s,@abs_top_builddir@,'
+ + meson.current_build_dir()
+ + ',g;s,@abs_top_srcdir@,'
+ + meson.current_source_dir()+',g\''
+ # Only mark files ending in .pl as executables
+ + ' "$0" > "$1" && { [[ "${1##*.}" == pl ]] && chmod +x "$1" || true; }',
+ '@INPUT0@', # $0
+ '@OUTPUT0@', # $1
+]
+complete_run = custom_target(
+ 'complete-run',
+ input: ['testcases/complete-run.pl.in'],
+ output: ['complete-run.pl'],
+ command: replace_dirs,
+ # build this target when running e.g. ninja or ninja test.
+ # This is required for older meson versions (< 0.46.0).
+ build_by_default: true,
+)
+i3test_pm = custom_target(
+ 'i3test-pm',
+ input: ['testcases/lib/i3test.pm.in'],
+ output: ['i3test.pm'],
+ command: replace_dirs,
+ # build this target when running e.g. ninja or ninja test.
+ # This is required for older meson versions (< 0.46.0).
+ build_by_default: true,
+)
+
+if get_option('docs')
+ i3_pod2html = find_program('docs/i3-pod2html')
+
+ custom_target(
+ 'lib-i3test.html',
+ input: i3test_pm,
+ output: 'lib-i3test.html',
+ command: [
+ i3_pod2html,
+ '@INPUT@',
+ '@OUTPUT@',
+ ],
+ install: true,
+ install_dir: join_paths(get_option('datadir'), 'doc', 'i3'),
+ )
+
+ custom_target(
+ 'lib-i3test-test.html',
+ input: 'testcases/lib/i3test/Test.pm',
+ output: 'lib-i3test-test.html',
+ command: [
+ i3_pod2html,
+ '@INPUT@',
+ '@OUTPUT@',
+ ],
+ install: true,
+ install_dir: join_paths(get_option('datadir'), 'doc', 'i3'),
+ )
+endif
+
+executable(
+ 'test.inject_randr15',
+ 'testcases/inject_randr1.5.c',
+ include_directories: inc,
+ dependencies: common_deps,
+ link_with: libi3,
+)
+
+executable(
+ 'test.commands_parser',
+ 'src/commands_parser.c',
+ include_directories: inc,
+ c_args: '-DTEST_PARSER',
+ dependencies: common_deps,
+ link_with: libi3,
+)
+
+executable(
+ 'test.config_parser',
+ 'src/config_parser.c',
+ include_directories: inc,
+ c_args: '-DTEST_PARSER',
+ dependencies: common_deps,
+ link_with: libi3,
+)
+
+anyevent_i3 = custom_target(
+ 'anyevent-i3',
+ # Should be AnyEvent-I3/blib/lib/AnyEvent/I3.pm,
+ # but see https://github.com/mesonbuild/meson/issues/2320
+ output: 'AnyEvent-I3.stamp',
+ command: [
+ 'sh',
+ '-c',
+ 'cp -r @0@/AnyEvent-I3 . && cd AnyEvent-I3 && perl Makefile.PL && make && touch ../AnyEvent-I3.stamp'.format(meson.current_source_dir()),
+ ],
+)
+
+if meson.version().version_compare('>=0.46.0')
+ test(
+ 'complete-run',
+ perl,
+ args: [complete_run],
+ depends: [
+ anyevent_i3,
+ i3test_pm,
+ ],
+ )
+else
+ # meson < 0.46.0 does not support the depends arg in test targets.
+ # Just hope for the best.
+ test(
+ 'complete-run',
+ perl,
+ args: [complete_run],
+ )
+ message('meson < 0.46 detected, you might need to run ninja test twice')
+endif
diff --git a/meson/meson-dist-script b/meson/meson-dist-script
new file mode 100755
index 00000000..47d9ce36
--- /dev/null
+++ b/meson/meson-dist-script
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+set -eu
+
+cd "${MESON_DIST_ROOT}"
+
+# Delete everything we do not want to have in the release tarballs:
+rm -rf \
+ contrib/banner.svg \
+ contrib/show-download-count.sh \
+ contrib/sticker-7x5cm-stickma.tif.lzma \
+ contrib/sticker_stickma_black.svg \
+ debian/ \
+ docs/GPN-2009-06-27/ \
+ docs/NoName-2009-03-12/ \
+ docs/slides-2012-01-25/ \
+ docs/slides-2012-03-16/ \
+ testcases/.gitignore \
+ travis/ \
+ .clang-format \
+ .editorconfig \
+ i3bar/.gitignore \
+ .travis.yml \
+ logo.svg \
+ README.md \
+ RELEASE-NOTES-next \
+ release.sh
+
+mkdir build
+cd build
+meson .. -Dprefix=/usr -Ddocs=true -Dmans=true
+ninja
+cp *.1 ../man/
+cp *.html ../docs/
+cd ..
+rm -rf build
diff --git a/meson/meson-install-i3-with-shmlog b/meson/meson-install-i3-with-shmlog
new file mode 100755
index 00000000..2290a47a
--- /dev/null
+++ b/meson/meson-install-i3-with-shmlog
@@ -0,0 +1,2 @@
+#!/bin/sh
+ln -sf "i3" "${MESON_INSTALL_DESTDIR_PREFIX}/$1/i3-with-shmlog"
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 00000000..0c4d4cfb
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,10 @@
+# -*- mode: meson -*-
+
+option('docs', type: 'boolean', value: false,
+ description: 'Build documentation from source (release tarballs contain a generated copy)')
+
+option('mans', type: 'boolean', value: false,
+ description: 'Build manpages from source (release tarballs contain a generated copy)')
+
+option('docdir', type: 'string', value: '',
+ description: 'documentation directory (default: $datadir/docs/i3)')
diff --git a/parser-specs/commands.spec b/parser-specs/commands.spec
index ed9cf0f2..4db81680 100644
--- a/parser-specs/commands.spec
+++ b/parser-specs/commands.spec
@@ -131,7 +131,7 @@ state WORKSPACE:
-> call cmd_workspace_back_and_forth()
'number'
-> WORKSPACE_NUMBER
- workspace = string
+ workspace = string
-> call cmd_workspace_name($workspace, $no_auto_back_and_forth)
state WORKSPACE_NUMBER:
@@ -321,14 +321,15 @@ state RENAME_WORKSPACE_TO_NEW_NAME:
new_name = string
-> call cmd_rename_workspace($old_name, $new_name)
-# move <direction> [<pixels> [px]]
+
+# move <direction> [<amount> [px|ppt]]
# move [window|container] [to] workspace [<str>|next|prev|next_on_output|prev_on_output|current]
# move [window|container] [to] output <str>
# move [window|container] [to] mark <str>
# move [window|container] [to] scratchpad
# move workspace to [output] <str>
# move scratchpad
-# move [window|container] [to] [absolute] position [ [<pixels> [px] <pixels> [px]] | center ]
+# move [window|container] [to] [absolute] position [ [<pos_x> [px|ppt] <pos_y> [px|ppt] ] | center ]
# move [window|container] [to] position mouse|cursor|pointer
state MOVE:
'window'
@@ -355,16 +356,16 @@ state MOVE:
-> MOVE_TO_ABSOLUTE_POSITION
state MOVE_DIRECTION:
- pixels = number
- -> MOVE_DIRECTION_PX
+ amount = number
+ -> MOVE_DIRECTION_NUMBER
end
- -> call cmd_move_direction($direction, 10)
+ -> call cmd_move_direction($direction, 10, "px")
-state MOVE_DIRECTION_PX:
- 'px'
- -> call cmd_move_direction($direction, &pixels)
+state MOVE_DIRECTION_NUMBER:
+ mode = 'px', 'ppt'
+ -> call cmd_move_direction($direction, &amount, $mode)
end
- -> call cmd_move_direction($direction, &pixels)
+ -> call cmd_move_direction($direction, &amount, "px")
state MOVE_WORKSPACE:
'to '
@@ -409,14 +410,16 @@ state MOVE_TO_POSITION:
-> MOVE_TO_POSITION_X
state MOVE_TO_POSITION_X:
- 'px'
+ mode_x = 'px', 'ppt'
->
coord_y = number
-> MOVE_TO_POSITION_Y
state MOVE_TO_POSITION_Y:
- 'px', end
- -> call cmd_move_window_to_position(&coord_x, &coord_y)
+ mode_y = 'px', 'ppt'
+ -> call cmd_move_window_to_position(&coord_x, $mode_x, &coord_y, $mode_y)
+ end
+ -> call cmd_move_window_to_position(&coord_x, $mode_x, &coord_y, 0)
# mode <string>
state MODE:
@@ -454,21 +457,27 @@ state TITLE_FORMAT:
# bar (hidden_state hide|show|toggle)|(mode dock|hide|invisible|toggle) [<bar_id>]
state BAR:
- bar_type = 'hidden_state'
+ 'hidden_state'
-> BAR_HIDDEN_STATE
- bar_type = 'mode'
+ 'mode'
-> BAR_MODE
state BAR_HIDDEN_STATE:
bar_value = 'hide', 'show', 'toggle'
- -> BAR_W_ID
+ -> BAR_HIDDEN_STATE_ID
+
+state BAR_HIDDEN_STATE_ID:
+ bar_id = word
+ ->
+ end
+ -> call cmd_bar_hidden_state($bar_value, $bar_id)
state BAR_MODE:
bar_value = 'dock', 'hide', 'invisible', 'toggle'
- -> BAR_W_ID
+ -> BAR_MODE_ID
-state BAR_W_ID:
+state BAR_MODE_ID:
bar_id = word
->
end
- -> call cmd_bar($bar_type, $bar_value, $bar_id)
+ -> call cmd_bar_mode($bar_value, $bar_id)
diff --git a/parser-specs/config.spec b/parser-specs/config.spec
index 93901fd9..bb9e226e 100644
--- a/parser-specs/config.spec
+++ b/parser-specs/config.spec
@@ -181,16 +181,18 @@ state NO_FOCUS_END:
# Criteria: Used by for_window and assign.
state CRITERIA:
- ctype = 'class' -> CRITERION
- ctype = 'instance' -> CRITERION
- ctype = 'window_role' -> CRITERION
- ctype = 'con_id' -> CRITERION
- ctype = 'id' -> CRITERION
- ctype = 'window_type' -> CRITERION
- ctype = 'con_mark' -> CRITERION
- ctype = 'title' -> CRITERION
- ctype = 'urgent' -> CRITERION
- ctype = 'workspace' -> CRITERION
+ ctype = 'class' -> CRITERION
+ ctype = 'instance' -> CRITERION
+ ctype = 'window_role' -> CRITERION
+ ctype = 'con_id' -> CRITERION
+ ctype = 'id' -> CRITERION
+ ctype = 'window_type' -> CRITERION
+ ctype = 'con_mark' -> CRITERION
+ ctype = 'title' -> CRITERION
+ ctype = 'urgent' -> CRITERION
+ ctype = 'workspace' -> CRITERION
+ ctype = 'floating_from' -> CRITERION_FROM
+ ctype = 'tiling_from' -> CRITERION_FROM
ctype = 'tiling', 'floating'
-> call cfg_criteria_add($ctype, NULL); CRITERIA
']'
@@ -199,6 +201,22 @@ state CRITERIA:
state CRITERION:
'=' -> CRITERION_STR
+state CRITERION_FROM:
+ '=' -> CRITERION_FROM_STR_START
+
+state CRITERION_FROM_STR_START:
+ '"' -> CRITERION_FROM_STR
+ kind = 'auto', 'user'
+ -> call cfg_criteria_add($ctype, $kind); CRITERIA
+
+state CRITERION_FROM_STR:
+ kind = 'auto', 'user'
+ -> CRITERION_FROM_STR_END
+
+state CRITERION_FROM_STR_END:
+ '"'
+ -> call cfg_criteria_add($ctype, $kind); CRITERIA
+
state CRITERION_STR:
cvalue = word
-> call cfg_criteria_add($ctype, $cvalue); CRITERIA
diff --git a/release.sh b/release.sh
index 095bc50b..c6b045c0 100755
--- a/release.sh
+++ b/release.sh
@@ -1,8 +1,8 @@
#!/bin/zsh
# This script is used to prepare a new release of i3.
-export RELEASE_VERSION="4.17"
-export PREVIOUS_VERSION="4.16"
+export RELEASE_VERSION="4.19"
+export PREVIOUS_VERSION="4.18"
export RELEASE_BRANCH="next"
if [ ! -e "../i3.github.io" ]
@@ -55,49 +55,43 @@ git checkout -b release-${RELEASE_VERSION}
cp "${STARTDIR}/RELEASE-NOTES-${RELEASE_VERSION}" "RELEASE-NOTES-${RELEASE_VERSION}"
git add RELEASE-NOTES-${RELEASE_VERSION}
git rm RELEASE-NOTES-${PREVIOUS_VERSION}
-sed -i "s,RELEASE-NOTES-${PREVIOUS_VERSION},RELEASE-NOTES-${RELEASE_VERSION},g" Makefile.am
-sed -i "s/AC_INIT(\[i3\], \[${PREVIOUS_VERSION}\]/AC_INIT([i3], [${RELEASE_VERSION}]/" configure.ac
-echo "${RELEASE_VERSION} ($(date +%F))" > I3_VERSION
-git add I3_VERSION
+sed -i "s/^\s*version: '${PREVIOUS_VERSION}'/ version: '${RELEASE_VERSION}'/" meson.build
git commit -a -m "release i3 ${RELEASE_VERSION}"
git tag "${RELEASE_VERSION}" -m "release i3 ${RELEASE_VERSION}" --sign --local-user=0x4AC8EE1D
-autoreconf -fi
mkdir build
-(cd build && ../configure && make dist-bzip2 -j8)
-cp build/i3-${RELEASE_VERSION}.tar.bz2 .
+(cd build && meson .. && ninja dist)
+cp build/meson-build/i3-${RELEASE_VERSION}.tar.xz .
echo "Differences in the release tarball file lists:"
-diff -u \
- <(tar tf ../i3-${PREVIOUS_VERSION}.tar.bz2 | sed "s,i3-${PREVIOUS_VERSION}/,,g" | sort) \
- <(tar tf i3-${RELEASE_VERSION}.tar.bz2 | sed "s,i3-${RELEASE_VERSION}/,,g" | sort) \
- | colordiff
-
+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)
-gpg --armor -b i3-${RELEASE_VERSION}.tar.bz2
+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."
-if [ "${RELEASE_BRANCH}" = "master" ]; then
- git checkout master
+if [ "${RELEASE_BRANCH}" = "stable" ]; then
+ git checkout stable
git merge --no-ff release-${RELEASE_VERSION} -m "Merge branch 'release-${RELEASE_VERSION}'"
git checkout next
- git merge --no-ff -s recursive -X ours -X no-renames master -m "Merge branch 'master' into next"
+ git merge --no-ff -s recursive -X ours -X no-renames stable -m "Merge branch 'stable' into next"
else
git checkout next
git merge --no-ff release-${RELEASE_VERSION} -m "Merge branch 'release-${RELEASE_VERSION}'"
- git checkout master
- git merge --no-ff -s recursive -X theirs -X no-renames next -m "Merge branch 'next' into master"
+ git checkout stable
+ git merge --no-ff -s recursive -X theirs -X no-renames next -m "Merge branch 'next' into stable"
fi
git remote remove origin
git remote add origin git@github.com:i3/i3.git
git config --add remote.origin.push "+refs/tags/*:refs/tags/*"
git config --add remote.origin.push "+refs/heads/next:refs/heads/next"
-git config --add remote.origin.push "+refs/heads/master:refs/heads/master"
+git config --add remote.origin.push "+refs/heads/stable:refs/heads/stable"
################################################################################
# Section 2: Debian packaging
@@ -115,9 +109,9 @@ cat > ${TMPDIR}/Dockerfile <<EOT
FROM debian:sid
RUN sed -i 's,^deb \(.*\),deb \1\ndeb-src \1,g' /etc/apt/sources.list
RUN apt-get update && apt-get install -y dpkg-dev devscripts
-COPY i3/i3-${RELEASE_VERSION}.tar.bz2 /usr/src/i3-wm_${RELEASE_VERSION}.orig.tar.bz2
+COPY i3/i3-${RELEASE_VERSION}.tar.xz /usr/src/i3-wm_${RELEASE_VERSION}.orig.tar.xz
WORKDIR /usr/src/
-RUN tar xf i3-wm_${RELEASE_VERSION}.orig.tar.bz2
+RUN tar xf i3-wm_${RELEASE_VERSION}.orig.tar.xz
WORKDIR /usr/src/i3-${RELEASE_VERSION}
COPY i3/debian /usr/src/i3-${RELEASE_VERSION}/debian/
RUN mkdir debian/source
@@ -130,7 +124,7 @@ RUN dpkg-buildpackage -S -sa -j8
EOT
CONTAINER_NAME=$(echo "i3-${TMPDIR}" | sed 's,/,,g')
-docker build -t i3 .
+docker build --no-cache -t i3 .
for file in $(docker run --name "${CONTAINER_NAME}" i3 /bin/sh -c "ls /usr/src/i3*_${RELEASE_VERSION}*")
do
docker cp "${CONTAINER_NAME}:${file}" ${TMPDIR}/debian/
@@ -161,14 +155,14 @@ tar cf - '--exclude=[0-9]\.[0-9e]*' docs | tar xf - --strip-components=1 -C docs
git add docs/${PREVIOUS_VERSION}
git commit -a -m "save docs for ${PREVIOUS_VERSION}"
-cp ${TMPDIR}/i3/i3-${RELEASE_VERSION}.tar.bz2* downloads/
-git add downloads/i3-${RELEASE_VERSION}.tar.bz2*
+cp ${TMPDIR}/i3/i3-${RELEASE_VERSION}.tar.xz* downloads/
+git add downloads/i3-${RELEASE_VERSION}.tar.xz*
cp ${TMPDIR}/i3/RELEASE-NOTES-${RELEASE_VERSION} downloads/RELEASE-NOTES-${RELEASE_VERSION}.txt
git add downloads/RELEASE-NOTES-${RELEASE_VERSION}.txt
sed -i "s,<h2>Documentation for i3 v[^<]*</h2>,<h2>Documentation for i3 v${RELEASE_VERSION}</h2>,g" docs/index.html
sed -i "s,<span style=\"margin-left: 2em; color: #c0c0c0\">[^<]*</span>,<span style=\"margin-left: 2em; color: #c0c0c0\">${RELEASE_VERSION}</span>,g" index.html
sed -i "s,The current stable version is .*$,The current stable version is ${RELEASE_VERSION}.,g" downloads/index.html
-sed -i "s,<tbody>,<tbody>\n <tr>\n <td>${RELEASE_VERSION}</td>\n <td><a href=\"/downloads/i3-${RELEASE_VERSION}.tar.bz2\">i3-${RELEASE_VERSION}.tar.bz2</a></td>\n <td>$(LC_ALL=en_US.UTF-8 ls -lh ../i3/i3-${RELEASE_VERSION}.tar.bz2 | awk -F " " {'print $5'} | sed 's/K$/ KiB/g' | sed 's/M$/ MiB/g')</td>\n <td><a href=\"/downloads/i3-${RELEASE_VERSION}.tar.bz2.asc\">signature</a></td>\n <td>$(date +'%Y-%m-%d')</td>\n <td><a href=\"/downloads/RELEASE-NOTES-${RELEASE_VERSION}.txt\">release notes</a></td>\n </tr>\n,g" downloads/index.html
+sed -i "s,<tbody>,<tbody>\n <tr>\n <td>${RELEASE_VERSION}</td>\n <td><a href=\"/downloads/i3-${RELEASE_VERSION}.tar.xz\">i3-${RELEASE_VERSION}.tar.xz</a></td>\n <td>$(LC_ALL=en_US.UTF-8 ls -lh ../i3/i3-${RELEASE_VERSION}.tar.xz | awk -F " " {'print $5'} | sed 's/K$/ KiB/g' | sed 's/M$/ MiB/g')</td>\n <td><a href=\"/downloads/i3-${RELEASE_VERSION}.tar.xz.asc\">signature</a></td>\n <td>$(date +'%Y-%m-%d')</td>\n <td><a href=\"/downloads/RELEASE-NOTES-${RELEASE_VERSION}.txt\">release notes</a></td>\n </tr>\n,g" downloads/index.html
git commit -a -m "add ${RELEASE_VERSION} release"
diff --git a/src/assignments.c b/src/assignments.c
index 998ca78a..8e2ee883 100644
--- a/src/assignments.c
+++ b/src/assignments.c
@@ -21,7 +21,7 @@ void run_assignments(i3Window *window) {
/* Check if any assignments match */
Assignment *current;
- TAILQ_FOREACH(current, &assignments, assignments) {
+ TAILQ_FOREACH (current, &assignments, assignments) {
if (current->type != A_COMMAND || !match_matches_window(&(current->match), window))
continue;
@@ -69,7 +69,7 @@ void run_assignments(i3Window *window) {
Assignment *assignment_for(i3Window *window, int type) {
Assignment *assignment;
- TAILQ_FOREACH(assignment, &assignments, assignments) {
+ TAILQ_FOREACH (assignment, &assignments, assignments) {
if ((type != A_ANY && (assignment->type & type) == 0) ||
!match_matches_window(&(assignment->match), window))
continue;
diff --git a/src/bindings.c b/src/bindings.c
index f2921a14..d6255e73 100644
--- a/src/bindings.c
+++ b/src/bindings.c
@@ -8,8 +8,10 @@
*/
#include "all.h"
-#include <xkbcommon/xkbcommon.h>
+#include <math.h>
+
#include <xkbcommon/xkbcommon-x11.h>
+#include <xkbcommon/xkbcommon.h>
static struct xkb_context *xkb_context;
static struct xkb_keymap *xkb_keymap;
@@ -31,7 +33,7 @@ static struct Mode *mode_from_name(const char *name, bool pango_markup) {
struct Mode *mode;
/* Try to find the mode in the list of modes and return it */
- SLIST_FOREACH(mode, &modes, modes) {
+ SLIST_FOREACH (mode, &modes, modes) {
if (strcmp(mode->name, name) == 0) {
return mode;
}
@@ -146,7 +148,7 @@ static void grab_keycode_for_binding(xcb_connection_t *conn, Binding *bind, uint
*/
void grab_all_keys(xcb_connection_t *conn) {
Binding *bind;
- TAILQ_FOREACH(bind, bindings, bindings) {
+ TAILQ_FOREACH (bind, bindings, bindings) {
if (bind->input_type != B_KEYBOARD)
continue;
@@ -160,7 +162,7 @@ void grab_all_keys(xcb_connection_t *conn) {
}
struct Binding_Keycode *binding_keycode;
- TAILQ_FOREACH(binding_keycode, &(bind->keycodes_head), keycodes) {
+ TAILQ_FOREACH (binding_keycode, &(bind->keycodes_head), keycodes) {
const int keycode = binding_keycode->keycode;
const int mods = (binding_keycode->modifiers & 0xFFFF);
DLOG("Binding %p Grabbing keycode %d with mods %d\n", bind, keycode, mods);
@@ -179,7 +181,7 @@ void regrab_all_buttons(xcb_connection_t *conn) {
xcb_grab_server(conn);
Con *con;
- TAILQ_FOREACH(con, &all_cons, all_cons) {
+ TAILQ_FOREACH (con, &all_cons, all_cons) {
if (con->window == NULL)
continue;
@@ -203,7 +205,7 @@ static Binding *get_binding(i3_event_state_mask_t state_filtered, bool is_releas
if (!is_release) {
/* On a press event, we first reset all B_UPON_KEYRELEASE_IGNORE_MODS
* bindings back to B_UPON_KEYRELEASE */
- TAILQ_FOREACH(bind, bindings, bindings) {
+ TAILQ_FOREACH (bind, bindings, bindings) {
if (bind->input_type != input_type)
continue;
if (bind->release == B_UPON_KEYRELEASE_IGNORE_MODS)
@@ -213,7 +215,7 @@ static Binding *get_binding(i3_event_state_mask_t state_filtered, bool is_releas
const uint32_t xkb_group_state = (state_filtered & 0xFFFF0000);
const uint32_t modifiers_state = (state_filtered & 0x0000FFFF);
- TAILQ_FOREACH(bind, bindings, bindings) {
+ TAILQ_FOREACH (bind, bindings, bindings) {
if (bind->input_type != input_type) {
continue;
}
@@ -232,7 +234,7 @@ static Binding *get_binding(i3_event_state_mask_t state_filtered, bool is_releas
if (input_type == B_KEYBOARD && bind->symbol != NULL) {
xcb_keycode_t input_keycode = (xcb_keycode_t)input_code;
struct Binding_Keycode *binding_keycode;
- TAILQ_FOREACH(binding_keycode, &(bind->keycodes_head), keycodes) {
+ TAILQ_FOREACH (binding_keycode, &(bind->keycodes_head), keycodes) {
const uint32_t modifiers_mask = (binding_keycode->modifiers & 0x0000FFFF);
const bool mods_match = (modifiers_mask == modifiers_state);
DLOG("binding_keycode->modifiers = %d, modifiers_mask = %d, modifiers_state = %d, mods_match = %s\n",
@@ -250,7 +252,7 @@ static Binding *get_binding(i3_event_state_mask_t state_filtered, bool is_releas
}
struct Binding_Keycode *binding_keycode;
- TAILQ_FOREACH(binding_keycode, &(bind->keycodes_head), keycodes) {
+ TAILQ_FOREACH (binding_keycode, &(bind->keycodes_head), keycodes) {
const uint32_t modifiers_mask = (binding_keycode->modifiers & 0x0000FFFF);
const bool mods_match = (modifiers_mask == modifiers_state);
DLOG("binding_keycode->modifiers = %d, modifiers_mask = %d, modifiers_state = %d, mods_match = %s\n",
@@ -445,7 +447,7 @@ void translate_keysyms(void) {
}
Binding *bind;
- TAILQ_FOREACH(bind, bindings, bindings) {
+ TAILQ_FOREACH (bind, bindings, bindings) {
if (bind->input_type == B_MOUSE) {
long button;
if (!parse_long(bind->symbol + (sizeof("button") - 1), &button, 10)) {
@@ -571,7 +573,7 @@ void translate_keysyms(void) {
char *keycodes = sstrdup("");
int num_keycodes = 0;
struct Binding_Keycode *binding_keycode;
- TAILQ_FOREACH(binding_keycode, &(bind->keycodes_head), keycodes) {
+ TAILQ_FOREACH (binding_keycode, &(bind->keycodes_head), keycodes) {
char *tmp;
sasprintf(&tmp, "%s %d", keycodes, binding_keycode->keycode);
free(keycodes);
@@ -580,7 +582,7 @@ void translate_keysyms(void) {
/* check for duplicate bindings */
Binding *check;
- TAILQ_FOREACH(check, bindings, bindings) {
+ TAILQ_FOREACH (check, bindings, bindings) {
if (check == bind)
continue;
if (check->symbol != NULL)
@@ -620,19 +622,20 @@ void switch_mode(const char *new_mode) {
DLOG("Switching to mode %s\n", new_mode);
- SLIST_FOREACH(mode, &modes, modes) {
+ SLIST_FOREACH (mode, &modes, modes) {
if (strcmp(mode->name, new_mode) != 0)
continue;
ungrab_all_keys(conn);
bindings = mode->bindings;
+ current_binding_mode = mode->name;
translate_keysyms();
grab_all_keys(conn);
/* Reset all B_UPON_KEYRELEASE_IGNORE_MODS bindings to avoid possibly
* activating one of them. */
Binding *bind;
- TAILQ_FOREACH(bind, bindings, bindings) {
+ TAILQ_FOREACH (bind, bindings, bindings) {
if (bind->release == B_UPON_KEYRELEASE_IGNORE_MODS)
bind->release = B_UPON_KEYRELEASE;
}
@@ -666,12 +669,12 @@ static void reorder_bindings_of_mode(struct Mode *mode) {
/* Copy the bindings into an array, so that we can use qsort(3). */
int n = 0;
Binding *current;
- TAILQ_FOREACH(current, mode->bindings, bindings) {
+ TAILQ_FOREACH (current, mode->bindings, bindings) {
n++;
}
Binding **tmp = scalloc(n, sizeof(Binding *));
n = 0;
- TAILQ_FOREACH(current, mode->bindings, bindings) {
+ TAILQ_FOREACH (current, mode->bindings, bindings) {
tmp[n++] = current;
}
@@ -706,7 +709,7 @@ static void reorder_bindings_of_mode(struct Mode *mode) {
*/
void reorder_bindings(void) {
struct Mode *mode;
- SLIST_FOREACH(mode, &modes, modes) {
+ SLIST_FOREACH (mode, &modes, modes) {
const bool current_mode = (mode->bindings == bindings);
reorder_bindings_of_mode(mode);
if (current_mode)
@@ -723,8 +726,8 @@ void reorder_bindings(void) {
*/
void check_for_duplicate_bindings(struct context *context) {
Binding *bind, *current;
- TAILQ_FOREACH(current, bindings, bindings) {
- TAILQ_FOREACH(bind, bindings, bindings) {
+ TAILQ_FOREACH (current, bindings, bindings) {
+ TAILQ_FOREACH (bind, bindings, bindings) {
/* Abort when we reach the current keybinding, only check the
* bindings before */
if (bind == current)
@@ -777,7 +780,7 @@ static Binding *binding_copy(Binding *bind) {
ret->command = sstrdup(bind->command);
TAILQ_INIT(&(ret->keycodes_head));
struct Binding_Keycode *binding_keycode;
- TAILQ_FOREACH(binding_keycode, &(bind->keycodes_head), keycodes) {
+ TAILQ_FOREACH (binding_keycode, &(bind->keycodes_head), keycodes) {
struct Binding_Keycode *ret_binding_keycode = smalloc(sizeof(struct Binding_Keycode));
*ret_binding_keycode = *binding_keycode;
TAILQ_INSERT_TAIL(&(ret->keycodes_head), ret_binding_keycode, keycodes);
@@ -995,7 +998,7 @@ int *bindings_get_buttons_to_grab(void) {
buffer[num++] = 3;
Binding *bind;
- TAILQ_FOREACH(bind, bindings, bindings) {
+ TAILQ_FOREACH (bind, bindings, bindings) {
if (num + 1 == num_max)
break;
diff --git a/src/click.c b/src/click.c
index 75710a82..7a2c0329 100644
--- a/src/click.c
+++ b/src/click.c
@@ -10,11 +10,6 @@
#include "all.h"
#include <time.h>
-#include <math.h>
-
-#include <xcb/xcb_icccm.h>
-
-#include <X11/XKBlib.h>
typedef enum { CLICK_BORDER = 0,
CLICK_DECORATION = 1,
@@ -48,7 +43,11 @@ static bool tiling_resize_for_border(Con *con, border_t border, xcb_button_press
bool res = resize_find_tiling_participants(&first, &second, search_direction, false);
if (!res) {
- LOG("No second container in this direction found.\n");
+ DLOG("No second container in this direction found.\n");
+ return false;
+ }
+ if (first->fullscreen_mode != second->fullscreen_mode) {
+ DLOG("Avoiding resize between containers with different fullscreen modes, %d != %d\n", first->fullscreen_mode, second->fullscreen_mode);
return false;
}
@@ -147,7 +146,7 @@ static bool tiling_resize(Con *con, xcb_button_press_event_t *event, const click
* functions for resizing/dragging.
*
*/
-static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod_pressed, const click_destination_t dest) {
+static void route_click(Con *con, xcb_button_press_event_t *event, const bool mod_pressed, const click_destination_t dest) {
DLOG("--> click properties: mod = %d, destination = %d\n", mod_pressed, dest);
DLOG("--> OUTCOME = %p\n", con);
DLOG("type = %d, name = %s\n", con->type, con->name);
@@ -156,26 +155,20 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod
if (con->parent->type == CT_DOCKAREA)
goto done;
- const bool is_left_or_right_click = (event->detail == XCB_BUTTON_CLICK_LEFT ||
- event->detail == XCB_BUTTON_CLICK_RIGHT);
-
/* if the user has bound an action to this click, it should override the
* default behavior. */
- if (dest == CLICK_DECORATION || dest == CLICK_INSIDE || dest == CLICK_BORDER) {
- Binding *bind = get_binding_from_xcb_event((xcb_generic_event_t *)event);
-
- if (bind != NULL && ((dest == CLICK_DECORATION && !bind->exclude_titlebar) ||
- (dest == CLICK_INSIDE && bind->whole_window) ||
- (dest == CLICK_BORDER && bind->border))) {
- CommandResult *result = run_binding(bind, con);
-
- /* ASYNC_POINTER eats the event */
- xcb_allow_events(conn, XCB_ALLOW_ASYNC_POINTER, event->time);
- xcb_flush(conn);
+ Binding *bind = get_binding_from_xcb_event((xcb_generic_event_t *)event);
+ if (bind && ((dest == CLICK_DECORATION && !bind->exclude_titlebar) ||
+ (dest == CLICK_INSIDE && bind->whole_window) ||
+ (dest == CLICK_BORDER && bind->border))) {
+ CommandResult *result = run_binding(bind, con);
+
+ /* ASYNC_POINTER eats the event */
+ xcb_allow_events(conn, XCB_ALLOW_ASYNC_POINTER, event->time);
+ xcb_flush(conn);
- command_result_free(result);
- return 0;
- }
+ command_result_free(result);
+ return;
}
/* There is no default behavior for button release events so we are done. */
@@ -203,14 +196,16 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod
const bool proportional = (event->state & XCB_KEY_BUT_MASK_SHIFT) == XCB_KEY_BUT_MASK_SHIFT;
const bool in_stacked = (con->parent->layout == L_STACKED || con->parent->layout == L_TABBED);
const bool was_focused = focused == con;
+ const bool is_left_click = (event->detail == XCB_BUTTON_CLICK_LEFT);
+ const bool is_right_click = (event->detail == XCB_BUTTON_CLICK_RIGHT);
+ const bool is_left_or_right_click = (is_left_click || is_right_click);
+ const bool is_scroll = (event->detail == XCB_BUTTON_SCROLL_UP ||
+ event->detail == XCB_BUTTON_SCROLL_DOWN ||
+ event->detail == XCB_BUTTON_SCROLL_LEFT ||
+ event->detail == XCB_BUTTON_SCROLL_RIGHT);
/* 1: see if the user scrolled on the decoration of a stacked/tabbed con */
- if (in_stacked &&
- dest == CLICK_DECORATION &&
- (event->detail == XCB_BUTTON_SCROLL_UP ||
- event->detail == XCB_BUTTON_SCROLL_DOWN ||
- event->detail == XCB_BUTTON_SCROLL_LEFT ||
- event->detail == XCB_BUTTON_SCROLL_RIGHT)) {
+ if (in_stacked && dest == CLICK_DECORATION && is_scroll) {
DLOG("Scrolling on a window decoration\n");
/* Use the focused child of the tabbed / stacked container, not the
* container the user scrolled on. */
@@ -231,63 +226,65 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod
Con *fs = con_get_fullscreen_covering_ws(ws);
if (floatingcon != NULL && fs != con) {
/* 4: floating_modifier plus left mouse button drags */
- if (mod_pressed && event->detail == XCB_BUTTON_CLICK_LEFT) {
+ if (mod_pressed && is_left_click) {
floating_drag_window(floatingcon, event, false);
- return 1;
+ return;
}
/* 5: resize (floating) if this was a (left or right) click on the
* left/right/bottom border, or a right click on the decoration.
- * also try resizing (tiling) if it was a click on the top */
- if (mod_pressed && event->detail == XCB_BUTTON_CLICK_RIGHT) {
+ * also try resizing (tiling) if possible */
+ if (mod_pressed && is_right_click) {
DLOG("floating resize due to floatingmodifier\n");
floating_resize_window(floatingcon, proportional, event);
- return 1;
+ return;
}
- if (!in_stacked && dest == CLICK_DECORATION &&
+ if ((dest == CLICK_BORDER || dest == CLICK_DECORATION) &&
is_left_or_right_click) {
/* try tiling resize, but continue if it doesn’t work */
DLOG("tiling resize with fallback\n");
- if (tiling_resize(con, event, dest, !was_focused))
+ if (tiling_resize(con, event, dest, dest == CLICK_DECORATION && !was_focused))
goto done;
}
- if (dest == CLICK_DECORATION && event->detail == XCB_BUTTON_CLICK_RIGHT) {
+ if (dest == CLICK_DECORATION && is_right_click) {
DLOG("floating resize due to decoration right click\n");
floating_resize_window(floatingcon, proportional, event);
- return 1;
+ return;
}
if (dest == CLICK_BORDER && is_left_or_right_click) {
DLOG("floating resize due to border click\n");
floating_resize_window(floatingcon, proportional, event);
- return 1;
+ return;
}
/* 6: dragging, if this was a click on a decoration (which did not lead
* to a resize) */
- if (dest == CLICK_DECORATION && event->detail == XCB_BUTTON_CLICK_LEFT) {
+ if (dest == CLICK_DECORATION && is_left_click) {
floating_drag_window(floatingcon, event, !was_focused);
- return 1;
+ return;
}
goto done;
}
/* 7: floating modifier pressed, initiate a resize */
- if (dest == CLICK_INSIDE && mod_pressed && event->detail == XCB_BUTTON_CLICK_RIGHT) {
- if (floating_mod_on_tiled_client(con, event))
- return 1;
+ if (dest == CLICK_INSIDE && mod_pressed && is_right_click) {
+ if (floating_mod_on_tiled_client(con, event)) {
+ return;
+ }
+ /* Avoid propagating events to clients, since the user expects
+ * $mod+click to be handled by i3. */
+ xcb_allow_events(conn, XCB_ALLOW_ASYNC_POINTER, event->time);
+ xcb_flush(conn);
+ return;
}
/* 8: otherwise, check for border/decoration clicks and resize */
- else if ((dest == CLICK_BORDER || dest == CLICK_DECORATION) &&
- is_left_or_right_click) {
+ if ((dest == CLICK_BORDER || dest == CLICK_DECORATION) &&
+ is_left_or_right_click) {
DLOG("Trying to resize (tiling)\n");
- /* Since we updated the tree (con_activate() above), we need to
- * re-render the tree before returning to the event loop (drag_pointer()
- * inside tiling_resize() runs its own event-loop). */
- tree_render();
tiling_resize(con, event, dest, dest == CLICK_DECORATION && !was_focused);
}
@@ -295,8 +292,6 @@ done:
xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, event->time);
xcb_flush(conn);
tree_render();
-
- return 0;
}
/*
@@ -307,7 +302,7 @@ done:
* Then, route_click is called on the appropriate con.
*
*/
-int handle_button_press(xcb_button_press_event_t *event) {
+void handle_button_press(xcb_button_press_event_t *event) {
Con *con;
DLOG("Button %d (state %d) %s on window 0x%08x (child 0x%08x) at (%d, %d) (root %d, %d)\n",
event->detail, event->state, (event->response_type == XCB_BUTTON_PRESS ? "press" : "release"),
@@ -319,8 +314,10 @@ int handle_button_press(xcb_button_press_event_t *event) {
const uint32_t mod = (config.floating_modifier & 0xFFFF);
const bool mod_pressed = (mod != 0 && (event->state & mod) == mod);
DLOG("floating_mod = %d, detail = %d\n", mod_pressed, event->detail);
- if ((con = con_by_window_id(event->event)))
- return route_click(con, event, mod_pressed, CLICK_INSIDE);
+ if ((con = con_by_window_id(event->event))) {
+ route_click(con, event, mod_pressed, CLICK_INSIDE);
+ return;
+ }
if (!(con = con_by_frame_id(event->event))) {
/* Run bindings on the root window as well, see #2097. We only run it
@@ -338,7 +335,7 @@ int handle_button_press(xcb_button_press_event_t *event) {
* click coordinates and focus the output's active workspace. */
if (event->event == root && event->response_type == XCB_BUTTON_PRESS) {
Con *output, *ws;
- TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
+ TAILQ_FOREACH (output, &(croot->nodes_head), nodes) {
if (con_is_internal(output) ||
!rect_contains(output->rect, event->event_x, event->event_y))
continue;
@@ -348,30 +345,32 @@ int handle_button_press(xcb_button_press_event_t *event) {
workspace_show(ws);
tree_render();
}
- return 1;
+ return;
}
- return 0;
+ return;
}
ELOG("Clicked into unknown window?!\n");
xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, event->time);
xcb_flush(conn);
- return 0;
+ return;
}
/* Check if the click was on the decoration of a child */
Con *child;
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH_REVERSE (child, &(con->nodes_head), nodes_head, nodes) {
if (!rect_contains(child->deco_rect, event->event_x, event->event_y))
continue;
- return route_click(child, event, mod_pressed, CLICK_DECORATION);
+ route_click(child, event, mod_pressed, CLICK_DECORATION);
+ return;
}
if (event->child != XCB_NONE) {
DLOG("event->child not XCB_NONE, so this is an event which originated from a click into the application, but the application did not handle it.\n");
- return route_click(con, event, mod_pressed, CLICK_INSIDE);
+ route_click(con, event, mod_pressed, CLICK_INSIDE);
+ return;
}
- return route_click(con, event, mod_pressed, CLICK_BORDER);
+ route_click(con, event, mod_pressed, CLICK_BORDER);
}
diff --git a/src/commands.c b/src/commands.c
index 70b0c8a2..8e8aece9 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -8,14 +8,11 @@
*
*/
#include "all.h"
+#include "shmlog.h"
+#include <fcntl.h>
#include <stdint.h>
-#include <float.h>
-#include <stdarg.h>
#include <unistd.h>
-#include <fcntl.h>
-
-#include "shmlog.h"
// Macros to make the YAJL API a bit easier to use.
#define y(x, ...) (cmd_output->json_gen != NULL ? yajl_gen_##x(cmd_output->json_gen, ##__VA_ARGS__) : 0)
@@ -132,9 +129,7 @@ static Con *maybe_auto_back_and_forth_workspace(Con *workspace) {
*/
typedef struct owindow {
Con *con;
-
- TAILQ_ENTRY(owindow)
- owindows;
+ TAILQ_ENTRY(owindow) owindows;
} owindow;
typedef TAILQ_HEAD(owindows_head, owindow) owindows_head;
@@ -160,7 +155,7 @@ void cmd_criteria_init(I3_CMD) {
}
TAILQ_INIT(&owindows);
/* copy all_cons */
- TAILQ_FOREACH(con, &all_cons, all_cons) {
+ TAILQ_FOREACH (con, &all_cons, all_cons) {
ow = smalloc(sizeof(owindow));
ow->con = con;
TAILQ_INSERT_TAIL(&owindows, ow, owindows);
@@ -210,7 +205,7 @@ void cmd_criteria_match_windows(I3_CMD) {
bool matched_by_mark = false;
mark_t *mark;
- TAILQ_FOREACH(mark, &(current->con->marks_head), marks) {
+ TAILQ_FOREACH (mark, &(current->con->marks_head), marks) {
if (!regex_matches(current_match->mark, mark->name))
continue;
@@ -245,7 +240,7 @@ void cmd_criteria_match_windows(I3_CMD) {
}
}
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
DLOG("matching: %p / %s\n", current->con, current->con->name);
}
}
@@ -261,7 +256,7 @@ void cmd_criteria_add(I3_CMD, const char *ctype, const char *cvalue) {
static void move_matches_to_workspace(Con *ws) {
owindow *current;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
DLOG("matching: %p / %s\n", current->con, current->con->name);
con_move_to_workspace(current->con, ws, true, false, false);
}
@@ -362,7 +357,7 @@ void cmd_move_con_to_workspace_name(I3_CMD, const char *name, const char *no_aut
LOG("should move window to workspace %s\n", name);
/* get the workspace */
- Con *ws = workspace_get(name, NULL);
+ Con *ws = workspace_get(name);
if (no_auto_back_and_forth == NULL) {
ws = maybe_auto_back_and_forth_workspace(ws);
@@ -393,7 +388,7 @@ void cmd_move_con_to_workspace_number(I3_CMD, const char *which, const char *no_
Con *ws = get_existing_workspace_by_num(parsed_num);
if (!ws) {
- ws = workspace_get(which, NULL);
+ ws = workspace_get(which);
}
if (no_auto_back_and_forth == NULL) {
@@ -524,7 +519,7 @@ static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, const char *dir
/* Ensure all the other children have a percentage set. */
Con *child;
- TAILQ_FOREACH(child, &(current->parent->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(current->parent->nodes_head), nodes) {
LOG("child->percent = %f (child %p)\n", child->percent, child);
if (child->percent == 0.0)
child->percent = percentage;
@@ -549,7 +544,7 @@ static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, const char *dir
LOG("subtract_percent = %f\n", subtract_percent);
/* Ensure that the new percentages are positive. */
if (subtract_percent >= 0.0) {
- TAILQ_FOREACH(child, &(current->parent->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(current->parent->nodes_head), nodes) {
if (child == current) {
continue;
}
@@ -563,7 +558,7 @@ static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, const char *dir
current->percent = new_current_percent;
LOG("current->percent after = %f\n", current->percent);
- TAILQ_FOREACH(child, &(current->parent->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(current->parent->nodes_head), nodes) {
if (child == current)
continue;
child->percent -= subtract_percent;
@@ -587,7 +582,7 @@ void cmd_resize(I3_CMD, const char *way, const char *direction, long resize_px,
HANDLE_EMPTY_MATCH;
owindow *current;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
/* Don't handle dock windows (issue #1201) */
if (current->con->window && current->con->window->dock) {
DLOG("This is a dock window. Not resizing (con = %p)\n)", current->con);
@@ -667,7 +662,7 @@ void cmd_resize_set(I3_CMD, long cwidth, const char *mode_width, long cheight, c
owindow *current;
bool success = true;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
Con *floating_con;
if ((floating_con = con_inside_floating(current->con))) {
Con *output = con_get_output(floating_con);
@@ -735,7 +730,7 @@ void cmd_border(I3_CMD, const char *border_style_str, long border_width) {
HANDLE_EMPTY_MATCH;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
DLOG("matching: %p / %s\n", current->con, current->con->name);
border_style_t border_style;
@@ -766,7 +761,7 @@ void cmd_border(I3_CMD, const char *border_style_str, long border_width) {
*/
void cmd_nop(I3_CMD, const char *comment) {
LOG("-------------------------------------------------\n");
- LOG(" NOP: %s\n", comment);
+ LOG(" NOP: %.4000s\n", comment);
LOG("-------------------------------------------------\n");
ysuccess(true);
}
@@ -1006,7 +1001,7 @@ void cmd_unmark(I3_CMD, const char *mark) {
con_unmark(NULL, mark);
} else {
owindow *current;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
con_unmark(current->con, mark);
}
}
@@ -1038,7 +1033,7 @@ void cmd_move_con_to_output(I3_CMD, const char *name) {
owindow *current;
bool had_error = false;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
DLOG("matching: %p / %s\n", current->con, current->con->name);
had_error |= !con_move_to_output_name(current->con, name, true);
@@ -1059,7 +1054,7 @@ void cmd_move_con_to_mark(I3_CMD, const char *mark) {
bool result = true;
owindow *current;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
DLOG("moving matched window %p / %s to mark \"%s\"\n", current->con, current->con->name, mark);
result &= con_move_to_mark(current->con, mark);
}
@@ -1079,7 +1074,7 @@ void cmd_floating(I3_CMD, const char *floating_mode) {
HANDLE_EMPTY_MATCH;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
DLOG("matching: %p / %s\n", current->con, current->con->name);
if (strcmp(floating_mode, "toggle") == 0) {
DLOG("should toggle mode\n");
@@ -1109,7 +1104,7 @@ void cmd_move_workspace_to_output(I3_CMD, const char *name) {
HANDLE_EMPTY_MATCH;
owindow *current;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
Con *ws = con_get_workspace(current->con);
if (con_is_internal(ws)) {
continue;
@@ -1138,7 +1133,7 @@ void cmd_split(I3_CMD, const char *direction) {
owindow *current;
LOG("splitting in direction %c\n", direction[0]);
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
if (con_is_docked(current->con)) {
ELOG("Cannot split a docked container, skipping.\n");
continue;
@@ -1191,7 +1186,7 @@ void cmd_kill(I3_CMD, const char *kill_mode_str) {
HANDLE_EMPTY_MATCH;
owindow *current;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
con_close(current->con, kill_mode);
}
@@ -1211,7 +1206,7 @@ void cmd_exec(I3_CMD, const char *nosn, const char *command) {
int count = 0;
owindow *current;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
count++;
}
@@ -1221,7 +1216,7 @@ void cmd_exec(I3_CMD, const char *nosn, const char *command) {
count);
}
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
DLOG("should execute %s, no_startup_id = %d\n", command, no_startup_id);
start_application(command, no_startup_id);
}
@@ -1233,7 +1228,7 @@ void cmd_exec(I3_CMD, const char *nosn, const char *command) {
do { \
int count = 0; \
owindow *current; \
- TAILQ_FOREACH(current, &owindows, owindows) { \
+ TAILQ_FOREACH (current, &owindows, owindows) { \
count++; \
} \
\
@@ -1265,7 +1260,7 @@ void cmd_focus_direction(I3_CMD, const char *direction_str) {
}
owindow *current;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
Con *ws = con_get_workspace(current->con);
if (!ws || con_is_internal(ws)) {
continue;
@@ -1292,7 +1287,7 @@ void cmd_focus_sibling(I3_CMD, const char *direction_str) {
const position_t direction = (STARTS_WITH(direction_str, "prev")) ? BEFORE : AFTER;
owindow *current;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
Con *ws = con_get_workspace(current->con);
if (!ws || con_is_internal(ws)) {
continue;
@@ -1336,7 +1331,7 @@ void cmd_focus_window_mode(I3_CMD, const char *window_mode) {
Con *ws = con_get_workspace(focused);
Con *current;
bool success = false;
- TAILQ_FOREACH(current, &(ws->focus_head), focused) {
+ TAILQ_FOREACH (current, &(ws->focus_head), focused) {
if ((to_floating && current->type != CT_FLOATING_CON) ||
(!to_floating && current->type == CT_FLOATING_CON))
continue;
@@ -1402,9 +1397,9 @@ void cmd_focus(I3_CMD) {
CMD_FOCUS_WARN_CHILDREN;
- Con *__i3_scratch = workspace_get("__i3_scratch", NULL);
+ Con *__i3_scratch = workspace_get("__i3_scratch");
owindow *current;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
Con *ws = con_get_workspace(current->con);
/* If no workspace could be found, this was a dock window.
* Just skip it, you cannot focus dock windows. */
@@ -1440,7 +1435,7 @@ void cmd_fullscreen(I3_CMD, const char *action, const char *fullscreen_mode) {
HANDLE_EMPTY_MATCH;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
DLOG("matching: %p / %s\n", current->con, current->con->name);
if (strcmp(action, "toggle") == 0) {
con_toggle_fullscreen(current->con, mode);
@@ -1465,7 +1460,7 @@ void cmd_sticky(I3_CMD, const char *action) {
HANDLE_EMPTY_MATCH;
owindow *current;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
if (current->con->window == NULL) {
ELOG("only containers holding a window can be made sticky, skipping con = %p\n", current->con);
continue;
@@ -1495,34 +1490,37 @@ void cmd_sticky(I3_CMD, const char *action) {
}
/*
- * Implementation of 'move <direction> [<pixels> [px]]'.
+ * Implementation of 'move <direction> [<amount> [px|ppt]]'.
*
*/
-void cmd_move_direction(I3_CMD, const char *direction_str, long move_px) {
+void cmd_move_direction(I3_CMD, const char *direction_str, long amount, const char *mode) {
owindow *current;
HANDLE_EMPTY_MATCH;
Con *initially_focused = focused;
direction_t direction = parse_direction(direction_str);
- TAILQ_FOREACH(current, &owindows, owindows) {
- DLOG("moving in direction %s, px %ld\n", direction_str, move_px);
+ const bool is_ppt = mode && strcmp(mode, "ppt") == 0;
+
+ DLOG("moving in direction %s, %ld %s\n", direction_str, amount, mode);
+ TAILQ_FOREACH (current, &owindows, owindows) {
if (con_is_floating(current->con)) {
- DLOG("floating move with %ld pixels\n", move_px);
+ DLOG("floating move with %ld %s\n", amount, mode);
Rect newrect = current->con->parent->rect;
+ Con *output = con_get_output(current->con);
switch (direction) {
case D_LEFT:
- newrect.x -= move_px;
+ newrect.x -= is_ppt ? output->rect.width * ((double)amount / 100.0) : amount;
break;
case D_RIGHT:
- newrect.x += move_px;
+ newrect.x += is_ppt ? output->rect.width * ((double)amount / 100.0) : amount;
break;
case D_UP:
- newrect.y -= move_px;
+ newrect.y -= is_ppt ? output->rect.height * ((double)amount / 100.0) : amount;
break;
case D_DOWN:
- newrect.y += move_px;
+ newrect.y += is_ppt ? output->rect.height * ((double)amount / 100.0) : amount;
break;
}
@@ -1559,7 +1557,7 @@ void cmd_layout(I3_CMD, const char *layout_str) {
DLOG("changing layout to %s (%d)\n", layout_str, layout);
owindow *current;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
if (con_is_docked(current->con)) {
ELOG("cannot change layout of a docked container, skipping it.\n");
continue;
@@ -1590,7 +1588,7 @@ void cmd_layout_toggle(I3_CMD, const char *toggle_mode) {
if (match_is_empty(current_match))
con_toggle_layout(focused, toggle_mode);
else {
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
DLOG("matching: %p / %s\n", current->con, current->con->name);
con_toggle_layout(current->con, toggle_mode);
}
@@ -1618,14 +1616,25 @@ void cmd_exit(I3_CMD) {
*/
void cmd_reload(I3_CMD) {
LOG("reloading\n");
- kill_nagbar(&config_error_nagbar_pid, false);
- kill_nagbar(&command_error_nagbar_pid, false);
+
+ kill_nagbar(config_error_nagbar_pid, false);
+ kill_nagbar(command_error_nagbar_pid, false);
+ /* start_nagbar() will refuse to start a new process if the passed pid is
+ * set. This will happen when our child watcher is triggered by libev when
+ * the loop re-starts. However, config errors might be detected before
+ * that since we will read the config right now with load_configuration.
+ * See #4104. */
+ config_error_nagbar_pid = command_error_nagbar_pid = -1;
+
load_configuration(NULL, C_RELOAD);
x_set_i3_atoms();
/* Send an IPC event just in case the ws names have changed */
ipc_send_workspace_event("reload", NULL, NULL);
- /* Send an update event for the barconfig just in case it has changed */
- update_barconfig();
+ /* Send an update event for each barconfig just in case it has changed */
+ Barconfig *current;
+ TAILQ_FOREACH (current, &barconfigs, configs) {
+ ipc_send_barconfig_update_event(current);
+ }
// XXX: default reply for now, make this a better reply
ysuccess(true);
@@ -1715,16 +1724,16 @@ void cmd_focus_output(I3_CMD, const char *name) {
}
/*
- * Implementation of 'move [window|container] [to] [absolute] position <px> [px] <px> [px]
+ * Implementation of 'move [window|container] [to] [absolute] position [<pos_x> [px|ppt] <pos_y> [px|ppt]]
*
*/
-void cmd_move_window_to_position(I3_CMD, long x, long y) {
+void cmd_move_window_to_position(I3_CMD, long x, const char *mode_x, long y, const char *mode_y) {
bool has_error = false;
owindow *current;
HANDLE_EMPTY_MATCH;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
if (!con_is_floating(current->con)) {
ELOG("Cannot change position. The window/container is not floating\n");
@@ -1737,10 +1746,11 @@ void cmd_move_window_to_position(I3_CMD, long x, long y) {
}
Rect newrect = current->con->parent->rect;
+ Con *output = con_get_output(current->con);
- DLOG("moving to position %ld %ld\n", x, y);
- newrect.x = x;
- newrect.y = y;
+ newrect.x = mode_x && strcmp(mode_x, "ppt") == 0 ? output->rect.width * ((double)x / 100.0) : x;
+ newrect.y = mode_y && strcmp(mode_y, "ppt") == 0 ? output->rect.height * ((double)y / 100.0) : y;
+ DLOG("moving to position %d %s %d %s\n", newrect.x, mode_x, newrect.y, mode_y);
if (!floating_reposition(current->con->parent, newrect)) {
yerror("Cannot move window/container out of bounds.");
@@ -1761,7 +1771,7 @@ void cmd_move_window_to_center(I3_CMD, const char *method) {
HANDLE_EMPTY_MATCH;
owindow *current;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
Con *floating_con = con_inside_floating(current->con);
if (floating_con == NULL) {
ELOG("con %p / %s is not floating, cannot move it to the center.\n",
@@ -1804,7 +1814,7 @@ void cmd_move_window_to_mouse(I3_CMD) {
HANDLE_EMPTY_MATCH;
owindow *current;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
Con *floating_con = con_inside_floating(current->con);
if (floating_con == NULL) {
DLOG("con %p / %s is not floating, cannot move it to the mouse position.\n",
@@ -1830,7 +1840,7 @@ void cmd_move_scratchpad(I3_CMD) {
HANDLE_EMPTY_MATCH;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
DLOG("matching: %p / %s\n", current->con, current->con->name);
scratchpad_move(current->con);
}
@@ -1852,7 +1862,7 @@ void cmd_scratchpad_show(I3_CMD) {
if (match_is_empty(current_match)) {
result = scratchpad_show(NULL);
} else {
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
DLOG("matching: %p / %s\n", current->con, current->con->name);
result |= scratchpad_show(current->con);
}
@@ -1930,7 +1940,7 @@ void cmd_title_format(I3_CMD, const char *format) {
HANDLE_EMPTY_MATCH;
owindow *current;
- TAILQ_FOREACH(current, &owindows, owindows) {
+ TAILQ_FOREACH (current, &owindows, owindows) {
DLOG("setting title_format for %p / %s\n", current->con, current->con->name);
FREE(current->con->title_format);
@@ -2018,26 +2028,9 @@ void cmd_rename_workspace(I3_CMD, const char *old_name, const char *new_name) {
con_attach(workspace, parent, false);
ipc_send_workspace_event("rename", workspace, NULL);
- /* Move the workspace to the correct output if it has an assignment */
- struct Workspace_Assignment *assignment = NULL;
- TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
- if (assignment->output == NULL)
- continue;
- if (strcmp(assignment->name, workspace->name) != 0 && (!name_is_digits(assignment->name) || ws_name_to_number(assignment->name) != workspace->num)) {
- continue;
- }
-
- Output *target_output = get_output_by_name(assignment->output, true);
- if (!target_output) {
- LOG("Could not get output named \"%s\"\n", assignment->output);
- continue;
- }
- if (!output_triggers_assignment(target_output, assignment)) {
- continue;
- }
- workspace_move_to_output(workspace, target_output);
-
- break;
+ Con *assigned = get_assigned_output(workspace->name, workspace->num);
+ if (assigned) {
+ workspace_move_to_output(workspace, get_output_for_con(assigned));
}
bool can_restore_focus = previously_focused != NULL;
@@ -2078,7 +2071,7 @@ void cmd_rename_workspace(I3_CMD, const char *old_name, const char *new_name) {
* Implementation of 'bar mode dock|hide|invisible|toggle [<bar_id>]'
*
*/
-static bool cmd_bar_mode(const char *bar_mode, const char *bar_id) {
+void cmd_bar_mode(I3_CMD, const char *bar_mode, const char *bar_id) {
int mode = M_DOCK;
bool toggle = false;
if (strcmp(bar_mode, "dock") == 0)
@@ -2091,39 +2084,53 @@ static bool cmd_bar_mode(const char *bar_mode, const char *bar_id) {
toggle = true;
else {
ELOG("Unknown bar mode \"%s\", this is a mismatch between code and parser spec.\n", bar_mode);
- return false;
+ assert(false);
+ }
+
+ if (TAILQ_EMPTY(&barconfigs)) {
+ yerror("No bars found\n");
+ return;
}
- bool changed_sth = false;
Barconfig *current = NULL;
- TAILQ_FOREACH(current, &barconfigs, configs) {
- if (bar_id && strcmp(current->id, bar_id) != 0)
+ TAILQ_FOREACH (current, &barconfigs, configs) {
+ if (bar_id && strcmp(current->id, bar_id) != 0) {
continue;
+ }
- if (toggle)
+ if (toggle) {
mode = (current->mode + 1) % 2;
+ }
- DLOG("Changing bar mode of bar_id '%s' to '%s (%d)'\n", current->id, bar_mode, mode);
- current->mode = mode;
- changed_sth = true;
+ DLOG("Changing bar mode of bar_id '%s' from '%d' to '%s (%d)'\n",
+ current->id, current->mode, bar_mode, mode);
+ if ((int)current->mode != mode) {
+ current->mode = mode;
+ ipc_send_barconfig_update_event(current);
+ }
- if (bar_id)
- break;
+ if (bar_id) {
+ /* We are looking for a specific bar and we found it */
+ ysuccess(true);
+ return;
+ }
}
- if (bar_id && !changed_sth) {
- DLOG("Changing bar mode of bar_id %s failed, bar_id not found.\n", bar_id);
- return false;
+ if (bar_id) {
+ /* We are looking for a specific bar and we did not find it */
+ yerror("Changing bar mode of bar_id %s failed, bar_id not found.\n", bar_id);
+ } else {
+ /* We have already handled the case of no bars, so we must have
+ * updated all active bars now. */
+ ysuccess(true);
}
-
- return true;
}
/*
* Implementation of 'bar hidden_state hide|show|toggle [<bar_id>]'
*
*/
-static bool cmd_bar_hidden_state(const char *bar_hidden_state, const char *bar_id) {
+void cmd_bar_hidden_state(I3_CMD, const char *bar_hidden_state, const char *bar_id) {
int hidden_state = S_SHOW;
bool toggle = false;
if (strcmp(bar_hidden_state, "hide") == 0)
@@ -2134,54 +2141,46 @@ static bool cmd_bar_hidden_state(const char *bar_hidden_state, const char *bar_i
toggle = true;
else {
ELOG("Unknown bar state \"%s\", this is a mismatch between code and parser spec.\n", bar_hidden_state);
- return false;
+ assert(false);
+ }
+
+ if (TAILQ_EMPTY(&barconfigs)) {
+ yerror("No bars found\n");
+ return;
}
- bool changed_sth = false;
Barconfig *current = NULL;
- TAILQ_FOREACH(current, &barconfigs, configs) {
- if (bar_id && strcmp(current->id, bar_id) != 0)
+ TAILQ_FOREACH (current, &barconfigs, configs) {
+ if (bar_id && strcmp(current->id, bar_id) != 0) {
continue;
+ }
- if (toggle)
+ if (toggle) {
hidden_state = (current->hidden_state + 1) % 2;
+ }
- DLOG("Changing bar hidden_state of bar_id '%s' to '%s (%d)'\n", current->id, bar_hidden_state, hidden_state);
- current->hidden_state = hidden_state;
- changed_sth = true;
-
- if (bar_id)
- break;
- }
+ DLOG("Changing bar hidden_state of bar_id '%s' from '%d' to '%s (%d)'\n",
+ current->id, current->hidden_state, bar_hidden_state, hidden_state);
+ if ((int)current->hidden_state != hidden_state) {
+ current->hidden_state = hidden_state;
+ ipc_send_barconfig_update_event(current);
+ }
- if (bar_id && !changed_sth) {
- DLOG("Changing bar hidden_state of bar_id %s failed, bar_id not found.\n", bar_id);
- return false;
+ if (bar_id) {
+ /* We are looking for a specific bar and we found it */
+ ysuccess(true);
+ return;
+ }
}
- return true;
-}
-
-/*
- * Implementation of 'bar (hidden_state hide|show|toggle)|(mode dock|hide|invisible|toggle) [<bar_id>]'
- *
- */
-void cmd_bar(I3_CMD, const char *bar_type, const char *bar_value, const char *bar_id) {
- bool ret;
- if (strcmp(bar_type, "mode") == 0)
- ret = cmd_bar_mode(bar_value, bar_id);
- else if (strcmp(bar_type, "hidden_state") == 0)
- ret = cmd_bar_hidden_state(bar_value, bar_id);
- else {
- ELOG("Unknown bar option type \"%s\", this is a mismatch between code and parser spec.\n", bar_type);
- ret = false;
+ if (bar_id) {
+ /* We are looking for a specific bar and we did not find it */
+ yerror("Changing bar hidden_state of bar_id %s failed, bar_id not found.\n", bar_id);
+ } else {
+ /* We have already handled the case of no bars, so we must have
+ * updated all active bars now. */
+ ysuccess(true);
}
-
- ysuccess(ret);
- if (!ret)
- return;
-
- update_barconfig();
}
/*
diff --git a/src/commands_parser.c b/src/commands_parser.c
index f734a7aa..6c791415 100644
--- a/src/commands_parser.c
+++ b/src/commands_parser.c
@@ -25,13 +25,6 @@
*/
#include "all.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdbool.h>
-#include <stdint.h>
-
// Macros to make the YAJL API a bit easier to use.
#define y(x, ...) (command_output.json_gen != NULL ? yajl_gen_##x(command_output.json_gen, ##__VA_ARGS__) : 0)
#define ystr(str) (command_output.json_gen != NULL ? yajl_gen_string(command_output.json_gen, (unsigned char *)str, strlen(str)) : 0)
@@ -263,7 +256,7 @@ char *parse_string(const char **walk, bool as_word) {
* Free the returned CommandResult with command_result_free().
*/
CommandResult *parse_command(const char *input, yajl_gen gen, ipc_client *client) {
- DLOG("COMMAND: *%s*\n", input);
+ DLOG("COMMAND: *%.4000s*\n", input);
state = INITIAL;
CommandResult *result = scalloc(1, sizeof(CommandResult));
diff --git a/src/con.c b/src/con.c
index 4d1c6167..1f0dbed3 100644
--- a/src/con.c
+++ b/src/con.c
@@ -10,7 +10,6 @@
*
*/
#include "all.h"
-
#include "yajl_utils.h"
static void con_on_remove_child(Con *con);
@@ -92,8 +91,8 @@ void con_free(Con *con) {
FREE(mark->name);
FREE(mark);
}
- free(con);
DLOG("con %p freed\n", con);
+ free(con);
}
static void _con_attach(Con *con, Con *parent, Con *previous, bool ignore_focus) {
@@ -132,13 +131,37 @@ static void _con_attach(Con *con, Con *parent, Con *previous, bool ignore_focus)
goto add_to_focus_head;
}
+ if (parent->type == CT_DOCKAREA) {
+ /* Insert dock client, sorting alphanumerically by class and then
+ * instance name. This makes dock client order deterministic. As a side
+ * effect, bars without a custom bar id will be sorted according to
+ * their declaration order in the config file. See #3491. */
+ current = NULL;
+ TAILQ_FOREACH (loop, nodes_head, nodes) {
+ int result = strcasecmp_nullable(con->window->class_class, loop->window->class_class);
+ if (result == 0) {
+ result = strcasecmp_nullable(con->window->class_instance, loop->window->class_instance);
+ }
+ if (result < 0) {
+ current = loop;
+ break;
+ }
+ }
+ if (current) {
+ TAILQ_INSERT_BEFORE(loop, con, nodes);
+ } else {
+ TAILQ_INSERT_TAIL(nodes_head, con, nodes);
+ }
+ goto add_to_focus_head;
+ }
+
if (con->type == CT_FLOATING_CON) {
DLOG("Inserting into floating containers\n");
TAILQ_INSERT_TAIL(&(parent->floating_head), con, floating_windows);
} else {
if (!ignore_focus) {
/* Get the first tiling container in focus stack */
- TAILQ_FOREACH(loop, &(parent->focus_head), focused) {
+ TAILQ_FOREACH (loop, &(parent->focus_head), focused) {
if (loop->type == CT_FLOATING_CON)
continue;
current = loop;
@@ -404,7 +427,7 @@ bool con_is_sticky(Con *con) {
return true;
Con *child;
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
if (con_is_sticky(child))
return true;
}
@@ -491,8 +514,7 @@ Con *con_parent_with_orientation(Con *con, orientation_t orientation) {
struct bfs_entry {
Con *con;
- TAILQ_ENTRY(bfs_entry)
- entries;
+ TAILQ_ENTRY(bfs_entry) entries;
};
/*
@@ -504,9 +526,7 @@ Con *con_get_fullscreen_con(Con *con, fullscreen_mode_t fullscreen_mode) {
/* TODO: is breadth-first-search really appropriate? (check as soon as
* fullscreen levels and fullscreen for containers is implemented) */
- TAILQ_HEAD(bfs_head, bfs_entry)
- bfs_head = TAILQ_HEAD_INITIALIZER(bfs_head);
-
+ TAILQ_HEAD(bfs_head, bfs_entry) bfs_head = TAILQ_HEAD_INITIALIZER(bfs_head);
struct bfs_entry *entry = smalloc(sizeof(struct bfs_entry));
entry->con = con;
TAILQ_INSERT_TAIL(&bfs_head, entry, entries);
@@ -527,13 +547,13 @@ Con *con_get_fullscreen_con(Con *con, fullscreen_mode_t fullscreen_mode) {
TAILQ_REMOVE(&bfs_head, entry, entries);
free(entry);
- TAILQ_FOREACH(child, &(current->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(current->nodes_head), nodes) {
entry = smalloc(sizeof(struct bfs_entry));
entry->con = child;
TAILQ_INSERT_TAIL(&bfs_head, entry, entries);
}
- TAILQ_FOREACH(child, &(current->floating_head), floating_windows) {
+ TAILQ_FOREACH (child, &(current->floating_head), floating_windows) {
entry = smalloc(sizeof(struct bfs_entry));
entry->con = child;
TAILQ_INSERT_TAIL(&bfs_head, entry, entries);
@@ -646,9 +666,11 @@ bool con_has_parent(Con *con, Con *parent) {
*/
Con *con_by_window_id(xcb_window_t window) {
Con *con;
- TAILQ_FOREACH(con, &all_cons, all_cons)
- if (con->window != NULL && con->window->id == window)
- return con;
+ TAILQ_FOREACH (con, &all_cons, all_cons) {
+ if (con->window != NULL && con->window->id == window) {
+ return con;
+ }
+ }
return NULL;
}
@@ -659,7 +681,7 @@ Con *con_by_window_id(xcb_window_t window) {
*/
Con *con_by_con_id(long target) {
Con *con;
- TAILQ_FOREACH(con, &all_cons, all_cons) {
+ TAILQ_FOREACH (con, &all_cons, all_cons) {
if (con == (Con *)target) {
return con;
}
@@ -684,9 +706,11 @@ bool con_exists(Con *con) {
*/
Con *con_by_frame_id(xcb_window_t frame) {
Con *con;
- TAILQ_FOREACH(con, &all_cons, all_cons)
- if (con->frame.id == frame)
- return con;
+ TAILQ_FOREACH (con, &all_cons, all_cons) {
+ if (con->frame.id == frame) {
+ return con;
+ }
+ }
return NULL;
}
@@ -697,7 +721,7 @@ Con *con_by_frame_id(xcb_window_t frame) {
*/
Con *con_by_mark(const char *mark) {
Con *con;
- TAILQ_FOREACH(con, &all_cons, all_cons) {
+ TAILQ_FOREACH (con, &all_cons, all_cons) {
if (con_has_mark(con, mark))
return con;
}
@@ -711,7 +735,7 @@ Con *con_by_mark(const char *mark) {
*/
bool con_has_mark(Con *con, const char *mark) {
mark_t *current;
- TAILQ_FOREACH(current, &(con->marks_head), marks) {
+ TAILQ_FOREACH (current, &(con->marks_head), marks) {
if (strcmp(current->name, mark) == 0)
return true;
}
@@ -774,7 +798,7 @@ void con_unmark(Con *con, const char *name) {
Con *current;
if (name == NULL) {
DLOG("Unmarking all containers.\n");
- TAILQ_FOREACH(current, &all_cons, all_cons) {
+ TAILQ_FOREACH (current, &all_cons, all_cons) {
if (con != NULL && current != con)
continue;
@@ -805,7 +829,7 @@ void con_unmark(Con *con, const char *name) {
current->mark_changed = true;
mark_t *mark;
- TAILQ_FOREACH(mark, &(current->marks_head), marks) {
+ TAILQ_FOREACH (mark, &(current->marks_head), marks) {
if (strcmp(mark->name, name) != 0)
continue;
@@ -830,8 +854,8 @@ Con *con_for_window(Con *con, i3Window *window, Match **store_match) {
//DLOG("searching con for window %p starting at con %p\n", window, con);
//DLOG("class == %s\n", window->class_class);
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
- TAILQ_FOREACH(match, &(child->swallow_head), matches) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (match, &(child->swallow_head), matches) {
if (!match_matches_window(match, window))
continue;
if (store_match != NULL)
@@ -843,8 +867,8 @@ Con *con_for_window(Con *con, i3Window *window, Match **store_match) {
return result;
}
- TAILQ_FOREACH(child, &(con->floating_head), floating_windows) {
- TAILQ_FOREACH(match, &(child->swallow_head), matches) {
+ TAILQ_FOREACH (child, &(con->floating_head), floating_windows) {
+ TAILQ_FOREACH (match, &(child->swallow_head), matches) {
if (!match_matches_window(match, window))
continue;
if (store_match != NULL)
@@ -863,7 +887,7 @@ static int num_focus_heads(Con *con) {
int focus_heads = 0;
Con *current;
- TAILQ_FOREACH(current, &(con->focus_head), focused) {
+ TAILQ_FOREACH (current, &(con->focus_head), focused) {
focus_heads++;
}
@@ -880,7 +904,7 @@ Con **get_focus_order(Con *con) {
Con **focus_order = smalloc(focus_heads * sizeof(Con *));
Con *current;
int idx = 0;
- TAILQ_FOREACH(current, &(con->focus_head), focused) {
+ TAILQ_FOREACH (current, &(con->focus_head), focused) {
assert(idx < focus_heads);
focus_order[idx++] = current;
}
@@ -923,8 +947,9 @@ int con_num_children(Con *con) {
Con *child;
int children = 0;
- TAILQ_FOREACH(child, &(con->nodes_head), nodes)
- children++;
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
+ children++;
+ }
return children;
}
@@ -940,7 +965,7 @@ int con_num_visible_children(Con *con) {
int children = 0;
Con *current = NULL;
- TAILQ_FOREACH(current, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (current, &(con->nodes_head), nodes) {
/* Visible leaf nodes are a child. */
if (!con_is_hidden(current) && con_is_leaf(current))
children++;
@@ -965,11 +990,11 @@ int con_num_windows(Con *con) {
int num = 0;
Con *current = NULL;
- TAILQ_FOREACH(current, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (current, &(con->nodes_head), nodes) {
num += con_num_windows(current);
}
- TAILQ_FOREACH(current, &(con->floating_head), floating_windows) {
+ TAILQ_FOREACH (current, &(con->floating_head), floating_windows) {
num += con_num_windows(current);
}
@@ -990,7 +1015,7 @@ void con_fix_percent(Con *con) {
// with a percentage set we have
double total = 0.0;
int children_with_percent = 0;
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
if (child->percent > 0.0) {
total += child->percent;
++children_with_percent;
@@ -1000,7 +1025,7 @@ void con_fix_percent(Con *con) {
// if there were children without a percentage set, set to a value that
// will make those children proportional to all others
if (children_with_percent != children) {
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
if (child->percent <= 0.0) {
if (children_with_percent == 0) {
total += (child->percent = 1.0);
@@ -1014,11 +1039,11 @@ void con_fix_percent(Con *con) {
// if we got a zero, just distribute the space equally, otherwise
// distribute according to the proportions we got
if (total == 0.0) {
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
child->percent = 1.0 / children;
}
} else if (total != 1.0) {
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
child->percent /= total;
}
}
@@ -1233,9 +1258,17 @@ static bool _con_move_to_con(Con *con, Con *target, bool behind_focused, bool fi
}
/* If moving a fullscreen container and the destination already has a
- * fullscreen window on it, un-fullscreen the target's fullscreen con. */
+ * fullscreen window on it, un-fullscreen the target's fullscreen con.
+ * con->fullscreen_mode is not enough in some edge cases:
+ * 1. con is CT_FLOATING_CON, child is fullscreen.
+ * 2. con is the parent of a fullscreen container, can be triggered by
+ * moving the parent with command criteria.
+ */
Con *fullscreen = con_get_fullscreen_con(target_ws, CF_OUTPUT);
- if (con->fullscreen_mode != CF_NONE && fullscreen != NULL) {
+ const bool con_has_fullscreen = con->fullscreen_mode != CF_NONE ||
+ con_get_fullscreen_con(con, CF_GLOBAL) ||
+ con_get_fullscreen_con(con, CF_OUTPUT);
+ if (con_has_fullscreen && fullscreen != NULL) {
con_toggle_fullscreen(fullscreen, CF_OUTPUT);
fullscreen = NULL;
}
@@ -1295,7 +1328,7 @@ static bool _con_move_to_con(Con *con, Con *target, bool behind_focused, bool fi
* delete it so child windows won't be created on the old workspace. */
if (!con_is_leaf(con)) {
Con *child;
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
if (!child->window)
continue;
startup_sequence_delete_by_window(child->window);
@@ -1334,7 +1367,7 @@ bool con_move_to_mark(Con *con, const char *mark) {
}
/* For target containers in the scratchpad, we just send the window to the scratchpad. */
- if (con_get_workspace(target) == workspace_get("__i3_scratch", NULL)) {
+ if (con_get_workspace(target) == workspace_get("__i3_scratch")) {
DLOG("target container is in the scratchpad, moving container to scratchpad.\n");
scratchpad_move(con);
return true;
@@ -1536,7 +1569,7 @@ Con *con_descend_tiling_focused(Con *con) {
return next;
do {
before = next;
- TAILQ_FOREACH(child, &(next->focus_head), focused) {
+ TAILQ_FOREACH (child, &(next->focus_head), focused) {
if (child->type == CT_FLOATING_CON)
continue;
@@ -1571,7 +1604,7 @@ Con *con_descend_direction(Con *con, direction_t direction) {
/* Wrong orientation. We use the last focused con. Within that con,
* we recurse to chose the left/right con or at least the last
* focused one. */
- TAILQ_FOREACH(current, &(con->focus_head), focused) {
+ TAILQ_FOREACH (current, &(con->focus_head), focused) {
if (current->type != CT_FLOATING_CON) {
most = current;
break;
@@ -1596,7 +1629,7 @@ Con *con_descend_direction(Con *con, direction_t direction) {
/* Wrong orientation. We use the last focused con. Within that con,
* we recurse to chose the top/bottom con or at least the last
* focused one. */
- TAILQ_FOREACH(current, &(con->focus_head), focused) {
+ TAILQ_FOREACH (current, &(con->focus_head), focused) {
if (current->type != CT_FLOATING_CON) {
most = current;
break;
@@ -2009,7 +2042,7 @@ Rect con_minimum_size(Con *con) {
if (con->layout == L_STACKED || con->layout == L_TABBED) {
uint32_t max_width = 0, max_height = 0, deco_height = 0;
Con *child;
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
Rect min = con_minimum_size(child);
deco_height += child->deco_rect.height;
max_width = max(max_width, min.width);
@@ -2026,7 +2059,7 @@ Rect con_minimum_size(Con *con) {
if (con_is_split(con)) {
uint32_t width = 0, height = 0;
Con *child;
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
Rect min = con_minimum_size(child);
if (con->layout == L_SPLITH) {
width += min.width;
@@ -2114,7 +2147,7 @@ bool con_has_urgent_child(Con *con) {
/* We are not interested in floating windows since they can only be
* attached to a workspace → nodes_head instead of focus_head */
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
if (con_has_urgent_child(child))
return true;
}
@@ -2236,7 +2269,7 @@ char *con_get_tree_representation(Con *con) {
/* 2) append representation of children */
Con *child;
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
char *child_txt = con_get_tree_representation(child);
char *tmp_buf;
@@ -2290,11 +2323,11 @@ i3String *con_parse_title_format(Con *con) {
char *formatted_str = format_placeholders(con->title_format, &placeholders[0], num);
i3String *formatted = i3string_from_utf8(formatted_str);
i3string_set_markup(formatted, pango_markup);
- FREE(formatted_str);
- for (size_t i = 0; i < num; i++) {
- FREE(placeholders[i].value);
- }
+ free(formatted_str);
+ free(title);
+ free(class);
+ free(instance);
return formatted;
}
@@ -2454,7 +2487,7 @@ void con_merge_into(Con *old, Con *new) {
con_set_urgency(new, old->urgent);
mark_t *mark;
- TAILQ_FOREACH(mark, &(old->marks_head), marks) {
+ TAILQ_FOREACH (mark, &(old->marks_head), marks) {
TAILQ_INSERT_TAIL(&(new->marks_head), mark, marks);
ipc_send_window_event("mark", new);
}
diff --git a/src/config.c b/src/config.c
index 81919566..ecc154c6 100644
--- a/src/config.c
+++ b/src/config.c
@@ -28,17 +28,6 @@ void ungrab_all_keys(xcb_connection_t *conn) {
xcb_ungrab_key(conn, XCB_GRAB_ANY, root, XCB_BUTTON_MASK_ANY);
}
-/*
- * Sends the current bar configuration as an event to all barconfig_update listeners.
- *
- */
-void update_barconfig(void) {
- Barconfig *current;
- TAILQ_FOREACH(current, &barconfigs, configs) {
- ipc_send_barconfig_update_event(current);
- }
-}
-
static void free_configuration(void) {
assert(conn != NULL);
@@ -141,7 +130,7 @@ static void free_configuration(void) {
}
Con *con;
- TAILQ_FOREACH(con, &all_cons, all_cons) {
+ TAILQ_FOREACH (con, &all_cons, all_cons) {
/* Assignments changed, previously ran assignments are invalid. */
if (con->window) {
con->window->nr_assignments = 0;
@@ -185,6 +174,7 @@ bool load_configuration(const char *override_configpath, config_load_t load_type
SLIST_INSERT_HEAD(&modes, default_mode, modes);
bindings = default_mode->bindings;
+ current_binding_mode = default_mode->name;
/* Clear the old config or initialize the data structure */
memset(&config, 0, sizeof(config));
diff --git a/src/config_directives.c b/src/config_directives.c
index 4712296c..c039e35f 100644
--- a/src/config_directives.c
+++ b/src/config_directives.c
@@ -9,9 +9,6 @@
*/
#include "all.h"
-#include <float.h>
-#include <stdarg.h>
-
/*******************************************************************************
* Criteria functions.
******************************************************************************/
@@ -128,7 +125,7 @@ CFGFUN(enter_mode, const char *pango_markup, const char *modename) {
}
struct Mode *mode;
- SLIST_FOREACH(mode, &modes, modes) {
+ SLIST_FOREACH (mode, &modes, modes) {
if (strcmp(mode->name, modename) == 0) {
ELOG("The binding mode with name \"%s\" is defined at least twice.\n", modename);
}
@@ -348,7 +345,7 @@ CFGFUN(workspace, const char *workspace, const char *output) {
if (workspace) {
FREE(current_workspace);
- TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
+ TAILQ_FOREACH (assignment, &ws_assignments, ws_assignments) {
if (strcasecmp(assignment->name, workspace) == 0) {
ELOG("You have a duplicate workspace assignment for workspace \"%s\"\n",
workspace);
@@ -542,7 +539,7 @@ static void bar_configure_binding(const char *button, const char *release, const
const bool release_bool = release != NULL;
struct Barbinding *current;
- TAILQ_FOREACH(current, &(current_bar->bar_bindings), bindings) {
+ TAILQ_FOREACH (current, &(current_bar->bar_bindings), bindings) {
if (current->input_code == input_code && current->release == release_bool) {
ELOG("command for button %s was already specified, ignoring.\n", button);
return;
diff --git a/src/config_parser.c b/src/config_parser.c
index bbeca576..f78e75f8 100644
--- a/src/config_parser.c
+++ b/src/config_parser.c
@@ -25,16 +25,17 @@
*/
#include "all.h"
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#include <stdbool.h>
-#include <stdint.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <sys/stat.h>
-#include <fcntl.h>
+#include <unistd.h>
+
#include <xcb/xcb_xrm.h>
// Macros to make the YAJL API a bit easier to use.
@@ -820,7 +821,7 @@ void start_config_error_nagbar(const char *configpath, bool has_errors) {
*/
static void upsert_variable(struct variables_head *variables, char *key, char *value) {
struct Variable *current;
- SLIST_FOREACH(current, variables, variables) {
+ SLIST_FOREACH (current, variables, variables) {
if (strcmp(current->key, key) != 0) {
continue;
}
@@ -838,7 +839,7 @@ static void upsert_variable(struct variables_head *variables, char *key, char *v
new->value = sstrdup(value);
/* ensure that the correct variable is matched in case of one being
* the prefix of another */
- SLIST_FOREACH(test, variables, variables) {
+ SLIST_FOREACH (test, variables, variables) {
if (strlen(new->key) >= strlen(test->key))
break;
loc = test;
@@ -1013,7 +1014,7 @@ bool parse_file(const char *f, bool use_nagbar) {
* variables (otherwise we will count them twice, which is bad when
* 'extra' is negative) */
char *bufcopy = sstrdup(buf);
- SLIST_FOREACH(current, &variables, variables) {
+ SLIST_FOREACH (current, &variables, variables) {
int extra = (strlen(current->value) - strlen(current->key));
char *next;
for (next = bufcopy;
@@ -1033,11 +1034,12 @@ bool parse_file(const char *f, bool use_nagbar) {
destwalk = new;
while (walk < (buf + stbuf.st_size)) {
/* Find the next variable */
- SLIST_FOREACH(current, &variables, variables)
- current->next_match = strcasestr(walk, current->key);
+ SLIST_FOREACH (current, &variables, variables) {
+ current->next_match = strcasestr(walk, current->key);
+ }
nearest = NULL;
int distance = stbuf.st_size;
- SLIST_FOREACH(current, &variables, variables) {
+ SLIST_FOREACH (current, &variables, variables) {
if (current->next_match == NULL)
continue;
if ((current->next_match - walk) < distance) {
diff --git a/src/display_version.c b/src/display_version.c
index da11bff3..32250c15 100644
--- a/src/display_version.c
+++ b/src/display_version.c
@@ -10,13 +10,9 @@
*/
#include "all.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <sys/un.h>
#include <fcntl.h>
#include <time.h>
+#include <unistd.h>
static bool human_readable_key, loaded_config_file_name_key;
static char *human_readable_version, *loaded_config_file_name;
@@ -98,7 +94,8 @@ void display_running_version(void) {
if (state != yajl_status_ok)
errx(EXIT_FAILURE, "Could not parse my own reply. That's weird. reply is %.*s", (int)reply_length, reply);
- printf("\rRunning i3 version: %s (pid %s)\n", human_readable_version, pid_from_atom);
+ printf("\r\x1b[K");
+ printf("Running i3 version: %s (pid %s)\n", human_readable_version, pid_from_atom);
if (loaded_config_file_name) {
struct stat sb;
diff --git a/src/drag.c b/src/drag.c
index 6b05311a..67ccff40 100644
--- a/src/drag.c
+++ b/src/drag.c
@@ -175,7 +175,7 @@ drag_result_t drag_pointer(Con *con, const xcb_button_press_event_t *event,
xcb_window_t confine_to, int cursor,
bool use_threshold, callback_t callback,
const void *extra) {
- xcb_cursor_t xcursor = (cursor && xcursor_supported) ? xcursor_get_cursor(cursor) : XCB_NONE;
+ xcb_cursor_t xcursor = cursor ? xcursor_get_cursor(cursor) : XCB_NONE;
/* Grab the pointer */
xcb_grab_pointer_cookie_t cookie;
diff --git a/src/ewmh.c b/src/ewmh.c
index 7bd23fb7..c61fb5f3 100644
--- a/src/ewmh.c
+++ b/src/ewmh.c
@@ -9,12 +9,14 @@
*/
#include "all.h"
+#include "i3-atoms_NET_SUPPORTED.xmacro.h"
+
xcb_window_t ewmh_window;
-#define FOREACH_NONINTERNAL \
- TAILQ_FOREACH(output, &(croot->nodes_head), nodes) \
- TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) \
- if (!con_is_internal(ws))
+#define FOREACH_NONINTERNAL \
+ TAILQ_FOREACH (output, &(croot->nodes_head), nodes) \
+ TAILQ_FOREACH (ws, &(output_get_content(output)->nodes_head), nodes) \
+ if (!con_is_internal(ws))
/*
* Updates _NET_CURRENT_DESKTOP with the current desktop number.
@@ -125,13 +127,13 @@ static void ewmh_update_wm_desktop_recursively(Con *con, const uint32_t desktop)
Con *child;
/* Recursively call this to descend through the entire subtree. */
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
ewmh_update_wm_desktop_recursively(child, desktop);
}
/* If con is a workspace, we also need to go through the floating windows on it. */
if (con->type == CT_WORKSPACE) {
- TAILQ_FOREACH(child, &(con->floating_head), floating_windows) {
+ TAILQ_FOREACH (child, &(con->floating_head), floating_windows) {
ewmh_update_wm_desktop_recursively(child, desktop);
}
}
@@ -183,9 +185,9 @@ void ewmh_update_wm_desktop(void) {
uint32_t desktop = 0;
Con *output;
- TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
+ TAILQ_FOREACH (output, &(croot->nodes_head), nodes) {
Con *workspace;
- TAILQ_FOREACH(workspace, &(output_get_content(output)->nodes_head), nodes) {
+ TAILQ_FOREACH (workspace, &(output_get_content(output)->nodes_head), nodes) {
ewmh_update_wm_desktop_recursively(workspace, desktop);
if (!con_is_internal(workspace)) {
@@ -305,7 +307,7 @@ void ewmh_update_focused(xcb_window_t window, bool is_focused) {
void ewmh_setup_hints(void) {
xcb_atom_t supported_atoms[] = {
#define xmacro(atom) A_##atom,
-#include "atoms_NET_SUPPORTED.xmacro"
+ I3_NET_SUPPORTED_ATOMS_XMACRO
#undef xmacro
};
diff --git a/src/fake_outputs.c b/src/fake_outputs.c
index e69acc8a..6b68ef44 100644
--- a/src/fake_outputs.c
+++ b/src/fake_outputs.c
@@ -18,9 +18,11 @@ static int num_screens;
*/
static Output *get_screen_at(unsigned int x, unsigned int y) {
Output *output;
- TAILQ_FOREACH(output, &outputs, outputs)
- if (output->rect.x == x && output->rect.y == y)
- return output;
+ TAILQ_FOREACH (output, &outputs, outputs) {
+ if (output->rect.x == x && output->rect.y == y) {
+ return output;
+ }
+ }
return NULL;
}
diff --git a/src/floating.c b/src/floating.c
index bb6c644c..f087832d 100644
--- a/src/floating.c
+++ b/src/floating.c
@@ -9,6 +9,8 @@
*/
#include "all.h"
+#include <math.h>
+
#ifndef MAX
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#endif
@@ -24,7 +26,7 @@ static Rect total_outputs_dimensions(void) {
Output *output;
/* Use Rect to encapsulate dimensions, ignoring x/y */
Rect outputs_dimensions = {0, 0, 0, 0};
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
outputs_dimensions.height += output->rect.height;
outputs_dimensions.width += output->rect.width;
}
@@ -39,7 +41,7 @@ static Rect total_outputs_dimensions(void) {
static void floating_set_hint_atom(Con *con, bool floating) {
if (!con_is_leaf(con)) {
Con *child;
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
floating_set_hint_atom(child, floating);
}
}
@@ -221,22 +223,22 @@ void floating_check_size(Con *floating_con, bool prefer_height) {
}
}
-void floating_enable(Con *con, bool automatic) {
+bool floating_enable(Con *con, bool automatic) {
bool set_focus = (con == focused);
if (con_is_docked(con)) {
LOG("Container is a dock window, not enabling floating mode.\n");
- return;
+ return false;
}
if (con_is_floating(con)) {
LOG("Container is already in floating mode, not doing anything.\n");
- return;
+ return false;
}
if (con->type == CT_WORKSPACE) {
LOG("Container is a workspace, not enabling floating mode.\n");
- return;
+ return false;
}
Con *focus_head_placeholder = NULL;
@@ -328,7 +330,7 @@ void floating_enable(Con *con, bool automatic) {
if (rect_equals(nc->rect, (Rect){0, 0, 0, 0})) {
DLOG("Geometry not set, combining children\n");
Con *child;
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
DLOG("child geometry: %d x %d\n", child->geometry.width, child->geometry.height);
nc->rect.width += child->geometry.width;
nc->rect.height = max(nc->rect.height, child->geometry.height);
@@ -419,6 +421,7 @@ void floating_enable(Con *con, bool automatic) {
floating_set_hint_atom(nc, true);
ipc_send_window_event("floating", con);
+ return true;
}
void floating_disable(Con *con) {
diff --git a/src/handlers.c b/src/handlers.c
index 24919b28..eba5fe29 100644
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -10,9 +10,9 @@
*/
#include "all.h"
-#include <time.h>
-#include <float.h>
#include <sys/time.h>
+#include <time.h>
+
#include <xcb/randr.h>
#define SN_API_NOT_YET_FROZEN 1
#include <libsn/sn-monitor.h>
@@ -62,7 +62,7 @@ bool event_is_ignored(const int sequence, const int response_type) {
event = SLIST_NEXT(event, ignore_events);
}
- SLIST_FOREACH(event, &ignore_events, ignore_events) {
+ SLIST_FOREACH (event, &ignore_events, ignore_events) {
if (event->sequence != sequence)
continue;
@@ -160,11 +160,12 @@ static void handle_enter_notify(xcb_enter_notify_event_t *event) {
layout_t layout = (enter_child ? con->parent->layout : con->layout);
if (layout == L_DEFAULT) {
Con *child;
- TAILQ_FOREACH(child, &(con->nodes_head), nodes)
- if (rect_contains(child->deco_rect, event->event_x, event->event_y)) {
- LOG("using child %p / %s instead!\n", child, child->name);
- con = child;
- break;
+ TAILQ_FOREACH_REVERSE (child, &(con->nodes_head), nodes_head, nodes) {
+ if (rect_contains(child->deco_rect, event->event_x, event->event_y)) {
+ LOG("using child %p / %s instead!\n", child, child->name);
+ con = child;
+ break;
+ }
}
}
@@ -216,7 +217,7 @@ static void handle_motion_notify(xcb_motion_notify_event_t *event) {
/* see over which rect the user is */
Con *current;
- TAILQ_FOREACH(current, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH_REVERSE (current, &(con->nodes_head), nodes_head, nodes) {
if (!rect_contains(current->deco_rect, event->event_x, event->event_y))
continue;
@@ -557,12 +558,7 @@ static bool window_name_changed(i3Window *window, char *old_name) {
* Called when a window changes its title
*
*/
-static bool handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t state,
- xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) {
- Con *con;
- if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
- return false;
-
+static bool handle_windowname_change(Con *con, xcb_get_property_reply_t *prop) {
char *old_name = (con->window->name != NULL ? sstrdup(i3string_as_utf8(con->window->name)) : NULL);
window_update_name(con->window, prop);
@@ -584,12 +580,7 @@ static bool handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t
* window_update_name_legacy().
*
*/
-static bool handle_windowname_change_legacy(void *data, xcb_connection_t *conn, uint8_t state,
- xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) {
- Con *con;
- if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
- return false;
-
+static bool handle_windowname_change_legacy(Con *con, xcb_get_property_reply_t *prop) {
char *old_name = (con->window->name != NULL ? sstrdup(i3string_as_utf8(con->window->name)) : NULL);
window_update_name_legacy(con->window, prop);
@@ -610,12 +601,7 @@ static bool handle_windowname_change_legacy(void *data, xcb_connection_t *conn,
* Called when a window changes its WM_WINDOW_ROLE.
*
*/
-static bool handle_windowrole_change(void *data, xcb_connection_t *conn, uint8_t state,
- xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) {
- Con *con;
- if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
- return false;
-
+static bool handle_windowrole_change(Con *con, xcb_get_property_reply_t *prop) {
window_update_role(con->window, prop);
con = remanage_window(con);
@@ -741,7 +727,7 @@ static void handle_client_message(xcb_client_message_event_t *event) {
return;
}
- if (con_is_internal(ws) && ws != workspace_get("__i3_scratch", NULL)) {
+ if (con_is_internal(ws) && ws != workspace_get("__i3_scratch")) {
DLOG("Workspace is internal but not scratchpad, ignoring _NET_ACTIVE_WINDOW\n");
return;
}
@@ -855,11 +841,13 @@ static void handle_client_message(xcb_client_message_event_t *event) {
* let's float it and make it sticky. */
DLOG("The window was requested to be visible on all workspaces, making it sticky and floating.\n");
- floating_enable(con, false);
+ if (floating_enable(con, false)) {
+ con->floating = FLOATING_AUTO_ON;
- con->sticky = true;
- ewmh_update_sticky(con->window->id, true);
- output_push_sticky_windows(focused);
+ con->sticky = true;
+ ewmh_update_sticky(con->window->id, true);
+ output_push_sticky_windows(focused);
+ }
} else {
Con *ws = ewmh_get_workspace_by_index(index);
if (ws == NULL) {
@@ -955,12 +943,7 @@ static void handle_client_message(xcb_client_message_event_t *event) {
}
}
-static bool handle_window_type(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
- xcb_atom_t atom, xcb_get_property_reply_t *reply) {
- Con *con;
- if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
- return false;
-
+static bool handle_window_type(Con *con, xcb_get_property_reply_t *reply) {
window_update_type(con->window, reply);
return true;
}
@@ -972,14 +955,7 @@ static bool handle_window_type(void *data, xcb_connection_t *conn, uint8_t state
* See ICCCM 4.1.2.3 for more details
*
*/
-static bool handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
- xcb_atom_t name, xcb_get_property_reply_t *reply) {
- Con *con = con_by_window_id(window);
- if (con == NULL) {
- DLOG("Received WM_NORMAL_HINTS for unknown client\n");
- return false;
- }
-
+static bool handle_normal_hints(Con *con, xcb_get_property_reply_t *reply) {
bool changed = window_update_normal_hints(con->window, reply, NULL);
if (changed) {
@@ -998,21 +974,11 @@ static bool handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t stat
* Handles the WM_HINTS property for extracting the urgency state of the window.
*
*/
-static bool handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
- xcb_atom_t name, xcb_get_property_reply_t *reply) {
- Con *con = con_by_window_id(window);
- if (con == NULL) {
- DLOG("Received WM_HINTS for unknown client\n");
- return false;
- }
-
+static bool handle_hints(Con *con, xcb_get_property_reply_t *reply) {
bool urgency_hint;
- if (reply == NULL)
- reply = xcb_get_property_reply(conn, xcb_icccm_get_wm_hints(conn, window), NULL);
window_update_hints(con->window, reply, &urgency_hint);
con_set_urgency(con, urgency_hint);
tree_render();
-
return true;
}
@@ -1023,24 +989,8 @@ static bool handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_
* See ICCCM 4.1.2.6 for more details
*
*/
-static bool handle_transient_for(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
- xcb_atom_t name, xcb_get_property_reply_t *prop) {
- Con *con;
-
- if ((con = con_by_window_id(window)) == NULL || con->window == NULL) {
- DLOG("No such window\n");
- return false;
- }
-
- if (prop == NULL) {
- prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn, false, window, XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 0, 32),
- NULL);
- if (prop == NULL)
- return false;
- }
-
+static bool handle_transient_for(Con *con, xcb_get_property_reply_t *prop) {
window_update_transient_for(con->window, prop);
-
return true;
}
@@ -1049,21 +999,8 @@ static bool handle_transient_for(void *data, xcb_connection_t *conn, uint8_t sta
* toolwindow (or similar) and to which window it belongs (logical parent).
*
*/
-static bool handle_clientleader_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
- xcb_atom_t name, xcb_get_property_reply_t *prop) {
- Con *con;
- if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
- return false;
-
- if (prop == NULL) {
- prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn, false, window, A_WM_CLIENT_LEADER, XCB_ATOM_WINDOW, 0, 32),
- NULL);
- if (prop == NULL)
- return false;
- }
-
+static bool handle_clientleader_change(Con *con, xcb_get_property_reply_t *prop) {
window_update_leader(con->window, prop);
-
return true;
}
@@ -1143,24 +1080,9 @@ static void handle_configure_notify(xcb_configure_notify_event_t *event) {
* Handles the WM_CLASS property for assignments and criteria selection.
*
*/
-static bool handle_class_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
- xcb_atom_t name, xcb_get_property_reply_t *prop) {
- Con *con;
- if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
- return false;
-
- if (prop == NULL) {
- prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn, false, window, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 0, 32),
- NULL);
-
- if (prop == NULL)
- return false;
- }
-
+static bool handle_class_change(Con *con, xcb_get_property_reply_t *prop) {
window_update_class(con->window, prop);
-
con = remanage_window(con);
-
return true;
}
@@ -1168,20 +1090,7 @@ static bool handle_class_change(void *data, xcb_connection_t *conn, uint8_t stat
* Handles the _MOTIF_WM_HINTS property of specifing window deocration settings.
*
*/
-static bool handle_motif_hints_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
- xcb_atom_t name, xcb_get_property_reply_t *prop) {
- Con *con;
- if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
- return false;
-
- if (prop == NULL) {
- prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn, false, window, A__MOTIF_WM_HINTS, XCB_GET_PROPERTY_TYPE_ANY, 0, 5 * sizeof(uint64_t)),
- NULL);
-
- if (prop == NULL)
- return false;
- }
-
+static bool handle_motif_hints_change(Con *con, xcb_get_property_reply_t *prop) {
border_style_t motif_border_style;
window_update_motif_hints(con->window, prop, &motif_border_style);
@@ -1199,34 +1108,7 @@ static bool handle_motif_hints_change(void *data, xcb_connection_t *conn, uint8_
* Handles the _NET_WM_STRUT_PARTIAL property for allocating space for dock clients.
*
*/
-static bool handle_strut_partial_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
- xcb_atom_t name, xcb_get_property_reply_t *prop) {
- DLOG("strut partial change for window 0x%08x\n", window);
-
- Con *con;
- if ((con = con_by_window_id(window)) == NULL || con->window == NULL) {
- return false;
- }
-
- if (prop == NULL) {
- xcb_generic_error_t *err = NULL;
- xcb_get_property_cookie_t strut_cookie = xcb_get_property(conn, false, window, A__NET_WM_STRUT_PARTIAL,
- XCB_GET_PROPERTY_TYPE_ANY, 0, UINT32_MAX);
- prop = xcb_get_property_reply(conn, strut_cookie, &err);
-
- if (err != NULL) {
- DLOG("got error when getting strut partial property: %d\n", err->error_code);
- free(err);
- return false;
- }
-
- if (prop == NULL) {
- return false;
- }
- }
-
- DLOG("That is con %p / %s\n", con, con->name);
-
+static bool handle_strut_partial_change(Con *con, xcb_get_property_reply_t *prop) {
window_update_strut_partial(con->window, prop);
/* we only handle this change for dock clients */
@@ -1267,18 +1149,35 @@ static bool handle_strut_partial_change(void *data, xcb_connection_t *conn, uint
/* attach the dock to the dock area */
con_detach(con);
- con->parent = dockarea;
- TAILQ_INSERT_HEAD(&(dockarea->focus_head), con, focused);
- TAILQ_INSERT_HEAD(&(dockarea->nodes_head), con, nodes);
+ con_attach(con, dockarea, true);
tree_render();
return true;
}
+/*
+ * Handles the _I3_FLOATING_WINDOW property to properly run assignments for
+ * floating window changes.
+ *
+ * This is needed to correctly run the assignments after changes in floating
+ * windows which are triggered by user commands (floating enable | disable). In
+ * that case, we can't call run_assignments because it will modify the parser
+ * state when it needs to parse the user-specified action, breaking the parser
+ * state for the original command.
+ *
+ */
+static bool handle_i3_floating(Con *con, xcb_get_property_reply_t *prop) {
+ DLOG("floating change for con %p\n", con);
+
+ remanage_window(con);
+
+ return true;
+}
+
/* Returns false if the event could not be processed (e.g. the window could not
* be found), true otherwise */
-typedef bool (*cb_property_handler_t)(void *data, xcb_connection_t *c, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *property);
+typedef bool (*cb_property_handler_t)(Con *con, xcb_get_property_reply_t *property);
struct property_handler_t {
xcb_atom_t atom;
@@ -1297,6 +1196,7 @@ static struct property_handler_t property_handlers[] = {
{0, 128, handle_class_change},
{0, UINT_MAX, handle_strut_partial_change},
{0, UINT_MAX, handle_window_type},
+ {0, UINT_MAX, handle_i3_floating},
{0, 5 * sizeof(uint64_t), handle_motif_hints_change}};
#define NUM_HANDLERS (sizeof(property_handlers) / sizeof(struct property_handler_t))
@@ -1318,12 +1218,15 @@ void property_handlers_init(void) {
property_handlers[7].atom = XCB_ATOM_WM_CLASS;
property_handlers[8].atom = A__NET_WM_STRUT_PARTIAL;
property_handlers[9].atom = A__NET_WM_WINDOW_TYPE;
- property_handlers[10].atom = A__MOTIF_WM_HINTS;
+ property_handlers[10].atom = A_I3_FLOATING_WINDOW;
+ property_handlers[11].atom = A__MOTIF_WM_HINTS;
}
static void property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom) {
struct property_handler_t *handler = NULL;
xcb_get_property_reply_t *propr = NULL;
+ xcb_generic_error_t *err = NULL;
+ Con *con;
for (size_t c = 0; c < NUM_HANDLERS; c++) {
if (property_handlers[c].atom != atom)
@@ -1338,13 +1241,23 @@ static void property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom)
return;
}
+ if ((con = con_by_window_id(window)) == NULL || con->window == NULL) {
+ DLOG("Received property for atom %d for unknown client\n", atom);
+ return;
+ }
+
if (state != XCB_PROPERTY_DELETE) {
xcb_get_property_cookie_t cookie = xcb_get_property(conn, 0, window, atom, XCB_GET_PROPERTY_TYPE_ANY, 0, handler->long_len);
- propr = xcb_get_property_reply(conn, cookie, 0);
+ propr = xcb_get_property_reply(conn, cookie, &err);
+ if (err != NULL) {
+ DLOG("got error %d when getting property of atom %d\n", err->error_code, atom);
+ FREE(err);
+ return;
+ }
}
/* the handler will free() the reply unless it returns false */
- if (!handler->cb(NULL, conn, state, window, atom, propr))
+ if (!handler->cb(con, propr))
FREE(propr);
}
diff --git a/src/ipc.c b/src/ipc.c
index c844409c..1711c526 100644
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -7,23 +7,25 @@
* ipc.c: UNIX domain socket IPC (initialization, client handling, protocol).
*
*/
-#include "all.h"
+#include "all.h"
#include "yajl_utils.h"
+#include <ev.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <locale.h>
#include <stdint.h>
#include <sys/socket.h>
#include <sys/un.h>
-#include <fcntl.h>
-#include <libgen.h>
-#include <ev.h>
+#include <unistd.h>
+
#include <yajl/yajl_gen.h>
#include <yajl/yajl_parse.h>
char *current_socketpath = NULL;
-TAILQ_HEAD(ipc_client_head, ipc_client)
-all_clients = TAILQ_HEAD_INITIALIZER(all_clients);
+TAILQ_HEAD(ipc_client_head, ipc_client) all_clients = TAILQ_HEAD_INITIALIZER(all_clients);
/*
* Puts the given socket file descriptor into non-blocking mode or dies if
@@ -160,7 +162,7 @@ static void free_ipc_client(ipc_client *client, int exempt_fd) {
*/
void ipc_send_event(const char *event, uint32_t message_type, const char *payload) {
ipc_client *current;
- TAILQ_FOREACH(current, &all_clients, clients) {
+ TAILQ_FOREACH (current, &all_clients, clients) {
for (int i = 0; i < current->num_events; i++) {
if (strcasecmp(current->events[i], event) == 0) {
ipc_send_client_message(current, strlen(payload), message_type, (uint8_t *)payload);
@@ -217,15 +219,14 @@ void ipc_shutdown(shutdown_reason_t reason, int exempt_fd) {
}
/*
- * Executes the command and returns whether it could be successfully parsed
- * or not (at the moment, always returns true).
+ * Executes the given command.
*
*/
IPC_HANDLER(run_command) {
/* To get a properly terminated buffer, we copy
* message_size bytes out of the buffer */
char *command = sstrndup((const char *)message, message_size);
- LOG("IPC: received: *%s*\n", command);
+ LOG("IPC: received: *%.4000s*\n", command);
yajl_gen gen = yajl_gen_alloc(NULL);
CommandResult *result = parse_command(command, gen, client);
@@ -410,17 +411,13 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
ystr("urgent");
y(bool, con->urgent);
- if (!TAILQ_EMPTY(&(con->marks_head))) {
- ystr("marks");
- y(array_open);
-
- mark_t *mark;
- TAILQ_FOREACH(mark, &(con->marks_head), marks) {
- ystr(mark->name);
- }
-
- y(array_close);
+ ystr("marks");
+ y(array_open);
+ mark_t *mark;
+ TAILQ_FOREACH (mark, &(con->marks_head), marks) {
+ ystr(mark->name);
}
+ y(array_close);
ystr("focused");
y(bool, (con == focused));
@@ -595,7 +592,7 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
y(array_open);
Con *node;
if (con->type != CT_DOCKAREA || !inplace_restart) {
- TAILQ_FOREACH(node, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (node, &(con->nodes_head), nodes) {
dump_node(gen, node, inplace_restart);
}
}
@@ -603,14 +600,14 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
ystr("floating_nodes");
y(array_open);
- TAILQ_FOREACH(node, &(con->floating_head), floating_windows) {
+ TAILQ_FOREACH (node, &(con->floating_head), floating_windows) {
dump_node(gen, node, inplace_restart);
}
y(array_close);
ystr("focus");
y(array_open);
- TAILQ_FOREACH(node, &(con->focus_head), focused) {
+ TAILQ_FOREACH (node, &(con->focus_head), focused) {
y(integer, (uintptr_t)node);
}
y(array_close);
@@ -640,7 +637,7 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
ystr("swallows");
y(array_open);
Match *match;
- TAILQ_FOREACH(match, &(con->swallow_head), matches) {
+ TAILQ_FOREACH (match, &(con->swallow_head), matches) {
/* We will generate a new restart_mode match specification after this
* loop, so skip this one. */
if (match->restart_mode)
@@ -703,7 +700,7 @@ static void dump_bar_bindings(yajl_gen gen, Barconfig *config) {
y(array_open);
struct Barbinding *current;
- TAILQ_FOREACH(current, &(config->bar_bindings), bindings) {
+ TAILQ_FOREACH (current, &(config->bar_bindings), bindings) {
y(map_open);
ystr("input_code");
@@ -752,7 +749,7 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
y(array_open);
struct tray_output_t *tray_output;
- TAILQ_FOREACH(tray_output, &(config->tray_outputs), tray_outputs) {
+ TAILQ_FOREACH (tray_output, &(config->tray_outputs), tray_outputs) {
ystr(canonicalize_output_name(tray_output->output));
}
@@ -898,11 +895,11 @@ IPC_HANDLER(get_workspaces) {
Con *focused_ws = con_get_workspace(focused);
Con *output;
- TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
+ TAILQ_FOREACH (output, &(croot->nodes_head), nodes) {
if (con_is_internal(output))
continue;
Con *ws;
- TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) {
+ TAILQ_FOREACH (ws, &(output_get_content(output)->nodes_head), nodes) {
assert(ws->type == CT_WORKSPACE);
y(map_open);
@@ -963,7 +960,7 @@ IPC_HANDLER(get_outputs) {
y(array_open);
Output *output;
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
y(map_open);
ystr("name");
@@ -1017,9 +1014,9 @@ IPC_HANDLER(get_marks) {
y(array_open);
Con *con;
- TAILQ_FOREACH(con, &all_cons, all_cons) {
+ TAILQ_FOREACH (con, &all_cons, all_cons) {
mark_t *mark;
- TAILQ_FOREACH(mark, &(con->marks_head), marks) {
+ TAILQ_FOREACH (mark, &(con->marks_head), marks) {
ystr(mark->name);
}
}
@@ -1079,7 +1076,7 @@ IPC_HANDLER(get_bar_config) {
if (message_size == 0) {
y(array_open);
Barconfig *current;
- TAILQ_FOREACH(current, &barconfigs, configs) {
+ TAILQ_FOREACH (current, &barconfigs, configs) {
ystr(current->id);
}
y(array_close);
@@ -1099,7 +1096,7 @@ IPC_HANDLER(get_bar_config) {
sasprintf(&bar_id, "%.*s", message_size, message);
LOG("IPC: looking for config for bar ID \"%s\"\n", bar_id);
Barconfig *current, *config = NULL;
- TAILQ_FOREACH(current, &barconfigs, configs) {
+ TAILQ_FOREACH (current, &barconfigs, configs) {
if (strcmp(current->id, bar_id) != 0)
continue;
@@ -1138,7 +1135,7 @@ IPC_HANDLER(get_binding_modes) {
y(array_open);
struct Mode *mode;
- SLIST_FOREACH(mode, &modes, modes) {
+ SLIST_FOREACH (mode, &modes, modes) {
ystr(mode->name);
}
y(array_close);
@@ -1339,9 +1336,27 @@ IPC_HANDLER(sync) {
ipc_send_client_message(client, strlen(reply), I3_IPC_REPLY_TYPE_SYNC, (const uint8_t *)reply);
}
+IPC_HANDLER(get_binding_state) {
+ yajl_gen gen = ygenalloc();
+
+ y(map_open);
+
+ ystr("name");
+ ystr(current_binding_mode);
+
+ y(map_close);
+
+ const unsigned char *payload;
+ ylength length;
+ y(get_buf, &payload, &length);
+
+ ipc_send_client_message(client, length, I3_IPC_REPLY_TYPE_GET_BINDING_STATE, payload);
+ y(free);
+}
+
/* The index of each callback function corresponds to the numeric
* value of the message type (see include/i3/ipc.h) */
-handler_t handlers[12] = {
+handler_t handlers[13] = {
handle_run_command,
handle_get_workspaces,
handle_subscribe,
@@ -1354,6 +1369,7 @@ handler_t handlers[12] = {
handle_get_config,
handle_send_tick,
handle_sync,
+ handle_get_binding_state,
};
/*
diff --git a/src/load_layout.c b/src/load_layout.c
index 461508c9..bb91ffa4 100644
--- a/src/load_layout.c
+++ b/src/load_layout.c
@@ -10,10 +10,9 @@
*/
#include "all.h"
-#include <yajl/yajl_common.h>
-#include <yajl/yajl_gen.h>
+#include <locale.h>
+
#include <yajl/yajl_parse.h>
-#include <yajl/yajl_version.h>
/* TODO: refactor the whole parsing thing */
@@ -45,9 +44,7 @@ struct pending_marks {
* array. */
struct focus_mapping {
int old_id;
-
- TAILQ_ENTRY(focus_mapping)
- focus_mappings;
+ TAILQ_ENTRY(focus_mapping) focus_mappings;
};
static TAILQ_HEAD(focus_mappings_head, focus_mapping) focus_mappings =
@@ -144,7 +141,7 @@ static int json_end_map(void *ctx) {
if (rect_equals(json_node->rect, (Rect){0, 0, 0, 0})) {
DLOG("Geometry not set, combining children\n");
Con *child;
- TAILQ_FOREACH(child, &(json_node->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(json_node->nodes_head), nodes) {
DLOG("child geometry: %d x %d\n", child->geometry.width, child->geometry.height);
json_node->rect.width += child->geometry.width;
json_node->rect.height = max(json_node->rect.height, child->geometry.height);
@@ -217,10 +214,10 @@ static int json_end_array(void *ctx) {
if (parsing_focus) {
/* Clear the list of focus mappings */
struct focus_mapping *mapping;
- TAILQ_FOREACH_REVERSE(mapping, &focus_mappings, focus_mappings_head, focus_mappings) {
+ TAILQ_FOREACH_REVERSE (mapping, &focus_mappings, focus_mappings_head, focus_mappings) {
LOG("focus (reverse) %d\n", mapping->old_id);
Con *con;
- TAILQ_FOREACH(con, &(json_node->focus_head), focused) {
+ TAILQ_FOREACH (con, &(json_node->focus_head), focused) {
if (con->old_id != mapping->old_id)
continue;
LOG("got it! %p\n", con);
diff --git a/src/log.c b/src/log.c
index 31db8b33..326f82b8 100644
--- a/src/log.c
+++ b/src/log.c
@@ -9,27 +9,24 @@
*/
#include <config.h>
+#include "all.h"
+#include "shmlog.h"
+
+#include <errno.h>
+#include <fcntl.h>
#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
#include <stdbool.h>
+#include <stdio.h>
#include <stdlib.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <fcntl.h>
+#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
-#include <errno.h>
+#include <sys/time.h>
+#include <unistd.h>
#if !defined(__OpenBSD__)
#include <pthread.h>
#endif
-#include "util.h"
-#include "log.h"
-#include "i3.h"
-#include "libi3.h"
-#include "shmlog.h"
-
#if defined(__APPLE__)
#include <sys/sysctl.h>
#endif
diff --git a/src/main.c b/src/main.c
index e4c6b2c9..22019559 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,18 +8,22 @@
*
*/
#include "all.h"
+#include "shmlog.h"
#include <ev.h>
#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/time.h>
-#include <sys/resource.h>
+#include <getopt.h>
+#include <libgen.h>
+#include <locale.h>
+#include <signal.h>
#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
#include <sys/stat.h>
-#include <libgen.h>
-#include "shmlog.h"
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
#ifdef I3_ASAN_ENABLED
#include <sanitizer/lsan_interface.h>
@@ -27,6 +31,9 @@
#include "sd-daemon.h"
+#include "i3-atoms_NET_SUPPORTED.xmacro.h"
+#include "i3-atoms_rest.xmacro.h"
+
/* The original value of RLIMIT_CORE when i3 was started. We need to restore
* this before starting any other process, since we set RLIMIT_CORE to
* RLIM_INFINITY for i3 debugging versions. */
@@ -72,6 +79,7 @@ const int default_shmlog_size = 25 * 1024 * 1024;
/* The list of key bindings */
struct bindings_head *bindings;
+const char *current_binding_mode = NULL;
/* The list of exec-lines */
struct autostarts_head autostarts = TAILQ_HEAD_INITIALIZER(autostarts);
@@ -87,7 +95,6 @@ struct assignments_head assignments = TAILQ_HEAD_INITIALIZER(assignments);
struct ws_assignments_head ws_assignments = TAILQ_HEAD_INITIALIZER(ws_assignments);
/* We hope that those are supported and set them to true */
-bool xcursor_supported = true;
bool xkb_supported = true;
bool shape_supported = true;
@@ -95,7 +102,8 @@ bool force_xinerama = false;
/* Define all atoms as global variables */
#define xmacro(atom) xcb_atom_t A_##atom;
-#include "atoms.xmacro"
+I3_NET_SUPPORTED_ATOMS_XMACRO
+I3_REST_ATOMS_XMACRO
#undef xmacro
/*
@@ -175,6 +183,10 @@ static void i3_exit(void) {
unlink(config.ipc_socket_path);
xcb_disconnect(conn);
+ /* If a nagbar is active, kill it */
+ kill_nagbar(config_error_nagbar_pid, false);
+ kill_nagbar(command_error_nagbar_pid, false);
+
/* We need ev >= 4 for the following code. Since it is not *that* important (it
* only makes sure that there are no i3-nagbar instances left behind) we still
* support old systems with libev 3. */
@@ -373,6 +385,11 @@ int main(int argc, char *argv[]) {
char *socket_path = root_atom_contents("I3_SOCKET_PATH", NULL, 0);
if (socket_path) {
printf("%s\n", socket_path);
+ /* With -O2 (i.e. the buildtype=debugoptimized meson
+ * option, which we set by default), gcc 9.2.1 optimizes
+ * away socket_path at this point, resulting in a Leak
+ * Sanitizer report. An explicit free helps: */
+ free(socket_path);
exit(EXIT_SUCCESS);
}
@@ -556,7 +573,8 @@ int main(int argc, char *argv[]) {
/* 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"
+ I3_NET_SUPPORTED_ATOMS_XMACRO
+ I3_REST_ATOMS_XMACRO
#undef xmacro
root_depth = root_screen->root_depth;
@@ -602,7 +620,8 @@ int main(int argc, char *argv[]) {
A_##name = reply->atom; \
free(reply); \
} while (0);
-#include "atoms.xmacro"
+ I3_NET_SUPPORTED_ATOMS_XMACRO
+ I3_REST_ATOMS_XMACRO
#undef xmacro
load_configuration(override_configpath, C_LOAD);
@@ -641,10 +660,7 @@ int main(int argc, char *argv[]) {
/* Set a cursor for the root window (otherwise the root window will show no
cursor until the first client is launched). */
- if (xcursor_supported)
- xcursor_set_root_cursor(XCURSOR_CURSOR_POINTER);
- else
- xcb_set_root_cursor(XCURSOR_CURSOR_POINTER);
+ xcursor_set_root_cursor(XCURSOR_CURSOR_POINTER);
const xcb_query_extension_reply_t *extreply;
xcb_prefetch_extension_data(conn, &xcb_xkb_id);
@@ -785,9 +801,9 @@ int main(int argc, char *argv[]) {
* and restarting i3. See #2326. */
if (layout_path != NULL && randr_base > -1) {
Con *con;
- TAILQ_FOREACH(con, &(croot->nodes_head), nodes) {
+ TAILQ_FOREACH (con, &(croot->nodes_head), nodes) {
Output *output;
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
if (output->active || strcmp(con->name, output_primary_name(output)) != 0)
continue;
@@ -1010,10 +1026,10 @@ int main(int argc, char *argv[]) {
/* Start i3bar processes for all configured bars */
Barconfig *barconfig;
- TAILQ_FOREACH(barconfig, &barconfigs, configs) {
+ TAILQ_FOREACH (barconfig, &barconfigs, configs) {
char *command = NULL;
sasprintf(&command, "%s %s --bar_id=%s --socket=\"%s\"",
- barconfig->i3bar_command ? barconfig->i3bar_command : "i3bar",
+ barconfig->i3bar_command ? barconfig->i3bar_command : "exec i3bar",
barconfig->verbose ? "-V" : "",
barconfig->id, current_socketpath);
LOG("Starting bar process: %s\n", command);
diff --git a/src/manage.c b/src/manage.c
index 8b56fd6e..da23ab3e 100644
--- a/src/manage.c
+++ b/src/manage.c
@@ -9,10 +9,6 @@
*/
#include "all.h"
-#include "yajl_utils.h"
-
-#include <yajl/yajl_gen.h>
-
/*
* Match frame and window depth. This is needed because X will refuse to reparent a
* window whose background is ParentRelative under a window with a different depth.
@@ -29,7 +25,7 @@ static xcb_window_t _match_depth(i3Window *win, Con *con) {
}
/*
- * Remove all match criteria, the first swallowed window wins.
+ * Remove all match criteria, the first swallowed window wins.
*
*/
static void _remove_matches(Con *con) {
@@ -83,15 +79,16 @@ void restore_geometry(void) {
DLOG("Restoring geometry\n");
Con *con;
- TAILQ_FOREACH(con, &all_cons, all_cons)
- if (con->window) {
- DLOG("Re-adding X11 border of %d px\n", con->border_width);
- con->window_rect.width += (2 * con->border_width);
- con->window_rect.height += (2 * con->border_width);
- xcb_set_window_rect(conn, con->window->id, con->window_rect);
- DLOG("placing window %08x at %d %d\n", con->window->id, con->rect.x, con->rect.y);
- xcb_reparent_window(conn, con->window->id, root,
- con->rect.x, con->rect.y);
+ TAILQ_FOREACH (con, &all_cons, all_cons) {
+ if (con->window) {
+ DLOG("Re-adding X11 border of %d px\n", con->border_width);
+ con->window_rect.width += (2 * con->border_width);
+ con->window_rect.height += (2 * con->border_width);
+ xcb_set_window_rect(conn, con->window->id, con->window_rect);
+ DLOG("placing window %08x at %d %d\n", con->window->id, con->rect.x, con->rect.y);
+ xcb_reparent_window(conn, con->window->id, root,
+ con->rect.x, con->rect.y);
+ }
}
/* Strictly speaking, this line doesn’t really belong here, but since we
@@ -273,6 +270,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
DLOG("Initial geometry: (%d, %d, %d, %d)\n", geom->x, geom->y, geom->width, geom->height);
/* See if any container swallows this new window */
+ cwindow->swallowed = false;
Match *match = NULL;
Con *nc = con_for_window(search_at, cwindow, &match);
const bool match_from_restart_mode = (match && match->restart_mode);
@@ -294,7 +292,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
/* A_TO_WORKSPACE type assignment or fallback from A_TO_WORKSPACE_NUMBER
* when the target workspace number does not exist yet. */
if (!assigned_ws) {
- assigned_ws = workspace_get(assignment->dest.workspace, NULL);
+ assigned_ws = workspace_get(assignment->dest.workspace);
}
nc = con_descend_tiling_focused(assigned_ws);
@@ -325,7 +323,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
} else if (startup_ws) {
/* If it was started on a specific workspace, we want to open it there. */
DLOG("Using workspace on which this application was started (%s)\n", startup_ws);
- nc = con_descend_tiling_focused(workspace_get(startup_ws, NULL));
+ nc = con_descend_tiling_focused(workspace_get(startup_ws));
DLOG("focused on ws %s: %p / %s\n", startup_ws, nc, nc->name);
if (nc->type == CT_WORKSPACE)
nc = tree_open_con(nc, cwindow);
@@ -361,6 +359,8 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
match_free(match);
FREE(match);
}
+
+ cwindow->swallowed = true;
}
DLOG("new container = %p\n", nc);
@@ -536,7 +536,9 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
* was not specified */
bool automatic_border = (motif_border_style == BS_NORMAL);
- floating_enable(nc, automatic_border);
+ if (floating_enable(nc, automatic_border)) {
+ nc->floating = FLOATING_AUTO_ON;
+ }
}
/* explicitly set the border width to the default */
@@ -696,6 +698,11 @@ out:
*
*/
Con *remanage_window(Con *con) {
+ /* Make sure this windows hasn't already been swallowed. */
+ if (con->window->swallowed) {
+ run_assignments(con->window);
+ return con;
+ }
Match *match;
Con *nc = con_for_window(croot, con->window, &match);
if (nc == NULL || nc->window == NULL || nc->window == con->window) {
@@ -741,5 +748,6 @@ Con *remanage_window(Con *con) {
ewmh_update_wm_desktop();
}
+ nc->window->swallowed = true;
return nc;
}
diff --git a/src/match.c b/src/match.c
index 83e37327..6ac312e5 100644
--- a/src/match.c
+++ b/src/match.c
@@ -92,11 +92,9 @@ bool match_matches_window(Match *match, i3Window *window) {
#define CHECK_WINDOW_FIELD(match_field, window_field, type) \
do { \
if (match->match_field != NULL) { \
- if (window->window_field == NULL) { \
- return false; \
- } \
- \
- const char *window_field_str = GET_FIELD_##type(window->window_field); \
+ const char *window_field_str = window->window_field == NULL \
+ ? "" \
+ : GET_FIELD_##type(window->window_field); \
if (strcmp(match->match_field->pattern, "__focused__") == 0 && \
focused && focused->window && focused->window->window_field && \
strcmp(window_field_str, GET_FIELD_##type(focused->window->window_field)) == 0) { \
@@ -139,7 +137,7 @@ bool match_matches_window(Match *match, i3Window *window) {
return false;
}
/* if we find a window that is newer than this one, bail */
- TAILQ_FOREACH(con, &all_cons, all_cons) {
+ TAILQ_FOREACH (con, &all_cons, all_cons) {
if ((con->window != NULL) &&
_i3_timercmp(con->window->urgent, window->urgent, >)) {
return false;
@@ -154,7 +152,7 @@ bool match_matches_window(Match *match, i3Window *window) {
return false;
}
/* if we find a window that is older than this one (and not 0), bail */
- TAILQ_FOREACH(con, &all_cons, all_cons) {
+ TAILQ_FOREACH (con, &all_cons, all_cons) {
if ((con->window != NULL) &&
(con->window->urgent.tv_sec != 0) &&
_i3_timercmp(con->window->urgent, window->urgent, <)) {
@@ -201,7 +199,7 @@ bool match_matches_window(Match *match, i3Window *window) {
bool matched = false;
mark_t *mark;
- TAILQ_FOREACH(mark, &(con->marks_head), marks) {
+ TAILQ_FOREACH (mark, &(con->marks_head), marks) {
if (regex_matches(match->mark, mark->name)) {
matched = true;
break;
@@ -217,15 +215,43 @@ bool match_matches_window(Match *match, i3Window *window) {
}
if (match->window_mode != WM_ANY) {
- if ((con = con_by_window_id(window->id)) == NULL)
+ if ((con = con_by_window_id(window->id)) == NULL) {
return false;
+ }
- const bool floating = (con_inside_floating(con) != NULL);
-
- if ((match->window_mode == WM_TILING && floating) ||
- (match->window_mode == WM_FLOATING && !floating)) {
- LOG("window_mode does not match\n");
- return false;
+ switch (match->window_mode) {
+ case WM_TILING_AUTO:
+ if (con->floating != FLOATING_AUTO_OFF) {
+ return false;
+ }
+ break;
+ case WM_TILING_USER:
+ if (con->floating != FLOATING_USER_OFF) {
+ return false;
+ }
+ break;
+ case WM_TILING:
+ if (con_inside_floating(con) != NULL) {
+ return false;
+ }
+ break;
+ case WM_FLOATING_AUTO:
+ if (con->floating != FLOATING_AUTO_ON) {
+ return false;
+ }
+ break;
+ case WM_FLOATING_USER:
+ if (con->floating != FLOATING_USER_ON) {
+ return false;
+ }
+ break;
+ case WM_FLOATING:
+ if (con_inside_floating(con) == NULL) {
+ return false;
+ }
+ break;
+ case WM_ANY:
+ assert(false);
}
LOG("window_mode matches\n");
@@ -369,10 +395,38 @@ void match_parse_property(Match *match, const char *ctype, const char *cvalue) {
return;
}
+ if (strcmp(ctype, "tiling_from") == 0 &&
+ cvalue != NULL &&
+ strcmp(cvalue, "auto") == 0) {
+ match->window_mode = WM_TILING_AUTO;
+ return;
+ }
+
+ if (strcmp(ctype, "tiling_from") == 0 &&
+ cvalue != NULL &&
+ strcmp(cvalue, "user") == 0) {
+ match->window_mode = WM_TILING_USER;
+ return;
+ }
+
if (strcmp(ctype, "floating") == 0) {
match->window_mode = WM_FLOATING;
return;
}
+ if (strcmp(ctype, "floating_from") == 0 &&
+ cvalue != NULL &&
+ strcmp(cvalue, "auto") == 0) {
+ match->window_mode = WM_FLOATING_AUTO;
+ return;
+ }
+
+ if (strcmp(ctype, "floating_from") == 0 &&
+ cvalue != NULL &&
+ strcmp(cvalue, "user") == 0) {
+ match->window_mode = WM_FLOATING_USER;
+ return;
+ }
+
ELOG("Unknown criterion: %s\n", ctype);
}
diff --git a/src/move.c b/src/move.c
index 298e1a06..967b4c02 100644
--- a/src/move.c
+++ b/src/move.c
@@ -91,7 +91,7 @@ void insert_con_into(Con *con, Con *target, position_t position) {
} else {
/* Look at the focus stack order of the children of the lowest common ancestor. */
Con *current;
- TAILQ_FOREACH(current, &(lca->focus_head), focused) {
+ TAILQ_FOREACH (current, &(lca->focus_head), focused) {
if (current == con_ancestor || current == target_ancestor) {
break;
}
diff --git a/src/output.c b/src/output.c
index 3d931b1b..1c22e1cf 100644
--- a/src/output.c
+++ b/src/output.c
@@ -16,9 +16,11 @@
Con *output_get_content(Con *output) {
Con *child;
- TAILQ_FOREACH(child, &(output->nodes_head), nodes)
- if (child->type == CT_CON)
- return child;
+ TAILQ_FOREACH (child, &(output->nodes_head), nodes) {
+ if (child->type == CT_CON) {
+ return child;
+ }
+ }
return NULL;
}
@@ -74,7 +76,7 @@ Output *get_output_for_con(Con *con) {
*/
void output_push_sticky_windows(Con *old_focus) {
Con *output;
- TAILQ_FOREACH(output, &(croot->focus_head), focused) {
+ TAILQ_FOREACH (output, &(croot->focus_head), focused) {
Con *workspace, *visible_ws = NULL;
GREP_FIRST(visible_ws, output_get_content(output), workspace_is_visible(child));
diff --git a/src/randr.c b/src/randr.c
index 1e87a7db..8e000ca6 100644
--- a/src/randr.c
+++ b/src/randr.c
@@ -12,6 +12,7 @@
#include "all.h"
#include <time.h>
+
#include <xcb/randr.h>
/* Pointer to the result of the query for primary output */
@@ -32,9 +33,11 @@ static bool has_randr_1_5 = false;
*/
static Output *get_output_by_id(xcb_randr_output_t id) {
Output *output;
- TAILQ_FOREACH(output, &outputs, outputs)
- if (output->id == id)
- return output;
+ TAILQ_FOREACH (output, &outputs, outputs) {
+ if (output->id == id) {
+ return output;
+ }
+ }
return NULL;
}
@@ -47,7 +50,7 @@ static Output *get_output_by_id(xcb_randr_output_t id) {
Output *get_output_by_name(const char *name, const bool require_active) {
Output *output;
bool get_primary = (strcasecmp("primary", name) == 0);
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
if (require_active && !output->active) {
continue;
}
@@ -55,7 +58,7 @@ Output *get_output_by_name(const char *name, const bool require_active) {
return output;
}
struct output_name *output_name;
- SLIST_FOREACH(output_name, &output->names_head, names) {
+ SLIST_FOREACH (output_name, &output->names_head, names) {
if (strcasecmp(output_name->name, name) == 0) {
return output;
}
@@ -72,7 +75,7 @@ Output *get_output_by_name(const char *name, const bool require_active) {
Output *get_first_output(void) {
Output *output, *result = NULL;
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
if (output->active) {
if (output->primary) {
return output;
@@ -97,7 +100,7 @@ Output *get_first_output(void) {
static bool any_randr_output_active(void) {
Output *output;
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
if (output != root_output && !output->to_be_disabled && output->active)
return true;
}
@@ -112,7 +115,7 @@ static bool any_randr_output_active(void) {
*/
Output *get_output_containing(unsigned int x, unsigned int y) {
Output *output;
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
if (!output->active)
continue;
DLOG("comparing x=%d y=%d with x=%d and y=%d width %d height %d\n",
@@ -146,7 +149,7 @@ Output *get_output_from_rect(Rect rect) {
*/
Output *get_output_with_dimensions(Rect rect) {
Output *output;
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
if (!output->active)
continue;
DLOG("comparing x=%d y=%d %dx%d with x=%d and y=%d %dx%d\n",
@@ -173,7 +176,7 @@ Output *output_containing_rect(Rect rect) {
int rx = rect.x + rect.width, by = rect.y + rect.height;
long max_area = 0;
Output *result = NULL;
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
if (!output->active)
continue;
int lx_o = (int)output->rect.x, uy_o = (int)output->rect.y;
@@ -241,7 +244,7 @@ Output *get_output_next(direction_t direction, Output *current, output_close_far
*other;
Output *output,
*best = NULL;
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
if (!output->active)
continue;
@@ -331,7 +334,7 @@ void output_init_con(Output *output) {
/* Search for a Con with that name directly below the root node. There
* might be one from a restored layout. */
- TAILQ_FOREACH(current, &(croot->nodes_head), nodes) {
+ TAILQ_FOREACH (current, &(croot->nodes_head), nodes) {
if (strcmp(current->name, output_primary_name(output)) != 0)
continue;
@@ -435,34 +438,29 @@ void init_ws_for_output(Output *output) {
Con *content = output_get_content(output->con);
Con *previous_focus = con_get_workspace(focused);
- /* go through all assignments and move the existing workspaces to this output */
- struct Workspace_Assignment *assignment;
- TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
- if (!output_triggers_assignment(output, assignment)) {
+ /* Iterate over all workspaces and check if any of them should be assigned
+ * to this output. */
+ Con *output_con;
+ TAILQ_FOREACH (output_con, &(croot->nodes_head), nodes) {
+ if (con_is_internal(output_con)) {
continue;
}
- Con *workspace = get_existing_workspace_by_name(assignment->name);
- if (workspace == NULL)
- continue;
- /* check that this workspace is not already attached (that means the
- * user configured this assignment twice) */
- Con *workspace_out = con_get_output(workspace);
- if (workspace_out == output->con) {
- LOG("Workspace \"%s\" assigned to output \"%s\", but it is already "
- "there. Do you have two assignment directives for the same "
- "workspace in your configuration file?\n",
- workspace->name, output_primary_name(output));
- continue;
- }
+ Con *workspace;
+ TAILQ_FOREACH (workspace, &(output_get_content(output_con)->nodes_head), nodes) {
+ Con *workspace_out = get_assigned_output(workspace->name, workspace->num);
+ if (output->con != workspace_out) {
+ continue;
+ }
- DLOG("Moving workspace \"%s\" from output \"%s\" to \"%s\" due to assignment\n",
- workspace->name, workspace_out->name, output_primary_name(output));
- /* Need to copy output's rect since content is not yet rendered. We
- * can't call render_con here because render_output only proceeds if a
- * workspace exists. */
- content->rect = output->con->rect;
- workspace_move_to_output(workspace, output);
+ DLOG("Moving workspace \"%s\" from output \"%s\" to \"%s\" due to assignment\n",
+ workspace->name, workspace_out->name, output_primary_name(output));
+ /* Need to copy output's rect since content is not yet rendered. We
+ * can't call render_con here because render_output only proceeds
+ * if a workspace exists. */
+ content->rect = output->con->rect;
+ workspace_move_to_output(workspace, output);
+ }
}
/* Temporarily set the focused container, might not be initialized yet. */
@@ -482,7 +480,8 @@ void init_ws_for_output(Output *output) {
}
/* otherwise, we create the first assigned ws for this output */
- TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
+ struct Workspace_Assignment *assignment;
+ TAILQ_FOREACH (assignment, &ws_assignments, ws_assignments) {
if (!output_triggers_assignment(output, assignment)) {
continue;
}
@@ -526,8 +525,8 @@ static void output_change_mode(xcb_connection_t *conn, Output *output) {
/* Fix the position of all floating windows on this output.
* The 'rect' of each workspace will be updated in src/render.c. */
- TAILQ_FOREACH(workspace, &(content->nodes_head), nodes) {
- TAILQ_FOREACH(child, &(workspace->floating_head), floating_windows) {
+ TAILQ_FOREACH (workspace, &(content->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(workspace->floating_head), floating_windows) {
floating_fix_coordinates(child, &(workspace->rect), &(output->con->rect));
}
}
@@ -536,7 +535,7 @@ static void output_change_mode(xcb_connection_t *conn, Output *output) {
* the workspaces and their children depending on output resolution. This is
* only done for workspaces with maximum one child. */
if (config.default_orientation == NO_ORIENTATION) {
- TAILQ_FOREACH(workspace, &(content->nodes_head), nodes) {
+ TAILQ_FOREACH (workspace, &(content->nodes_head), nodes) {
/* Workspaces with more than one child are left untouched because
* we do not want to change an existing layout. */
if (con_num_children(workspace) > 1)
@@ -582,7 +581,7 @@ static bool randr_query_outputs_15(void) {
/* Mark all outputs as to_be_disabled, since xcb_randr_get_monitors() will
* only return active outputs. */
Output *output;
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
if (output != root_output) {
output->to_be_disabled = true;
}
@@ -825,6 +824,76 @@ static void randr_query_outputs_14(void) {
}
/*
+ * Move the content of an outputs container to the first output.
+ *
+ * TODO: Maybe use an on_destroy callback which is implement differently for
+ * different container types (CT_CONTENT vs. CT_DOCKAREA)?
+ *
+ */
+static void move_content(Con *con) {
+ Con *first = get_first_output()->con;
+ Con *first_content = output_get_content(first);
+
+ /* We need to move the workspaces from the disappearing output to the first output */
+ /* 1: Get the con to focus next */
+ Con *next = focused;
+
+ /* 2: iterate through workspaces and re-assign them, fixing the coordinates
+ * of floating containers as we go */
+ Con *current;
+ Con *old_content = output_get_content(con);
+ while (!TAILQ_EMPTY(&(old_content->nodes_head))) {
+ current = TAILQ_FIRST(&(old_content->nodes_head));
+ if (current != next && TAILQ_EMPTY(&(current->focus_head))) {
+ /* the workspace is empty and not focused, get rid of it */
+ DLOG("Getting rid of current = %p / %s (empty, unfocused)\n", current, current->name);
+ tree_close_internal(current, DONT_KILL_WINDOW, false);
+ continue;
+ }
+ DLOG("Detaching current = %p / %s\n", current, current->name);
+ con_detach(current);
+ DLOG("Re-attaching current = %p / %s\n", current, current->name);
+ con_attach(current, first_content, false);
+ DLOG("Fixing the coordinates of floating containers\n");
+ Con *floating_con;
+ TAILQ_FOREACH (floating_con, &(current->floating_head), floating_windows) {
+ floating_fix_coordinates(floating_con, &(con->rect), &(first->rect));
+ }
+ }
+
+ /* Restore focus after con_detach / con_attach. next can be NULL, see #3523. */
+ if (next) {
+ DLOG("now focusing next = %p\n", next);
+ con_focus(next);
+ workspace_show(con_get_workspace(next));
+ }
+
+ /* 3: move the dock clients to the first output */
+ Con *child;
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
+ if (child->type != CT_DOCKAREA) {
+ continue;
+ }
+ DLOG("Handling dock con %p\n", child);
+ Con *dock;
+ while (!TAILQ_EMPTY(&(child->nodes_head))) {
+ dock = TAILQ_FIRST(&(child->nodes_head));
+ Con *nc;
+ Match *match;
+ nc = con_for_window(first, dock->window, &match);
+ DLOG("Moving dock client %p to nc %p\n", dock, nc);
+ con_detach(dock);
+ DLOG("Re-attaching\n");
+ con_attach(dock, nc, false);
+ DLOG("Done\n");
+ }
+ }
+
+ DLOG("Destroying disappearing con %p\n", con);
+ tree_close_internal(con, DONT_KILL_WINDOW, true);
+}
+
+/*
* (Re-)queries the outputs via RandR and stores them in the list of outputs.
*
* If no outputs are found use the root window.
@@ -850,7 +919,7 @@ void randr_query_outputs(void) {
/* Check for clones, disable the clones and reduce the mode to the
* lowest common mode */
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
if (!output->active || output->to_be_disabled)
continue;
DLOG("output %p / %s, position (%d, %d), checking for clones\n",
@@ -866,7 +935,7 @@ void randr_query_outputs(void) {
other->rect.y != output->rect.y)
continue;
- DLOG("output %p has the same position, his mode = %d x %d\n",
+ DLOG("output %p has the same position, its mode = %d x %d\n",
other, other->rect.width, other->rect.height);
uint32_t width = min(other->rect.width, output->rect.width);
uint32_t height = min(other->rect.height, output->rect.height);
@@ -891,7 +960,7 @@ void randr_query_outputs(void) {
* necessary because in the next step, a clone might get disabled. Example:
* LVDS1 active, VGA1 gets activated as a clone of LVDS1 (has no con).
* LVDS1 gets disabled. */
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
if (output->active && output->con == NULL) {
DLOG("Need to initialize a Con for output %s\n", output_primary_name(output));
output_init_con(output);
@@ -899,9 +968,24 @@ void randr_query_outputs(void) {
}
}
+ /* Ensure that all containers with type CT_OUTPUT have a valid
+ * corresponding entry in outputs. This can happen in situations related to
+ * those mentioned #3767 e.g. when a CT_OUTPUT is created from an in-place
+ * restart's layout but the output is disabled by a randr query happening
+ * at the same time. */
+ Con *con;
+ for (con = TAILQ_FIRST(&(croot->nodes_head)); con;) {
+ Con *next = TAILQ_NEXT(con, nodes);
+ if (!con_is_internal(con) && get_output_by_name(con->name, true) == NULL) {
+ DLOG("No output %s found, moving its old content to first output\n", con->name);
+ move_content(con);
+ }
+ con = next;
+ }
+
/* Handle outputs which have a new mode or are disabled now (either
* because the user disabled them or because they are clones) */
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
if (output->to_be_disabled) {
randr_disable_output(output);
}
@@ -913,7 +997,7 @@ void randr_query_outputs(void) {
}
/* Just go through each active output and assign one workspace */
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
if (!output->active)
continue;
Con *content = output_get_content(output->con);
@@ -924,7 +1008,7 @@ void randr_query_outputs(void) {
}
/* Focus the primary screen, if possible */
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
if (!output->primary || !output->con)
continue;
@@ -935,6 +1019,7 @@ void randr_query_outputs(void) {
}
/* render_layout flushes */
+ ewmh_update_desktop_properties();
tree_render();
FREE(primary);
@@ -950,74 +1035,11 @@ void randr_disable_output(Output *output) {
output->active = false;
DLOG("Output %s disabled, re-assigning workspaces/docks\n", output_primary_name(output));
- Output *first = get_first_output();
-
- /* TODO: refactor the following code into a nice function. maybe
- * use an on_destroy callback which is implement differently for
- * different container types (CT_CONTENT vs. CT_DOCKAREA)? */
- Con *first_content = output_get_content(first->con);
-
if (output->con != NULL) {
- /* We need to move the workspaces from the disappearing output to the first output */
- /* 1: Get the con to focus next */
- Con *next = focused;
-
- /* 2: iterate through workspaces and re-assign them, fixing the coordinates
- * of floating containers as we go */
- Con *current;
- Con *old_content = output_get_content(output->con);
- while (!TAILQ_EMPTY(&(old_content->nodes_head))) {
- current = TAILQ_FIRST(&(old_content->nodes_head));
- if (current != next && TAILQ_EMPTY(&(current->focus_head))) {
- /* the workspace is empty and not focused, get rid of it */
- DLOG("Getting rid of current = %p / %s (empty, unfocused)\n", current, current->name);
- tree_close_internal(current, DONT_KILL_WINDOW, false);
- continue;
- }
- DLOG("Detaching current = %p / %s\n", current, current->name);
- con_detach(current);
- DLOG("Re-attaching current = %p / %s\n", current, current->name);
- con_attach(current, first_content, false);
- DLOG("Fixing the coordinates of floating containers\n");
- Con *floating_con;
- TAILQ_FOREACH(floating_con, &(current->floating_head), floating_windows) {
- floating_fix_coordinates(floating_con, &(output->con->rect), &(first->con->rect));
- }
- }
-
- /* Restore focus after con_detach / con_attach. next can be NULL, see #3523. */
- if (next) {
- DLOG("now focusing next = %p\n", next);
- con_focus(next);
- workspace_show(con_get_workspace(next));
- }
-
- /* 3: move the dock clients to the first output */
- Con *child;
- TAILQ_FOREACH(child, &(output->con->nodes_head), nodes) {
- if (child->type != CT_DOCKAREA)
- continue;
- DLOG("Handling dock con %p\n", child);
- Con *dock;
- while (!TAILQ_EMPTY(&(child->nodes_head))) {
- dock = TAILQ_FIRST(&(child->nodes_head));
- Con *nc;
- Match *match;
- nc = con_for_window(first->con, dock->window, &match);
- DLOG("Moving dock client %p to nc %p\n", dock, nc);
- con_detach(dock);
- DLOG("Re-attaching\n");
- con_attach(dock, nc, false);
- DLOG("Done\n");
- }
- }
-
- DLOG("destroying disappearing con %p\n", output->con);
+ /* clear the pointer before move_content calls tree_close_internal in which the memory is freed */
Con *con = output->con;
- /* clear the pointer before calling tree_close_internal in which the memory is freed */
output->con = NULL;
- tree_close_internal(con, DONT_KILL_WINDOW, true);
- DLOG("Done. Should be fine now\n");
+ move_content(con);
}
output->to_be_disabled = false;
diff --git a/src/render.c b/src/render.c
index 42992f3a..cf4fd45f 100644
--- a/src/render.c
+++ b/src/render.c
@@ -10,6 +10,8 @@
*/
#include "all.h"
+#include <math.h>
+
/* Forward declarations */
static int *precalculate_sizes(Con *con, render_params *p);
static void render_root(Con *con, Con *fullscreen);
@@ -64,6 +66,8 @@ void render_con(Con *con) {
inset->width -= (2 * con->border_width);
inset->height -= (2 * con->border_width);
+ *inset = rect_sanitize_dimensions(*inset);
+
/* NB: We used to respect resize increment size hints for tiling
* windows up until commit 0db93d9 here. However, since all terminal
* emulators cope with ignoring the size hints in a better way than we
@@ -108,7 +112,7 @@ void render_con(Con *con) {
render_root(con, fullscreen);
} else {
Con *child;
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
assert(params.children > 0);
if (con->layout == L_SPLITH || con->layout == L_SPLITV) {
@@ -121,6 +125,8 @@ void render_con(Con *con) {
render_con_dockarea(con, child, &params);
}
+ child->rect = rect_sanitize_dimensions(child->rect);
+
DLOG("child at (%d, %d) with (%d x %d)\n",
child->rect.x, child->rect.y, child->rect.width, child->rect.height);
x_raise_con(child);
@@ -130,8 +136,9 @@ void render_con(Con *con) {
/* in a stacking or tabbed container, we ensure the focused client is raised */
if (con->layout == L_STACKED || con->layout == L_TABBED) {
- TAILQ_FOREACH_REVERSE(child, &(con->focus_head), focus_head, focused)
- x_raise_con(child);
+ TAILQ_FOREACH_REVERSE (child, &(con->focus_head), focus_head, focused) {
+ x_raise_con(child);
+ }
if ((child = TAILQ_FIRST(&(con->focus_head)))) {
/* By rendering the stacked container again, we handle the case
* that we have a non-leaf-container inside the stack. In that
@@ -164,7 +171,7 @@ static int *precalculate_sizes(Con *con, render_params *p) {
Con *child;
int i = 0, assigned = 0;
int total = con_rect_size_in_orientation(con);
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
double percentage = child->percent > 0.0 ? child->percent : 1.0 / p->children;
assigned += sizes[i++] = lround(percentage * total);
}
@@ -185,7 +192,7 @@ static int *precalculate_sizes(Con *con, render_params *p) {
static void render_root(Con *con, Con *fullscreen) {
Con *output;
if (!fullscreen) {
- TAILQ_FOREACH(output, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (output, &(con->nodes_head), nodes) {
render_con(output);
}
}
@@ -195,7 +202,7 @@ static void render_root(Con *con, Con *fullscreen) {
* all times. This is important when the user places floating
* windows/containers so that they overlap on another output. */
DLOG("Rendering floating windows:\n");
- TAILQ_FOREACH(output, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (output, &(con->nodes_head), nodes) {
if (con_is_internal(output))
continue;
/* Get the active workspace of that output */
@@ -207,7 +214,7 @@ static void render_root(Con *con, Con *fullscreen) {
Con *workspace = TAILQ_FIRST(&(content->focus_head));
Con *fullscreen = con_get_fullscreen_covering_ws(workspace);
Con *child;
- TAILQ_FOREACH(child, &(workspace->floating_head), floating_windows) {
+ TAILQ_FOREACH (child, &(workspace->floating_head), floating_windows) {
if (fullscreen != NULL) {
/* Don’t render floating windows when there is a fullscreen
* window on that workspace. Necessary to make floating
@@ -272,7 +279,7 @@ static void render_output(Con *con) {
/* Find the content container and ensure that there is exactly one. Also
* check for any non-CT_DOCKAREA clients. */
Con *content = NULL;
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
if (child->type == CT_CON) {
if (content != NULL) {
DLOG("More than one CT_CON on output container\n");
@@ -308,19 +315,20 @@ static void render_output(Con *con) {
/* First pass: determine the height of all CT_DOCKAREAs (the sum of their
* children) and figure out how many pixels we have left for the rest */
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
if (child->type != CT_DOCKAREA)
continue;
child->rect.height = 0;
- TAILQ_FOREACH(dockchild, &(child->nodes_head), nodes)
- child->rect.height += dockchild->geometry.height;
+ TAILQ_FOREACH (dockchild, &(child->nodes_head), nodes) {
+ child->rect.height += dockchild->geometry.height;
+ }
height -= child->rect.height;
}
/* Second pass: Set the widths/heights */
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
if (child->type == CT_CON) {
child->rect.x = x;
child->rect.y = y;
@@ -418,7 +426,7 @@ static void render_con_tabbed(Con *con, Con *child, render_params *p, int i) {
/* Since the tab width may be something like 31,6 px per tab, we
* let the last tab have all the extra space (0,6 * children). */
if (i == (p->children - 1)) {
- child->deco_rect.width += (child->rect.width - (child->deco_rect.x + child->deco_rect.width));
+ child->deco_rect.width = child->rect.width - child->deco_rect.x;
}
if (p->children > 1 || (child->border_style != BS_PIXEL && child->border_style != BS_NONE)) {
diff --git a/src/resize.c b/src/resize.c
index 97a0f946..6ad92cc0 100644
--- a/src/resize.c
+++ b/src/resize.c
@@ -238,6 +238,10 @@ void resize_graphical_handler(Con *first, Con *second, orientation_t orientation
const struct callback_params params = {orientation, output, helpwin, &new_position, &threshold_exceeded};
+ /* Re-render the tree before returning to the event loop (drag_pointer()
+ * runs its own event-loop) in case if there are unrendered updates. */
+ tree_render();
+
/* `drag_pointer' blocks until the drag is completed. */
drag_result_t drag_result = drag_pointer(NULL, event, grabwin, 0, use_threshold, resize_callback, &params);
diff --git a/src/restore_layout.c b/src/restore_layout.c
index 186c0907..c51bfcbe 100644
--- a/src/restore_layout.c
+++ b/src/restore_layout.c
@@ -29,8 +29,7 @@ typedef struct placeholder_state {
/** The drawable surface */
surface_t surface;
- TAILQ_ENTRY(placeholder_state)
- state;
+ TAILQ_ENTRY(placeholder_state) state;
} placeholder_state;
static TAILQ_HEAD(state_head, placeholder_state) state_head =
@@ -140,7 +139,7 @@ static void update_placeholder_contents(placeholder_state *state) {
Match *swallows;
int n = 0;
- TAILQ_FOREACH(swallows, &(state->con->swallow_head), matches) {
+ TAILQ_FOREACH (swallows, &(state->con->swallow_head), matches) {
char *serialized = NULL;
#define APPEND_REGEX(re_name) \
@@ -234,10 +233,10 @@ static void open_placeholder_window(Con *con) {
}
Con *child;
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
open_placeholder_window(child);
}
- TAILQ_FOREACH(child, &(con->floating_head), floating_windows) {
+ TAILQ_FOREACH (child, &(con->floating_head), floating_windows) {
open_placeholder_window(child);
}
}
@@ -251,10 +250,10 @@ static void open_placeholder_window(Con *con) {
*/
void restore_open_placeholder_windows(Con *parent) {
Con *child;
- TAILQ_FOREACH(child, &(parent->nodes_head), nodes) {
+ TAILQ_FOREACH (child, &(parent->nodes_head), nodes) {
open_placeholder_window(child);
}
- TAILQ_FOREACH(child, &(parent->floating_head), floating_windows) {
+ TAILQ_FOREACH (child, &(parent->floating_head), floating_windows) {
open_placeholder_window(child);
}
@@ -270,7 +269,7 @@ void restore_open_placeholder_windows(Con *parent) {
*/
bool restore_kill_placeholder(xcb_window_t placeholder) {
placeholder_state *state;
- TAILQ_FOREACH(state, &state_head, state) {
+ TAILQ_FOREACH (state, &state_head, state) {
if (state->window != placeholder)
continue;
@@ -288,7 +287,7 @@ bool restore_kill_placeholder(xcb_window_t placeholder) {
static void expose_event(xcb_expose_event_t *event) {
placeholder_state *state;
- TAILQ_FOREACH(state, &state_head, state) {
+ TAILQ_FOREACH (state, &state_head, state) {
if (state->window != event->window)
continue;
@@ -310,7 +309,7 @@ static void expose_event(xcb_expose_event_t *event) {
*/
static void configure_notify(xcb_configure_notify_event_t *event) {
placeholder_state *state;
- TAILQ_FOREACH(state, &state_head, state) {
+ TAILQ_FOREACH (state, &state_head, state) {
if (state->window != event->window)
continue;
diff --git a/src/scratchpad.c b/src/scratchpad.c
index cce4c0bf..24cde612 100644
--- a/src/scratchpad.c
+++ b/src/scratchpad.c
@@ -32,7 +32,7 @@ void scratchpad_move(Con *con) {
}
DLOG("should move con %p to __i3_scratch\n", con);
- Con *__i3_scratch = workspace_get("__i3_scratch", NULL);
+ Con *__i3_scratch = workspace_get("__i3_scratch");
if (con_get_workspace(con) == __i3_scratch) {
DLOG("This window is already on __i3_scratch.\n");
return;
@@ -84,7 +84,7 @@ void scratchpad_move(Con *con) {
*/
bool scratchpad_show(Con *con) {
DLOG("should show scratchpad window %p\n", con);
- Con *__i3_scratch = workspace_get("__i3_scratch", NULL);
+ Con *__i3_scratch = workspace_get("__i3_scratch");
Con *floating;
/* If this was 'scratchpad show' without criteria, we check if the
@@ -112,7 +112,7 @@ bool scratchpad_show(Con *con) {
* unfocused scratchpad on the current workspace and focus it */
Con *walk_con;
Con *focused_ws = con_get_workspace(focused);
- TAILQ_FOREACH(walk_con, &(focused_ws->floating_head), floating_windows) {
+ TAILQ_FOREACH (walk_con, &(focused_ws->floating_head), floating_windows) {
if (!con && (floating = con_inside_floating(walk_con)) &&
floating->scratchpad_state != SCRATCHPAD_NONE &&
floating != con_inside_floating(focused)) {
@@ -130,7 +130,7 @@ bool scratchpad_show(Con *con) {
* visible scratchpad window on another workspace. In this case we move it
* to the current workspace. */
focused_ws = con_get_workspace(focused);
- TAILQ_FOREACH(walk_con, &all_cons, all_cons) {
+ TAILQ_FOREACH (walk_con, &all_cons, all_cons) {
Con *walk_ws = con_get_workspace(walk_con);
if (!con && walk_ws &&
!con_is_internal(walk_ws) && focused_ws != walk_ws &&
@@ -245,7 +245,7 @@ static int _lcm(const int m, const int n) {
*
*/
void scratchpad_fix_resolution(void) {
- Con *__i3_scratch = workspace_get("__i3_scratch", NULL);
+ Con *__i3_scratch = workspace_get("__i3_scratch");
Con *__i3_output = con_get_output(__i3_scratch);
DLOG("Current resolution: (%d, %d) %d x %d\n",
__i3_output->rect.x, __i3_output->rect.y,
@@ -253,7 +253,7 @@ void scratchpad_fix_resolution(void) {
Con *output;
int new_width = -1,
new_height = -1;
- TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
+ TAILQ_FOREACH (output, &(croot->nodes_head), nodes) {
if (output == __i3_output)
continue;
DLOG("output %s's resolution: (%d, %d) %d x %d\n",
@@ -284,7 +284,7 @@ void scratchpad_fix_resolution(void) {
DLOG("Fixing coordinates of scratchpad windows\n");
Con *con;
- TAILQ_FOREACH(con, &(__i3_scratch->floating_head), floating_windows) {
+ TAILQ_FOREACH (con, &(__i3_scratch->floating_head), floating_windows) {
floating_fix_coordinates(con, &old_rect, &new_rect);
}
}
diff --git a/src/sd-daemon.c b/src/sd-daemon.c
index 28a88bfd..84761025 100644
--- a/src/sd-daemon.c
+++ b/src/sd-daemon.c
@@ -28,21 +28,21 @@
#define _GNU_SOURCE
#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/fcntl.h>
-#include <netinet/in.h>
-#include <stdlib.h>
+#include "sd-daemon.h"
+
#include <errno.h>
-#include <unistd.h>
-#include <string.h>
+#include <netinet/in.h>
#include <stdarg.h>
-#include <stdio.h>
#include <stddef.h>
-
-#include "sd-daemon.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/fcntl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
int sd_listen_fds(int unset_environment) {
int r, fd;
diff --git a/src/sighandler.c b/src/sighandler.c
index 9f40e7d1..2be69c31 100644
--- a/src/sighandler.c
+++ b/src/sighandler.c
@@ -7,23 +7,16 @@
*/
#include "all.h"
-#include <ev.h>
-#include <iconv.h>
#include <signal.h>
#include <sys/wait.h>
-
-#include <xcb/xcb_event.h>
-
-#include <X11/keysym.h>
+#include <unistd.h>
typedef struct dialog_t {
xcb_window_t id;
xcb_colormap_t colormap;
Rect dims;
surface_t surface;
-
- TAILQ_ENTRY(dialog_t)
- dialogs;
+ TAILQ_ENTRY(dialog_t) dialogs;
} dialog_t;
static TAILQ_HEAD(dialogs_head, dialog_t) dialogs = TAILQ_HEAD_INITIALIZER(dialogs);
@@ -155,7 +148,7 @@ static void sighandler_setup(void) {
static void sighandler_create_dialogs(void) {
Output *output;
- TAILQ_FOREACH(output, &outputs, outputs) {
+ TAILQ_FOREACH (output, &outputs, outputs) {
if (!output->active) {
continue;
}
@@ -230,7 +223,7 @@ static void sighandler_destroy_dialogs(void) {
static void sighandler_handle_expose(void) {
dialog_t *current;
- TAILQ_FOREACH(current, &dialogs, dialogs) {
+ TAILQ_FOREACH (current, &dialogs, dialogs) {
sighandler_draw_dialog(current);
}
diff --git a/src/startup.c b/src/startup.c
index 0646d7af..9b0576e8 100644
--- a/src/startup.c
+++ b/src/startup.c
@@ -11,12 +11,12 @@
*
*/
#include "all.h"
-
#include "sd-daemon.h"
+#include <paths.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <paths.h>
+#include <unistd.h>
#define SN_API_NOT_YET_FROZEN 1
#include <libsn/sn-launcher.h>
@@ -36,7 +36,7 @@ static void startup_timeout(EV_P_ ev_timer *w, int revents) {
DLOG("Timeout for startup sequence %s\n", id);
struct Startup_Sequence *current, *sequence = NULL;
- TAILQ_FOREACH(current, &startup_sequences, sequences) {
+ TAILQ_FOREACH (current, &startup_sequences, sequences) {
if (strcmp(current->id, id) != 0)
continue;
@@ -201,10 +201,7 @@ void start_application(const char *command, bool no_startup_id) {
if (!no_startup_id) {
/* Change the pointer of the root window to indicate progress */
- if (xcursor_supported)
- xcursor_set_root_cursor(XCURSOR_CURSOR_WATCH);
- else
- xcb_set_root_cursor(XCURSOR_CURSOR_WATCH);
+ xcursor_set_root_cursor(XCURSOR_CURSOR_WATCH);
}
}
@@ -220,7 +217,7 @@ void startup_monitor_event(SnMonitorEvent *event, void *userdata) {
/* Get the corresponding internal startup sequence */
const char *id = sn_startup_sequence_get_id(snsequence);
struct Startup_Sequence *current, *sequence = NULL;
- TAILQ_FOREACH(current, &startup_sequences, sequences) {
+ TAILQ_FOREACH (current, &startup_sequences, sequences) {
if (strcmp(current->id, id) != 0)
continue;
@@ -246,10 +243,7 @@ void startup_monitor_event(SnMonitorEvent *event, void *userdata) {
if (_prune_startup_sequences() == 0) {
DLOG("No more startup sequences running, changing root window cursor to default pointer.\n");
/* Change the pointer of the root window to indicate progress */
- if (xcursor_supported)
- xcursor_set_root_cursor(XCURSOR_CURSOR_POINTER);
- else
- xcb_set_root_cursor(XCURSOR_CURSOR_POINTER);
+ xcursor_set_root_cursor(XCURSOR_CURSOR_POINTER);
}
break;
default:
@@ -264,7 +258,7 @@ void startup_monitor_event(SnMonitorEvent *event, void *userdata) {
*/
void startup_sequence_rename_workspace(const char *old_name, const char *new_name) {
struct Startup_Sequence *current;
- TAILQ_FOREACH(current, &startup_sequences, sequences) {
+ TAILQ_FOREACH (current, &startup_sequences, sequences) {
if (strcmp(current->workspace, old_name) != 0)
continue;
DLOG("Renaming workspace \"%s\" to \"%s\" in startup sequence %s.\n",
@@ -320,7 +314,7 @@ struct Startup_Sequence *startup_sequence_get(i3Window *cwindow,
sasprintf(&startup_id, "%.*s", xcb_get_property_value_length(startup_id_reply),
(char *)xcb_get_property_value(startup_id_reply));
struct Startup_Sequence *current, *sequence = NULL;
- TAILQ_FOREACH(current, &startup_sequences, sequences) {
+ TAILQ_FOREACH (current, &startup_sequences, sequences) {
if (strcmp(current->id, startup_id) != 0)
continue;
diff --git a/src/tree.c b/src/tree.c
index 408afddd..178ba057 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -431,13 +431,15 @@ static void mark_unmapped(Con *con) {
Con *current;
con->mapped = false;
- TAILQ_FOREACH(current, &(con->nodes_head), nodes)
- mark_unmapped(current);
+ TAILQ_FOREACH (current, &(con->nodes_head), nodes) {
+ mark_unmapped(current);
+ }
if (con->type == CT_WORKSPACE) {
/* We need to call mark_unmapped on floating nodes as well since we can
* make containers floating. */
- TAILQ_FOREACH(current, &(con->floating_head), floating_windows)
- mark_unmapped(current);
+ TAILQ_FOREACH (current, &(con->floating_head), floating_windows) {
+ mark_unmapped(current);
+ }
}
}
diff --git a/src/util.c b/src/util.c
index e9df9575..cf7f41c8 100644
--- a/src/util.c
+++ b/src/util.c
@@ -10,19 +10,16 @@
*/
#include "all.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libgen.h>
+#include <locale.h>
#include <sys/wait.h>
-#include <stdarg.h>
+#include <unistd.h>
#if defined(__OpenBSD__)
#include <sys/cdefs.h>
#endif
-#include <fcntl.h>
-#include <pwd.h>
-#include <yajl/yajl_version.h>
-#include <libgen.h>
-#include <ctype.h>
-
-#define SN_API_NOT_YET_FROZEN 1
-#include <libsn/sn-launcher.h>
int min(int a, int b) {
return (a < b ? a : b);
@@ -53,6 +50,12 @@ Rect rect_sub(Rect a, Rect b) {
a.height - b.height};
}
+Rect rect_sanitize_dimensions(Rect rect) {
+ rect.width = (int32_t)rect.width <= 0 ? 1 : rect.width;
+ rect.height = (int32_t)rect.height <= 0 ? 1 : rect.height;
+ return rect;
+}
+
bool rect_equals(Rect a, Rect b) {
return a.x == b.x && a.y == b.y && a.width == b.width && a.height == b.height;
}
@@ -103,14 +106,12 @@ bool layout_from_name(const char *layout_str, layout_t *out) {
* interpreted as a "named workspace".
*
*/
-long ws_name_to_number(const char *name) {
+int ws_name_to_number(const char *name) {
/* positive integers and zero are interpreted as numbers */
char *endptr = NULL;
- long parsed_num = strtol(name, &endptr, 10);
- if (parsed_num == LONG_MIN ||
- parsed_num == LONG_MAX ||
- parsed_num < 0 ||
- endptr == name) {
+ errno = 0;
+ long long parsed_num = strtoll(name, &endptr, 10);
+ if (errno != 0 || parsed_num > INT32_MAX || parsed_num < 0 || endptr == name) {
parsed_num = -1;
}
@@ -286,8 +287,8 @@ static char *store_restart_layout(void) {
void i3_restart(bool forget_layout) {
char *restart_filename = forget_layout ? NULL : store_restart_layout();
- kill_nagbar(&config_error_nagbar_pid, true);
- kill_nagbar(&command_error_nagbar_pid, true);
+ kill_nagbar(config_error_nagbar_pid, true);
+ kill_nagbar(command_error_nagbar_pid, true);
restore_geometry();
@@ -335,30 +336,19 @@ char *pango_escape_markup(char *input) {
static void nagbar_exited(EV_P_ ev_child *watcher, int revents) {
ev_child_stop(EV_A_ watcher);
- if (!WIFEXITED(watcher->rstatus)) {
- ELOG("ERROR: i3-nagbar did not exit normally.\n");
- return;
- }
-
int exitcode = WEXITSTATUS(watcher->rstatus);
- DLOG("i3-nagbar process exited with status %d\n", exitcode);
- if (exitcode == 2) {
- ELOG("ERROR: i3-nagbar could not be found. Is it correctly installed on your system?\n");
+ if (!WIFEXITED(watcher->rstatus)) {
+ ELOG("i3-nagbar (%d) did not exit normally. This is not an error if the config was reloaded while a nagbar was active.\n", watcher->pid);
+ } else if (exitcode != 0) {
+ ELOG("i3-nagbar (%d) process exited with status %d\n", watcher->pid, exitcode);
+ } else {
+ DLOG("i3-nagbar (%d) process exited with status %d\n", watcher->pid, exitcode);
}
- *((pid_t *)watcher->data) = -1;
-}
-
-/*
- * Cleanup handler. Will be called when i3 exits. Kills i3-nagbar with signal
- * SIGKILL (9) to make sure there are no left-over i3-nagbar processes.
- *
- */
-static void nagbar_cleanup(EV_P_ ev_cleanup *watcher, int revent) {
- pid_t *nagbar_pid = (pid_t *)watcher->data;
- if (*nagbar_pid != -1) {
- LOG("Sending SIGKILL (%d) to i3-nagbar with PID %d\n", SIGKILL, *nagbar_pid);
- kill(*nagbar_pid, SIGKILL);
+ pid_t *nagbar_pid = watcher->data;
+ if (*nagbar_pid == watcher->pid) {
+ /* Only reset if the watched nagbar is the active nagbar */
+ *nagbar_pid = -1;
}
}
@@ -394,27 +384,20 @@ void start_nagbar(pid_t *nagbar_pid, char *argv[]) {
ev_child_init(child, &nagbar_exited, *nagbar_pid, 0);
child->data = nagbar_pid;
ev_child_start(main_loop, child);
-
- /* install a cleanup watcher (will be called when i3 exits and i3-nagbar is
- * still running) */
- ev_cleanup *cleanup = smalloc(sizeof(ev_cleanup));
- ev_cleanup_init(cleanup, nagbar_cleanup);
- cleanup->data = nagbar_pid;
- ev_cleanup_start(main_loop, cleanup);
}
/*
- * Kills the i3-nagbar process, if *nagbar_pid != -1.
+ * Kills the i3-nagbar process, if nagbar_pid != -1.
*
* If wait_for_it is set (restarting i3), this function will waitpid(),
* otherwise, ev is assumed to handle it (reloading).
*
*/
-void kill_nagbar(pid_t *nagbar_pid, bool wait_for_it) {
- if (*nagbar_pid == -1)
+void kill_nagbar(pid_t nagbar_pid, bool wait_for_it) {
+ if (nagbar_pid == -1)
return;
- if (kill(*nagbar_pid, SIGTERM) == -1)
+ if (kill(nagbar_pid, SIGTERM) == -1)
warn("kill(configerror_nagbar) failed");
if (!wait_for_it)
@@ -424,7 +407,7 @@ void kill_nagbar(pid_t *nagbar_pid, bool wait_for_it) {
* exec(), our old pid is no longer watched. So, ev won’t handle SIGCHLD
* for us and we would end up with a <defunct> process. Therefore we
* waitpid() here. */
- waitpid(*nagbar_pid, NULL, 0);
+ waitpid(nagbar_pid, NULL, 0);
}
/*
diff --git a/src/window.c b/src/window.c
index 369aaa96..bee3fa66 100644
--- a/src/window.c
+++ b/src/window.c
@@ -9,6 +9,8 @@
*/
#include "all.h"
+#include <math.h>
+
/*
* Frees an i3Window and all its members.
*
@@ -288,7 +290,7 @@ bool window_update_normal_hints(i3Window *win, xcb_get_property_reply_t *reply,
ASSIGN_IF_CHANGED(win->max_width, max_width);
ASSIGN_IF_CHANGED(win->max_height, max_height);
} else {
- DLOG("Clearing maximum size \n");
+ DLOG("Clearing maximum size\n");
ASSIGN_IF_CHANGED(win->max_width, 0);
ASSIGN_IF_CHANGED(win->max_height, 0);
diff --git a/src/workspace.c b/src/workspace.c
index ea4705f7..f3ddf01c 100644
--- a/src/workspace.c
+++ b/src/workspace.c
@@ -29,7 +29,7 @@ static char **binding_workspace_names = NULL;
*/
Con *get_existing_workspace_by_name(const char *name) {
Con *output, *workspace = NULL;
- TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
+ TAILQ_FOREACH (output, &(croot->nodes_head), nodes) {
GREP_FIRST(workspace, output_get_content(output), !strcasecmp(child->name, name));
}
@@ -43,7 +43,7 @@ Con *get_existing_workspace_by_name(const char *name) {
*/
Con *get_existing_workspace_by_num(int num) {
Con *output, *workspace = NULL;
- TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
+ TAILQ_FOREACH (output, &(croot->nodes_head), nodes) {
GREP_FIRST(workspace, output_get_content(output), child->num == num);
}
@@ -72,21 +72,22 @@ static void _workspace_apply_default_orientation(Con *ws) {
/*
* Returns the first output that is assigned to a workspace specified by the
- * given name or number or NULL if no such output exists. If there is a
- * workspace with a matching name and another workspace with a matching number,
- * the output assigned to the first one is returned.
- * The order of the 'ws_assignments' queue is respected: if multiple assignments
- * match the specified workspace, the first one is returned.
- * If 'name' is NULL it will be ignored.
- * If 'parsed_num' is -1 it will be ignored.
+ * given name or number. Returns NULL if no such output exists.
+ *
+ * If an assignment matches by number but there is an assignment later that
+ * matches by name, the second one is preferred.
+ * The order of the 'ws_assignments' queue is respected: if multiple
+ * assignments match the criteria, the first one is returned.
+ * 'name' is ignored when NULL, 'parsed_num' is ignored when it is -1.
*
*/
-static Con *get_assigned_output(const char *name, long parsed_num) {
+Con *get_assigned_output(const char *name, long parsed_num) {
Con *output = NULL;
struct Workspace_Assignment *assignment;
- TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
+ TAILQ_FOREACH (assignment, &ws_assignments, ws_assignments) {
if (name && strcmp(assignment->name, name) == 0) {
- DLOG("Found workspace name assignment to output \"%s\"\n", assignment->output);
+ DLOG("Found workspace name=\"%s\" assignment to output \"%s\"\n",
+ name, assignment->output);
Output *assigned_by_name = get_output_by_name(assignment->output, true);
if (assigned_by_name) {
/* When the name matches exactly, skip numbered assignments. */
@@ -96,7 +97,8 @@ static Con *get_assigned_output(const char *name, long parsed_num) {
parsed_num != -1 &&
name_is_digits(assignment->name) &&
ws_name_to_number(assignment->name) == parsed_num) {
- DLOG("Found workspace number assignment to output \"%s\"\n", assignment->output);
+ DLOG("Found workspace number=%ld assignment to output \"%s\"\n",
+ parsed_num, assignment->output);
Output *assigned_by_num = get_output_by_name(assignment->output, true);
if (assigned_by_num) {
output = assigned_by_num->con;
@@ -122,52 +124,45 @@ bool output_triggers_assignment(Output *output, struct Workspace_Assignment *ass
* memory and initializing the data structures correctly).
*
*/
-Con *workspace_get(const char *num, bool *created) {
+Con *workspace_get(const char *num) {
Con *workspace = get_existing_workspace_by_name(num);
+ if (workspace) {
+ return workspace;
+ }
- if (workspace == NULL) {
- LOG("Creating new workspace \"%s\"\n", num);
+ LOG("Creating new workspace \"%s\"\n", 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. */
- long parsed_num = ws_name_to_number(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);
- Con *output = get_assigned_output(num, parsed_num);
- /* if an assignment is not found, we create this workspace on the current output */
- if (!output) {
- output = con_get_output(focused);
- }
-
- Con *content = output_get_content(output);
- LOG("got output %p with content %p\n", output, content);
- /* We need to attach this container after setting its type. con_attach
- * will handle CT_WORKSPACEs differently */
- workspace = con_new(NULL, NULL);
- char *name;
- sasprintf(&name, "[i3 con] workspace %s", num);
- x_set_name(workspace, name);
- free(name);
- workspace->type = CT_WORKSPACE;
- FREE(workspace->name);
- workspace->name = sstrdup(num);
- workspace->workspace_layout = config.default_layout;
- workspace->num = parsed_num;
- LOG("num = %d\n", workspace->num);
-
- workspace->parent = content;
- _workspace_apply_default_orientation(workspace);
-
- con_attach(workspace, content, false);
-
- ipc_send_workspace_event("init", workspace, NULL);
- ewmh_update_desktop_properties();
- if (created != NULL)
- *created = true;
- } else if (created != NULL) {
- *created = false;
+ Con *output = get_assigned_output(num, parsed_num);
+ /* if an assignment is not found, we create this workspace on the current output */
+ if (!output) {
+ output = con_get_output(focused);
}
+ /* No parent because we need to attach this container after setting its
+ * type. con_attach will handle CT_WORKSPACEs differently. */
+ workspace = con_new(NULL, NULL);
+
+ char *name;
+ sasprintf(&name, "[i3 con] workspace %s", num);
+ x_set_name(workspace, name);
+ free(name);
+
+ FREE(workspace->name);
+ workspace->name = sstrdup(num);
+ workspace->workspace_layout = config.default_layout;
+ workspace->num = parsed_num;
+ workspace->type = CT_WORKSPACE;
+
+ con_attach(workspace, output_get_content(output), false);
+ _workspace_apply_default_orientation(workspace);
+
+ ipc_send_workspace_event("init", workspace, NULL);
+ ewmh_update_desktop_properties();
+
return workspace;
}
@@ -187,7 +182,7 @@ void extract_workspace_names_from_bindings(void) {
}
FREE(binding_workspace_names);
}
- TAILQ_FOREACH(bind, bindings, bindings) {
+ TAILQ_FOREACH (bind, bindings, bindings) {
DLOG("binding with command %s\n", bind->command);
if (strlen(bind->command) < strlen("workspace ") ||
strncasecmp(bind->command, "workspace", strlen("workspace")) != 0)
@@ -321,7 +316,7 @@ bool workspace_is_visible(Con *ws) {
static Con *_get_sticky(Con *con, const char *sticky_group, Con *exclude) {
Con *current;
- TAILQ_FOREACH(current, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (current, &(con->nodes_head), nodes) {
if (current != exclude &&
current->sticky_group != NULL &&
current->window != NULL &&
@@ -333,7 +328,7 @@ static Con *_get_sticky(Con *con, const char *sticky_group, Con *exclude) {
return recurse;
}
- TAILQ_FOREACH(current, &(con->floating_head), floating_windows) {
+ TAILQ_FOREACH (current, &(con->floating_head), floating_windows) {
if (current != exclude &&
current->sticky_group != NULL &&
current->window != NULL &&
@@ -360,7 +355,7 @@ static void workspace_reassign_sticky(Con *con) {
/* 1: go through all containers */
/* handle all children and floating windows of this node */
- TAILQ_FOREACH(current, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (current, &(con->nodes_head), nodes) {
if (current->sticky_group == NULL) {
workspace_reassign_sticky(current);
continue;
@@ -388,8 +383,9 @@ static void workspace_reassign_sticky(Con *con) {
LOG("re-assigned window from src %p to dest %p\n", src, current);
}
- TAILQ_FOREACH(current, &(con->floating_head), floating_windows)
- workspace_reassign_sticky(current);
+ TAILQ_FOREACH (current, &(con->floating_head), floating_windows) {
+ workspace_reassign_sticky(current);
+ }
}
/*
@@ -427,7 +423,7 @@ void workspace_show(Con *workspace) {
/* disable fullscreen for the other workspaces and get the workspace we are
* currently on. */
- TAILQ_FOREACH(current, &(workspace->parent->nodes_head), nodes) {
+ TAILQ_FOREACH (current, &(workspace->parent->nodes_head), nodes) {
if (current->fullscreen_mode == CF_OUTPUT)
old = current;
current->fullscreen_mode = CF_NONE;
@@ -551,9 +547,7 @@ void workspace_show(Con *workspace) {
*
*/
void workspace_show_by_name(const char *num) {
- Con *workspace;
- workspace = workspace_get(num, NULL);
- workspace_show(workspace);
+ workspace_show(workspace_get(num));
}
/*
@@ -570,11 +564,11 @@ Con *workspace_next(void) {
if ((next = TAILQ_NEXT(current, nodes)) != NULL)
return next;
bool found_current = false;
- TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
+ TAILQ_FOREACH (output, &(croot->nodes_head), nodes) {
/* Skip outputs starting with __, they are internal. */
if (con_is_internal(output))
continue;
- NODES_FOREACH(output_get_content(output)) {
+ NODES_FOREACH (output_get_content(output)) {
if (child->type != CT_WORKSPACE)
continue;
if (!first)
@@ -591,11 +585,11 @@ Con *workspace_next(void) {
}
} else {
/* If currently a numbered workspace, find next numbered workspace. */
- TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
+ TAILQ_FOREACH (output, &(croot->nodes_head), nodes) {
/* Skip outputs starting with __, they are internal. */
if (con_is_internal(output))
continue;
- NODES_FOREACH(output_get_content(output)) {
+ NODES_FOREACH (output_get_content(output)) {
if (child->type != CT_WORKSPACE)
continue;
if (!first || (child->num != -1 && child->num < first->num))
@@ -635,11 +629,11 @@ Con *workspace_prev(void) {
prev = NULL;
if (!prev) {
bool found_current = false;
- TAILQ_FOREACH_REVERSE(output, &(croot->nodes_head), nodes_head, nodes) {
+ TAILQ_FOREACH_REVERSE (output, &(croot->nodes_head), nodes_head, nodes) {
/* Skip outputs starting with __, they are internal. */
if (con_is_internal(output))
continue;
- NODES_FOREACH_REVERSE(output_get_content(output)) {
+ NODES_FOREACH_REVERSE (output_get_content(output)) {
if (child->type != CT_WORKSPACE)
continue;
if (!last)
@@ -657,11 +651,11 @@ Con *workspace_prev(void) {
}
} else {
/* If numbered workspace, find previous numbered workspace. */
- TAILQ_FOREACH_REVERSE(output, &(croot->nodes_head), nodes_head, nodes) {
+ TAILQ_FOREACH_REVERSE (output, &(croot->nodes_head), nodes_head, nodes) {
/* Skip outputs starting with __, they are internal. */
if (con_is_internal(output))
continue;
- NODES_FOREACH_REVERSE(output_get_content(output)) {
+ NODES_FOREACH_REVERSE (output_get_content(output)) {
if (child->type != CT_WORKSPACE)
continue;
if (!last || (child->num != -1 && last->num < child->num))
@@ -699,7 +693,7 @@ Con *workspace_next_on_output(void) {
next = TAILQ_NEXT(current, nodes);
} else {
/* If currently a numbered workspace, find next numbered workspace. */
- NODES_FOREACH(output_get_content(output)) {
+ NODES_FOREACH (output_get_content(output)) {
if (child->type != CT_WORKSPACE)
continue;
if (child->num == -1)
@@ -715,7 +709,7 @@ Con *workspace_next_on_output(void) {
/* Find next named workspace. */
if (!next) {
bool found_current = false;
- NODES_FOREACH(output_get_content(output)) {
+ NODES_FOREACH (output_get_content(output)) {
if (child->type != CT_WORKSPACE)
continue;
if (child == current) {
@@ -729,7 +723,7 @@ Con *workspace_next_on_output(void) {
/* Find first workspace. */
if (!next) {
- NODES_FOREACH(output_get_content(output)) {
+ NODES_FOREACH (output_get_content(output)) {
if (child->type != CT_WORKSPACE)
continue;
if (!next || (child->num != -1 && child->num < next->num))
@@ -757,7 +751,7 @@ Con *workspace_prev_on_output(void) {
prev = NULL;
} else {
/* If numbered workspace, find previous numbered workspace. */
- NODES_FOREACH_REVERSE(output_get_content(output)) {
+ NODES_FOREACH_REVERSE (output_get_content(output)) {
if (child->type != CT_WORKSPACE || child->num == -1)
continue;
/* Need to check child against current and previous because we
@@ -771,7 +765,7 @@ Con *workspace_prev_on_output(void) {
/* Find previous named workspace. */
if (!prev) {
bool found_current = false;
- NODES_FOREACH_REVERSE(output_get_content(output)) {
+ NODES_FOREACH_REVERSE (output_get_content(output)) {
if (child->type != CT_WORKSPACE)
continue;
if (child == current) {
@@ -785,7 +779,7 @@ Con *workspace_prev_on_output(void) {
/* Find last workspace. */
if (!prev) {
- NODES_FOREACH_REVERSE(output_get_content(output)) {
+ NODES_FOREACH_REVERSE (output_get_content(output)) {
if (child->type != CT_WORKSPACE)
continue;
if (!prev || child->num > prev->num)
@@ -820,21 +814,22 @@ Con *workspace_back_and_forth_get(void) {
return NULL;
}
- Con *workspace;
- workspace = workspace_get(previous_workspace_name, NULL);
-
- return workspace;
+ return workspace_get(previous_workspace_name);
}
static bool get_urgency_flag(Con *con) {
Con *child;
- TAILQ_FOREACH(child, &(con->nodes_head), nodes)
- if (child->urgent || get_urgency_flag(child))
- return true;
+ TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
+ if (child->urgent || get_urgency_flag(child)) {
+ return true;
+ }
+ }
- TAILQ_FOREACH(child, &(con->floating_head), floating_windows)
- if (child->urgent || get_urgency_flag(child))
- return true;
+ TAILQ_FOREACH (child, &(con->floating_head), floating_windows) {
+ if (child->urgent || get_urgency_flag(child)) {
+ return true;
+ }
+ }
return false;
}
@@ -991,7 +986,7 @@ void workspace_move_to_output(Con *ws, Output *output) {
/* check if we can find a workspace assigned to this output */
bool used_assignment = false;
struct Workspace_Assignment *assignment;
- TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
+ TAILQ_FOREACH (assignment, &ws_assignments, ws_assignments) {
bool attached;
int num;
if (!output_triggers_assignment(current_output, assignment)) {
@@ -1006,7 +1001,7 @@ void workspace_move_to_output(Con *ws, Output *output) {
/* so create the workspace referenced to by this assignment */
DLOG("Creating workspace from assignment %s.\n", assignment->name);
- workspace_get(assignment->name, NULL);
+ workspace_get(assignment->name);
used_assignment = true;
break;
}
@@ -1034,7 +1029,7 @@ void workspace_move_to_output(Con *ws, Output *output) {
/* fix the coordinates of the floating containers */
Con *floating_con;
- TAILQ_FOREACH(floating_con, &(ws->floating_head), floating_windows) {
+ TAILQ_FOREACH (floating_con, &(ws->floating_head), floating_windows) {
floating_fix_coordinates(floating_con, &(old_content->rect), &(content->rect));
}
@@ -1055,7 +1050,7 @@ void workspace_move_to_output(Con *ws, Output *output) {
* order/number of other workspaces on the output. Instead, we loop through
* the available workspaces and only work with previously_visible_ws if we
* still find it. */
- TAILQ_FOREACH(ws, &(content->nodes_head), nodes) {
+ TAILQ_FOREACH (ws, &(content->nodes_head), nodes) {
if (ws != previously_visible_ws) {
continue;
}
diff --git a/src/x.c b/src/x.c
index 8d89eafd..48af5f37 100644
--- a/src/x.c
+++ b/src/x.c
@@ -10,6 +10,8 @@
*/
#include "all.h"
+#include <unistd.h>
+
#ifndef MAX
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#endif
@@ -61,26 +63,18 @@ typedef struct con_state {
char *name;
- CIRCLEQ_ENTRY(con_state)
- state;
-
- CIRCLEQ_ENTRY(con_state)
- old_state;
-
- TAILQ_ENTRY(con_state)
- initial_mapping_order;
+ CIRCLEQ_ENTRY(con_state) state;
+ CIRCLEQ_ENTRY(con_state) old_state;
+ TAILQ_ENTRY(con_state) initial_mapping_order;
} con_state;
-CIRCLEQ_HEAD(state_head, con_state)
-state_head =
+CIRCLEQ_HEAD(state_head, con_state) state_head =
CIRCLEQ_HEAD_INITIALIZER(state_head);
-CIRCLEQ_HEAD(old_state_head, con_state)
-old_state_head =
+CIRCLEQ_HEAD(old_state_head, con_state) old_state_head =
CIRCLEQ_HEAD_INITIALIZER(old_state_head);
-TAILQ_HEAD(initial_mapping_head, con_state)
-initial_mapping_head =
+TAILQ_HEAD(initial_mapping_head, con_state) initial_mapping_head =
TAILQ_HEAD_INITIALIZER(initial_mapping_head);
/*
@@ -92,9 +86,11 @@ initial_mapping_head =
*/
static con_state *state_for_frame(xcb_window_t window) {
con_state *state;
- CIRCLEQ_FOREACH(state, &state_head, state)
- if (state->id == window)
- return state;
+ CIRCLEQ_FOREACH (state, &state_head, state) {
+ if (state->id == window) {
+ return state;
+ }
+ }
/* TODO: better error handling? */
ELOG("No state found for window 0x%08x\n", window);
@@ -588,11 +584,6 @@ void x_draw_decoration(Con *con) {
}
}
- /* if this is a borderless/1pixel window, we don’t need to render the
- * decoration. */
- if (p->border_style != BS_NORMAL)
- goto copy_pixmaps;
-
/* If the parent hasn't been set up yet, skip the decoration rendering
* for now. */
if (parent->frame_buffer.id == XCB_NONE)
@@ -606,6 +597,11 @@ void x_draw_decoration(Con *con) {
FREE(con->parent->deco_render_params);
}
+ /* if this is a borderless/1pixel window, we don’t need to render the
+ * decoration. */
+ if (p->border_style != BS_NORMAL)
+ goto copy_pixmaps;
+
/* 4: paint the bar */
draw_util_rectangle(&(parent->frame_buffer), p->color->background,
con->deco_rect.x, con->deco_rect.y, con->deco_rect.width, con->deco_rect.height);
@@ -624,7 +620,7 @@ void x_draw_decoration(Con *con) {
bool had_visible_mark = false;
mark_t *mark;
- TAILQ_FOREACH(mark, &(con->marks_head), marks) {
+ TAILQ_FOREACH (mark, &(con->marks_head), marks) {
if (mark->name[0] == '_')
continue;
had_visible_mark = true;
@@ -726,11 +722,13 @@ void x_deco_recurse(Con *con) {
con_state *state = state_for_frame(con->frame.id);
if (!leaf) {
- TAILQ_FOREACH(current, &(con->nodes_head), nodes)
- x_deco_recurse(current);
+ TAILQ_FOREACH (current, &(con->nodes_head), nodes) {
+ x_deco_recurse(current);
+ }
- TAILQ_FOREACH(current, &(con->floating_head), floating_windows)
- x_deco_recurse(current);
+ TAILQ_FOREACH (current, &(con->floating_head), floating_windows) {
+ x_deco_recurse(current);
+ }
if (state->mapped) {
draw_util_copy_surface(&(con->frame_buffer), &(con->frame), 0, 0, 0, 0, con->rect.width, con->rect.height);
@@ -858,7 +856,7 @@ void x_push_node(Con *con) {
/* Calculate the height of all window decorations which will be drawn on to
* this frame. */
uint32_t max_y = 0, max_height = 0;
- TAILQ_FOREACH(current, &(con->nodes_head), nodes) {
+ TAILQ_FOREACH (current, &(con->nodes_head), nodes) {
Rect *dr = &(current->deco_rect);
if (dr->y >= max_y && dr->height >= max_height) {
max_y = dr->y;
@@ -1070,7 +1068,7 @@ void x_push_node(Con *con) {
/* Handle all children and floating windows of this node. We recurse
* in focus order to display the focused client in a stack first when
* switching workspaces (reduces flickering). */
- TAILQ_FOREACH(current, &(con->focus_head), focused) {
+ TAILQ_FOREACH (current, &(con->focus_head), focused) {
x_push_node(current);
}
}
@@ -1116,11 +1114,13 @@ static void x_push_node_unmaps(Con *con) {
}
/* handle all children and floating windows of this node */
- TAILQ_FOREACH(current, &(con->nodes_head), nodes)
- x_push_node_unmaps(current);
+ TAILQ_FOREACH (current, &(con->nodes_head), nodes) {
+ x_push_node_unmaps(current);
+ }
- TAILQ_FOREACH(current, &(con->floating_head), floating_windows)
- x_push_node_unmaps(current);
+ TAILQ_FOREACH (current, &(con->floating_head), floating_windows) {
+ x_push_node_unmaps(current);
+ }
}
/*
@@ -1133,7 +1133,7 @@ static bool is_con_attached(Con *con) {
return false;
Con *current;
- TAILQ_FOREACH(current, &(con->parent->nodes_head), nodes) {
+ TAILQ_FOREACH (current, &(con->parent->nodes_head), nodes) {
if (current == con)
return true;
}
@@ -1167,7 +1167,7 @@ void x_push_changes(Con *con) {
* ConfigureWindow requests and get them applied directly instead of having
* them become ConfigureRequests that i3 handles. */
uint32_t values[1] = {XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT};
- CIRCLEQ_FOREACH_REVERSE(state, &state_head, state) {
+ CIRCLEQ_FOREACH_REVERSE (state, &state_head, state) {
if (state->mapped)
xcb_change_window_attributes(conn, state->id, XCB_CW_EVENT_MASK, values);
}
@@ -1178,9 +1178,11 @@ void x_push_changes(Con *con) {
/* count first, necessary to (re)allocate memory for the bottom-to-top
* stack afterwards */
int cnt = 0;
- CIRCLEQ_FOREACH_REVERSE(state, &state_head, state)
- if (con_has_managed_window(state->con))
- cnt++;
+ CIRCLEQ_FOREACH_REVERSE (state, &state_head, state) {
+ if (con_has_managed_window(state->con)) {
+ cnt++;
+ }
+ }
/* The bottom-to-top window stack of all windows which are managed by i3.
* Used for x_get_window_stack(). */
@@ -1195,7 +1197,7 @@ void x_push_changes(Con *con) {
xcb_window_t *walk = client_list_windows;
/* X11 correctly represents the stack if we push it from bottom to top */
- CIRCLEQ_FOREACH_REVERSE(state, &state_head, state) {
+ CIRCLEQ_FOREACH_REVERSE (state, &state_head, state) {
if (con_has_managed_window(state->con))
memcpy(walk++, &(state->con->window->id), sizeof(xcb_window_t));
@@ -1226,7 +1228,7 @@ void x_push_changes(Con *con) {
walk = client_list_windows;
/* reorder by initial mapping */
- TAILQ_FOREACH(state, &initial_mapping_head, initial_mapping_order) {
+ TAILQ_FOREACH (state, &initial_mapping_head, initial_mapping_order) {
if (con_has_managed_window(state->con))
*walk++ = state->con->window->id;
}
@@ -1261,7 +1263,7 @@ void x_push_changes(Con *con) {
//DLOG("Re-enabling EnterNotify\n");
values[0] = FRAME_EVENT_MASK;
- CIRCLEQ_FOREACH_REVERSE(state, &state_head, state) {
+ CIRCLEQ_FOREACH_REVERSE (state, &state_head, state) {
if (state->mapped)
xcb_change_window_attributes(conn, state->id, XCB_CW_EVENT_MASK, values);
}
@@ -1337,7 +1339,7 @@ void x_push_changes(Con *con) {
* unmapped, the second one appears under the cursor and therefore gets an
* EnterNotify event. */
values[0] = FRAME_EVENT_MASK & ~XCB_EVENT_MASK_ENTER_WINDOW;
- CIRCLEQ_FOREACH_REVERSE(state, &state_head, state) {
+ CIRCLEQ_FOREACH_REVERSE (state, &state_head, state) {
if (!state->unmap_now)
continue;
xcb_change_window_attributes(conn, state->id, XCB_CW_EVENT_MASK, values);
@@ -1347,7 +1349,7 @@ void x_push_changes(Con *con) {
x_push_node_unmaps(con);
/* save the current stack as old stack */
- CIRCLEQ_FOREACH(state, &state_head, state) {
+ CIRCLEQ_FOREACH (state, &state_head, state) {
CIRCLEQ_REMOVE(&old_state_head, state, old_state);
CIRCLEQ_INSERT_TAIL(&old_state_head, state, old_state);
}
@@ -1439,7 +1441,7 @@ void x_mask_event_mask(uint32_t mask) {
uint32_t values[] = {FRAME_EVENT_MASK & mask};
con_state *state;
- CIRCLEQ_FOREACH_REVERSE(state, &state_head, state) {
+ CIRCLEQ_FOREACH_REVERSE (state, &state_head, state) {
if (state->mapped)
xcb_change_window_attributes(conn, state->id, XCB_CW_EVENT_MASK, values);
}
diff --git a/src/xcb.c b/src/xcb.c
index bdfb08bc..5258dcc2 100644
--- a/src/xcb.c
+++ b/src/xcb.c
@@ -45,20 +45,8 @@ xcb_window_t create_window(xcb_connection_t *conn, Rect dims,
}
/* Set the cursor */
- if (xcursor_supported) {
- mask = XCB_CW_CURSOR;
- values[0] = xcursor_get_cursor(cursor);
- xcb_change_window_attributes(conn, result, mask, values);
- } else {
- xcb_cursor_t cursor_id = xcb_generate_id(conn);
- i3Font cursor_font = load_font("cursor", false);
- int xcb_cursor = xcursor_get_xcb_cursor(cursor);
- xcb_create_glyph_cursor(conn, cursor_id, cursor_font.specific.xcb.id,
- cursor_font.specific.xcb.id, xcb_cursor, xcb_cursor + 1, 0, 0, 0,
- 65535, 65535, 65535);
- xcb_change_window_attributes(conn, result, XCB_CW_CURSOR, &cursor_id);
- xcb_free_cursor(conn, cursor_id);
- }
+ uint32_t cursor_values[] = {xcursor_get_cursor(cursor)};
+ xcb_change_window_attributes(conn, result, XCB_CW_CURSOR, cursor_values);
/* Map the window (= make it visible) */
if (map)
@@ -176,24 +164,6 @@ bool xcb_reply_contains_atom(xcb_get_property_reply_t *prop, xcb_atom_t atom) {
}
/*
- * Set the cursor of the root window to the given cursor id.
- * This function should only be used if xcursor_supported == false.
- * Otherwise, use xcursor_set_root_cursor().
- *
- */
-void xcb_set_root_cursor(int cursor) {
- xcb_cursor_t cursor_id = xcb_generate_id(conn);
- i3Font cursor_font = load_font("cursor", false);
- int xcb_cursor = xcursor_get_xcb_cursor(cursor);
- xcb_create_glyph_cursor(conn, cursor_id, cursor_font.specific.xcb.id,
- cursor_font.specific.xcb.id, xcb_cursor, xcb_cursor + 1, 0, 0, 0,
- 65535, 65535, 65535);
- xcb_change_window_attributes(conn, root, XCB_CW_CURSOR, &cursor_id);
- xcb_free_cursor(conn, cursor_id);
- xcb_flush(conn);
-}
-
-/*
* Get depth of visual specified by visualid
*
*/
diff --git a/src/xcursor.c b/src/xcursor.c
index cbfe808b..cb98399f 100644
--- a/src/xcursor.c
+++ b/src/xcursor.c
@@ -9,27 +9,19 @@
*/
#include <config.h>
+#include "all.h"
+
#include <assert.h>
-#include <xcb/xcb_cursor.h>
+#include <err.h>
-#include "i3.h"
-#include "xcb.h"
-#include "xcursor.h"
+#include <xcb/xcb_cursor.h>
static xcb_cursor_context_t *ctx;
static xcb_cursor_t cursors[XCURSOR_CURSOR_MAX];
-static const int xcb_cursors[XCURSOR_CURSOR_MAX] = {
- XCB_CURSOR_LEFT_PTR,
- XCB_CURSOR_SB_H_DOUBLE_ARROW,
- XCB_CURSOR_SB_V_DOUBLE_ARROW,
- XCB_CURSOR_WATCH};
-
void xcursor_load_cursors(void) {
if (xcb_cursor_context_new(conn, root_screen, &ctx) < 0) {
- ELOG("xcursor support unavailable\n");
- xcursor_supported = false;
- return;
+ errx(EXIT_FAILURE, "Cannot allocate xcursor context");
}
#define LOAD_CURSOR(constant, name) \
do { \
@@ -63,8 +55,3 @@ xcb_cursor_t xcursor_get_cursor(enum xcursor_cursor_t c) {
assert(c < XCURSOR_CURSOR_MAX);
return cursors[c];
}
-
-int xcursor_get_xcb_cursor(enum xcursor_cursor_t c) {
- assert(c < XCURSOR_CURSOR_MAX);
- return xcb_cursors[c];
-}
diff --git a/src/xinerama.c b/src/xinerama.c
index efae10dc..ffaaa009 100644
--- a/src/xinerama.c
+++ b/src/xinerama.c
@@ -21,9 +21,11 @@ static int num_screens;
*/
static Output *get_screen_at(unsigned int x, unsigned int y) {
Output *output;
- TAILQ_FOREACH(output, &outputs, outputs)
- if (output->rect.x == x && output->rect.y == y)
- return output;
+ TAILQ_FOREACH (output, &outputs, outputs) {
+ if (output->rect.x == x && output->rect.y == y) {
+ return output;
+ }
+ }
return NULL;
}
diff --git a/testcases/complete-run.pl.in b/testcases/complete-run.pl.in
index 96b93bed..00f8e609 100755
--- a/testcases/complete-run.pl.in
+++ b/testcases/complete-run.pl.in
@@ -18,7 +18,7 @@ use Time::HiRes qw(time);
use IO::Handle;
# these are shipped with the testsuite
-use lib qw(@abs_top_builddir@/testcases/lib @abs_top_srcdir@/testcases/lib @abs_top_srcdir@/AnyEvent-I3/blib/lib);
+use lib qw(@abs_top_builddir@ @abs_top_builddir@/testcases/lib @abs_top_srcdir@/testcases/lib @abs_top_builddir@/AnyEvent-I3/blib/lib);
use i3test::Util qw(slurp);
use StartXServer;
use StatusLine;
@@ -78,12 +78,12 @@ pod2usage(-verbose => 2, -exitcode => 0) if $help;
# Check for missing executables
my @binaries = qw(
@abs_top_builddir@/i3
- @abs_top_builddir@/i3bar/i3bar
- @abs_top_builddir@/i3-config-wizard/i3-config-wizard
- @abs_top_builddir@/i3-dump-log/i3-dump-log
- @abs_top_builddir@/i3-input/i3-input
- @abs_top_builddir@/i3-msg/i3-msg
- @abs_top_builddir@/i3-nagbar/i3-nagbar
+ @abs_top_builddir@/i3bar
+ @abs_top_builddir@/i3-config-wizard
+ @abs_top_builddir@/i3-dump-log
+ @abs_top_builddir@/i3-input
+ @abs_top_builddir@/i3-msg
+ @abs_top_builddir@/i3-nagbar
);
foreach my $binary (@binaries) {
@@ -103,12 +103,6 @@ foreach my $binary (@test_binaries) {
}
$ENV{PATH} = join(':',
- '@abs_top_builddir@/i3-nagbar',
- '@abs_top_builddir@/i3-msg',
- '@abs_top_builddir@/i3-input',
- '@abs_top_builddir@/i3-dump-log',
- '@abs_top_builddir@/i3-config-wizard',
- '@abs_top_builddir@/i3bar',
'@abs_top_builddir@',
'@abs_top_srcdir@',
$ENV{PATH});
diff --git a/testcases/inject_randr1.5.c b/testcases/inject_randr1.5.c
index 29b6a33d..9c0b73d4 100644
--- a/testcases/inject_randr1.5.c
+++ b/testcases/inject_randr1.5.c
@@ -16,15 +16,17 @@
#include <ev.h>
#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/time.h>
-#include <sys/resource.h>
+#include <getopt.h>
+#include <libgen.h>
#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
#include <sys/wait.h>
-#include <libgen.h>
+#include <unistd.h>
static void uds_connection_cb(EV_P_ ev_io *w, int revents);
static void read_client_setup_request_cb(EV_P_ ev_io *w, int revents);
@@ -59,7 +61,7 @@ struct connstate {
ev_io *clientw;
/* serverw is a libev watcher for the connection to X11 which we initiated
- * on behalf of the client. */
+ * on behalf of the client. */
ev_io *serverw;
/* sequence is the client-side sequence number counter. In X11’s wire
diff --git a/testcases/lib/i3test.pm.in b/testcases/lib/i3test.pm.in
index 161ddf79..aedaa601 100644
--- a/testcases/lib/i3test.pm.in
+++ b/testcases/lib/i3test.pm.in
@@ -7,7 +7,7 @@ use Test::Builder;
use X11::XCB::Rect;
use X11::XCB::Window;
use X11::XCB qw(:all);
-use lib qw(@abs_top_srcdir@/AnyEvent-I3/blib/lib);
+use lib qw(@abs_top_builddir@/AnyEvent-I3/blib/lib);
use AnyEvent::I3;
use List::Util qw(first);
use Time::HiRes qw(sleep);
diff --git a/testcases/lib/i3test/XTEST.pm b/testcases/lib/i3test/XTEST.pm
index 4c464c5e..89b8facb 100644
--- a/testcases/lib/i3test/XTEST.pm
+++ b/testcases/lib/i3test/XTEST.pm
@@ -7,7 +7,7 @@ use v5.10;
use Test::More;
use i3test::Util qw(get_socket_path);
-use lib qw(@abs_top_srcdir@/AnyEvent-I3/blib/lib);
+use lib qw(@abs_top_builddir@/AnyEvent-I3/blib/lib);
use AnyEvent::I3;
use ExtUtils::PkgConfig;
diff --git a/testcases/t/116-nestedcons.t b/testcases/t/116-nestedcons.t
index 4f13b1e5..6a2274d4 100644
--- a/testcases/t/116-nestedcons.t
+++ b/testcases/t/116-nestedcons.t
@@ -72,6 +72,7 @@ my $expected = {
'floating_nodes' => $ignore,
workspace_layout => 'default',
current_border_width => -1,
+ marks => $ignore,
};
# a shallow copy is sufficient, since we only ignore values at the root
diff --git a/testcases/t/117-workspace.t b/testcases/t/117-workspace.t
index c97d4fbf..48a0dbf6 100644
--- a/testcases/t/117-workspace.t
+++ b/testcases/t/117-workspace.t
@@ -130,6 +130,21 @@ $ws = get_ws("aa: $tmp");
ok(defined($ws), "workspace aa: $tmp was created");
is($ws->{num}, -1, 'workspace number is -1');
+cmd "workspace -42: $tmp";
+$ws = get_ws("-42: $tmp");
+ok(defined($ws), "workspace -42: $tmp was created");
+is($ws->{num}, -1, 'negative workspace number is ignored');
+
+cmd "workspace 2147483647: $tmp";
+$ws = get_ws("2147483647: $tmp");
+ok(defined($ws), "workspace 2147483647: $tmp was created");
+is($ws->{num}, 2147483647, 'workspace number is 2147483647');
+
+cmd "workspace 2147483648: $tmp";
+$ws = get_ws("2147483648: $tmp");
+ok(defined($ws), "workspace 2147483648: $tmp was created");
+is($ws->{num}, -1, 'workspace number past the limit is ignored');
+
################################################################################
# Check that we can go to workspace "4: foo" with the command
# "workspace number 4".
diff --git a/testcases/t/119-match.t b/testcases/t/119-match.t
index 64ffa4ed..65c41f1f 100644
--- a/testcases/t/119-match.t
+++ b/testcases/t/119-match.t
@@ -33,9 +33,7 @@ my $win = $content->[0];
# not match it
######################################################################
# TODO: specify more match types
-# we can match on any (non-empty) class here since that window does not have
-# WM_CLASS set
-cmd q|[class=".*"] kill|;
+# Try matching with an empty pattern since there isn't a WM_CLASS set.
cmd q|[con_id="99999"] kill|;
is_num_children($tmp, 1, 'window still there');
@@ -103,4 +101,18 @@ cmd '[title="^\w [3]$"] kill';
wait_for_unmap $left;
is_num_children($tmp, 0, 'window killed');
+######################################################################
+# check that we can match empty properties
+######################################################################
+
+$tmp = fresh_workspace;
+
+$left = open_window(name => 'class is empty', wm_class => '');
+ok($left->mapped, 'left window mapped');
+is_num_children($tmp, 1, 'window opened');
+
+cmd '[class="^$"] kill';
+wait_for_unmap $left;
+is_num_children($tmp, 0, 'window killed');
+
done_testing;
diff --git a/testcases/t/124-move.t b/testcases/t/124-move.t
index b7ef0b2c..b4a8ca3e 100644
--- a/testcases/t/124-move.t
+++ b/testcases/t/124-move.t
@@ -220,21 +220,49 @@ is($absolute->y, $absolute_before->y, 'y not changed');
is($absolute->width, $absolute_before->width, 'width not changed');
is($absolute->height, $absolute_before->height, 'height not changed');
+$absolute_before = $absolute;
+$top_before = $top;
+
######################################################################
-# 6) test moving floating window to a specified position
+# 7) test moving floating containers with a specific amount of ppt
+######################################################################
+
+cmd 'move right 25 ppt';
+
+sync_with_i3;
+
+($absolute, $top) = $floatwin->rect;
+
+is($absolute->x, int($x->root->rect->width * 0.25) + $absolute_before->x, 'moved 25 ppt to the right');
+is($absolute->y, $absolute_before->y, 'y not changed');
+is($absolute->width, $absolute_before->width, 'width not changed');
+is($absolute->height, $absolute_before->height, 'height not changed');
+
+######################################################################
+# 8) test moving floating window to a specified position
# and to absolute center
######################################################################
$tmp = fresh_workspace;
open_floating_window; my @floatcon;
+# Move to specified position with px
cmd 'move position 5 px 15 px';
@floatcon = @{get_ws($tmp)->{floating_nodes}};
-is($floatcon[0]->{rect}->{x}, 5, 'moved to position 5 x');
-is($floatcon[0]->{rect}->{y}, 15, 'moved to position 15 y');
+is($floatcon[0]->{rect}->{x}, 5, 'moved to position 5 (px) x');
+is($floatcon[0]->{rect}->{y}, 15, 'moved to position 15 (px) y');
+
+# Move to specified position with ppt
+cmd 'move position 20 ppt 20 ppt';
+
+@floatcon = @{get_ws($tmp)->{floating_nodes}};
+
+is($floatcon[0]->{rect}->{x}, int($x->root->rect->width * 0.20), "moved to position 20 (ppt) x");
+is($floatcon[0]->{rect}->{y}, int($x->root->rect->height * 0.20), "moved to position 20 (ppt) y");
+# Move to absolute center
cmd 'move absolute position center';
@floatcon = @{get_ws($tmp)->{floating_nodes}};
diff --git a/testcases/t/132-move-workspace.t b/testcases/t/132-move-workspace.t
index 60705f96..c7721c3d 100644
--- a/testcases/t/132-move-workspace.t
+++ b/testcases/t/132-move-workspace.t
@@ -340,6 +340,53 @@ is_num_children($tmp2, 0, 'no regular nodes on second workspace');
is(@{$ws->{floating_nodes}}, 1, 'one floating node on second workspace');
###################################################################
+# Test that when moving a fullscreen floating window to a workspace
+# that already has an other fullscreen container, the second
+# container gets un-fullscreened.
+# See #4124
+###################################################################
+$tmp2 = fresh_workspace;
+$second = open_window;
+cmd 'fullscreen enable';
+$ws = get_ws($tmp2);
+is($ws->{nodes}->[0]->{fullscreen_mode}, 1, 'sanity check: fullscreen enabled');
+
+$tmp = fresh_workspace;
+$first = open_window;
+cmd 'floating enable, fullscreen enable';
+cmd "move workspace $tmp2";
+
+$ws = get_ws($tmp2);
+is_num_children($tmp2, 1, 'one regular node on second workspace');
+is_num_fullscreen($tmp2, 1, 'one fullscreen node on second workspace');
+is(@{$ws->{floating_nodes}}, 1, 'one floating node on second workspace');
+is($ws->{nodes}->[0]->{fullscreen_mode}, 0, 'previous fullscreen disabled');
+
+###################################################################
+# Same as above, but trigger the bug with the parent of a
+# fullscreen container, instead of a CT_FLOATING_CON.
+###################################################################
+$tmp2 = fresh_workspace;
+$second = open_window;
+cmd 'fullscreen enable';
+$ws = get_ws($tmp2);
+is($ws->{nodes}->[0]->{fullscreen_mode}, 1, 'sanity check: fullscreen enabled');
+
+$tmp = fresh_workspace;
+open_window;
+$first = open_window;
+cmd 'layout tabbed';
+cmd 'focus parent, mark a, focus child';
+cmd 'fullscreen enable';
+cmd "[con_mark=a] move workspace $tmp2";
+
+$ws = get_ws($tmp2);
+is(sum_nodes(get_ws_content($tmp2)), 4, '3 leafs & 1 split node in second workspace');
+# is_num_fullscreen does not catch this nested fullscreen container
+is($ws->{nodes}->[0]->{fullscreen_mode}, 0, 'previous fullscreen disabled');
+is($ws->{nodes}->[1]->{nodes}->[1]->{fullscreen_mode}, 1, 'nested fullscreen from moved container preserved');
+
+###################################################################
# Check that moving an empty workspace using criteria doesn't
# create unfocused empty workspace.
###################################################################
diff --git a/testcases/t/180-fd-leaks.t b/testcases/t/180-fd-leaks.t
index 4e3369e9..6ca0dc6f 100644
--- a/testcases/t/180-fd-leaks.t
+++ b/testcases/t/180-fd-leaks.t
@@ -29,6 +29,10 @@ my $tmp = tmpnam();
mkfifo($tmp, 0600) or die "Could not create FIFO in $tmp";
my ($outfh, $outname) = tempfile('/tmp/i3-ls-output.XXXXXX', UNLINK => 1);
+# Get fds from a clean shell
+my $shoutput = `sh -c "ls -l /proc/self/fd"`;
+
+# Get fds from i3
cmd qq|exec ls -l /proc/self/fd >$outname && echo done >$tmp|;
open(my $fh, '<', $tmp);
@@ -38,29 +42,39 @@ close($fh);
unlink($tmp);
# Get the ls /proc/self/fd output
-my $output;
+my $i3output;
{
local $/;
- $output = <$outfh>;
+ $i3output = <$outfh>;
}
close($outfh);
-# Split lines, keep only those which are symlinks.
-my @lines = grep { /->/ } split("\n", $output);
+sub extract_fds {
+ my $output = @_;
+
+ # Split lines, keep only those which are symlinks.
+ my @lines = grep { /->/ } split("\n", $output);
-my %fds = map { /([0-9]+) -> (.+)$/; ($1, $2) } @lines;
+ my %fds = map { /([0-9]+) -> (.+)$/; ($1, $2) } @lines;
-# Filter out 0, 1, 2 (stdin, stdout, stderr).
-delete $fds{0};
-delete $fds{1};
-delete $fds{2};
+ # Filter out 0, 1, 2 (stdin, stdout, stderr).
+ delete $fds{0};
+ delete $fds{1};
+ delete $fds{2};
-# Filter out the fd which is caused by ls calling readdir().
-for my $fd (keys %fds) {
- delete $fds{$fd} if $fds{$fd} =~ m,^/proc/\d+/fd$,;
+ # filter out the fd which is caused by ls calling readdir().
+ for my $fd (keys %fds) {
+ delete $fds{$fd} if $fds{$fd} =~ m,^/proc/\d+/fd$,;
+ }
+
+ return %fds;
}
-is(scalar keys %fds, 0, 'No file descriptors leaked');
+my %i3fds = extract_fds($i3output);
+my %shfds = extract_fds($shoutput);
+
+# Diff the fds to account for services that keep fds open, such as the System Security Services Daemon (sssd)
+is(scalar keys %i3fds, scalar keys %shfds, 'No file descriptors leaked');
}
diff --git a/testcases/t/193-ipc-version.t b/testcases/t/193-ipc-version.t
index d5f4badf..82449de7 100644
--- a/testcases/t/193-ipc-version.t
+++ b/testcases/t/193-ipc-version.t
@@ -32,6 +32,5 @@ cmp_ok($version->{minor}, '>', 0, 'minor version > 0');
is(int($version->{minor}), $version->{minor}, 'minor version is an integer');
is(int($version->{patch}), $version->{patch}, 'patch version is an integer');
-like($version->{human_readable}, qr/branch/, 'human readable version contains branch name');
done_testing;
diff --git a/testcases/t/201-config-parser.t b/testcases/t/201-config-parser.t
index a8d45325..e2d885ba 100644
--- a/testcases/t/201-config-parser.t
+++ b/testcases/t/201-config-parser.t
@@ -98,18 +98,53 @@ is(parser_calls($config),
################################################################################
$config = <<'EOT';
+for_window [] nop empty
for_window [class="^Chrome"] floating enable
+for_window [class=^Chrome] floating enable
+for_window [floating_from = "auto" class= ==Class== ] nop floating
+for_window [tiling_from=auto class="==Class=="]nop floating
EOT
$expected = <<'EOT';
+cfg_for_window(nop empty)
cfg_criteria_add(class, ^Chrome)
cfg_for_window(floating enable)
+cfg_criteria_add(class, ^Chrome)
+cfg_for_window(floating enable)
+cfg_criteria_add(floating_from, auto)
+cfg_criteria_add(class, ==Class==)
+cfg_for_window(nop floating)
+cfg_criteria_add(tiling_from, auto)
+cfg_criteria_add(class, ==Class==)
+cfg_for_window(nop floating)
EOT
is(parser_calls($config),
$expected,
'for_window okay');
+$config = <<'EOT';
+for_window [tiling_from=typo] nop typo
+for_window [tiling_from="typo"] nop typo
+EOT
+
+$expected = <<'EOT';
+ERROR: CONFIG: Expected one of these tokens: '"', 'auto', 'user'
+ERROR: CONFIG: (in file <stdin>)
+ERROR: CONFIG: Line 1: for_window [tiling_from=typo] nop typo
+ERROR: CONFIG: ^^^^^^^^^^^^^^
+ERROR: CONFIG: Line 2: for_window [tiling_from="typo"] nop typo
+ERROR: CONFIG: Expected one of these tokens: 'auto', 'user'
+ERROR: CONFIG: (in file <stdin>)
+ERROR: CONFIG: Line 1: for_window [tiling_from=typo] nop typo
+ERROR: CONFIG: Line 2: for_window [tiling_from="typo"] nop typo
+ERROR: CONFIG: ^^^^^^^^^^^^^^^
+EOT
+
+is(parser_calls($config),
+ $expected,
+ 'for_window errors okay');
+
################################################################################
# assign
################################################################################
diff --git a/testcases/t/210-mark-unmark.t b/testcases/t/210-mark-unmark.t
index 32f898e6..0d9a073b 100644
--- a/testcases/t/210-mark-unmark.t
+++ b/testcases/t/210-mark-unmark.t
@@ -98,7 +98,7 @@ cmd 'focus left';
cmd 'mark important';
is_deeply(get_mark_for_window_on_workspace($tmp, $first), [ 'important' ], 'first container now has the mark');
-ok(!get_mark_for_window_on_workspace($tmp, $second), 'second container lost the mark');
+is_deeply(get_mark_for_window_on_workspace($tmp, $second), [], 'second container lost the mark');
##############################################################
# 5: mark a con, toggle the mark, check that the mark is gone
@@ -107,7 +107,7 @@ ok(!get_mark_for_window_on_workspace($tmp, $second), 'second container lost the
$con = open_window;
cmd 'mark important';
cmd 'mark --toggle important';
-ok(!get_mark_for_window_on_workspace($tmp, $con), 'container no longer has the mark');
+is_deeply(get_mark_for_window_on_workspace($tmp, $con), [], 'container no longer has the mark');
##############################################################
# 6: toggle a mark on an unmarked con, check it is marked
@@ -140,7 +140,7 @@ cmd 'focus left';
cmd 'mark --toggle important';
is_deeply(get_mark_for_window_on_workspace($tmp, $first), [ 'important' ], 'left container has the mark now');
-ok(!get_mark_for_window_on_workspace($tmp, $second), 'second containr no longer has the mark');
+is_deeply(get_mark_for_window_on_workspace($tmp, $second), [], 'second containr no longer has the mark');
##############################################################
# 9: try to mark two cons with the same mark and check that
@@ -154,8 +154,8 @@ my $result = cmd "[instance=iamnotunique] mark important";
is($result->[0]->{success}, 0, 'command was unsuccessful');
is($result->[0]->{error}, 'A mark must not be put onto more than one window', 'correct error is returned');
-ok(!get_mark_for_window_on_workspace($tmp, $first), 'first container is not marked');
-ok(!get_mark_for_window_on_workspace($tmp, $second), 'second containr is not marked');
+is_deeply(get_mark_for_window_on_workspace($tmp, $first), [], 'first container is not marked');
+is_deeply(get_mark_for_window_on_workspace($tmp, $second), [], 'second containr is not marked');
##############################################################
diff --git a/testcases/t/271-for_window_tilingfloating.t b/testcases/t/271-for_window_tilingfloating.t
index caee328d..f3947d6e 100644
--- a/testcases/t/271-for_window_tilingfloating.t
+++ b/testcases/t/271-for_window_tilingfloating.t
@@ -17,27 +17,69 @@
use i3test i3_config => <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-for_window [tiling] mark tiled
-for_window [floating] mark floated
+for_window [tiling] mark --add tiling
+for_window [floating] mark --add floating
+
+for_window [tiling_from="auto"] mark --add tiling_auto
+for_window [floating_from="auto"] mark --add floating_auto
+
+for_window [tiling_from="user"] mark --add tiling_user
+for_window [floating_from="user"] mark --add floating_user
EOT
use X11::XCB qw(PROP_MODE_REPLACE);
##############################################################
-# 13: check that the tiling / floating criteria work.
+# Check that the auto tiling / floating criteria work.
##############################################################
my $tmp = fresh_workspace;
-
-open_window;
-open_floating_window;
+my $A = open_window;
+my $B = open_floating_window;
my @nodes = @{get_ws($tmp)->{nodes}};
cmp_ok(@nodes, '==', 1, 'one tiling container on this workspace');
-is_deeply($nodes[0]->{marks}, [ 'tiled' ], "mark set for 'tiling' criterion");
+is_deeply($nodes[0]->{marks}, [ 'tiling', 'tiling_auto' ], "mark set for 'tiling' criterion");
+
+@nodes = @{get_ws($tmp)->{floating_nodes}};
+cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
+is_deeply($nodes[0]->{nodes}[0]->{marks}, [ 'floating', 'floating_auto' ], "mark set for 'floating' criterion");
+
+################################################################################
+# Check that the user tiling / floating criteria work.
+# The following rules are triggered here: 'tiling', 'tiling_user', 'floating',
+# 'floating_user'. Therefore, the old marks 'tiling' and 'floating' are
+# replaced but the 'tiling_auto' and 'floating_auto' marks are preserved.
+################################################################################
+
+cmd '[id=' . $A->{id} . '] floating enable';
+cmd '[id=' . $B->{id} . '] floating disable';
+
+@nodes = @{get_ws($tmp)->{nodes}};
+cmp_ok(@nodes, '==', 1, 'one tiling container on this workspace');
+is_deeply($nodes[0]->{marks}, [ 'floating_auto', 'tiling', 'tiling_user' ], "Marks updated after 'floating_user' criterion");
+
+@nodes = @{get_ws($tmp)->{floating_nodes}};
+cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
+is_deeply($nodes[0]->{nodes}[0]->{marks}, [ 'tiling_auto', 'floating', 'floating_user' ], "Marks updated after 'tiling_user' criterion");
+
+################################################################################
+# Check that the default and auto rules do not re-trigger
+# Here, the windows are returned to their original state but since the rules
+# `tiling`, `tiling_auto`, `floating` and `floating_auto` where already
+# triggered, only the `tiling_user` and `floating_user` rules should trigger.
+################################################################################
+
+# Use 'mark' to clear old marks
+cmd '[id=' . $A->{id} . '] mark A, floating disable';
+cmd '[id=' . $B->{id} . '] mark B, floating enable';
+
+@nodes = @{get_ws($tmp)->{nodes}};
+cmp_ok(@nodes, '==', 1, 'one tiling container on this workspace');
+is_deeply($nodes[0]->{marks}, [ 'A', 'tiling_user' ], "Only 'tiling_user' rule triggered");
@nodes = @{get_ws($tmp)->{floating_nodes}};
cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
-is_deeply($nodes[0]->{nodes}[0]->{marks}, [ 'floated' ], "mark set for 'floating' criterion");
+is_deeply($nodes[0]->{nodes}[0]->{marks}, [ 'B', 'floating_user' ], "Only 'floating_user' rule triggered");
##############################################################
diff --git a/testcases/t/297-assign-workspace-to-output.t b/testcases/t/297-assign-workspace-to-output.t
index eb8f24b2..4e251e5d 100644
--- a/testcases/t/297-assign-workspace-to-output.t
+++ b/testcases/t/297-assign-workspace-to-output.t
@@ -41,7 +41,7 @@ my $pid = launch_with_config($config);
sub check_output {
my ($workspace, $output, $msg) = @_;
- is(get_output_for_workspace($workspace), $output, $msg);
+ is(get_output_for_workspace($workspace), $output, "[$workspace->$output] " . $msg);
}
check_output('9', '', 'Numbered workspace with a big number that is assigned to output that does not exist is not used');
@@ -82,6 +82,10 @@ workspace 4 output whitespace fake-0
workspace foo output doesnotexist1 doesnotexist2 doesnotexist3
workspace bar output doesnotexist
workspace bar output fake-0
+workspace 5 output fake-0
+workspace 5:xxx output fake-1
+workspace 6:xxx output fake-0
+workspace 6 output fake-1
EOT
$pid = launch_with_config($config);
@@ -90,8 +94,11 @@ do_test('1', 'fake-0', 'Multiple assignments do not override a single one');
do_test('2', 'fake-3', 'First output out of multiple assignments is used');
do_test('3', 'fake-0', 'First existing output is used');
do_test('4', 'fake-0', 'Excessive whitespace is ok');
-do_test('5', 'fake-1', 'Numbered initialization for fake-1');
-do_test('6', 'fake-2', 'Numbered initialization for fake-2');
+do_test('5', 'fake-0', 'Numbered assignment ok');
+do_test('5:xxx', 'fake-1', 'Named assignment overrides number');
+do_test('6', 'fake-1', 'Numbered assignment ok');
+do_test('6:xxx', 'fake-0', 'Named assignment overrides number');
+do_test('7', 'fake-2', 'Numbered initialization for fake-2');
cmd 'focus output fake-0, workspace foo';
check_output('foo', 'fake-0', 'Workspace with only non-existing assigned outputs opened in current output');
@@ -103,5 +110,14 @@ check_output('bar', 'fake-0', 'Second workspace assignment line ignored');
cmd 'workspace 2, move workspace to output left';
check_output('2', 'fake-2', 'Moved assigned workspace up');
+# Specific name overrides assignment by number after renaming
+# See #4021
+cmd 'workspace 5, rename workspace to 5:xxx';
+check_output('5:xxx', 'fake-1', 'workspace triggered correct, specific assignment after renaming');
+
+# Same but opposite order
+cmd 'workspace 6, rename workspace to 6:xxx';
+check_output('6:xxx', 'fake-0', 'workspace triggered correct, specific assignment after renaming');
+
exit_gracefully($pid);
done_testing;
diff --git a/testcases/t/310-client-message-sticky.t b/testcases/t/310-client-message-sticky.t
new file mode 100644
index 00000000..0e7d8b7c
--- /dev/null
+++ b/testcases/t/310-client-message-sticky.t
@@ -0,0 +1,70 @@
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • https://build.i3wm.org/docs/testsuite.html
+# (or docs/testsuite)
+#
+# • https://build.i3wm.org/docs/lib-i3test.html
+# (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • https://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)
+#
+# Verify that _NET_WM_DESKTOP sticky requests do not conflict with dock
+# clients, resulting in a crash
+# Ticket: #4039
+# Bug still in: 4.18-238-g4d55bba7f
+use i3test;
+
+sub send_sticky_request {
+ my ($win) = @_;
+
+ my $msg = pack "CCSLLLLLL",
+ X11::XCB::CLIENT_MESSAGE, # response_type
+ 32, # format
+ 0, # sequence
+ $win->id, # window
+ $x->atom(name => '_NET_WM_DESKTOP')->id, # message type
+ hex '0xFFFFFFFF', # data32[0] = NET_WM_DESKTOP_ALL
+ 0, # data32[1]
+ 0, # data32[2]
+ 0, # data32[3]
+ 0; # data32[4]
+
+ $x->send_event(0, $x->get_root_window(), X11::XCB::EVENT_MASK_SUBSTRUCTURE_REDIRECT, $msg);
+}
+
+# Test the normal functionality first
+my $ws = fresh_workspace;
+my $win = open_window;
+
+is(@{get_ws($ws)->{floating_nodes}}, 0, 'No floating windows yet');
+send_sticky_request($win);
+sync_with_i3;
+
+is(@{get_ws($ws)->{floating_nodes}}, 1, 'One floating (sticky) window');
+$ws = fresh_workspace;
+is(@{get_ws($ws)->{floating_nodes}}, 1, 'Sticky window in new workspace');
+
+# See #4039
+kill_all_windows;
+$win = open_window({
+ window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK')
+});
+
+send_sticky_request($win);
+sync_with_i3;
+is(@{get_ws($ws)->{floating_nodes}}, 0, 'Dock client did not get sticky/floating');
+
+# Cause a ConfigureRequest by setting the window’s position/size.
+my ($a, $t) = $win->rect;
+$win->rect(X11::XCB::Rect->new(x => 0, y => 0, width => $a->width, height => $a->height));
+
+does_i3_live;
+is(@{get_ws($ws)->{floating_nodes}}, 0, 'Dock client still not sticky/floating');
+
+done_testing;
diff --git a/testcases/t/311-get-binding-modes.t b/testcases/t/311-get-binding-modes.t
new file mode 100644
index 00000000..3a00f695
--- /dev/null
+++ b/testcases/t/311-get-binding-modes.t
@@ -0,0 +1,41 @@
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • https://build.i3wm.org/docs/testsuite.html
+# (or docs/testsuite)
+#
+# • https://build.i3wm.org/docs/lib-i3test.html
+# (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • https://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)
+#
+# Verifies the GET_BINDING_MODE IPC command
+# Ticket: #3892
+# Bug still in: 4.18-318-g50160eb1
+use i3test i3_config => <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+mode "extra" {
+ bindsym Mod1+x nop foo
+}
+EOT
+
+my $i3 = i3(get_socket_path());
+$i3->connect->recv;
+# TODO: use the symbolic name for the command/reply type instead of the
+# numerical 12:
+my $binding_state = $i3->message(12, "")->recv;
+is($binding_state->{name}, 'default', 'at startup, binding mode is default');
+
+cmd 'mode extra';
+
+$binding_state = $i3->message(12, "")->recv;
+is($binding_state->{name}, 'extra', 'after switching, binding mode is extra');
+
+done_testing;
diff --git a/testcases/t/542-layout-restore-remanage.t b/testcases/t/542-layout-restore-remanage.t
index 26b50835..82ec84d0 100644
--- a/testcases/t/542-layout-restore-remanage.t
+++ b/testcases/t/542-layout-restore-remanage.t
@@ -83,4 +83,70 @@ is($nodes[0]->{name}, 'different_title', 'test window got swallowed');
close($fh);
+############################################################
+# Make sure window only gets swallowed once
+############################################################
+# Regression, issue #3888
+$ws = fresh_workspace;
+
+($fh, $filename) = tempfile(UNLINK => 1);
+print $fh <<'EOT';
+// vim:ts=4:sw=4:et
+{
+ // splith split container with 2 children
+ "layout": "splith",
+ "type": "con",
+ "nodes": [
+ {
+ "type": "con",
+ "swallows": [
+ {
+ "class": "^foo$"
+ }
+ ]
+ },
+ {
+ // splitv split container with 2 children
+ "layout": "splitv",
+ "type": "con",
+ "nodes": [
+ {
+ "type": "con",
+ "swallows": [
+ {
+ "class": "^foo$"
+ }
+ ]
+ },
+ {
+ "type": "con",
+ "swallows": [
+ {
+ "class": "^foo$"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
+EOT
+$fh->flush;
+cmd "append_layout $filename";
+
+$window = open_window wm_class => 'foo';
+
+# Changing an unrelated window property originally resulted in the window
+# getting remanaged and swallowd by a different placeholder, even though the
+# matching property (class for the layout above) didn't change.
+change_window_title($window, "different_title");
+
+@content = @{get_ws_content($ws)};
+
+subtest 'regression test that window gets only swallowed once', sub {
+ is($content[0]->{nodes}[0]->{window}, $window->id, 'first placeholder swallowed window');
+ isnt($content[0]->{nodes}[1]->{nodes}[0]->{window}, $window->id, 'second placeholder did not swallow window');
+ isnt($content[0]->{nodes}[1]->{nodes}[1]->{window}, $window->id, 'thid placeholder did not swallow window');
+};
+
done_testing;
diff --git a/travis/bintray-autobuild-debian.json b/travis/bintray-autobuild-debian.json
index 23fe6050..d01b7dba 100644
--- a/travis/bintray-autobuild-debian.json
+++ b/travis/bintray-autobuild-debian.json
@@ -13,7 +13,7 @@
"files": [
{
- "includePattern": "build/deb/debian-amd64/(.*\\.deb)$",
+ "includePattern": "distbuild/deb/debian-amd64/(.*\\.deb)$",
"matrixParams": {
"deb_distribution": "sid",
"deb_component": "main",
@@ -22,7 +22,7 @@
"uploadPattern": "$1"
},
{
- "includePattern": "build/deb/debian-i386/(.*\\.deb)$",
+ "includePattern": "distbuild/deb/debian-i386/(.*\\.deb)$",
"matrixParams": {
"deb_distribution": "sid",
"deb_component": "main",
diff --git a/travis/bintray-autobuild-ubuntu.json b/travis/bintray-autobuild-ubuntu.json
index 37f2f180..4c0d6114 100644
--- a/travis/bintray-autobuild-ubuntu.json
+++ b/travis/bintray-autobuild-ubuntu.json
@@ -13,7 +13,7 @@
"files": [
{
- "includePattern": "build/deb/ubuntu-amd64/(.*\\.deb)$",
+ "includePattern": "distbuild/deb/ubuntu-amd64/(.*\\.deb)$",
"matrixParams": {
"deb_distribution": "bionic",
"deb_component": "main",
@@ -22,7 +22,7 @@
"uploadPattern": "$1"
},
{
- "includePattern": "build/deb/ubuntu-i386/(.*\\.deb)$",
+ "includePattern": "distbuild/deb/ubuntu-i386/(.*\\.deb)$",
"matrixParams": {
"deb_distribution": "bionic",
"deb_component": "main",
diff --git a/travis/check-formatting.sh b/travis/check-formatting.sh
index 7aa2f565..3424513f 100755
--- a/travis/check-formatting.sh
+++ b/travis/check-formatting.sh
@@ -3,4 +3,4 @@
set -e
set -x
-clang-format-6.0 -i $(find . -name "*.[ch]" | tr '\n' ' ') && git diff --exit-code || (echo 'Code was not formatted using clang-format!'; false)
+clang-format-9 -i $(find . -name "*.[ch]" | tr '\n' ' ') && git diff --exit-code || (echo 'Code was not formatted using clang-format!'; false)
diff --git a/travis/check-spelling.pl b/travis/check-spelling.pl
index 2a112c50..f2e79b51 100755
--- a/travis/check-spelling.pl
+++ b/travis/check-spelling.pl
@@ -17,8 +17,11 @@ use Lintian::Spelling qw(check_spelling);
# Lintian complains if we don’t set a vendor.
use Lintian::Data;
use Lintian::Profile;
-Lintian::Data->set_vendor(
- Lintian::Profile->new('debian', ['/usr/share/lintian'], {}));
+
+my $profile = Lintian::Profile->new;
+$profile->load('debian', ['/usr/share/lintian']);
+
+Lintian::Data->set_vendor($profile);
my $exitcode = 0;
@@ -30,12 +33,12 @@ my $binary_spelling_exceptions = {
};
my @binaries = qw(
build/i3
- build/i3-config-wizard/i3-config-wizard
- build/i3-dump-log/i3-dump-log
- build/i3-input/i3-input
- build/i3-msg/i3-msg
- build/i3-nagbar/i3-nagbar
- build/i3bar/i3bar
+ build/i3-config-wizard
+ build/i3-dump-log
+ build/i3-input
+ build/i3-msg
+ build/i3-nagbar
+ build/i3bar
);
for my $binary (@binaries) {
check_spelling(slurp($binary), $binary_spelling_exceptions, sub {
diff --git a/travis/debian-build.sh b/travis/debian-build.sh
index 9ce5a5af..6e66155a 100755
--- a/travis/debian-build.sh
+++ b/travis/debian-build.sh
@@ -5,14 +5,10 @@ set -x
DEST=$1
-mkdir -p build
-cd build
-../configure
-make echo-version > ../I3_VERSION
-make dist-bzip2
+cd distbuild
# unpack dist tarball
mkdir -p "${DEST}"
-tar xf *.tar.bz2 -C "${DEST}" --strip-components=1
+tar xf meson-dist/*.tar.xz -C "${DEST}" --strip-components=1
cp -r ../debian "${DEST}"
sed -i '/^\s*libxcb-xrm-dev/d' deb/ubuntu-*/DIST/debian/control || true
cd "${DEST}"
diff --git a/travis/docker-build-and-push.sh b/travis/docker-build-and-push.sh
index 686b81b0..243d36a9 100755
--- a/travis/docker-build-and-push.sh
+++ b/travis/docker-build-and-push.sh
@@ -5,10 +5,6 @@ set -e
BASENAME=$1
DOCKERFILE=$2
-# .dockerignore is created on demand so that release.sh and other scripts are
-# not influenced by our travis setup.
-echo .git > .dockerignore
-
docker build --pull --no-cache --rm -t=${BASENAME} -f ${DOCKERFILE} .
# For pull requests, travis does not add secure environment variables to the
# environment (because pull requests could then steal their values), so skip
diff --git a/travis/docs.sh b/travis/docs.sh
index b11c097a..501946fa 100755
--- a/travis/docs.sh
+++ b/travis/docs.sh
@@ -3,20 +3,24 @@
set -e
set -x
-for f in $(grep '\.html$' debian/i3-wm.docs | grep -v 'docs/refcard.html' | grep -v 'docs/lib-i3test')
+# TODO: install the docs via meson, inject styles with an option
+
+for f in $(sed -n "s/^\s*'\(docs\/.*\)',$/\1/gp" meson.build | grep -vF .)
do
asciidoc -a linkcss -a stylesdir=https://i3wm.org/css -a scriptsdir=https://i3wm.org/js --backend=xhtml11 -f docs/asciidoc-git.conf $(dirname $f)/$(basename $f .html)
done
-./docs/i3-pod2html i3-dmenu-desktop man/i3-dmenu-desktop.html
-./docs/i3-pod2html i3-save-tree man/i3-save-tree.html
-./docs/i3-pod2html build/testcases/lib/i3test.pm docs/lib-i3test.html
-./docs/i3-pod2html testcases/lib/i3test/Test.pm docs/lib-i3test-test.html
-for file in $(sed 's/\.1$/.man/g' debian/i3-wm.manpages)
+
+./docs/i3-pod2html --stylesurl=https://i3wm.org/css i3-dmenu-desktop man/i3-dmenu-desktop.html
+./docs/i3-pod2html --stylesurl=https://i3wm.org/css i3-save-tree man/i3-save-tree.html
+./docs/i3-pod2html --stylesurl=https://i3wm.org/css build/i3test.pm docs/lib-i3test.html
+./docs/i3-pod2html --stylesurl=https://i3wm.org/css testcases/lib/i3test/Test.pm docs/lib-i3test-test.html
+
+for file in $(sed -n "s/^\s*'\(man\/.*\).man',$/\1.man/gp" meson.build)
do
[ -f "$file" ] && asciidoc -a linkcss -a stylesdir=https://i3wm.org/css -a scriptsdir=https://i3wm.org/js --backend=xhtml11 -f docs/asciidoc-git.conf "$file"
done
mkdir -p deb/COPY-DOCS
-cp $(tr "\n" ' ' < debian/i3-wm.docs) deb/COPY-DOCS/
-cp $(sed 's/\.1$/.html/g' debian/i3-wm.manpages | tr "\n" ' ') deb/COPY-DOCS/
+cp $(sed -n "s/^\s*'\(docs\/.*\)',$/\1/gp" meson.build | grep -F .) deb/COPY-DOCS/
+cp $(sed -n "s/^\s*'\(man\/.*\).man',$/\1.html/gp" meson.build) deb/COPY-DOCS/
diff --git a/travis/run-tests.sh b/travis/run-tests.sh
index eac2ea8a..4cc70479 100755
--- a/travis/run-tests.sh
+++ b/travis/run-tests.sh
@@ -26,7 +26,7 @@ fi
# Try running the tests in parallel so that the common case (tests pass) is
# quick, but fall back to running them in sequence to make debugging easier.
-if ! make check
+if ! ninja test
then
- ./testcases/complete-run.pl --parallel=1 || (cat latest/complete-run.log; false)
+ ./complete-run.pl --parallel=1 || (cat latest/complete-run.log; false)
fi
diff --git a/travis/travis-base-386.Dockerfile b/travis/travis-base-386.Dockerfile
index 355c2588..fc035034 100644
--- a/travis/travis-base-386.Dockerfile
+++ b/travis/travis-base-386.Dockerfile
@@ -13,12 +13,12 @@ RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry
# (3608 kB/s)). Hence, let’s stick with httpredir.debian.org (default) for now.
# Install mk-build-deps (for installing the i3 build dependencies),
-# clang and clang-format-6.0 (for checking formatting and building with clang),
+# clang and clang-format-9 (for checking formatting and building with clang),
# lintian (for checking spelling errors),
RUN linux32 apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
dpkg-dev devscripts git equivs \
- clang clang-format-6.0 \
+ build-essential clang clang-format-9 \
lintian && \
rm -rf /var/lib/apt/lists/*
diff --git a/travis/travis-base-ubuntu-386.Dockerfile b/travis/travis-base-ubuntu-386.Dockerfile
index d52df4b8..747330aa 100644
--- a/travis/travis-base-ubuntu-386.Dockerfile
+++ b/travis/travis-base-ubuntu-386.Dockerfile
@@ -13,12 +13,12 @@ RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry
# (3608 kB/s)). Hence, let’s stick with httpredir.debian.org (default) for now.
# Install mk-build-deps (for installing the i3 build dependencies),
-# clang and clang-format-6.0 (for checking formatting and building with clang),
+# clang and clang-format-9 (for checking formatting and building with clang),
# lintian (for checking spelling errors),
RUN linux32 apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
dpkg-dev devscripts git equivs \
- clang clang-format-6.0 \
+ build-essential clang clang-format-9 \
lintian && \
rm -rf /var/lib/apt/lists/*
diff --git a/travis/travis-base-ubuntu.Dockerfile b/travis/travis-base-ubuntu.Dockerfile
index d1057a39..8a728af3 100644
--- a/travis/travis-base-ubuntu.Dockerfile
+++ b/travis/travis-base-ubuntu.Dockerfile
@@ -13,13 +13,13 @@ RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry
# (3608 kB/s)). Hence, let’s stick with httpredir.debian.org (default) for now.
# Install mk-build-deps (for installing the i3 build dependencies),
-# clang and clang-format-6.0 (for checking formatting and building with clang),
+# clang and clang-format-9 (for checking formatting and building with clang),
# lintian (for checking spelling errors),
# test suite dependencies (for running tests)
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
dpkg-dev devscripts git equivs \
- clang clang-format-6.0 \
+ build-essential clang clang-format-9 \
lintian && \
rm -rf /var/lib/apt/lists/*
diff --git a/travis/travis-base.Dockerfile b/travis/travis-base.Dockerfile
index def7598d..e5552c14 100644
--- a/travis/travis-base.Dockerfile
+++ b/travis/travis-base.Dockerfile
@@ -11,13 +11,13 @@ RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry
# (3608 kB/s)). Hence, let’s stick with httpredir.debian.org (default) for now.
# Install mk-build-deps (for installing the i3 build dependencies),
-# clang and clang-format-6.0 (for checking formatting and building with clang),
+# clang and clang-format-9 (for checking formatting and building with clang),
# lintian (for checking spelling errors),
# test suite dependencies (for running tests)
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
dpkg-dev devscripts git equivs \
- clang clang-format-6.0 \
+ build-essential clang clang-format-9 \
lintian \
libmodule-install-perl libanyevent-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-perl libinline-c-perl libxml-simple-perl libmouse-perl libmousex-nativetraits-perl libextutils-depends-perl perl libtest-deep-perl libtest-exception-perl libxml-parser-perl libtest-simple-perl libtest-fatal-perl libdata-dump-perl libtest-differences-perl libxml-tokeparser-perl libipc-run-perl libxcb-xtest0-dev libx11-xcb-perl libjson-xs-perl x11-xserver-utils && \
rm -rf /var/lib/apt/lists/*