From 018a47ceef4632b5f103fdbd8a08d62e96ef854b Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 6 Mar 2016 16:26:03 +0100 Subject: [PATCH 001/150] debian: update changelog --- debian/changelog | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 1cb2e681..f351574a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,19 @@ -i3-wm (4.11.1-1) unstable; urgency=medium +i3-wm (4.12.1-1) unstable; urgency=medium * UNRELEASED -- Michael Stapelberg Wed, 30 Sep 2015 09:03:26 +0200 +i3-wm (4.12-1) unstable; urgency=medium + + * New upstream release. + * Move to debhelper 9 + * Bump Standards-Version to 3.9.7 (no changes necessary) + * debian/watch: verify signature, use https + * Enable full hardening + + -- Michael Stapelberg Sun, 06 Mar 2016 14:20:38 +0100 + i3-wm (4.11-1) unstable; urgency=medium * New upstream release. From cb4235706fd4cc076b7f9eb8b009238b7a1b21d2 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 6 Mar 2016 16:27:49 +0100 Subject: [PATCH 002/150] update release.sh for the 4.12 release --- release.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release.sh b/release.sh index 766f4d30..c8d8fc4c 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.11" -export PREVIOUS_VERSION="4.10.4" +export RELEASE_VERSION="4.12" +export PREVIOUS_VERSION="4.11" export RELEASE_BRANCH="next" if [ ! -e "../i3.github.io" ] From efff2361cbd27b5095e42155507121f2270de4af Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 6 Mar 2016 16:31:11 +0100 Subject: [PATCH 003/150] release.sh: update i3-announce mailing list address --- release.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release.sh b/release.sh index c8d8fc4c..720636fc 100755 --- a/release.sh +++ b/release.sh @@ -194,7 +194,7 @@ git config --add remote.origin.push "+refs/heads/master:refs/heads/master" cd ${TMPDIR} cat >email.txt < -To: i3-announce@i3.zekjur.net +To: i3-announce@freelists.org Subject: i3 v${RELEASE_VERSION} released Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit From ab2d46b65bdbce4df772fee884a821c9d0a9f4f3 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 6 Mar 2016 17:02:12 +0100 Subject: [PATCH 004/150] release.sh: clone from canonical location This ensures the repository is up-to-date (in all branches!), hopefully preventing merge mistakes such as the one fixed with https://github.com/i3/i3/commit/0e29101ae5f3753626ba447b83a9b8bd490de37e --- release.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release.sh b/release.sh index 720636fc..7b521145 100755 --- a/release.sh +++ b/release.sh @@ -45,7 +45,7 @@ if ! wget https://i3wm.org/downloads/i3-${PREVIOUS_VERSION}.tar.bz2; then echo "Could not download i3-${PREVIOUS_VERSION}.tar.bz2 (required for comparing files)." exit 1 fi -git clone --quiet --branch "${RELEASE_BRANCH}" file://${STARTDIR} +git clone --quiet --branch "${RELEASE_BRANCH}" https://github.com/i3/i3 cd i3 if [ ! -e "${STARTDIR}/RELEASE-NOTES-${RELEASE_VERSION}" ]; then echo "Required file RELEASE-NOTES-${RELEASE_VERSION} not found." From 42f5a6ce479968a8f95dd5a827524865094d6a5c Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 6 Mar 2016 18:51:52 +0100 Subject: [PATCH 005/150] travis: skip login+push for pull requests --- travis/docker-build-and-push.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/travis/docker-build-and-push.sh b/travis/docker-build-and-push.sh index 7dfd3392..76e2a132 100755 --- a/travis/docker-build-and-push.sh +++ b/travis/docker-build-and-push.sh @@ -7,5 +7,11 @@ set -e echo .git > .dockerignore docker build --pull --no-cache --rm -t=${BASENAME} -f travis-build.Dockerfile . -docker login -e ${DOCKER_EMAIL} -u ${DOCKER_USER} -p ${DOCKER_PASS} -docker push ${BASENAME} +# For pull requests, travis does not add secure environment variables to the +# environment (because pull requests could then steal their values), so skip +# the login+push step when the variable isn’t set. +if [ -n "${DOCKER_PASS}" ] +then + docker login -e ${DOCKER_EMAIL} -u ${DOCKER_USER} -p ${DOCKER_PASS} + docker push ${BASENAME} +fi From df4b4d0f40d8d4aac1f84f9a72c334d13b8cf64a Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Tue, 8 Mar 2016 17:54:28 +0100 Subject: [PATCH 006/150] Make i3.applications.desktop file more complete Add GenericName to i3.applications.desktop file. --- i3.applications.desktop | 1 + 1 file changed, 1 insertion(+) diff --git a/i3.applications.desktop b/i3.applications.desktop index e40689dd..28445922 100644 --- a/i3.applications.desktop +++ b/i3.applications.desktop @@ -2,6 +2,7 @@ Type=Application Name=i3 NoDisplay=true +GenericName=A dynamic tiling window manager Comment=improved dynamic tiling window manager Exec=i3 X-GNOME-WMName=i3 From 868180565e2e6e847e4967d73c794fb04299c1f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98ystein=20Walle?= Date: Tue, 8 Mar 2016 18:02:04 +0100 Subject: [PATCH 007/150] Update information on where to find #i3 on IRC --- PACKAGE-MAINTAINER | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PACKAGE-MAINTAINER b/PACKAGE-MAINTAINER index 22e10997..5a922ee8 100644 --- a/PACKAGE-MAINTAINER +++ b/PACKAGE-MAINTAINER @@ -42,7 +42,7 @@ 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.twice-irc.de). +(#i3 on irc.freenode.net). Thanks again for your efforts, Michael From ac97dbdf90d637eee572a55b45fdc7f58982581b Mon Sep 17 00:00:00 2001 From: Kenneth Lyons Date: Sat, 19 Mar 2016 09:54:16 -0700 Subject: [PATCH 008/150] Fix typos in documentation. --- docs/hacking-howto | 6 +++--- docs/i3bar-protocol | 4 ++-- docs/ipc | 2 +- docs/testsuite | 8 ++++---- docs/userguide | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/hacking-howto b/docs/hacking-howto index 247a1791..bd99b900 100644 --- a/docs/hacking-howto +++ b/docs/hacking-howto @@ -593,7 +593,7 @@ optimize this and call +x_push_node+ on the appropriate con directly. itself for the container’s children. This function actually pushes the state, see the next paragraph. 4. If the pointer needs to be warped to a different position (for example when - changing focus to a differnt output), it will be warped now. + changing focus to a different output), it will be warped now. 5. The eventmask is restored for all mapped windows. 6. Window decorations will be rendered by calling +x_deco_recurse+ on the root container, which then recursively calls itself for the children. @@ -850,7 +850,7 @@ empty. Afterwards, +con_focus+ will be called to fix the focus stack and the tree will be flattened. -=== Case 3: Moving to non-existant top/bottom +=== Case 3: Moving to non-existent top/bottom Like in case 1, the reference layout for this case is a single workspace in horizontal orientation with two containers on it. Focus is on the left @@ -877,7 +877,7 @@ container and the container above/below the current one (on the level of Now, +con_focus+ will be called to fix the focus stack and the tree will be flattened. -=== Case 4: Moving to existant top/bottom +=== Case 4: Moving to existent top/bottom The reference layout for this case is a vertical workspace with two containers. The bottom one is a h-split containing two containers (1 and 2). Focus is on diff --git a/docs/i3bar-protocol b/docs/i3bar-protocol index 3ae14453..0ad1967f 100644 --- a/docs/i3bar-protocol +++ b/docs/i3bar-protocol @@ -6,7 +6,7 @@ August 2012 This document explains the protocol in which i3bar expects its input. It provides support for colors, urgency, shortening and easy manipulation. -== Rationale for chosing JSON +== Rationale for choosing JSON Before describing the protocol, let’s cover why JSON is a building block of this protocol. @@ -233,7 +233,7 @@ name:: instance:: Instance of the block, if set x, y:: - X11 root window coordinates where the click occured + X11 root window coordinates where the click occurred button:: X11 button ID (for example 1 to 3 for left/middle/right mouse button) diff --git a/docs/ipc b/docs/ipc index dc4e6947..f6f6c928 100644 --- a/docs/ipc +++ b/docs/ipc @@ -285,7 +285,7 @@ type (string):: Type of this container. Can be one of "root", "output", "con", "floating_con", "workspace" or "dockarea". border (string):: - Can be either "normal", "none" or "1pixel", dependending on the + Can be either "normal", "none" or "1pixel", depending on the container’s border style. current_border_width (integer):: Number of pixels of the border width. diff --git a/docs/testsuite b/docs/testsuite index 8fdb9635..71c6a427 100644 --- a/docs/testsuite +++ b/docs/testsuite @@ -109,7 +109,7 @@ run the tests on a separate X server instance (using Xephyr). Xephyr will open a window where you can inspect the running test. You can run the tests without an X session with Xvfb, such as with +xvfb-run -./complete-run+. This will also speed up the tests signficantly especially on +./complete-run+. This will also speed up the tests significantly especially on machines without a powerful video card. .Example invocation of complete-run.pl+ @@ -196,7 +196,7 @@ In order to open new windows, change attributes, get events, etc., the testsuite uses X11::XCB, a new (and quite specific to i3 at the moment) Perl module which uses the XCB protocol description to generate Perl bindings to X11. They work in a very similar way to libxcb (which i3 uses) and provide -relatively high-level interfaces (objects such as +X11::XCB::Window+) aswell as +relatively high-level interfaces (objects such as +X11::XCB::Window+) as well as access to the low-level interface, which is very useful when testing a window manager. @@ -450,7 +450,7 @@ cmd 'focus left'; is($x->input_focus, $left->id, 'left window focused'); ---------- -However, the test fails. Sometimes. Apparantly, there is a race condition in +However, the test fails. Sometimes. Apparently, there is a race condition in your test. If you think about it, this is because you are using two different pieces of software: You tell i3 to update focus, i3 confirms that, and then you ask X11 to give you the current focus. There is a certain time i3 needs to @@ -614,7 +614,7 @@ activation, we decreased the total amount of time necessary to run all tests it significantly more attractive to run the test suite more often (or at all) during development. -An alternative approach to using socket activation is polling for the existance +An alternative approach to using socket activation is polling for the existence of the IPC socket and connecting to it. While this might be slightly easier to implement, it wastes CPU time and is considerably uglier than this solution :). After all, +lib/SocketActivation.pm+ contains only 54 SLOC. diff --git a/docs/userguide b/docs/userguide index f3f80c96..f46a0be7 100644 --- a/docs/userguide +++ b/docs/userguide @@ -1372,7 +1372,7 @@ NetworkManager, VLC, Pidgin, etc. can place little icons. You can configure on which output (monitor) the icons should be displayed or you can turn off the functionality entirely. -You can use mutliple +tray_output+ directives in your config to specify a list +You can use multiple +tray_output+ directives in your config to specify a list of outputs on which you want the tray to appear. The first available output in that list as defined by the order of the directives will be used for the tray output. @@ -2204,7 +2204,7 @@ bindsym $mod+g exec i3-input -p 'goto ' -l 1 -P 'Goto: ' --------------------------------------- Alternatively, if you do not want to mess with +i3-input+, you could create -seperate bindings for a specific set of labels and then only use those labels. +separate bindings for a specific set of labels and then only use those labels. /////////////////////////////////////////////////////////////////// [[pango_markup]] From 301320585e1a34b51e7229345ed7f1013cd870cd Mon Sep 17 00:00:00 2001 From: "Kacper Kowalik (Xarthisius)" Date: Mon, 7 Mar 2016 19:40:02 -0600 Subject: [PATCH 009/150] Add missing MAX macros, ensure that i3 can be compiled without pango --- libi3/font.c | 2 ++ src/floating.c | 4 ++++ src/util.c | 2 ++ src/x.c | 4 ++++ 4 files changed, 12 insertions(+) diff --git a/libi3/font.c b/libi3/font.c index 5a2504fa..00e7dfb3 100644 --- a/libi3/font.c +++ b/libi3/font.c @@ -397,9 +397,11 @@ static void draw_text_xcb(const xcb_char2b_t *text, size_t text_len, xcb_drawabl void draw_text(i3String *text, xcb_drawable_t drawable, xcb_gcontext_t gc, xcb_visualtype_t *visual, int x, int y, int max_width) { assert(savedFont != NULL); +#if PANGO_SUPPORT if (visual == NULL) { visual = root_visual_type; } +#endif switch (savedFont->type) { case FONT_TYPE_NONE: diff --git a/src/floating.c b/src/floating.c index 231577fd..65a2810a 100644 --- a/src/floating.c +++ b/src/floating.c @@ -11,6 +11,10 @@ */ #include "all.h" +#ifndef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#endif + /* * Calculates sum of heights and sum of widths of all currently active outputs * diff --git a/src/util.c b/src/util.c index 35ce8b19..53f78d72 100644 --- a/src/util.c +++ b/src/util.c @@ -341,10 +341,12 @@ char *pango_escape_markup(char *input) { if (!font_is_pango()) return input; +#if PANGO_SUPPORT char *escaped = g_markup_escape_text(input, -1); FREE(input); return escaped; +#endif } /* diff --git a/src/x.c b/src/x.c index f44bc37a..43db952d 100644 --- a/src/x.c +++ b/src/x.c @@ -12,6 +12,10 @@ */ #include "all.h" +#ifndef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#endif + xcb_window_t ewmh_window; /* Stores the X11 window ID of the currently focused window */ From eb0a0a166ff0ae26d2f65b4d99757673e43c88a7 Mon Sep 17 00:00:00 2001 From: "Kacper Kowalik (Xarthisius)" Date: Mon, 7 Mar 2016 20:04:59 -0600 Subject: [PATCH 010/150] Convert ifdef CAIRO_SUPPORT to if statements to keep consistency with common.mk --- include/libi3.h | 6 +++--- libi3/draw_util.c | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/libi3.h b/include/libi3.h index 4c722671..da5ad891 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -20,7 +20,7 @@ #if PANGO_SUPPORT #include #endif -#ifdef CAIRO_SUPPORT +#if CAIRO_SUPPORT #include #endif @@ -518,7 +518,7 @@ typedef struct placeholder_t { */ char *format_placeholders(char *format, placeholder_t *placeholders, int num); -#ifdef CAIRO_SUPPORT +#if CAIRO_SUPPORT /* We need to flush cairo surfaces twice to avoid an assertion bug. See #1989 * and https://bugs.freedesktop.org/show_bug.cgi?id=92455. */ #define CAIRO_SURFACE_FLUSH(surface) \ @@ -542,7 +542,7 @@ typedef struct surface_t { int width; int height; -#ifdef CAIRO_SUPPORT +#if CAIRO_SUPPORT /* A cairo surface representing the drawable. */ cairo_surface_t *surface; diff --git a/libi3/draw_util.c b/libi3/draw_util.c index dcd881c2..b69d51b4 100644 --- a/libi3/draw_util.c +++ b/libi3/draw_util.c @@ -11,7 +11,7 @@ #include #include #include -#ifdef CAIRO_SUPPORT +#if CAIRO_SUPPORT #include #endif @@ -50,7 +50,7 @@ void draw_util_surface_init(xcb_connection_t *conn, surface_t *surface, xcb_draw ELOG("Could not create graphical context. Error code: %d. Please report this bug.\n", error->error_code); } -#ifdef CAIRO_SUPPORT +#if CAIRO_SUPPORT surface->surface = cairo_xcb_surface_create(conn, surface->id, surface->visual_type, width, height); surface->cr = cairo_create(surface->surface); #endif @@ -62,7 +62,7 @@ void draw_util_surface_init(xcb_connection_t *conn, surface_t *surface, xcb_draw */ void draw_util_surface_free(xcb_connection_t *conn, surface_t *surface) { xcb_free_gc(conn, surface->gc); -#ifdef CAIRO_SUPPORT +#if CAIRO_SUPPORT cairo_surface_destroy(surface->surface); cairo_destroy(surface->cr); @@ -81,7 +81,7 @@ void draw_util_surface_free(xcb_connection_t *conn, surface_t *surface) { void draw_util_surface_set_size(surface_t *surface, int width, int height) { surface->width = width; surface->height = height; -#ifdef CAIRO_SUPPORT +#if CAIRO_SUPPORT cairo_xcb_surface_set_size(surface->surface, width, height); #endif } @@ -121,7 +121,7 @@ color_t draw_util_hex_to_color(const char *color) { static void draw_util_set_source_color(xcb_connection_t *conn, surface_t *surface, color_t color) { RETURN_UNLESS_SURFACE_INITIALIZED(surface); -#ifdef CAIRO_SUPPORT +#if CAIRO_SUPPORT cairo_set_source_rgba(surface->cr, color.red, color.green, color.blue, color.alpha); #else uint32_t colorpixel = color.colorpixel; @@ -139,7 +139,7 @@ static void draw_util_set_source_color(xcb_connection_t *conn, surface_t *surfac void draw_util_text(i3String *text, surface_t *surface, color_t fg_color, color_t bg_color, int x, int y, int max_width) { RETURN_UNLESS_SURFACE_INITIALIZED(surface); -#ifdef CAIRO_SUPPORT +#if CAIRO_SUPPORT /* Flush any changes before we draw the text as this might use XCB directly. */ CAIRO_SURFACE_FLUSH(surface->surface); #endif @@ -147,7 +147,7 @@ void draw_util_text(i3String *text, surface_t *surface, color_t fg_color, color_ set_font_colors(surface->gc, fg_color, bg_color); draw_text(text, surface->id, surface->gc, surface->visual_type, x, y, max_width); -#ifdef CAIRO_SUPPORT +#if CAIRO_SUPPORT /* Notify cairo that we (possibly) used another way to draw on the surface. */ cairo_surface_mark_dirty(surface->surface); #endif @@ -162,7 +162,7 @@ void draw_util_text(i3String *text, surface_t *surface, color_t fg_color, color_ void draw_util_rectangle(xcb_connection_t *conn, surface_t *surface, color_t color, double x, double y, double w, double h) { RETURN_UNLESS_SURFACE_INITIALIZED(surface); -#ifdef CAIRO_SUPPORT +#if CAIRO_SUPPORT cairo_save(surface->cr); /* Using the SOURCE operator will copy both color and alpha information directly @@ -194,7 +194,7 @@ void draw_util_rectangle(xcb_connection_t *conn, surface_t *surface, color_t col void draw_util_clear_surface(xcb_connection_t *conn, surface_t *surface, color_t color) { RETURN_UNLESS_SURFACE_INITIALIZED(surface); -#ifdef CAIRO_SUPPORT +#if CAIRO_SUPPORT cairo_save(surface->cr); /* Using the SOURCE operator will copy both color and alpha information directly @@ -227,7 +227,7 @@ void draw_util_copy_surface(xcb_connection_t *conn, surface_t *src, surface_t *d RETURN_UNLESS_SURFACE_INITIALIZED(src); RETURN_UNLESS_SURFACE_INITIALIZED(dest); -#ifdef CAIRO_SUPPORT +#if CAIRO_SUPPORT cairo_save(dest->cr); /* Using the SOURCE operator will copy both color and alpha information directly From 7b1729a85bd511d591e620fcc32985a76180358f Mon Sep 17 00:00:00 2001 From: Cedric Date: Sun, 20 Mar 2016 12:12:11 +0100 Subject: [PATCH 011/150] i3-dmenu-desktop: do not die on failed open --- i3-dmenu-desktop | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/i3-dmenu-desktop b/i3-dmenu-desktop index a0549ead..3b81cb20 100755 --- a/i3-dmenu-desktop +++ b/i3-dmenu-desktop @@ -25,7 +25,11 @@ binmode STDERR, ':utf8'; # reads in a whole file sub slurp { my ($filename) = @_; - open(my $fh, '<', $filename) or die "$!"; + my $fh; + if (!open($fh, '<', $filename)) { + warn "Could not open $filename: $!"; + return undef; + } local $/; my $result; eval { From 5dd4508c742cec1cde9ea12ebd4900440e63b089 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 1 Apr 2016 15:57:41 +0200 Subject: [PATCH 012/150] *.xsession.desktop: add Keywords= See also https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=693918 and https://wiki.gnome.org/Initiatives/GnomeGoals/DesktopFileKeywords --- i3-with-shmlog.xsession.desktop | 1 + i3.xsession.desktop | 1 + 2 files changed, 2 insertions(+) diff --git a/i3-with-shmlog.xsession.desktop b/i3-with-shmlog.xsession.desktop index 8cd9431b..3c634500 100644 --- a/i3-with-shmlog.xsession.desktop +++ b/i3-with-shmlog.xsession.desktop @@ -3,3 +3,4 @@ Name=i3 (with debug log) Comment=improved dynamic tiling window manager Exec=i3-with-shmlog Type=Application +Keywords=tiling;wm;windowmanager;window;manager; diff --git a/i3.xsession.desktop b/i3.xsession.desktop index d1340053..11a64e26 100644 --- a/i3.xsession.desktop +++ b/i3.xsession.desktop @@ -6,3 +6,4 @@ TryExec=i3 Type=Application X-LightDM-DesktopName=i3 DesktopNames=i3 +Keywords=tiling;wm;windowmanager;window;manager; From ba550382a31c22b2d808cc9cca67a8c8c9b9f27c Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 1 Apr 2016 16:34:56 +0200 Subject: [PATCH 013/150] debian: remove menu file, add lintian-overrides --- debian/changelog | 10 +++++++++- debian/i3-wm.lintian-overrides | 2 ++ debian/i3-wm.menu | 5 ----- 3 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 debian/i3-wm.lintian-overrides delete mode 100644 debian/i3-wm.menu diff --git a/debian/changelog b/debian/changelog index f351574a..3c88a21e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,7 +2,15 @@ i3-wm (4.12.1-1) unstable; urgency=medium * UNRELEASED - -- Michael Stapelberg Wed, 30 Sep 2015 09:03:26 +0200 + -- Michael Stapelberg Fri, 01 Apr 2016 16:34:35 +0200 + +i3-wm (4.12-2) unstable; urgency=medium + + * Override lintian warning desktop-entry-contains-unknown-key for + DesktopNames, gdm needs that key. + * Remove i3-wm.menu to conform to the tech-ctte decision on #741573. + + -- Michael Stapelberg Fri, 01 Apr 2016 15:51:23 +0200 i3-wm (4.12-1) unstable; urgency=medium diff --git a/debian/i3-wm.lintian-overrides b/debian/i3-wm.lintian-overrides new file mode 100644 index 00000000..a999fe4c --- /dev/null +++ b/debian/i3-wm.lintian-overrides @@ -0,0 +1,2 @@ +# gdm needs the DesktopNames key, even though lintian doesn’t recognize it yet. +desktop-entry-contains-unknown-key usr/share/xsessions/i3.desktop:* DesktopNames diff --git a/debian/i3-wm.menu b/debian/i3-wm.menu deleted file mode 100644 index 6c0704fb..00000000 --- a/debian/i3-wm.menu +++ /dev/null @@ -1,5 +0,0 @@ -?package(i3-wm): \ - needs="wm" \ - section="Window Managers" \ - title="i3" \ - command="/usr/bin/i3" From a2632fd3080e523216ce3427ff110af086efd68a Mon Sep 17 00:00:00 2001 From: Hong Xu Date: Sun, 3 Apr 2016 23:47:07 -0700 Subject: [PATCH 014/150] Point out the default ipc message type in i3-msg.man --- man/i3-msg.man | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/i3-msg.man b/man/i3-msg.man index e0c70c44..000d9bf2 100644 --- a/man/i3-msg.man +++ b/man/i3-msg.man @@ -29,7 +29,7 @@ from the root window and then try /tmp/i3-ipc.sock before exiting with an error. *-t* 'type':: -Send ipc message, see below. +Send ipc message, see below. This option defaults to "command". *message*:: Send ipc message, see below. From 66d9c983e44888dbf58435f8793ff0dcd9bc9054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20Engestr=C3=B6m?= Date: Mon, 4 Apr 2016 08:33:59 +0100 Subject: [PATCH 015/150] Fix spelling mistakes --- docs/hacking-howto | 2 +- i3-input/keysym.map | 2 +- i3-input/main.c | 2 +- i3bar/src/mode.c | 2 +- i3bar/src/outputs.c | 2 +- i3bar/src/workspaces.c | 2 +- i3bar/src/xcb.c | 2 +- include/shmlog.h | 2 +- src/commands.c | 2 +- src/randr.c | 2 +- src/render.c | 2 +- src/sighandler.c | 4 ++-- src/tree.c | 2 +- testcases/complete-run.pl | 4 ++-- testcases/lib/StatusLine.pm | 4 ++-- testcases/t/103-move.t | 2 +- testcases/t/105-stacking.t | 2 +- testcases/t/131-stacking-order.t | 2 +- testcases/t/159-socketpaths.t | 2 +- 19 files changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/hacking-howto b/docs/hacking-howto index bd99b900..74a690e7 100644 --- a/docs/hacking-howto +++ b/docs/hacking-howto @@ -187,7 +187,7 @@ 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 dependant on anything. +Contains useful functions which are not really dependent on anything. src/window.c:: Handlers to update X11 window properties like +WM_CLASS+, +_NET_WM_NAME+, diff --git a/i3-input/keysym.map b/i3-input/keysym.map index 6e587bdc..b198dd6d 100644 --- a/i3-input/keysym.map +++ b/i3-input/keysym.map @@ -1,7 +1,7 @@ # This list can be used to convert X11 Keysyms to Unicode 2.1 character. # The list is not checked for correctness by Unicode officials. Use it # at your own risk and the creator is not responsable for any damage that -# occured due to using this list. +# occurred due to using this list. # # The list is created by looking at the Keysym names and the Unicode data # file. Other mapping tables were used as a reference where needed. diff --git a/i3-input/main.c b/i3-input/main.c index 64a089dd..7115727e 100644 --- a/i3-input/main.c +++ b/i3-input/main.c @@ -80,7 +80,7 @@ void debuglog(char *fmt, ...) { } /* - * Restores the X11 input focus to whereever it was before. + * Restores the X11 input focus to wherever it was before. * This is necessary because i3-input’s window has override_redirect=1 * (→ unmanaged by the window manager) and thus i3-input changes focus itself. * This function is called on exit(). diff --git a/i3bar/src/mode.c b/i3bar/src/mode.c index d6767786..3e52f0b1 100644 --- a/i3bar/src/mode.c +++ b/i3bar/src/mode.c @@ -119,7 +119,7 @@ void parse_mode_json(char *json) { state = yajl_parse(handle, (const unsigned char *)json, strlen(json)); - /* FIXME: Propper error handling for JSON parsing */ + /* FIXME: Proper error handling for JSON parsing */ switch (state) { case yajl_status_ok: break; diff --git a/i3bar/src/outputs.c b/i3bar/src/outputs.c index 841a7565..b53d8cc8 100644 --- a/i3bar/src/outputs.c +++ b/i3bar/src/outputs.c @@ -271,7 +271,7 @@ void parse_outputs_json(char *json) { state = yajl_parse(handle, (const unsigned char *)json, strlen(json)); - /* FIXME: Propper errorhandling for JSON-parsing */ + /* FIXME: Proper errorhandling for JSON-parsing */ switch (state) { case yajl_status_ok: break; diff --git a/i3bar/src/workspaces.c b/i3bar/src/workspaces.c index 77b351e8..1187a946 100644 --- a/i3bar/src/workspaces.c +++ b/i3bar/src/workspaces.c @@ -233,7 +233,7 @@ void parse_workspaces_json(char *json) { state = yajl_parse(handle, (const unsigned char *)json, strlen(json)); - /* FIXME: Propper error handling for JSON parsing */ + /* FIXME: Proper error handling for JSON parsing */ switch (state) { case yajl_status_ok: break; diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 496035c2..9bf36187 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -445,7 +445,7 @@ void init_colors(const struct xcb_color_strings_t *new_colors) { /* * Handle a button press event (i.e. a mouse click on one of our bars). - * We determine, whether the click occured on a workspace button or if the scroll- + * We determine, whether the click occurred on a workspace button or if the scroll- * wheel was used and change the workspace appropriately * */ diff --git a/include/shmlog.h b/include/shmlog.h index 231681ca..01fea8b4 100644 --- a/include/shmlog.h +++ b/include/shmlog.h @@ -24,7 +24,7 @@ typedef struct i3_shmlog_header { /* Byte offset where the next line will be written to. */ uint32_t offset_next_write; - /* Byte offset where the last wrap occured. */ + /* Byte offset where the last wrap occurred. */ uint32_t offset_last_wrap; /* The size of the logfile in bytes. Since the size is limited to 25 MiB diff --git a/src/commands.c b/src/commands.c index 0faf2775..405bb429 100644 --- a/src/commands.c +++ b/src/commands.c @@ -46,7 +46,7 @@ } \ } while (0) -/** If an error occured during parsing of the criteria, we want to exit instead +/** If an error occurred during parsing of the criteria, we want to exit instead * of relying on fallback behavior. See #2091. */ #define HANDLE_INVALID_MATCH \ do { \ diff --git a/src/randr.c b/src/randr.c index 6753f8a6..f0234c5c 100644 --- a/src/randr.c +++ b/src/randr.c @@ -420,7 +420,7 @@ void init_ws_for_output(Output *output, Con *content) { /* In case the workspace we just moved was visible but there was no * other workspace to switch to, we need to initialize the source - * output aswell */ + * output as well */ if (visible && previous == NULL) { LOG("There is no workspace left on \"%s\", re-initializing\n", workspace_out->name); diff --git a/src/render.c b/src/render.c index 9fa40f03..7ee501f0 100644 --- a/src/render.c +++ b/src/render.c @@ -167,7 +167,7 @@ void render_con(Con *con, bool render_fullscreen) { /* By rendering the stacked container again, we handle the case * that we have a non-leaf-container inside the stack. In that * case, the children of the non-leaf-container need to be raised - * aswell. */ + * as well. */ render_con(child, false); } diff --git a/src/sighandler.c b/src/sighandler.c index 80d2fae2..400cd5a5 100644 --- a/src/sighandler.c +++ b/src/sighandler.c @@ -116,7 +116,7 @@ static int backtrace(void) { waitpid(pid_gdb, &status, 0); - /* see if the backtrace was succesful or not */ + /* see if the backtrace was successful or not */ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { DLOG("GDB did not run properly\n"); return -1; @@ -176,7 +176,7 @@ static int sig_draw_window(xcb_window_t win, int width, int height, int font_hei static int sig_handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press_event_t *event) { uint16_t state = event->state; - /* Apparantly, after activating numlock once, the numlock modifier + /* Apparently, after activating numlock once, the numlock modifier * stays turned on (use xev(1) to verify). So, to resolve useful * keysyms, we remove the numlock flag from the event state */ state &= ~xcb_numlock_mask; diff --git a/src/tree.c b/src/tree.c index 0c301209..e848a6ac 100644 --- a/src/tree.c +++ b/src/tree.c @@ -477,7 +477,7 @@ static void mark_unmapped(Con *con) { TAILQ_FOREACH(current, &(con->nodes_head), nodes) mark_unmapped(current); if (con->type == CT_WORKSPACE) { - /* We need to call mark_unmapped on floating nodes aswell since we can + /* 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); diff --git a/testcases/complete-run.pl b/testcases/complete-run.pl index 2d61e993..14c0a15d 100755 --- a/testcases/complete-run.pl +++ b/testcases/complete-run.pl @@ -49,7 +49,7 @@ binmode STDERR, ':utf8'; # subshell or situations like that. AnyEvent::Util::close_all_fds_except(0, 1, 2); -# convinience wrapper to write to the log file +# convenience wrapper to write to the log file my $log; sub Log { say $log "@_" } @@ -208,7 +208,7 @@ $single_cv->recv; $aggregator->stop(); -# print empty lines to seperate failed tests from statuslines +# print empty lines to separate failed tests from statuslines print "\n\n"; for (@done) { diff --git a/testcases/lib/StatusLine.pm b/testcases/lib/StatusLine.pm index f2487797..6d32104a 100644 --- a/testcases/lib/StatusLine.pm +++ b/testcases/lib/StatusLine.pm @@ -46,8 +46,8 @@ sub status_init { status_completed(0); } -# generates the status text, prints it in the appropiate line -# and returns it, so it can be used in conjuction with C +# generates the status text, prints it in the appropriate line +# and returns it, so it can be used in conjunction with C sub status { my ($display, $msg) = @_; my $status = "[$display] $msg"; diff --git a/testcases/t/103-move.t b/testcases/t/103-move.t index 0e01d90b..64a9d621 100644 --- a/testcases/t/103-move.t +++ b/testcases/t/103-move.t @@ -33,7 +33,7 @@ my $x = X11::XCB::Connection->new; my $i3 = i3; -# Switch to the nineth workspace +# Switch to the ninth workspace $i3->command('9')->recv; ##################################################################### diff --git a/testcases/t/105-stacking.t b/testcases/t/105-stacking.t index 96c64975..e9d84851 100644 --- a/testcases/t/105-stacking.t +++ b/testcases/t/105-stacking.t @@ -33,7 +33,7 @@ my $x = X11::XCB::Connection->new; my $i3 = i3; -# Switch to the nineth workspace +# Switch to the ninth workspace $i3->command('9')->recv; ##################################################################### diff --git a/testcases/t/131-stacking-order.t b/testcases/t/131-stacking-order.t index c04f1b09..8993a071 100644 --- a/testcases/t/131-stacking-order.t +++ b/testcases/t/131-stacking-order.t @@ -14,7 +14,7 @@ # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf # (unless you are already familiar with Perl) # -# Check if stacking containers can be used independantly of +# Check if stacking containers can be used independently of # the split mode (horizontal/vertical) of the underlying # container. # diff --git a/testcases/t/159-socketpaths.t b/testcases/t/159-socketpaths.t index d21581d1..6c214d20 100644 --- a/testcases/t/159-socketpaths.t +++ b/testcases/t/159-socketpaths.t @@ -65,7 +65,7 @@ ok(-S $socketpath, "file $socketpath exists and is a socket"); exit_gracefully($pid); ##################################################################### -# configuration file case: socket gets placed whereever we specify +# configuration file case: socket gets placed wherever we specify ##################################################################### my $tmpdir = tempdir(CLEANUP => 1); From fec1a9511e75f83b8707758c04d5a201edbc652d Mon Sep 17 00:00:00 2001 From: wentasah Date: Wed, 6 Apr 2016 21:19:10 +0200 Subject: [PATCH 016/150] Make fullscreen windows open on the output which is indicated by their geometry With this change, multi-monitor presentations (e.g. as implemented by LibreOffice Impress) work out of the box. Previously, one had to move the presentation windows to the right outputs oneself. --- include/con.h | 7 ++ include/randr.h | 7 ++ src/con.c | 13 ++++ src/manage.c | 10 ++- src/randr.c | 21 ++++++ testcases/t/531-fullscreen-on-given-output.t | 75 ++++++++++++++++++++ 6 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 testcases/t/531-fullscreen-on-given-output.t diff --git a/include/con.h b/include/con.h index 5b48120b..130dd83b 100644 --- a/include/con.h +++ b/include/con.h @@ -268,6 +268,13 @@ void con_disable_fullscreen(Con *con); void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool dont_warp, bool ignore_focus); +/** + * Moves the given container to the currently focused container on the + * visible workspace on the given output. + * + */ +void con_move_to_output(Con *con, Output *output); + /** * Moves the given container to the given mark. * diff --git a/include/randr.h b/include/randr.h index 998f0d59..8d4b4def 100644 --- a/include/randr.h +++ b/include/randr.h @@ -79,6 +79,13 @@ Output *get_output_by_name(const char *name); */ Output *get_output_containing(unsigned int x, unsigned int y); +/** + * Returns the active output which spans exactly the area specified by + * rect or NULL if there is no output like this. + * + */ +Output *get_output_with_dimensions(Rect rect); + /* * In contained_by_output, we check if any active output contains part of the container. * We do this by checking if the output rect is intersected by the Rect. diff --git a/src/con.c b/src/con.c index cd17f9e5..17cdd2d6 100644 --- a/src/con.c +++ b/src/con.c @@ -1157,6 +1157,19 @@ void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool _con_move_to_con(con, target, true, fix_coordinates, dont_warp, ignore_focus); } +/* + * Moves the given container to the currently focused container on the + * visible workspace on the given output. + * + */ +void con_move_to_output(Con *con, Output *output) { + Con *ws = NULL; + GREP_FIRST(ws, output_get_content(output->con), workspace_is_visible(child)); + assert(ws != NULL); + DLOG("Moving con %p to output %s\n", con, output->name); + con_move_to_workspace(con, ws, false, false, false); +} + /* * Returns the orientation of the given container (for stacked containers, * vertical orientation is used regardless of the actual orientation of the diff --git a/src/manage.c b/src/manage.c index 93272f1b..81a62ab8 100644 --- a/src/manage.c +++ b/src/manage.c @@ -359,8 +359,16 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki if (xcb_reply_contains_atom(state_reply, A__NET_WM_STATE_FULLSCREEN)) { /* If this window is already fullscreen (after restarting!), skip * toggling fullscreen, that would drop it out of fullscreen mode. */ - if (fs != nc) + if (fs != nc) { + Output *output = get_output_with_dimensions((Rect){geom->x, geom->y, geom->width, geom->height}); + /* If the requested window geometry spans the whole area + * of an output, move the window to that output. This is + * needed e.g. for LibreOffice Impress multi-monitor + * presentations to work out of the box. */ + if (output != NULL) + con_move_to_output(nc, output); con_toggle_fullscreen(nc, CF_OUTPUT); + } fs = NULL; } diff --git a/src/randr.c b/src/randr.c index f0234c5c..6aed40cf 100644 --- a/src/randr.c +++ b/src/randr.c @@ -108,6 +108,27 @@ Output *get_output_containing(unsigned int x, unsigned int y) { return NULL; } +/* + * Returns the active output which spans exactly the area specified by + * rect or NULL if there is no output like this. + * + */ +Output *get_output_with_dimensions(Rect rect) { + Output *output; + 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", + rect.x, rect.y, rect.width, rect.height, + output->rect.x, output->rect.y, output->rect.width, output->rect.height); + if (rect.x == output->rect.x && rect.width == output->rect.width && + rect.y == output->rect.y && rect.height == output->rect.height) + return output; + } + + return NULL; +} + /* * In contained_by_output, we check if any active output contains part of the container. * We do this by checking if the output rect is intersected by the Rect. diff --git a/testcases/t/531-fullscreen-on-given-output.t b/testcases/t/531-fullscreen-on-given-output.t new file mode 100644 index 00000000..fd328653 --- /dev/null +++ b/testcases/t/531-fullscreen-on-given-output.t @@ -0,0 +1,75 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Please read the following documents before working on tests: +# • http://build.i3wm.org/docs/testsuite.html +# (or docs/testsuite) +# +# • http://build.i3wm.org/docs/lib-i3test.html +# (alternatively: perldoc ./testcases/lib/i3test.pm) +# +# • http://build.i3wm.org/docs/ipc.html +# (or docs/ipc) +# +# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf +# (unless you are already familiar with Perl) +# +# Tests that fullscreen windows appear on the output indicated by +# their geometry +use i3test i3_autostart => 0; +use List::Util qw(first); + +my $config = <fullscreen(1); +} + +sub find_window { + my ($nodes, $id) = @_; + + foreach (@{$nodes}) { + return $_ if ($_->{window} // 0) == $id; + my $node = find_window($_->{nodes}, $id); + return $node if $node; + }; + return undef; +} + +# Create two fullscreen windows, each on different output +my $orig_rect1 = X11::XCB::Rect->new(x => 0, y => 0, width => 1024, height => 768); +my $orig_rect2 = X11::XCB::Rect->new(x => 1024, y => 0, width => 1024, height => 768); + +my $win_on_first_output = open_window(rect => $orig_rect1, + before_map => \&fullscreen); + +my $win_on_second_output = open_window(rect => $orig_rect2, + before_map => \&fullscreen); + +sync_with_i3; + +# Check that the windows are on the correct output +is_deeply(scalar $win_on_first_output->rect, $orig_rect1, "first window spans the first output"); +is_deeply(scalar $win_on_second_output->rect, $orig_rect2, "second window spans the sencond output"); + +# Check that both windows remained fullscreen +my $tree = i3(get_socket_path())->get_tree->recv; + +my $node1 = find_window($tree->{nodes}, $win_on_first_output->{id}); +my $node2 = find_window($tree->{nodes}, $win_on_second_output->{id}); + +is($node1->{fullscreen_mode}, 1, "first window is fullscreen"); +is($node2->{fullscreen_mode}, 1, "second window is fullscreen"); + +exit_gracefully($pid); + +done_testing; From ea55729cf26c5ae3908883f0a676c6fc2ae77220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Thu, 7 Apr 2016 08:35:29 +0200 Subject: [PATCH 017/150] Remove unmaintained CHANGELOG file from i3bar --- i3bar/CHANGELOG | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 i3bar/CHANGELOG diff --git a/i3bar/CHANGELOG b/i3bar/CHANGELOG deleted file mode 100644 index 32d880cd..00000000 --- a/i3bar/CHANGELOG +++ /dev/null @@ -1,30 +0,0 @@ -v0.7 -===== -- Make i3bar compatible with i3-4.0 -- Implement disabling the workspace buttons -- Add Color for focused ws -- Add support for I3_SOCKET_PATH-atom -- Implement different dock-positions -- Hide-on-modifier is now the default behavior -- Change default socketpath to /tmp/i3-ipc.sock -- Use I3SOCK environment-variable -- Bugfix: Stop the reconn-timer before starting it again, else it's running twice -- Bugfix: Don't SIGSTOP child in dockmode -- Bugfix: If hide-on-modifier is set, stop the child after starting -- Bugfix: Recover from closed socket -- Some minor bugfixes - -v0.6 -===== -- Add manpage -- Implement hide-on-modifier -- Custom colors can be set from the commandline -- Use double-buffering -- Bugfix: Correctly render long text -- Bugfix: Don't segfault on SIGCHILD -- Bugfix: Double-fork() to avoid zombies -- Some minor bugfixes - -v0.5 -===== -- Initial release From 64c81132d28efc286c438754b82b3977421a0a6a Mon Sep 17 00:00:00 2001 From: Johannes Lange Date: Sun, 3 Apr 2016 14:22:47 +0200 Subject: [PATCH 018/150] initial (manual) version files check-in --- I3_VERSION | 1 + VERSION | 1 + 2 files changed, 2 insertions(+) create mode 100644 I3_VERSION create mode 100644 VERSION diff --git a/I3_VERSION b/I3_VERSION new file mode 100644 index 00000000..f3d68995 --- /dev/null +++ b/I3_VERSION @@ -0,0 +1 @@ +4.12-non-git diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..f5885845 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +4.12 From 808bad10efec652ec8dc27d76081f6e6a8c087fd Mon Sep 17 00:00:00 2001 From: Johannes Lange Date: Sun, 3 Apr 2016 14:26:01 +0200 Subject: [PATCH 019/150] auto-creating (I3_)VERSION for each release and post-release version files with 'non-git' suffix fixes #1993 --- release.sh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/release.sh b/release.sh index 7b521145..61b3c444 100755 --- a/release.sh +++ b/release.sh @@ -56,6 +56,9 @@ cp "${STARTDIR}/RELEASE-NOTES-${RELEASE_VERSION}" "RELEASE-NOTES-${RELEASE_VERSI git add RELEASE-NOTES-${RELEASE_VERSION} git rm RELEASE-NOTES-${PREVIOUS_VERSION} sed -i "s,[^<]*,${RELEASE_VERSION},g" man/asciidoc.conf +echo "${RELEASE_VERSION}" > VERSION +echo "${RELEASE_VERSION} ($(date +%F))" > I3_VERSION +git add VERSION I3_VERSION git commit -a -m "release i3 ${RELEASE_VERSION}" git tag "${RELEASE_VERSION}" -m "release i3 ${RELEASE_VERSION}" --sign --local-user=0x4AC8EE1D @@ -68,14 +71,13 @@ diff -u \ <(tar tf i3-${RELEASE_VERSION}.tar.bz2 | sed "s,i3-${RELEASE_VERSION}/,,g" | sort) \ | colordiff -if ! tar xf i3-${RELEASE_VERSION}.tar.bz2 --to-stdout --strip-components=1 i3-${RELEASE_VERSION}/I3_VERSION | grep -q "^${RELEASE_VERSION} " -then - echo "I3_VERSION file does not start with ${RELEASE_VERSION}" - exit 1 -fi gpg --armor -b i3-${RELEASE_VERSION}.tar.bz2 +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 git merge --no-ff release-${RELEASE_VERSION} -m "Merge branch 'release-${RELEASE_VERSION}'" From 9f27716d16349a7189622e05f35266a5e2af649b Mon Sep 17 00:00:00 2001 From: Johannes Lange Date: Sun, 3 Apr 2016 14:34:57 +0200 Subject: [PATCH 020/150] dist tarball uses existing (I3_)VERSION file --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index fd302101..57513b0e 100644 --- a/Makefile +++ b/Makefile @@ -48,8 +48,8 @@ dist: distclean # Only copy source code from i3-input mkdir i3-${VERSION}/i3-input find i3-input -maxdepth 1 -type f \( -name "*.c" -or -name "*.mk" -or -name "*.h" -or -name "Makefile" \) -exec cp '{}' i3-${VERSION}/i3-input \; - echo -n ${I3_VERSION} > i3-${VERSION}/I3_VERSION - echo -n ${VERSION} > i3-${VERSION}/VERSION + cp I3_VERSION i3-${VERSION}/I3_VERSION + cp VERSION i3-${VERSION}/VERSION # Pre-generate a manpage to allow distributors to skip this step and save some dependencies $(MAKE) mans cp man/*.1 i3-${VERSION}/man/ From f74327e7c6497b1818bc6cacdd12d5a6ae2145fb Mon Sep 17 00:00:00 2001 From: Johannes Lange Date: Sun, 3 Apr 2016 14:38:08 +0200 Subject: [PATCH 021/150] use git version information if possible, otherwise use information from (I3_)VERSION files (for tarballs) --- common.mk | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/common.mk b/common.mk index 4fe8f2b0..1e738b04 100644 --- a/common.mk +++ b/common.mk @@ -18,12 +18,14 @@ ifndef SYSCONFDIR endif endif -# In dist tarballs, the version is stored in the I3_VERSION and VERSION files. -I3_VERSION := '$(shell [ -f $(TOPDIR)/I3_VERSION ] && cat $(TOPDIR)/I3_VERSION)' -VERSION := '$(shell [ -f $(TOPDIR)/VERSION ] && cat $(TOPDIR)/VERSION)' -ifeq ('',$(I3_VERSION)) -VERSION := $(shell git describe --tags --abbrev=0) -I3_VERSION := '$(shell git describe --tags --always) ($(shell git log --pretty=format:%cd --date=short -n1), branch \"$(shell git describe --tags --always --all | sed s:heads/::)\")' +# In dist and snapshot tarballs, use the I3_VERSION and VERSION files. Otherwise use git information. +ifeq ($(wildcard .git),) + # not in git repository + VERSION := '$(shell [ -f $(TOPDIR)/VERSION ] && cat $(TOPDIR)/VERSION)' + I3_VERSION := '$(shell [ -f $(TOPDIR)/I3_VERSION ] && cat $(TOPDIR)/I3_VERSION)' +else + VERSION := $(shell git describe --tags --abbrev=0) + I3_VERSION := '$(shell git describe --tags --always) ($(shell git log --pretty=format:%cd --date=short -n1), branch \"$(shell git describe --tags --always --all | sed s:heads/::)\")' endif MAJOR_VERSION := $(shell echo ${VERSION} | cut -d '.' -f 1) From bd29745effe949aed847d4e8a519c66696ff6025 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 27 Mar 2016 21:11:30 +0200 Subject: [PATCH 022/150] travis: build debian packages and documentation The resulting packages are pushed to Debian repositories hosted on bintray.com. This is the first step to move away from our custom buildbot setup (see https://i3wm.org/docs/buildbot.html for details on that) towards infrastructure which is more standard (travis) and in the open. --- .travis.yml | 53 ++++++++++++++++++- travis/bintray-autobuild-debian.json | 36 +++++++++++++ travis/bintray-autobuild-ubuntu.json | 36 +++++++++++++ travis/check-formatting.sh | 4 ++ travis/clang-analyze.sh | 9 ++++ travis/cleanup-bintray.pl | 37 +++++++++++++ travis/debian-build.sh | 15 ++++++ travis/deploy-github-pages.sh | 23 ++++++++ travis/docker-build-and-push.sh | 5 +- travis/docs.sh | 17 ++++++ travis/ha.sh | 2 +- travis/prep-bintray.sh | 6 +++ travis/run-tests.sh | 4 ++ travis/skip-pkg.sh | 14 +++++ travis/travis-base-386.Dockerfile | 29 ++++++++++ travis/travis-base-ubuntu-386.Dockerfile | 29 ++++++++++ travis/travis-base-ubuntu.Dockerfile | 30 +++++++++++ .../travis-base.Dockerfile | 0 18 files changed, 345 insertions(+), 4 deletions(-) create mode 100644 travis/bintray-autobuild-debian.json create mode 100644 travis/bintray-autobuild-ubuntu.json create mode 100755 travis/clang-analyze.sh create mode 100755 travis/cleanup-bintray.pl create mode 100755 travis/debian-build.sh create mode 100755 travis/deploy-github-pages.sh create mode 100755 travis/docs.sh create mode 100755 travis/prep-bintray.sh create mode 100755 travis/skip-pkg.sh create mode 100644 travis/travis-base-386.Dockerfile create mode 100644 travis/travis-base-ubuntu-386.Dockerfile create mode 100644 travis/travis-base-ubuntu.Dockerfile rename travis-build.Dockerfile => travis/travis-base.Dockerfile (100%) diff --git a/.travis.yml b/.travis.yml index aa574d09..4951fe64 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,18 +6,67 @@ language: c compiler: - gcc - clang +addons: + apt: + packages: + # For https support in HTTP::Tiny. + - libio-socket-ssl-perl env: global: - - BASENAME="i3wm/travis-base:$(date +'%Y-%m')-$(./travis/ha.sh)" + - BASENAME="i3wm/travis-base:$(date +'%Y-%m')-$(./travis/ha.sh travis/travis-base.Dockerfile)" + - BASENAME_386="i3wm/travis-base-386:$(date +'%Y-%m')-$(./travis/ha.sh travis/travis-base-386.Dockerfile)" + - BASENAME_UBUNTU="i3wm/travis-base-ubuntu:$(date +'%Y-%m')-$(./travis/ha.sh travis/travis-base-ubuntu.Dockerfile)" + - BASENAME_UBUNTU_386="i3wm/travis-base-ubuntu-386:$(date +'%Y-%m')-$(./travis/ha.sh travis/travis-base-ubuntu-386.Dockerfile)" - secure: "B5IICA8MPx/FKaB50rTPqL8P1NU+Q0yuWl+lElL4+a9xSyLikfm3NzUPHoVwx8lNw2AVK6br7p0OmF7vMFjqAgrgc1cajTtEae5uFRKNUrWLpXM046YgNEYLLIHsQOjInxE+S4O6EFVzsUqsu8aeo2Xhq4sm4iUocG7e5isYgYo=" # DOCKER_PASS - secure: "EIvrq8PG7lRjidppG0RCv4F0X4GP3DT9F5+ixVuGPfhK/hZT3jYC2AVY9G+NnUcXVwQEpW92rlqpftQ/qZ13FoyWokC8ZyoyD06fr5FPCfoFF3OczZwAJzZYkObI/hE9+/hXcylx/Os6N4INd2My1ntGk3JPsWL9riopod5EjSg=" # DOCKER_EMAIL - secure: "hvhBunS4xXTgnIOsk/BPT7I7FrJhvVwCSt5PfxxvMqNaztOJI9BuK7ZrZ5Cy38KyHwlh3VHAH5AaCygJcPauoSQCV3bpnlbaWn3ruq2F0Q697Q5uNf73liXzyUqb9/Zvfvge4y4WWOhP5tVz1C6ZBe/NfhU7pqKLMA+6ads+99c=" # DOCKER_USER + - secure: "uJuuefmnJUuEH15ZD8xQilibx7EeBvMHBLoIZ8bgGHeleEImBD0XbD1ypvhYJKpviOmw5BkZmc9bVO8DGDEHYbSlIa2xDlF6vGrwgCEaxcMIhOAhv+dW9C/maJVieLOEPM01/fK2qdKESZaLvlopkWmxZwDyMObI9L7AMW9zQD8=" # BINTRAY_USER + - secure: "L3aPSNLySPXtWCW+xf8h/AAdquwNgxyTQpYOwexJmTPav82Qx8uQlp1yJkUmt+a+FLZDFfQeMivaHq0311RvuQVmkAJx49DjaddrwqOJut2UPsoVDn1WeuAcSHIXOq/0H+zgFMr/PGY0HXIsw1mTMhgheGJNqg09BvYWROCEAcA=" # BINTRAY_KEY + - secure: "sBMVn4C/WRWgoAytEFGx4CC5O55Q63h02AcuBnb1jXcBm0RenoBpzUPtxSseJwDPUA1o/UkuEDDjm3PosT5NF+dvED01VDFMsPVE11K0u6+avYy3jYXqyUEDW3G2o6Wo/2aqNjmd++8jskBdS9+Cx9gaFbgxfzSp0Yfu3oJm/4c=" # GH_TOKEN install: - if [ -a .git/shallow ]; then git fetch --unshallow; fi - - docker pull ${BASENAME} || ./travis/docker-build-and-push.sh + - docker pull ${BASENAME} || ./travis/docker-build-and-push.sh ${BASENAME} travis/travis-base.Dockerfile + - ./travis/skip-pkg.sh || docker pull ${BASENAME_UBUNTU} || ./travis/docker-build-and-push.sh ${BASENAME_UBUNTU} travis/travis-base-ubuntu.Dockerfile + - ./travis/skip-pkg.sh || docker pull ${BASENAME_386} || ./travis/docker-build-and-push.sh ${BASENAME_386} travis/travis-base-386.Dockerfile + - ./travis/skip-pkg.sh || docker pull ${BASENAME_UBUNTU_386} || ./travis/docker-build-and-push.sh ${BASENAME_UBUNTU_386} travis/travis-base-ubuntu-386.Dockerfile 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 -e CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Werror" ${BASENAME} make all mans -j ASAN=1 - 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 ${BASENAME} ./travis/run-tests.sh + - ./travis/skip-pkg.sh || docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/debian-build.sh deb/debian-amd64/DIST + - ./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 + - ./travis/skip-pkg.sh || docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME_UBUNTU_386} linux32 ./travis/debian-build.sh deb/ubuntu-i386/DIST + - ./travis/skip-pkg.sh || docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/clang-analyze.sh + - ./travis/skip-pkg.sh || docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/docs.sh + - ./travis/skip-pkg.sh || travis/prep-bintray.sh + +deploy: + - provider: bintray + file: travis/bintray-autobuild-debian.json + user: $BINTRAY_USER + key: $BINTRAY_KEY + skip_cleanup: true + on: + branch: next + condition: $CC = gcc + - provider: bintray + file: travis/bintray-autobuild-ubuntu.json + user: $BINTRAY_USER + key: $BINTRAY_KEY + skip_cleanup: true + on: + branch: next + condition: $CC = gcc + - provider: script + script: travis/deploy-github-pages.sh + skip_cleanup: true + on: + branch: next + condition: $CC = gcc + +after_deploy: + - travis/cleanup-bintray.pl i3-autobuild + - travis/cleanup-bintray.pl i3-autobuild-ubuntu diff --git a/travis/bintray-autobuild-debian.json b/travis/bintray-autobuild-debian.json new file mode 100644 index 00000000..554d2b74 --- /dev/null +++ b/travis/bintray-autobuild-debian.json @@ -0,0 +1,36 @@ +{ + "package": { + "name": "i3-wm", + "repo": "i3-autobuild", + "subject": "i3" + }, + + "version": { + "name": "%version%", + "desc": "TODO", + "gpgSign": false + }, + + "files": [ + { + "includePattern": "deb/debian-amd64/(.*\\.deb)$", + "matrixParams": { + "deb_distribution": "sid", + "deb_component": "main", + "deb_architecture": "amd64" + }, + "uploadPattern": "$1" + }, + { + "includePattern": "deb/debian-i386/(.*\\.deb)$", + "matrixParams": { + "deb_distribution": "sid", + "deb_component": "main", + "deb_architecture": "i386" + }, + "uploadPattern": "$1" + } + ], + + "publish": true +} diff --git a/travis/bintray-autobuild-ubuntu.json b/travis/bintray-autobuild-ubuntu.json new file mode 100644 index 00000000..2ceef7d4 --- /dev/null +++ b/travis/bintray-autobuild-ubuntu.json @@ -0,0 +1,36 @@ +{ + "package": { + "name": "i3-wm", + "repo": "i3-autobuild-ubuntu", + "subject": "i3" + }, + + "version": { + "name": "%version%", + "desc": "TODO", + "gpgSign": false + }, + + "files": [ + { + "includePattern": "deb/ubuntu-amd64/(.*\\.deb)$", + "matrixParams": { + "deb_distribution": "wily", + "deb_component": "main", + "deb_architecture": "amd64" + }, + "uploadPattern": "$1" + }, + { + "includePattern": "deb/ubuntu-i386/(.*\\.deb)$", + "matrixParams": { + "deb_distribution": "wily", + "deb_component": "main", + "deb_architecture": "i386" + }, + "uploadPattern": "$1" + } + ], + + "publish": true +} diff --git a/travis/check-formatting.sh b/travis/check-formatting.sh index abdb1168..ead25157 100755 --- a/travis/check-formatting.sh +++ b/travis/check-formatting.sh @@ -1,2 +1,6 @@ #!/bin/sh + +set -e +set -x + clang-format-3.5 -i $(find . -name "*.[ch]" | tr '\n' ' ') && git diff --exit-code || (echo 'Code was not formatted using clang-format!'; false) diff --git a/travis/clang-analyze.sh b/travis/clang-analyze.sh new file mode 100755 index 00000000..05d54119 --- /dev/null +++ b/travis/clang-analyze.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +set -e +set -x + +mkdir -p deb/DIST-clang +tar xf *.tar.bz2 -C deb/DIST-clang --strip-components=1 +(cd deb/DIST-clang && scan-build -o ../CLANG --html-title="Analysis of i3 v$(git describe --tags)" make -j8) +mv deb/CLANG/*/* deb/CLANG diff --git a/travis/cleanup-bintray.pl b/travis/cleanup-bintray.pl new file mode 100755 index 00000000..d150d1ed --- /dev/null +++ b/travis/cleanup-bintray.pl @@ -0,0 +1,37 @@ +#!/usr/bin/env perl +# vim:ts=4:sw=4:expandtab + +use strict; +use warnings; +use Data::Dumper; +use HTTP::Tiny; # in core since v5.13.9 +use JSON::PP; # in core since v5.13.9 +use MIME::Base64; # in core since v5.7 +use v5.13; + +my $repo = shift; + +my $auth = $ENV{'BINTRAY_USER'} . ':' . $ENV{'BINTRAY_KEY'}; +die "BINTRAY_USER and/or BINTRAY_KEY environment variables not set" if $auth eq ':'; +# TODO(stapelberg): switch to putting $auth into the URL once perl-modules ≥ +# 5.20 is available on travis (Ubuntu Wily or newer). +my $auth_header = 'Basic ' . MIME::Base64::encode_base64($auth, ""); +my $apiurl = 'https://api.bintray.com/packages/i3/' . $repo . '/i3-wm'; +my $client = HTTP::Tiny->new( + verify_SSL => 1, + default_headers => { + 'authorization' => $auth_header, + }); +my $resp = $client->get($apiurl); +die "Getting versions failed: HTTP status $resp->{status} (content: $resp->{content})" unless $resp->{success}; +my $decoded = decode_json($resp->{content}); +my @versions = sort @{$decoded->{versions}}; + +# Keep the most recent 5 versions. +splice(@versions, 0, 5); + +for my $version (@versions) { + say "Deleting old version $version"; + $resp = $client->request('DELETE', "$apiurl/versions/$version"); + die "Deletion of version $version failed: HTTP status $resp->{status} (content: $resp->{content})" unless $resp->{success}; +} diff --git a/travis/debian-build.sh b/travis/debian-build.sh new file mode 100755 index 00000000..3fa4abad --- /dev/null +++ b/travis/debian-build.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +set -e +set -x + +DEST=$1 + +make dist +# unpack dist tarball +mkdir -p "${DEST}" +tar xf *.tar.bz2 -C "${DEST}" --strip-components=1 +cp -r debian "${DEST}" +cd "${DEST}" +debchange -m -l+g$(git describe --tags) 'Automatically built' +dpkg-buildpackage -b diff --git a/travis/deploy-github-pages.sh b/travis/deploy-github-pages.sh new file mode 100755 index 00000000..f86fbf22 --- /dev/null +++ b/travis/deploy-github-pages.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +set -e +set -x + +GITVERSION=$(git describe --tags) + +mkdir build.i3wm.org +cp -r deb/CLANG build.i3wm.org/clang-analyze +cp -r deb/COPY-DOCS build.i3wm.org/docs +cd build.i3wm.org +echo build.i3wm.org > CNAME +git init + +git config user.name "Travis CI" +git config user.email "i3bot@i3wm.org" +git add . +git commit -m "Publish docs/static analysis for github.com/i3/i3 v${GITVERSION}" + +# Hide stdout/stderr because it might contain sensitive info. +set +x +echo "git push" +git push --force --quiet "https://${GH_TOKEN}@github.com/i3/build.i3wm.org.git" master:gh-pages >/dev/null 2>&1 diff --git a/travis/docker-build-and-push.sh b/travis/docker-build-and-push.sh index 76e2a132..9b654a84 100755 --- a/travis/docker-build-and-push.sh +++ b/travis/docker-build-and-push.sh @@ -2,11 +2,14 @@ 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 travis-build.Dockerfile . +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 # the login+push step when the variable isn’t set. diff --git a/travis/docs.sh b/travis/docs.sh new file mode 100755 index 00000000..5cd51966 --- /dev/null +++ b/travis/docs.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +set -e +set -x + +make -C docs ASCIIDOC="asciidoc -a linkcss -a stylesdir=http://i3wm.org/css -a scriptsdir=http://i3wm.org/js --backend=xhtml11 -f docs/asciidoc-git.conf" +./docs/i3-pod2html i3-dmenu-desktop man/i3-dmenu-desktop.html +./docs/i3-pod2html i3-save-tree man/i3-save-tree.html +for file in $(sed 's/\.1$/.man/g' debian/i3-wm.manpages) +do + [ -f "$file" ] && asciidoc -a linkcss -a stylesdir=http://i3wm.org/css -a scriptsdir=http://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/ diff --git a/travis/ha.sh b/travis/ha.sh index 688755c3..ed70320d 100755 --- a/travis/ha.sh +++ b/travis/ha.sh @@ -4,4 +4,4 @@ # installed in the container, so that any changes in what needs to be installed # will result in a cache invalidation. -cat debian/control travis-build.Dockerfile | sha256sum | dd bs=1 count=8 status=none +cat debian/control "$1" | sha256sum | dd bs=1 count=8 status=none diff --git a/travis/prep-bintray.sh b/travis/prep-bintray.sh new file mode 100755 index 00000000..4ea56dcd --- /dev/null +++ b/travis/prep-bintray.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +set -e +set -x + +sed -i "s,%version%,$(git describe --tags),g" travis/bintray-autobuild-*.json diff --git a/travis/run-tests.sh b/travis/run-tests.sh index 87c5dbb7..3ab3df4d 100755 --- a/travis/run-tests.sh +++ b/travis/run-tests.sh @@ -1,4 +1,8 @@ #!/bin/sh + +set -e +set -x + cd testcases # 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. diff --git a/travis/skip-pkg.sh b/travis/skip-pkg.sh new file mode 100755 index 00000000..4337120b --- /dev/null +++ b/travis/skip-pkg.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# Returns true if Debian/Ubuntu packages should be skipped because this CI run +# was triggered by a pull request. + +# Verify BINTRAY_USER is present (only set on github.com/i3/i3), +# otherwise the CI run was triggered by a pull request. +# Verify CC=gcc so that we only build packages once for each commit, +# not twice (with gcc and clang). +if [ ! -z "$BINTRAY_USER" ] && [ "$CC" = "gcc" ] +then + exit 1 +fi + +exit 0 diff --git a/travis/travis-base-386.Dockerfile b/travis/travis-base-386.Dockerfile new file mode 100644 index 00000000..9f2b8129 --- /dev/null +++ b/travis/travis-base-386.Dockerfile @@ -0,0 +1,29 @@ +# vim:ft=Dockerfile +# Same as travis-base.Dockerfile, but without the test suite dependencies since +# we only build Debian packages on i386, we don’t run the tests. +FROM i386/debian:sid + +RUN echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup +# Paper over occasional network flakiness of some mirrors. +RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry + +# NOTE: I tried exclusively using gce_debian_mirror.storage.googleapis.com +# instead of httpredir.debian.org, but the results (Fetched 123 MB in 36s (3357 +# kB/s)) are not any better than httpredir.debian.org (Fetched 123 MB in 34s +# (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-3.5 (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-3.5 \ + lintian && \ + rm -rf /var/lib/apt/lists/* + +# Install i3 build dependencies. +COPY debian/control /usr/src/i3-debian-packaging/control +RUN linux32 apt-get update && \ + DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ + rm -rf /var/lib/apt/lists/* diff --git a/travis/travis-base-ubuntu-386.Dockerfile b/travis/travis-base-ubuntu-386.Dockerfile new file mode 100644 index 00000000..b1ee1c0c --- /dev/null +++ b/travis/travis-base-ubuntu-386.Dockerfile @@ -0,0 +1,29 @@ +# vim:ft=Dockerfile +# Same as travis-base.Dockerfile, but without the test suite dependencies since +# we only build Debian packages on Ubuntu i386, we don’t run the tests. +FROM i386/ubuntu:wily + +RUN echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup +# Paper over occasional network flakiness of some mirrors. +RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry + +# NOTE: I tried exclusively using gce_debian_mirror.storage.googleapis.com +# instead of httpredir.debian.org, but the results (Fetched 123 MB in 36s (3357 +# kB/s)) are not any better than httpredir.debian.org (Fetched 123 MB in 34s +# (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-3.5 (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-3.5 \ + lintian && \ + rm -rf /var/lib/apt/lists/* + +# Install i3 build dependencies. +COPY debian/control /usr/src/i3-debian-packaging/control +RUN linux32 apt-get update && \ + DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ + rm -rf /var/lib/apt/lists/* diff --git a/travis/travis-base-ubuntu.Dockerfile b/travis/travis-base-ubuntu.Dockerfile new file mode 100644 index 00000000..e76229eb --- /dev/null +++ b/travis/travis-base-ubuntu.Dockerfile @@ -0,0 +1,30 @@ +# vim:ft=Dockerfile +# Same as travis-base.Dockerfile, but without the test suite dependencies since +# we only build Debian packages on Ubuntu, we don’t run the tests. +FROM ubuntu:wily + +RUN echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup +# Paper over occasional network flakiness of some mirrors. +RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry + +# NOTE: I tried exclusively using gce_debian_mirror.storage.googleapis.com +# instead of httpredir.debian.org, but the results (Fetched 123 MB in 36s (3357 +# kB/s)) are not any better than httpredir.debian.org (Fetched 123 MB in 34s +# (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-3.5 (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-3.5 \ + lintian && \ + rm -rf /var/lib/apt/lists/* + +# Install i3 build dependencies. +COPY debian/control /usr/src/i3-debian-packaging/control +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ + rm -rf /var/lib/apt/lists/* diff --git a/travis-build.Dockerfile b/travis/travis-base.Dockerfile similarity index 100% rename from travis-build.Dockerfile rename to travis/travis-base.Dockerfile From 12c073e2ee62289d73ff54d0dbab4245695ce416 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 9 Apr 2016 11:55:25 +0200 Subject: [PATCH 023/150] cleanup-bintray: keep the most recent, not delete the most recent --- travis/cleanup-bintray.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis/cleanup-bintray.pl b/travis/cleanup-bintray.pl index d150d1ed..296ae388 100755 --- a/travis/cleanup-bintray.pl +++ b/travis/cleanup-bintray.pl @@ -25,7 +25,7 @@ my $client = HTTP::Tiny->new( my $resp = $client->get($apiurl); die "Getting versions failed: HTTP status $resp->{status} (content: $resp->{content})" unless $resp->{success}; my $decoded = decode_json($resp->{content}); -my @versions = sort @{$decoded->{versions}}; +my @versions = reverse sort @{$decoded->{versions}}; # Keep the most recent 5 versions. splice(@versions, 0, 5); From c7e92ead94e52deffe8f73869bd44d0f8d114e73 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 9 Apr 2016 12:46:15 +0200 Subject: [PATCH 024/150] travis: clean old docs before building with asciidoc git config --- travis/docs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis/docs.sh b/travis/docs.sh index 5cd51966..35bc12bb 100755 --- a/travis/docs.sh +++ b/travis/docs.sh @@ -3,7 +3,7 @@ set -e set -x -make -C docs ASCIIDOC="asciidoc -a linkcss -a stylesdir=http://i3wm.org/css -a scriptsdir=http://i3wm.org/js --backend=xhtml11 -f docs/asciidoc-git.conf" +make clean-docs docs ASCIIDOC="asciidoc -a linkcss -a stylesdir=http://i3wm.org/css -a scriptsdir=http://i3wm.org/js --backend=xhtml11 -f docs/asciidoc-git.conf" ./docs/i3-pod2html i3-dmenu-desktop man/i3-dmenu-desktop.html ./docs/i3-pod2html i3-save-tree man/i3-save-tree.html for file in $(sed 's/\.1$/.man/g' debian/i3-wm.manpages) From b3fb3cbfead349ef337243843ecd55ee37e74969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sun, 10 Apr 2016 13:15:49 +0200 Subject: [PATCH 025/150] Update i3bar LICENSE to conform to other LICENSE files. (#2284) This change of the LICENSE has been approved by Axel Wagner in #2281. --- i3bar/LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i3bar/LICENSE b/i3bar/LICENSE index 6fe0f421..c78c062d 100644 --- a/i3bar/LICENSE +++ b/i3bar/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2010-2011, Axel Wagner +Copyright © 2010 Axel Wagner All rights reserved. Redistribution and use in source and binary forms, with or without From 8dc7691a6f4adaf259062f4844a023d6f23cabd0 Mon Sep 17 00:00:00 2001 From: Guillaume Maudoux Date: Mon, 11 Apr 2016 14:50:01 +0200 Subject: [PATCH 026/150] Remove "dereferencing type-punned pointer" warning Fix the remaining warning discussed in #1538. This is obviously a false positive from gcc. --- src/floating.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/floating.c b/src/floating.c index 65a2810a..094d0e88 100644 --- a/src/floating.c +++ b/src/floating.c @@ -782,16 +782,17 @@ drag_result_t drag_pointer(Con *con, const xcb_button_press_event_t *event, xcb_ .callback = callback, .extra = extra, }; + ev_check *check = &loop.check; if (con) loop.old_rect = con->rect; - ev_check_init(&loop.check, xcb_drag_check_cb); + ev_check_init(check, xcb_drag_check_cb); main_set_x11_cb(false); - ev_check_start(main_loop, &loop.check); + ev_check_start(main_loop, check); while (loop.result == DRAGGING) ev_run(main_loop, EVRUN_ONCE); - ev_check_stop(main_loop, &loop.check); + ev_check_stop(main_loop, check); main_set_x11_cb(true); xcb_ungrab_keyboard(conn, XCB_CURRENT_TIME); From b52482705e805021c5c37a9139c60e63409a08f2 Mon Sep 17 00:00:00 2001 From: Guillaume Maudoux Date: Mon, 11 Apr 2016 15:00:47 +0200 Subject: [PATCH 027/150] Avoid hazardous casting. --- src/floating.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/floating.c b/src/floating.c index 094d0e88..17a99638 100644 --- a/src/floating.c +++ b/src/floating.c @@ -621,7 +621,7 @@ void floating_resize_window(Con *con, const bool proportional, con->scratchpad_state = SCRATCHPAD_CHANGED; } -/* As endorsed by “ASSOCIATING CUSTOM DATA WITH A WATCHER” in ev(3) */ +/* Custom data structure used to track dragging-related events. */ struct drag_x11_cb { ev_check check; @@ -643,7 +643,7 @@ struct drag_x11_cb { }; static void xcb_drag_check_cb(EV_P_ ev_check *w, int revents) { - struct drag_x11_cb *dragloop = (struct drag_x11_cb *)w; + struct drag_x11_cb *dragloop = (struct drag_x11_cb *)w->data; xcb_motion_notify_event_t *last_motion_notify = NULL; xcb_generic_event_t *event; @@ -786,6 +786,7 @@ drag_result_t drag_pointer(Con *con, const xcb_button_press_event_t *event, xcb_ if (con) loop.old_rect = con->rect; ev_check_init(check, xcb_drag_check_cb); + check->data = &loop; main_set_x11_cb(false); ev_check_start(main_loop, check); From 83c8740bf143c213ce4a6ce1f9c39095cafe7435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 13 Apr 2016 19:45:57 +0200 Subject: [PATCH 028/150] Only grab the mouse buttons that need to be grabbed. (#2290) This is a followup to #2049. While we had fixed that bug by only grabbing buttons 4 and 5 if there is a whole-window binding for that button, this did not consider buttons higher than 5 as found on many mice. Therefore, we now ditch the special handling for scrollwheel buttons and instead do the same for all buttons higher than 3. fixes #2271 --- include/bindings.h | 12 ++++++------ include/xcb.h | 2 +- src/bindings.c | 49 ++++++++++++++++++++++++++++++++++------------ src/manage.c | 4 +++- src/xcb.c | 18 +++++------------ 5 files changed, 51 insertions(+), 34 deletions(-) diff --git a/include/bindings.h b/include/bindings.h index 9b14e988..d15598ea 100644 --- a/include/bindings.h +++ b/include/bindings.h @@ -104,10 +104,10 @@ CommandResult *run_binding(Binding *bind, Con *con); bool load_keymap(void); /** - * Returns true if the current config has any binding to a scroll wheel button - * (4 or 5) which is a whole-window binding. - * We need this to figure out whether we should grab all buttons or just 1-3 - * when managing a window. See #2049. - * + * Returns a list of buttons that should be grabbed on a window. + * This list will always contain 1–3, all higher buttons will only be returned + * if there is a whole-window binding for it on some window in the current + * config. + * The list is terminated by a 0. */ -bool bindings_should_grab_scrollwheel_buttons(void); +int *bindings_get_buttons_to_grab(void); diff --git a/include/xcb.h b/include/xcb.h index 86019c5d..b7eed2cb 100644 --- a/include/xcb.h +++ b/include/xcb.h @@ -171,4 +171,4 @@ void xcb_remove_property_atom(xcb_connection_t *conn, xcb_window_t window, xcb_a * Grab the specified buttons on a window when managing it. * */ -void xcb_grab_buttons(xcb_connection_t *conn, xcb_window_t window, bool bind_scrollwheel); +void xcb_grab_buttons(xcb_connection_t *conn, xcb_window_t window, int *buttons); diff --git a/src/bindings.c b/src/bindings.c index 351a5862..759cfff9 100644 --- a/src/bindings.c +++ b/src/bindings.c @@ -152,7 +152,7 @@ void grab_all_keys(xcb_connection_t *conn) { * */ void regrab_all_buttons(xcb_connection_t *conn) { - bool grab_scrollwheel = bindings_should_grab_scrollwheel_buttons(); + int *buttons = bindings_get_buttons_to_grab(); xcb_grab_server(conn); Con *con; @@ -161,9 +161,10 @@ void regrab_all_buttons(xcb_connection_t *conn) { continue; xcb_ungrab_button(conn, XCB_BUTTON_INDEX_ANY, con->window->id, XCB_BUTTON_MASK_ANY); - xcb_grab_buttons(conn, con->window->id, grab_scrollwheel); + xcb_grab_buttons(conn, con->window->id, buttons); } + FREE(buttons); xcb_ungrab_server(conn); } @@ -811,15 +812,30 @@ bool load_keymap(void) { } /* - * Returns true if the current config has any binding to a scroll wheel button - * (4 or 5) which is a whole-window binding. - * We need this to figure out whether we should grab all buttons or just 1-3 - * when managing a window. See #2049. - * + * Returns a list of buttons that should be grabbed on a window. + * This list will always contain 1–3, all higher buttons will only be returned + * if there is a whole-window binding for it on some window in the current + * config. + * The list is terminated by a 0. */ -bool bindings_should_grab_scrollwheel_buttons(void) { +int *bindings_get_buttons_to_grab(void) { + /* Let's make the reasonable assumption that there's no more than 25 + * buttons. */ + int num_max = 25; + + int buffer[num_max]; + int num = 0; + + /* We always return buttons 1 through 3. */ + buffer[num++] = 1; + buffer[num++] = 2; + buffer[num++] = 3; + Binding *bind; TAILQ_FOREACH(bind, bindings, bindings) { + if (num + 1 == num_max) + break; + /* We are only interested in whole window mouse bindings. */ if (bind->input_type != B_MOUSE || !bind->whole_window) continue; @@ -831,11 +847,18 @@ bool bindings_should_grab_scrollwheel_buttons(void) { continue; } - /* If the binding is for either scrollwheel button, we need to grab everything. */ - if (button == 4 || button == 5) { - return true; + /* Avoid duplicates. */ + for (int i = 0; i < num_max; i++) { + if (buffer[i] == button) + continue; } - } - return false; + buffer[num++] = button; + } + buffer[num++] = 0; + + int *buttons = scalloc(num, sizeof(int)); + memcpy(buttons, buffer, num * sizeof(int)); + + return buttons; } diff --git a/src/manage.c b/src/manage.c index 81a62ab8..f86e98f5 100644 --- a/src/manage.c +++ b/src/manage.c @@ -170,7 +170,9 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki cwindow->id = window; cwindow->depth = get_visual_depth(attr->visual); - xcb_grab_buttons(conn, window, bindings_should_grab_scrollwheel_buttons()); + int *buttons = bindings_get_buttons_to_grab(); + xcb_grab_buttons(conn, window, buttons); + FREE(buttons); /* update as much information as possible so far (some replies may be NULL) */ window_update_class(cwindow, xcb_get_property_reply(conn, class_cookie, NULL), true); diff --git a/src/xcb.c b/src/xcb.c index 9d181cfa..630c68f9 100644 --- a/src/xcb.c +++ b/src/xcb.c @@ -346,20 +346,12 @@ release_grab: * Grab the specified buttons on a window when managing it. * */ -void xcb_grab_buttons(xcb_connection_t *conn, xcb_window_t window, bool bind_scrollwheel) { - uint8_t buttons[3]; - int num = 0; - - if (bind_scrollwheel) { - buttons[num++] = XCB_BUTTON_INDEX_ANY; - } else { - buttons[num++] = XCB_BUTTON_INDEX_1; - buttons[num++] = XCB_BUTTON_INDEX_2; - buttons[num++] = XCB_BUTTON_INDEX_3; - } - - for (int i = 0; i < num; i++) { +void xcb_grab_buttons(xcb_connection_t *conn, xcb_window_t window, int *buttons) { + int i = 0; + while (buttons[i] > 0) { xcb_grab_button(conn, false, window, XCB_EVENT_MASK_BUTTON_PRESS, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, root, XCB_NONE, buttons[i], XCB_BUTTON_MASK_ANY); + + i++; } } From 80dddd9961263be8ac3b46a15a9cc9302525071d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Fri, 15 Apr 2016 09:26:42 +0200 Subject: [PATCH 029/150] Correctly count the number of windows for no_focus. (#2296) Previously we counted the number of (direct) children of the workspace to decide whether no_focus should be applied or not. However, this doesn't work correctly if there's a single container with multiple windows on the workspace. This patch correctly counts all windows on the workspace. fixes #2292 --- include/con.h | 6 ++++++ src/con.c | 20 ++++++++++++++++++++ src/manage.c | 2 +- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/include/con.h b/include/con.h index 130dd83b..7fa7facf 100644 --- a/include/con.h +++ b/include/con.h @@ -200,6 +200,12 @@ Con *con_for_window(Con *con, i3Window *window, Match **store_match); */ int con_num_children(Con *con); +/** + * Count the number of windows (i.e., leaf containers). + * + */ +int con_num_windows(Con *con); + /** * Attaches the given container to the given parent. This happens when moving * a container or when inserting a new container at a specific place in the diff --git a/src/con.c b/src/con.c index 17cdd2d6..1ab4a841 100644 --- a/src/con.c +++ b/src/con.c @@ -727,6 +727,26 @@ int con_num_children(Con *con) { return children; } +/* + * Count the number of windows (i.e., leaf containers). + * + */ +int con_num_windows(Con *con) { + if (con == NULL) + return 0; + + if (con_has_managed_window(con)) + return 1; + + int num = 0; + Con *current = NULL; + TAILQ_FOREACH(current, &(con->nodes_head), nodes) { + num += con_num_windows(current); + } + + return num; +} + /* * Updates the percent attribute of the children of the given container. This * function needs to be called when a window is added or removed from a diff --git a/src/manage.c b/src/manage.c index f86e98f5..f868c85d 100644 --- a/src/manage.c +++ b/src/manage.c @@ -577,7 +577,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki /* The first window on a workspace should always be focused. We have to * compare with == 1 because the container has already been inserted at * this point. */ - if (con_num_children(ws) == 1) { + if (con_num_windows(ws) == 1) { DLOG("This is the first window on this workspace, ignoring no_focus.\n"); } else { DLOG("no_focus was set for con = %p, not setting focus.\n", nc); From e690e3d483d602867936cfb7423901db42f3a1db Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Fri, 15 Apr 2016 03:27:43 -0400 Subject: [PATCH 030/150] Cast con id as uintptr_t (#2298) Use `uintptr_t` to cast the con id to int instead of `long int`. This type is guaranteed to hold the pointer as an int regardless of platform. fixes #2283 --- src/commands.c | 3 ++- src/ipc.c | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/commands.c b/src/commands.c index 405bb429..403c3b3a 100644 --- a/src/commands.c +++ b/src/commands.c @@ -9,6 +9,7 @@ * commands.c: all command functions (see commands_parser.c) * */ +#include #include #include @@ -1625,7 +1626,7 @@ void cmd_open(I3_CMD) { ystr("success"); y(bool, true); ystr("id"); - y(integer, (long int)con); + y(integer, (uintptr_t)con); y(map_close); cmd_output->needs_tree_render = true; diff --git a/src/ipc.c b/src/ipc.c index 566fe52a..2bd5f59d 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -12,6 +12,7 @@ #include "all.h" #include "yajl_utils.h" +#include #include #include #include @@ -217,7 +218,7 @@ static void dump_binding(yajl_gen gen, Binding *bind) { void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) { y(map_open); ystr("id"); - y(integer, (long int)con); + y(integer, (uintptr_t)con); ystr("type"); switch (con->type) { @@ -444,7 +445,7 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) { ystr("focus"); y(array_open); TAILQ_FOREACH(node, &(con->focus_head), focused) { - y(integer, (long int)node); + y(integer, (uintptr_t)node); } y(array_close); From c3db74a1f8cdcd5d7df263878f208bc9aa00f320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 13 Apr 2016 19:48:53 +0200 Subject: [PATCH 031/150] Only redraw right-hand side border if a non-pango font is used. relates to #2247 --- src/x.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/x.c b/src/x.c index 43db952d..5e50b4cd 100644 --- a/src/x.c +++ b/src/x.c @@ -332,8 +332,10 @@ static void x_draw_decoration_after_title(Con *con, struct deco_render_params *p /* Redraw the right border to cut off any text that went past it. * This is necessary when the text was drawn using XCB since cutting text off * automatically does not work there. For pango rendering, this isn't necessary. */ - draw_util_rectangle(conn, &(con->parent->frame_buffer), p->color->background, - dr->x + dr->width + br.width, dr->y, -br.width, dr->height); + if (!font_is_pango()) { + draw_util_rectangle(conn, &(con->parent->frame_buffer), p->color->background, + dr->x + dr->width + br.width, dr->y, -br.width, dr->height); + } /* Draw a 1px separator line before and after every tab, so that tabs can * be easily distinguished. */ From 057517b80935a39e1fde594001a3926b4f28d2fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 13 Apr 2016 19:51:26 +0200 Subject: [PATCH 032/150] Redraw right-hand side border correctly. Since we don't actually stop drawing a title (or marks) with the distance of the border width on the right side, but instead with a hard-coded two pixel distance, we can only redraw that much of the border without potentiall cutting off text. relates to #2247 --- src/x.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/x.c b/src/x.c index 5e50b4cd..a6e3bde9 100644 --- a/src/x.c +++ b/src/x.c @@ -327,14 +327,19 @@ static void x_draw_decoration_after_title(Con *con, struct deco_render_params *p assert(con->parent != NULL); Rect *dr = &(con->deco_rect); - Rect br = con_border_style_rect(con); /* Redraw the right border to cut off any text that went past it. * This is necessary when the text was drawn using XCB since cutting text off * automatically does not work there. For pango rendering, this isn't necessary. */ if (!font_is_pango()) { + /* We actually only redraw the far right two pixels as that is the + * distance we keep from the edge (not the entire border width). + * Redrawing the entire border would cause text to be cut off. */ draw_util_rectangle(conn, &(con->parent->frame_buffer), p->color->background, - dr->x + dr->width + br.width, dr->y, -br.width, dr->height); + dr->x + dr->width - 2 * logical_px(1), + dr->y, + 2 * logical_px(1), + dr->height); } /* Draw a 1px separator line before and after every tab, so that tabs can From e9798b7e3ee5d15c0ca62169b9f976fb15dedd02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 13 Apr 2016 19:55:59 +0200 Subject: [PATCH 033/150] Use logical_px() and fix indentation. relates to #2247 --- src/x.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/x.c b/src/x.c index a6e3bde9..0fbc4d1c 100644 --- a/src/x.c +++ b/src/x.c @@ -555,8 +555,9 @@ void x_draw_decoration(Con *con) { draw_util_text(title, &(parent->frame_buffer), p->color->text, p->color->background, - con->deco_rect.x + 2, con->deco_rect.y + text_offset_y, - con->deco_rect.width - 2); + con->deco_rect.x + logical_px(2), + con->deco_rect.y + text_offset_y, + con->deco_rect.width - 2 * logical_px(2)); I3STRING_FREE(title); goto after_title; @@ -617,8 +618,9 @@ void x_draw_decoration(Con *con) { i3String *title = con->title_format == NULL ? win->name : con_parse_title_format(con); draw_util_text(title, &(parent->frame_buffer), p->color->text, p->color->background, - con->deco_rect.x + logical_px(2) + indent_px, con->deco_rect.y + text_offset_y, - con->deco_rect.width - logical_px(2) - indent_px - mark_width - logical_px(2)); + con->deco_rect.x + logical_px(2) + indent_px, + con->deco_rect.y + text_offset_y, + con->deco_rect.width - indent_px - mark_width - 2 * logical_px(2)); if (con->title_format != NULL) I3STRING_FREE(title); From ba5240d62166f85c8e2cda391b5cafcf6f3b13aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 23 Apr 2016 13:36:59 +0200 Subject: [PATCH 034/150] Remove skipped tests. (#2305) We simply remove these tests since they are sufficiently covered by other testcases. relates to #2289 --- testcases/t/103-move.t | 96 ------------------------- testcases/t/105-stacking.t | 144 ------------------------------------- 2 files changed, 240 deletions(-) delete mode 100644 testcases/t/103-move.t delete mode 100644 testcases/t/105-stacking.t diff --git a/testcases/t/103-move.t b/testcases/t/103-move.t deleted file mode 100644 index 64a9d621..00000000 --- a/testcases/t/103-move.t +++ /dev/null @@ -1,96 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Please read the following documents before working on tests: -# • http://build.i3wm.org/docs/testsuite.html -# (or docs/testsuite) -# -# • http://build.i3wm.org/docs/lib-i3test.html -# (alternatively: perldoc ./testcases/lib/i3test.pm) -# -# • http://build.i3wm.org/docs/ipc.html -# (or docs/ipc) -# -# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf -# (unless you are already familiar with Perl) -# -# Beware that this test uses workspace 9 to perform some tests (it expects -# the workspace to be empty). -# TODO: skip it by default? - -use i3test tests => 8; -use X11::XCB qw(:all); -use Time::HiRes qw(sleep); - -BEGIN { - use_ok('X11::XCB::Connection') or BAIL_OUT('Cannot load X11::XCB::Connection'); -} - -SKIP: { - skip "Testcase not yet modified for new move concept", 7; - -my $x = X11::XCB::Connection->new; - -my $i3 = i3; - -# Switch to the ninth workspace -$i3->command('9')->recv; - -##################################################################### -# Create two windows and make sure focus switching works -##################################################################### - -my $top = i3test::open_standard_window($x); -sleep(0.25); -my $mid = i3test::open_standard_window($x); -sleep(0.25); -my $bottom = i3test::open_standard_window($x); -sleep(0.25); - -diag("top id = " . $top->id); -diag("mid id = " . $mid->id); -diag("bottom id = " . $bottom->id); - -# -# Returns the input focus after sending the given command to i3 via IPC -# end sleeping for half a second to make sure i3 reacted -# -sub focus_after { - my $msg = shift; - - $i3->command($msg)->recv; - return $x->input_focus; -} - -my $focus = $x->input_focus; -is($focus, $bottom->id, "Latest window focused"); - -$focus = focus_after("ml"); -is($focus, $bottom->id, "Right window still focused"); - -$focus = focus_after("h"); -is($focus, $mid->id, "Middle window focused"); - -##################################################################### -# Now move to the top window, move right, then move left again -# (e.g., does i3 remember the focus in the last container?) -##################################################################### - -$focus = focus_after("k"); -is($focus, $top->id, "Top window focused"); - -$focus = focus_after("l"); -is($focus, $bottom->id, "Right window focused"); - -$focus = focus_after("h"); -is($focus, $top->id, "Top window focused"); - -##################################################################### -# Move window cross-workspace -##################################################################### - -for my $cmd (qw(m12 t m13 12 13)) { - $i3->command($cmd)->recv; -} -ok(1, "Still living"); -} diff --git a/testcases/t/105-stacking.t b/testcases/t/105-stacking.t deleted file mode 100644 index e9d84851..00000000 --- a/testcases/t/105-stacking.t +++ /dev/null @@ -1,144 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Please read the following documents before working on tests: -# • http://build.i3wm.org/docs/testsuite.html -# (or docs/testsuite) -# -# • http://build.i3wm.org/docs/lib-i3test.html -# (alternatively: perldoc ./testcases/lib/i3test.pm) -# -# • http://build.i3wm.org/docs/ipc.html -# (or docs/ipc) -# -# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf -# (unless you are already familiar with Perl) -# -# Beware that this test uses workspace 9 to perform some tests (it expects -# the workspace to be empty). -# TODO: skip it by default? - -use i3test tests => 22; -use X11::XCB qw(:all); -use Time::HiRes qw(sleep); - -BEGIN { - use_ok('X11::XCB::Connection') or BAIL_OUT('Cannot load X11::XCB::Connection'); -} - -SKIP: { - skip "stacking test not yet updated", 21; - -my $x = X11::XCB::Connection->new; - -my $i3 = i3; - -# Switch to the ninth workspace -$i3->command('9')->recv; - -##################################################################### -# Create two windows and make sure focus switching works -##################################################################### - -my $top = i3test::open_standard_window($x); -my $mid = i3test::open_standard_window($x); -my $bottom = i3test::open_standard_window($x); -sleep(0.25); - -diag("top id = " . $top->id); -diag("mid id = " . $mid->id); -diag("bottom id = " . $bottom->id); - -# -# Returns the input focus after sending the given command to i3 via IPC -# end sleeping for half a second to make sure i3 reacted -# -sub focus_after { - my $msg = shift; - - $i3->command($msg)->recv; - return $x->input_focus; -} - -my $focus = $x->input_focus; -is($focus, $bottom->id, "Latest window focused"); - -$focus = focus_after("s"); -is($focus, $bottom->id, "Last window still focused"); - -$focus = focus_after("k"); -is($focus, $mid->id, "Middle window focused"); - -$focus = focus_after("k"); -is($focus, $top->id, "Top window focused"); - -##################################################################### -# Test focus wrapping -##################################################################### - -$focus = focus_after("k"); -is($focus, $bottom->id, "Bottom window focused (wrapping to the top works)"); - -$focus = focus_after("j"); -is($focus, $top->id, "Top window focused (wrapping to the bottom works)"); - -##################################################################### -# Restore of focus after moving windows out/into the stack -##################################################################### - -$focus = focus_after("ml"); -is($focus, $top->id, "Top window still focused (focus after moving)"); - -$focus = focus_after("h"); -is($focus, $bottom->id, "Bottom window focused (focus after moving)"); - -my $new = i3test::open_standard_window($x); -sleep(0.25); - -# By now, we have this layout: -# ---------------- -# | mid | -# | bottom | top -# | new | -# ---------------- - -$focus = focus_after("l"); -is($focus, $top->id, "Got top window"); - -$focus = focus_after("mh"); -is($focus, $top->id, "Moved it into the stack"); - -$focus = focus_after("k"); -is($focus, $new->id, "Window above is new"); - -$focus = focus_after("k"); -is($focus, $bottom->id, "Window above is bottom"); - -$focus = focus_after("k"); -is($focus, $mid->id, "Window above is mid"); - -$focus = focus_after("k"); -is($focus, $top->id, "At top again"); - -$focus = focus_after("ml"); -is($focus, $top->id, "Still at top, moved out"); - -$focus = focus_after("h"); -is($focus, $mid->id, "At mid again"); - -$focus = focus_after("j"); -is($focus, $bottom->id, "At bottom again"); - -$focus = focus_after("l"); -is($focus, $top->id, "At top again"); - -$focus = focus_after("mh"); -is($focus, $top->id, "Still at top, moved into"); - -$focus = focus_after("k"); -is($focus, $bottom->id, "Window above is bottom"); - -$focus = focus_after("k"); -is($focus, $mid->id, "Window above is mid"); - -} From 42a3371013a66729d808e9cf535b8a3abd43ab58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 23 Apr 2016 13:43:23 +0200 Subject: [PATCH 035/150] Update "mark" to "marks" in i3-save-tree. (#2308) When allowing multiple marks on a container, we renamed the "mark" field to "marks". This breaks i3-save-tree which will now filter out the marks on a window because it doesn't match anymore. This commit fixes that issue. Thanks to /u/xenomachina for hinting to this issue. --- i3-save-tree | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i3-save-tree b/i3-save-tree index b00e1fe1..1e56a045 100755 --- a/i3-save-tree +++ b/i3-save-tree @@ -98,7 +98,7 @@ my %allowed_keys = map { ($_, 1) } qw( name geometry window_properties - mark + marks rect ); From 23beac46b74fea66c7680443e384b7ed5c5933e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Tue, 26 Apr 2016 09:09:07 +0200 Subject: [PATCH 036/150] Focus a newly managed container only if it doesn't use the globally active input model. (#2317) fixes #1784 --- src/manage.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/manage.c b/src/manage.c index f868c85d..37d50e7b 100644 --- a/src/manage.c +++ b/src/manage.c @@ -602,9 +602,20 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki xcb_discard_reply(conn, wm_user_time_cookie.sequence); } + if (set_focus) { + /* Even if the client doesn't want focus, we still need to focus the + * container to not break focus workflows. Our handling towards X will + * take care of not setting the input focus. However, one exception to + * this are clients using the globally active input model which we + * don't want to focus at all. */ + if (nc->window->doesnt_accept_focus && !nc->window->needs_take_focus) { + set_focus = false; + } + } + /* Defer setting focus after the 'new' event has been sent to ensure the * proper window event sequence. */ - if (set_focus && !nc->window->doesnt_accept_focus && nc->mapped) { + if (set_focus && nc->mapped) { DLOG("Now setting focus.\n"); con_focus(nc); } From 2123888d4de8cce9ade79933638a9548fd5fcef2 Mon Sep 17 00:00:00 2001 From: Kyle Kneitinger Date: Tue, 26 Apr 2016 00:20:42 -0700 Subject: [PATCH 037/150] Ensure config variables match on longest-length (#2306) fixes #2235 --- src/config_parser.c | 16 +++++++++++++++- testcases/t/183-config-variables.t | 16 ++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/config_parser.c b/src/config_parser.c index e97a37e1..5ee69e8d 100644 --- a/src/config_parser.c +++ b/src/config_parser.c @@ -879,9 +879,23 @@ bool parse_file(const char *f, bool use_nagbar) { v_value++; struct Variable *new = scalloc(1, sizeof(struct Variable)); + struct Variable *test = NULL, *loc = NULL; new->key = sstrdup(v_key); new->value = sstrdup(v_value); - SLIST_INSERT_HEAD(&variables, new, variables); + /* ensure that the correct variable is matched in case of one being + * the prefix of another */ + SLIST_FOREACH(test, &variables, variables) { + if (strlen(new->key) >= strlen(test->key)) + break; + loc = test; + } + + if (loc == NULL) { + SLIST_INSERT_HEAD(&variables, new, variables); + } else { + SLIST_INSERT_AFTER(loc, new, variables); + } + DLOG("Got new variable %s = %s\n", v_key, v_value); continue; } diff --git a/testcases/t/183-config-variables.t b/testcases/t/183-config-variables.t index 8fbbff70..65f16679 100644 --- a/testcases/t/183-config-variables.t +++ b/testcases/t/183-config-variables.t @@ -79,6 +79,22 @@ EOT is(launch_get_border($config), 'none', 'no border'); +##################################################################### +# test that longest matching variable name is substituted +##################################################################### + +$config = <<'EOT'; +# i3 config file (v4) +font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 + +set $var normal title +set $vartest special title +set $vart mundane title +for_window [title="$vartest"] border none +EOT + +is(launch_get_border($config), 'none', 'no border'); + done_testing; From 4365f46d1bcbc7451afc3d3f0891e5293f6ad4ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 30 Apr 2016 23:04:58 +0200 Subject: [PATCH 038/150] i3-input: Proper position in non-standard cases. (#2313) This commit fixes two issues: * We detect the EWMH support window from the root window. If this window currently has the input focus, we ignore this. We do this because this window is not a window the user is aware of and positioning relative to it makes no sense. * We also detect whether the current input focus is in an i3-frame window. This can happen, e.g., when selecting a parent (split) container. Since frame windows are direct children of the root window, we must not translate its coordinates or we get weird results and i3-input ends up off-screen (see #2312). For all other windows, including those without any WM_CLASS, we proceed as before. fixes #2312 --- i3-input/main.c | 57 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/i3-input/main.c b/i3-input/main.c index 7115727e..2241f2cf 100644 --- a/i3-input/main.c +++ b/i3-input/main.c @@ -317,10 +317,31 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press static xcb_rectangle_t get_window_position(void) { xcb_rectangle_t result = (xcb_rectangle_t){logical_px(50), logical_px(50), logical_px(500), font.height + logical_px(8)}; + xcb_get_property_reply_t *supporting_wm_reply = NULL; xcb_get_input_focus_reply_t *input_focus = NULL; xcb_get_geometry_reply_t *geometry = NULL; + xcb_get_property_reply_t *wm_class = NULL; xcb_translate_coordinates_reply_t *coordinates = NULL; + xcb_atom_t A__NET_SUPPORTING_WM_CHECK; + xcb_intern_atom_cookie_t nswc_cookie = xcb_intern_atom(conn, 0, strlen("_NET_SUPPORTING_WM_CHECK"), "_NET_SUPPORTING_WM_CHECK"); + 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); + } + A__NET_SUPPORTING_WM_CHECK = nswc_reply->atom; + free(nswc_reply); + + supporting_wm_reply = xcb_get_property_reply( + conn, xcb_get_property(conn, false, root, A__NET_SUPPORTING_WM_CHECK, XCB_ATOM_WINDOW, 0, 32), NULL); + xcb_window_t *supporting_wm_win = NULL; + if (supporting_wm_reply == NULL || xcb_get_property_value_length(supporting_wm_reply) == 0) { + DLOG("Could not determine EWMH support window.\n"); + } else { + supporting_wm_win = xcb_get_property_value(supporting_wm_reply); + } + /* In rare cases, the window holding the input focus might disappear while we are figuring out its * position. To avoid this, we grab the server in the meantime. */ xcb_grab_server(conn); @@ -331,29 +352,47 @@ static xcb_rectangle_t get_window_position(void) { goto free_resources; } + /* We need to ignore the EWMH support window to which the focus can be set if there's no suitable window to focus. */ + if (supporting_wm_win != NULL && input_focus->focus == *supporting_wm_win) { + DLOG("Input focus is on the EWMH support window, ignoring.\n"); + goto free_resources; + } + geometry = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, input_focus->focus), NULL); if (geometry == NULL) { DLOG("Failed to received window geometry.\n"); goto free_resources; } - coordinates = xcb_translate_coordinates_reply( - conn, xcb_translate_coordinates(conn, input_focus->focus, root, geometry->x, geometry->y), NULL); - if (coordinates == NULL) { - DLOG("Failed to translate coordinates.\n"); - goto free_resources; - } + wm_class = xcb_get_property_reply( + conn, xcb_get_property(conn, false, input_focus->focus, XCB_ATOM_WM_CLASS, XCB_GET_PROPERTY_TYPE_ANY, 0, 32), NULL); - DLOG("Determined coordinates of window with input focus at x = %i / y = %i.\n", coordinates->dst_x, coordinates->dst_y); - result.x += coordinates->dst_x; - result.y += coordinates->dst_y; + /* We need to find out whether the input focus is on an i3 frame window. If it is, we must not translate the coordinates. */ + if (wm_class == NULL || xcb_get_property_value_length(wm_class) == 0 || strcmp(xcb_get_property_value(wm_class), "i3-frame") != 0) { + coordinates = xcb_translate_coordinates_reply( + conn, xcb_translate_coordinates(conn, input_focus->focus, root, geometry->x, geometry->y), NULL); + if (coordinates == NULL) { + DLOG("Failed to translate coordinates.\n"); + goto free_resources; + } + + DLOG("Determined coordinates of window with input focus at x = %i / y = %i.\n", coordinates->dst_x, coordinates->dst_y); + result.x += coordinates->dst_x; + result.y += coordinates->dst_y; + } else { + DLOG("Determined coordinates of window with input focus at x = %i / y = %i.\n", geometry->x, geometry->y); + result.x += geometry->x; + result.y += geometry->y; + } free_resources: xcb_ungrab_server(conn); xcb_flush(conn); + FREE(supporting_wm_reply); FREE(input_focus); FREE(geometry); + FREE(wm_class); FREE(coordinates); return result; } From 3b089d0771e236ea215a40067ad7a04162e9f69d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sun, 1 May 2016 18:59:50 +0200 Subject: [PATCH 039/150] Remove title indentation in nested containers. (#2330) This commit removes the title indentation in certain nested container situations. The behavior was considered broken as it didn't seem to make sense and it was unclear why this was introduced. Given that nobody on i3-discuss@ complained about removing this logic within two weeks, we are now removing it to make the title rendering code a little less complex. fixes #2247 --- src/x.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/src/x.c b/src/x.c index 0fbc4d1c..ed23431c 100644 --- a/src/x.c +++ b/src/x.c @@ -566,23 +566,6 @@ void x_draw_decoration(Con *con) { if (win->name == NULL) goto copy_pixmaps; - int indent_level = 0, - indent_mult = 0; - Con *il_parent = parent; - if (il_parent->layout != L_STACKED) { - while (1) { - //DLOG("il_parent = %p, layout = %d\n", il_parent, il_parent->layout); - if (il_parent->layout == L_STACKED) - indent_level++; - if (il_parent->type == CT_WORKSPACE || il_parent->type == CT_DOCKAREA || il_parent->type == CT_OUTPUT) - break; - il_parent = il_parent->parent; - indent_mult++; - } - } - //DLOG("indent_level = %d, indent_mult = %d\n", indent_level, indent_mult); - int indent_px = (indent_level * 5) * indent_mult; - int mark_width = 0; if (config.show_marks && !TAILQ_EMPTY(&(con->marks_head))) { char *formatted_mark = sstrdup(""); @@ -618,9 +601,9 @@ void x_draw_decoration(Con *con) { i3String *title = con->title_format == NULL ? win->name : con_parse_title_format(con); draw_util_text(title, &(parent->frame_buffer), p->color->text, p->color->background, - con->deco_rect.x + logical_px(2) + indent_px, + con->deco_rect.x + logical_px(2), con->deco_rect.y + text_offset_y, - con->deco_rect.width - indent_px - mark_width - 2 * logical_px(2)); + con->deco_rect.width - mark_width - 2 * logical_px(2)); if (con->title_format != NULL) I3STRING_FREE(title); From d242ae17454cb49f693227436e40703753d5749a Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 2 May 2016 08:49:16 +0200 Subject: [PATCH 040/150] travis: snapshot git version before creating dist tarball fixes #2334 --- Makefile | 4 ++++ travis/debian-build.sh | 1 + 2 files changed, 5 insertions(+) diff --git a/Makefile b/Makefile index 57513b0e..d62db5d0 100644 --- a/Makefile +++ b/Makefile @@ -32,6 +32,10 @@ real-all: $(ALL_TARGETS) install: $(INSTALL_TARGETS) +store_git_version: + echo -n ${I3_VERSION} > I3_VERSION + echo -n ${VERSION} > VERSION + dist: distclean [ ! -d i3-${VERSION} ] || rm -rf i3-${VERSION} [ ! -e i3-${VERSION}.tar.bz2 ] || rm i3-${VERSION}.tar.bz2 diff --git a/travis/debian-build.sh b/travis/debian-build.sh index 3fa4abad..dafa5d7d 100755 --- a/travis/debian-build.sh +++ b/travis/debian-build.sh @@ -5,6 +5,7 @@ set -x DEST=$1 +make store_git_version make dist # unpack dist tarball mkdir -p "${DEST}" From 152318bccf9bbc3f80a7be94c7b601b425d49b4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Thu, 5 May 2016 14:18:04 +0200 Subject: [PATCH 041/150] =?UTF-8?q?Remove=20dead=20code=20guarded=20with?= =?UTF-8?q?=20"#if=200=20=E2=80=A6=20#endif"=20(#2338)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This code has been neutralized for many years now and served no purpose other than cluttering up the code. We obviously don't need it and it's out of date anyway. If there's ever any reason to restore (parts of) it, we have git for that. But we don't need to keep commented out code around. --- i3-input/main.c | 4 --- include/floating.h | 45 -------------------------- include/manage.h | 16 ---------- include/workspace.h | 11 ------- src/config.c | 24 -------------- src/floating.c | 77 --------------------------------------------- src/handlers.c | 43 ------------------------- src/x.c | 5 --- src/xinerama.c | 10 ------ 9 files changed, 235 deletions(-) diff --git a/i3-input/main.c b/i3-input/main.c index 2241f2cf..b467c4c3 100644 --- a/i3-input/main.c +++ b/i3-input/main.c @@ -216,10 +216,6 @@ static void finish_input() { free(full); -#if 0 - free(command); - return 1; -#endif exit(0); } diff --git a/include/floating.h b/include/floating.h index 466c0e79..e187b98f 100644 --- a/include/floating.h +++ b/include/floating.h @@ -76,25 +76,6 @@ void floating_center(Con *con, Rect rect); */ void floating_move_to_pointer(Con *con); -#if 0 -/** - * Removes the floating client from its workspace and attaches it to the new - * workspace. This is centralized here because it may happen if you move it - * via keyboard and if you move it using your mouse. - * - */ -void floating_assign_to_workspace(Client *client, Workspace *new_workspace); - -/** - * Called whenever the user clicks on a border (not the titlebar!) of a - * floating window. Determines on which border the user clicked and launches - * the drag_pointer function with the resize_callback. - * - */ -int floating_border_click(xcb_connection_t *conn, Client *client, - xcb_button_press_event_t *event); - -#endif /** * Called when the user clicked on the titlebar of a floating window. * Calls the drag_pointer function with the drag_window callback @@ -118,32 +99,6 @@ void floating_resize_window(Con *con, const bool proportional, const xcb_button_ */ void floating_check_size(Con *floating_con); -#if 0 -/** - * Changes focus in the given direction for floating clients. - * - * Changing to the left/right means going to the previous/next floating client, - * changing to top/bottom means cycling through the Z-index. - * - */ -void floating_focus_direction(xcb_connection_t *conn, Client *currently_focused, - direction_t direction); - -/** - * Moves the client 10px to the specified direction. - * - */ -void floating_move(xcb_connection_t *conn, Client *currently_focused, - direction_t direction); - -/** - * Hides all floating clients (or show them if they are currently hidden) on - * the specified workspace. - * - */ -void floating_toggle_hide(xcb_connection_t *conn, Workspace *workspace); - -#endif /** * This is the return value of a drag operation like drag_pointer. * diff --git a/include/manage.h b/include/manage.h index b0c42381..520f0c06 100644 --- a/include/manage.h +++ b/include/manage.h @@ -35,19 +35,3 @@ void restore_geometry(void); void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cookie, bool needs_to_be_mapped); - -#if 0 -/** - * reparent_window() gets called when a new window was opened and becomes a - * child of the root window, or it gets called by us when we manage the - * already existing windows at startup. - * - * Essentially, this is the point where we take over control. - * - */ -void reparent_window(xcb_connection_t *conn, xcb_window_t child, - xcb_visualid_t visual, xcb_window_t root, uint8_t depth, - int16_t x, int16_t y, uint16_t width, uint16_t height, - uint32_t border_width); - -#endif diff --git a/include/workspace.h b/include/workspace.h index 0ff5cd30..8e5ff841 100644 --- a/include/workspace.h +++ b/include/workspace.h @@ -50,17 +50,6 @@ void extract_workspace_names_from_bindings(void); */ Con *create_workspace_on_output(Output *output, Con *content); -#if 0 -/** - * Sets the name (or just its number) for the given workspace. This has to - * be called for every workspace as the rendering function - * (render_internal_bar) relies on workspace->name and workspace->name_len - * being ready-to-use. - * - */ -void workspace_set_name(Workspace *ws, const char *name); -#endif - /** * Returns true if the workspace is currently visible. Especially important for * multi-monitor environments, as they can have multiple currenlty active diff --git a/src/config.c b/src/config.c index 9028a881..c2824ca2 100644 --- a/src/config.c +++ b/src/config.c @@ -160,13 +160,6 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath, FREE(barconfig); } -/* Clear workspace names */ -#if 0 - Workspace *ws; - TAILQ_FOREACH(ws, workspaces, workspaces) - workspace_set_name(ws, NULL); -#endif - /* Invalidate pixmap caches in case font or colors changed */ Con *con; TAILQ_FOREACH(con, &all_cons, all_cons) @@ -254,21 +247,4 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath, x_deco_recurse(croot); xcb_flush(conn); } - -#if 0 - /* Set an empty name for every workspace which got no name */ - Workspace *ws; - TAILQ_FOREACH(ws, workspaces, workspaces) { - if (ws->name != NULL) { - /* If the font was not specified when the workspace name - * was loaded, we need to predict the text width now */ - if (ws->text_width == 0) - ws->text_width = predict_text_width(global_conn, - config.font, ws->name, ws->name_len); - continue; - } - - workspace_set_name(ws, NULL); - } -#endif } diff --git a/src/floating.c b/src/floating.c index 17a99638..e9c7a801 100644 --- a/src/floating.c +++ b/src/floating.c @@ -886,80 +886,3 @@ void floating_fix_coordinates(Con *con, Rect *old_rect, Rect *new_rect) { con->rect.y = (int32_t)new_rect->y + (double)(rel_y * (int32_t)new_rect->height) / (int32_t)old_rect->height - (int32_t)(con->rect.height / 2); DLOG("Resulting coordinates: x = %d, y = %d\n", con->rect.x, con->rect.y); } - -#if 0 -/* - * Moves the client 10px to the specified direction. - * - */ -void floating_move(xcb_connection_t *conn, Client *currently_focused, direction_t direction) { - DLOG("floating move\n"); - - Rect destination = currently_focused->rect; - Rect *screen = &(currently_focused->workspace->output->rect); - - switch (direction) { - case D_LEFT: - destination.x -= 10; - break; - case D_RIGHT: - destination.x += 10; - break; - case D_UP: - destination.y -= 10; - break; - case D_DOWN: - destination.y += 10; - break; - /* to make static analyzers happy */ - default: - break; - } - - /* Prevent windows from vanishing completely */ - if ((int32_t)(destination.x + destination.width - 5) <= (int32_t)screen->x || - (int32_t)(destination.x + 5) >= (int32_t)(screen->x + screen->width) || - (int32_t)(destination.y + destination.height - 5) <= (int32_t)screen->y || - (int32_t)(destination.y + 5) >= (int32_t)(screen->y + screen->height)) { - DLOG("boundary check failed, not moving\n"); - return; - } - - currently_focused->rect = destination; - reposition_client(conn, currently_focused); - - /* Because reposition_client does not send a faked configure event (only resize does), - * we need to initiate that on our own */ - fake_absolute_configure_notify(conn, currently_focused); - /* fake_absolute_configure_notify flushes */ -} - -/* - * Hides all floating clients (or show them if they are currently hidden) on - * the specified workspace. - * - */ -void floating_toggle_hide(xcb_connection_t *conn, Workspace *workspace) { - Client *client; - - workspace->floating_hidden = !workspace->floating_hidden; - DLOG("floating_hidden is now: %d\n", workspace->floating_hidden); - TAILQ_FOREACH(client, &(workspace->floating_clients), floating_clients) { - if (workspace->floating_hidden) - client_unmap(conn, client); - else client_map(conn, client); - } - - /* If we just unmapped all floating windows we should ensure that the focus - * is set correctly, that ist, to the first non-floating client in stack */ - if (workspace->floating_hidden) - SLIST_FOREACH(client, &(workspace->focus_stack), focus_clients) { - if (client_is_floating(client)) - continue; - set_focus(conn, client, true); - return; - } - - xcb_flush(conn); -} -#endif diff --git a/src/handlers.c b/src/handlers.c index 2991d7c3..2d18cbbd 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -172,16 +172,6 @@ static void handle_enter_notify(xcb_enter_notify_event_t *event) { } } -#if 0 - if (client->workspace != c_ws && client->workspace->output == c_ws->output) { - /* This can happen when a client gets assigned to a different workspace than - * the current one (see src/mainx.c:reparent_window). Shortly after it was created, - * an enter_notify will follow. */ - DLOG("enter_notify for a client on a different workspace but the same screen, ignoring\n"); - return 1; - } -#endif - if (config.disable_focus_follows_mouse) return; @@ -421,22 +411,6 @@ static void handle_configure_request(xcb_configure_request_event_t *event) { return; } -#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) { - DLOG("configure_event, sequence %d\n", event->sequence); - /* We ignore this sequence twice because events for child and frame should be ignored */ - add_ignore_event(event->sequence); - add_ignore_event(event->sequence); - - return 1; -} -#endif /* * Gets triggered upon a RandR screen change event, that is when the user @@ -630,23 +604,6 @@ static bool handle_windowrole_change(void *data, xcb_connection_t *conn, uint8_t return true; } -#if 0 -/* - * Updates the client’s WM_CLASS property - * - */ -static int handle_windowclass_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 1; - - window_update_class(con->window, prop, false); - - return 0; -} -#endif - /* * Expose event means we should redraw our windows (= title bar) * diff --git a/src/x.c b/src/x.c index ed23431c..1f812076 100644 --- a/src/x.c +++ b/src/x.c @@ -464,11 +464,6 @@ void x_draw_decoration(Con *con) { borders_to_hide = con_adjacent_borders(con) & config.hide_edge_borders; Rect br = con_border_style_rect(con); -#if 0 - DLOG("con->rect spans %d x %d\n", con->rect.width, con->rect.height); - DLOG("border_rect spans (%d, %d) with %d x %d\n", br.x, br.y, br.width, br.height); - DLOG("window_rect spans (%d, %d) with %d x %d\n", con->window_rect.x, con->window_rect.y, con->window_rect.width, con->window_rect.height); -#endif /* These rectangles represent the border around the child window * (left, bottom and right part). We don’t just fill the whole diff --git a/src/xinerama.c b/src/xinerama.c index fb3b8603..ddf98375 100644 --- a/src/xinerama.c +++ b/src/xinerama.c @@ -121,14 +121,4 @@ void xinerama_init(void) { FREE(reply); } - -#if 0 - Output *output; - Workspace *ws; - /* Just go through each active output and associate one workspace */ - TAILQ_FOREACH(output, &outputs, outputs) { - ws = get_first_workspace_for_output(output); - initialize_output(conn, output, ws); - } -#endif } From b2397c9f016b299f066c1ebe22eb8f9dc4ff06f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Thu, 5 May 2016 14:18:27 +0200 Subject: [PATCH 042/150] Remove redundant depth argument from x_con_init(). (#2323) --- include/x.h | 2 +- src/con.c | 2 +- src/load_layout.c | 2 +- src/x.c | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/x.h b/include/x.h index b6855cb3..39e0eb2f 100644 --- a/include/x.h +++ b/include/x.h @@ -18,7 +18,7 @@ extern xcb_window_t focused_id; * every container from con_new(). * */ -void x_con_init(Con *con, uint16_t depth); +void x_con_init(Con *con); /** * Moves a child window from Container src to Container dest. diff --git a/src/con.c b/src/con.c index 1ab4a841..2c637a1f 100644 --- a/src/con.c +++ b/src/con.c @@ -68,7 +68,7 @@ Con *con_new_skeleton(Con *parent, i3Window *window) { */ Con *con_new(Con *parent, i3Window *window) { Con *new = con_new_skeleton(parent, window); - x_con_init(new, new->depth); + x_con_init(new); return new; } diff --git a/src/load_layout.c b/src/load_layout.c index 173e573b..863770b7 100644 --- a/src/load_layout.c +++ b/src/load_layout.c @@ -150,7 +150,7 @@ static int json_end_map(void *ctx) { LOG("attaching\n"); con_attach(json_node, json_node->parent, true); LOG("Creating window\n"); - x_con_init(json_node, json_node->depth); + x_con_init(json_node); json_node = json_node->parent; } diff --git a/src/x.c b/src/x.c index 1f812076..ca7d8ae4 100644 --- a/src/x.c +++ b/src/x.c @@ -98,7 +98,7 @@ static con_state *state_for_frame(xcb_window_t window) { * every container from con_new(). * */ -void x_con_init(Con *con, uint16_t depth) { +void x_con_init(Con *con) { /* TODO: maybe create the window when rendering first? we could then even * get the initial geometry right */ @@ -107,7 +107,7 @@ void x_con_init(Con *con, uint16_t depth) { /* For custom visuals, we need to create a colormap before creating * this window. It will be freed directly after creating the window. */ - xcb_visualid_t visual = get_visualid_by_depth(depth); + xcb_visualid_t visual = get_visualid_by_depth(con->depth); xcb_colormap_t win_colormap = xcb_generate_id(conn); xcb_create_colormap_checked(conn, XCB_COLORMAP_ALLOC_NONE, win_colormap, root, visual); @@ -133,7 +133,7 @@ void x_con_init(Con *con, uint16_t depth) { values[4] = win_colormap; Rect dims = {-15, -15, 10, 10}; - xcb_window_t frame_id = create_window(conn, dims, depth, visual, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCURSOR_CURSOR_POINTER, false, mask, values); + xcb_window_t frame_id = create_window(conn, dims, con->depth, visual, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCURSOR_CURSOR_POINTER, false, mask, values); draw_util_surface_init(conn, &(con->frame), frame_id, get_visualtype_by_id(visual), dims.width, dims.height); xcb_change_property(conn, XCB_PROP_MODE_REPLACE, From 6746aa4b5ff884f9bbebd45685f2aadb0a8a62f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Thu, 5 May 2016 20:46:33 +0200 Subject: [PATCH 043/150] Use the last known timestamp when calling xcb_set_input_focus(). (#2332) In most cases this won't make a difference, but consider the following scenario: * Some application acquires input focus on its own (which the window manager is not involved in, so it will "always" work). * Before the FocusIn / FocusOut events are processed by i3, the workflow to push X changes is run, resulting in xcb_set_input_focus() being called. Using XCB_CURRENT_TIME, this means i3 will "win" and override the focus, even though it simply wasn't aware (yet) that focus had already been taken over by someone else. When processing the FocusIn / FocusOut events, i3 assumes that the focus is already set which results in a broken focus state as i3 assumes some container has the input focus when it doesn't. With the new behavior, i3's attempt to set the input focus will fail if the FocusIn / FocusOut events have not yet processed. Once they are processed, the focus state will be automatically corrected. fixes #2322 --- src/x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/x.c b/src/x.c index ca7d8ae4..6fd3297a 100644 --- a/src/x.c +++ b/src/x.c @@ -1115,7 +1115,7 @@ void x_push_changes(Con *con) { values[0] = CHILD_EVENT_MASK & ~(XCB_EVENT_MASK_FOCUS_CHANGE); xcb_change_window_attributes(conn, focused->window->id, XCB_CW_EVENT_MASK, values); } - xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, to_focus, XCB_CURRENT_TIME); + xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, to_focus, last_timestamp); if (focused->window != NULL) { values[0] = CHILD_EVENT_MASK; xcb_change_window_attributes(conn, focused->window->id, XCB_CW_EVENT_MASK, values); @@ -1135,7 +1135,7 @@ void x_push_changes(Con *con) { /* If we still have no window to focus, we focus the EWMH window instead. We use this rather than the * root window in order to avoid an X11 fallback mechanism causing a ghosting effect (see #1378). */ DLOG("Still no window focused, better set focus to the EWMH support window (%d)\n", ewmh_window); - xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, ewmh_window, XCB_CURRENT_TIME); + xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, ewmh_window, last_timestamp); ewmh_update_active_window(XCB_WINDOW_NONE); focused_id = ewmh_window; } From a8757625c32e58676a3aa99c1859734b7ac09c8d Mon Sep 17 00:00:00 2001 From: Johannes Lange Date: Sun, 8 May 2016 00:20:08 +0200 Subject: [PATCH 044/150] Do not count '\' in comment as line continuation (#2181) fixes #2176 --- docs/userguide | 4 ++++ src/config_parser.c | 17 +++++++++++++---- testcases/t/247-config-line-continuation.t | 16 ++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/docs/userguide b/docs/userguide index f46a0be7..d0ac2ddb 100644 --- a/docs/userguide +++ b/docs/userguide @@ -1115,11 +1115,15 @@ show_marks yes Config files support line continuation, meaning when you end a line in a backslash character (`\`), the line-break will be ignored by the parser. This feature can be used to create more readable configuration files. +Commented lines are not continued. *Examples*: ------------------- bindsym Mod1+f \ fullscreen toggle + +# this line is not continued \ +bindsym Mod1+F fullscreen toggle ------------------- == Configuring i3bar diff --git a/src/config_parser.c b/src/config_parser.c index 5ee69e8d..b197eb22 100644 --- a/src/config_parser.c +++ b/src/config_parser.c @@ -846,17 +846,26 @@ bool parse_file(const char *f, bool use_nagbar) { if (buffer[strlen(buffer) - 1] != '\n' && !feof(fstr)) { ELOG("Your line continuation is too long, it exceeds %zd bytes\n", sizeof(buffer)); } + + /* sscanf implicitly strips whitespace. */ + const bool skip_line = (sscanf(buffer, "%511s %511[^\n]", key, value) < 1 || strlen(key) < 3); + const bool comment = (key[0] == '#'); + continuation = strstr(buffer, "\\\n"); if (continuation) { - continue; + if (!comment) { + continue; + } + DLOG("line continuation in comment is ignored: \"%.*s\"\n", (int)strlen(buffer) - 1, buffer); + continuation = NULL; } strncpy(buf + strlen(buf), buffer, strlen(buffer) + 1); - /* sscanf implicitly strips whitespace. Also, we skip comments and empty lines. */ - if (sscanf(buffer, "%511s %511[^\n]", key, value) < 1 || - key[0] == '#' || strlen(key) < 3) + /* Skip comments and empty lines. */ + if (skip_line || comment) { continue; + } if (strcasecmp(key, "set") == 0) { if (value[0] != '$') { diff --git a/testcases/t/247-config-line-continuation.t b/testcases/t/247-config-line-continuation.t index 0396d872..cb429083 100644 --- a/testcases/t/247-config-line-continuation.t +++ b/testcases/t/247-config-line-continuation.t @@ -198,4 +198,20 @@ EOT is(launch_get_border($config), 'none', 'no border'); +##################################################################### +# test ignoring of line continuation within a comment +##################################################################### + +$config = <<'EOT'; +# i3 config file (v4) +font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 + +set $vartest \"special title\" +for_window [title="$vartest"] border pixel 1 +# this line is not continued, so the following is not contained in this comment\ +for_window [title="$vartest"] border none +EOT + +is(launch_get_border($config), 'none', 'no border'); + done_testing; From dbafb3cf23d99eab88ff94e302b5fd7b6994a5b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sun, 8 May 2016 12:49:24 +0200 Subject: [PATCH 045/150] Properly close disabled outputs restored during a restart. (#2337) If an output is disabled during a restart, for example because a binding such as bindsym $mod+Shift+r exec "xrandr --auto", restart is used, it can happen that we first write the layout to disk and only then receive the RandR change events. This leads to a situation where the restored tree will contain these outputs, but the restarted i3 process will not receive the RandR events, thus the internal output in i3 is marked disabled. This patch finds these cases after a restart and force-disables the affected outputs. fixes #2326 --- include/randr.h | 6 ++ src/main.c | 30 ++++++++- src/randr.c | 169 ++++++++++++++++++++++++++---------------------- 3 files changed, 124 insertions(+), 81 deletions(-) diff --git a/include/randr.h b/include/randr.h index 8d4b4def..30dd955d 100644 --- a/include/randr.h +++ b/include/randr.h @@ -60,6 +60,12 @@ void init_ws_for_output(Output *output, Con *content); */ void randr_query_outputs(void); +/** + * Disables the output and moves its content. + * + */ +void randr_disable_output(Output *output); + /** * Returns the first output which is active. * diff --git a/src/main.c b/src/main.c index b2ce17d8..8bbd23ba 100644 --- a/src/main.c +++ b/src/main.c @@ -623,7 +623,7 @@ int main(int argc, char *argv[]) { grab_all_keys(conn); bool needs_tree_init = true; - if (layout_path) { + if (layout_path != NULL) { LOG("Trying to restore the layout from \"%s\".\n", layout_path); needs_tree_init = !tree_restore(layout_path, greply); if (delete_layout_path) { @@ -633,7 +633,6 @@ int main(int argc, char *argv[]) { * sockets) left. */ rmdir(dir); } - free(layout_path); } if (needs_tree_init) tree_init(greply); @@ -658,6 +657,33 @@ int main(int argc, char *argv[]) { randr_init(&randr_base); } + /* We need to force disabling outputs which have been loaded from the + * layout file but are no longer active. This can happen if the output has + * been disabled in the short time between writing the restart layout file + * and restarting i3. See #2326. */ + if (layout_path != NULL && randr_base > -1) { + Con *con; + TAILQ_FOREACH(con, &(croot->nodes_head), nodes) { + Output *output; + TAILQ_FOREACH(output, &outputs, outputs) { + if (output->active || strcmp(con->name, output->name) != 0) + continue; + + /* This will correctly correlate the output with its content + * container. We need to make the connection to properly + * disable the output. */ + if (output->con == NULL) { + output_init_con(output); + output->changed = false; + } + + output->to_be_disabled = true; + randr_disable_output(output); + } + } + } + FREE(layout_path); + scratchpad_fix_resolution(); xcb_query_pointer_reply_t *pointerreply; diff --git a/src/randr.c b/src/randr.c index 6aed40cf..512e0d28 100644 --- a/src/randr.c +++ b/src/randr.c @@ -622,7 +622,7 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id, * */ void randr_query_outputs(void) { - Output *output, *other, *first; + Output *output, *other; xcb_randr_get_output_primary_cookie_t pcookie; xcb_randr_get_screen_resources_current_cookie_t rcookie; @@ -733,84 +733,7 @@ void randr_query_outputs(void) { * because the user disabled them or because they are clones) */ TAILQ_FOREACH(output, &outputs, outputs) { if (output->to_be_disabled) { - output->active = false; - DLOG("Output %s disabled, re-assigning workspaces/docks\n", output->name); - - 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, if the disappearing ws is focused */ - Con *next = NULL; - if (TAILQ_FIRST(&(croot->focus_head)) == output->con) { - DLOG("This output (%p) was focused! Getting next\n", output->con); - next = focused; - DLOG("next = %p\n", next); - } - - /* 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, 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)); - DLOG("Done, next\n"); - } - DLOG("re-attached all workspaces\n"); - - 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); - tree_close_internal(output->con, DONT_KILL_WINDOW, true, false); - DLOG("Done. Should be fine now\n"); - output->con = NULL; - } - - output->to_be_disabled = false; - output->changed = false; + randr_disable_output(output); } if (output->changed) { @@ -846,6 +769,94 @@ void randr_query_outputs(void) { FREE(primary); } +/* + * Disables the output and moves its content. + * + */ +void randr_disable_output(Output *output) { + assert(output->to_be_disabled); + + output->active = false; + DLOG("Output %s disabled, re-assigning workspaces/docks\n", output->name); + + 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, if the disappearing ws is focused */ + Con *next = NULL; + if (TAILQ_FIRST(&(croot->focus_head)) == output->con) { + DLOG("This output (%p) was focused! Getting next\n", output->con); + next = focused; + DLOG("next = %p\n", next); + } + + /* 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, 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)); + } + DLOG("Done, next\n"); + } + DLOG("re-attached all workspaces\n"); + + 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); + tree_close_internal(output->con, DONT_KILL_WINDOW, true, false); + DLOG("Done. Should be fine now\n"); + output->con = NULL; + } + + output->to_be_disabled = false; + output->changed = false; +} + /* * We have just established a connection to the X server and need the initial * XRandR information to setup workspaces for each screen. From 47562b414389711a82db25a694b064ad39117f82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sun, 8 May 2016 12:55:27 +0200 Subject: [PATCH 046/150] Introduce support for specifying variables from X resources. (#2286) This patch introduces a new 'set_from_resource' config directive which allows defining a variable by retrieving its value from the X resource database. This avoids having to configure a color scheme in multiple files. The directive takes an additional fallback value which is used in case the resource cannot be found or during config validation where no X connection is available. Furthermore, this patch includes the following changes: - If the same variable is defined twice, we now properly overwrite the value of the assignment rather than inserting two variable definitions with the same key. - We now depend on xcb-util-xrm to query the resource. - Increase the buffer size for variable / resource assignments. fixes #2130 --- DEPENDS | 45 ++++---- common.mk | 4 + debian/control | 1 + docs/userguide | 32 ++++++ include/config_parser.h | 1 + parser-specs/config.spec | 1 + src/config_parser.c | 132 +++++++++++++++++------ src/i3.mk | 4 +- testcases/t/201-config-parser.t | 2 +- testcases/t/532-xresources.t | 64 +++++++++++ travis/travis-base-ubuntu-386.Dockerfile | 11 ++ travis/travis-base-ubuntu.Dockerfile | 11 ++ 12 files changed, 253 insertions(+), 55 deletions(-) create mode 100644 testcases/t/532-xresources.t diff --git a/DEPENDS b/DEPENDS index fad11da5..227aaec3 100644 --- a/DEPENDS +++ b/DEPENDS @@ -4,28 +4,29 @@ "min" means minimum required version "lkgv" means last known good version -┌──────────────┬────────┬────────┬────────────────────────────────────────┐ -│ dependency │ min. │ lkgv │ URL │ -├──────────────┼────────┼────────┼────────────────────────────────────────┤ -│ pkg-config │ 0.25 │ 0.28 │ http://pkgconfig.freedesktop.org/ │ -│ libxcb │ 1.1.93 │ 1.11 │ http://xcb.freedesktop.org/dist/ │ -│ xcb-util │ 0.3.3 │ 0.4.1 │ http://xcb.freedesktop.org/dist/ │ -│ xkbcommon │ 0.4.0 │ 0.5.0 │ http://xkbcommon.org/ │ -│ xkbcommon-x11│ 0.4.0 │ 0.5.0 │ http://xkbcommon.org/ │ -│ util-cursor³⁴│ 0.0.99 │ 0.1.2 │ http://xcb.freedesktop.org/dist/ │ -│ util-wm⁴ │ 0.3.8 │ 0.3.8 │ http://xcb.freedesktop.org/dist/ │ -│ util-keysyms⁴│ 0.3.8 │ 0.4.0 │ http://xcb.freedesktop.org/dist/ │ -│ libev │ 4.0 │ 4.19 │ http://libev.schmorp.de/ │ -│ yajl │ 2.0.1 │ 2.1.0 │ http://lloyd.github.com/yajl/ │ -│ asciidoc │ 8.3.0 │ 8.6.8 │ http://www.methods.co.nz/asciidoc/ │ -│ xmlto │ 0.0.23 │ 0.0.23 │ http://www.methods.co.nz/asciidoc/ │ -│ Pod::Simple² │ 3.22 │ 3.22 │ http://search.cpan.org/~dwheeler/Pod-Simple-3.23/ -│ docbook-xml │ 4.5 │ 4.5 │ http://www.methods.co.nz/asciidoc/ │ -│ PCRE │ 8.12 │ 8.35 │ http://www.pcre.org/ │ -│ libsn¹ │ 0.10 │ 0.12 │ http://freedesktop.org/wiki/Software/startup-notification -│ pango │ 1.30.0 | 1.36.8 │ http://www.pango.org/ │ -│ cairo │ 1.14.4 │ 1.14.4 │ http://cairographics.org/ │ -└──────────────┴────────┴────────┴────────────────────────────────────────┘ +┌──────────────┬────────┬────────┬───────────────────────────────────────────────────────────┐ +│ dependency │ min. │ lkgv │ URL │ +├──────────────┼────────┼────────┼───────────────────────────────────────────────────────────┤ +│ pkg-config │ 0.25 │ 0.28 │ http://pkgconfig.freedesktop.org/ │ +│ libxcb │ 1.1.93 │ 1.11 │ http://xcb.freedesktop.org/dist/ │ +│ xcb-util │ 0.3.3 │ 0.4.1 │ http://xcb.freedesktop.org/dist/ │ +│ xkbcommon │ 0.4.0 │ 0.5.0 │ http://xkbcommon.org/ │ +│ xkbcommon-x11│ 0.4.0 │ 0.5.0 │ http://xkbcommon.org/ │ +│ util-cursor³⁴│ 0.0.99 │ 0.1.2 │ http://xcb.freedesktop.org/dist/ │ +│ util-wm⁴ │ 0.3.8 │ 0.3.8 │ http://xcb.freedesktop.org/dist/ │ +│ util-keysyms⁴│ 0.3.8 │ 0.4.0 │ http://xcb.freedesktop.org/dist/ │ +│ util-xrm⁴ │ 1.0.0 │ 1.0.0 │ https://github.com/Airblader/xcb-util-xrm │ +│ libev │ 4.0 │ 4.19 │ http://libev.schmorp.de/ │ +│ yajl │ 2.0.1 │ 2.1.0 │ http://lloyd.github.com/yajl/ │ +│ asciidoc │ 8.3.0 │ 8.6.8 │ http://www.methods.co.nz/asciidoc/ │ +│ xmlto │ 0.0.23 │ 0.0.23 │ http://www.methods.co.nz/asciidoc/ │ +│ Pod::Simple² │ 3.22 │ 3.22 │ http://search.cpan.org/~dwheeler/Pod-Simple-3.23/ │ +│ docbook-xml │ 4.5 │ 4.5 │ http://www.methods.co.nz/asciidoc/ │ +│ PCRE │ 8.12 │ 8.35 │ http://www.pcre.org/ │ +│ libsn¹ │ 0.10 │ 0.12 │ http://freedesktop.org/wiki/Software/startup-notification │ +│ pango │ 1.30.0 | 1.36.8 │ http://www.pango.org/ │ +│ cairo │ 1.14.4 │ 1.14.4 │ http://cairographics.org/ │ +└──────────────┴────────┴────────┴───────────────────────────────────────────────────────────┘ ¹ libsn = libstartup-notification ² Pod::Simple is a Perl module required for converting the testsuite documentation to HTML. See http://michael.stapelberg.de/cpan/#Pod::Simple diff --git a/common.mk b/common.mk index 1e738b04..0215d35b 100644 --- a/common.mk +++ b/common.mk @@ -126,6 +126,10 @@ XKB_COMMON_LIBS := $(call ldflags_for_lib, xkbcommon,xkbcommon) XKB_COMMON_X11_CFLAGS := $(call cflags_for_lib, xkbcommon-x11,xkbcommon-x11) XKB_COMMON_X11_LIBS := $(call ldflags_for_lib, xkbcommon-x11,xkbcommon-x11) +# XCB xrm +XCB_XRM_CFLAGS := $(call cflags_for_lib, xcb-xrm) +XCB_XRM_LIBS := $(call ldflags_for_lib, xcb-xrm,xcb-xrm) + # yajl YAJL_CFLAGS := $(call cflags_for_lib, yajl) YAJL_LIBS := $(call ldflags_for_lib, yajl,yajl) diff --git a/debian/control b/debian/control index 577bb4d4..6b1530b8 100644 --- a/debian/control +++ b/debian/control @@ -10,6 +10,7 @@ Build-Depends: debhelper (>= 9), libxcb-randr0-dev, libxcb-icccm4-dev, libxcb-cursor-dev, + libxcb-xrm-dev, libxcb-xkb-dev, libxkbcommon-dev (>= 0.4.0), libxkbcommon-x11-dev (>= 0.4.0), diff --git a/docs/userguide b/docs/userguide index d0ac2ddb..d9cfc642 100644 --- a/docs/userguide +++ b/docs/userguide @@ -700,6 +700,38 @@ absolutely no plans to change this. If you need a more dynamic configuration you should create a little script which generates a configuration file and run it before starting i3 (for example in your +~/.xsession+ file). +Also see <> to learn how to create variables based on resources +loaded from the X resource database. + +[[xresources]] +=== X resources + +<> can also be created using a value configured in the X resource +database. This is useful, for example, to avoid configuring color values within +the i3 configuration. Instead, the values can be configured, once, in the X +resource database to achieve an easily maintainable, consistent color theme +across many X applications. + +Defining a resource will load this resource from the resource database and +assign its value to the specified variable. A fallback must be specified in +case the resource cannot be loaded from the database. + +*Syntax*: +---------------------------------------------------- +set_from_resource $ +---------------------------------------------------- + +*Example*: +---------------------------------------------------------------------------- +# The ~/.Xresources should contain a line such as +# *color0: #121212 +# and must be loaded properly, e.g., by using +# xrdb ~/.Xresources +# This value is picked up on by other applications (e.g., the URxvt terminal +# emulator) and can be used in i3 like this: +set_from_resource $black i3wm.color0 #000000 +---------------------------------------------------------------------------- + [[assign_workspace]] === Automatically putting clients on specific workspaces diff --git a/include/config_parser.h b/include/config_parser.h index 9c23a11d..2ba79a68 100644 --- a/include/config_parser.h +++ b/include/config_parser.h @@ -11,6 +11,7 @@ #include +SLIST_HEAD(variables_head, Variable); extern pid_t config_error_nagbar_pid; /* diff --git a/parser-specs/config.spec b/parser-specs/config.spec index ef3bc2e0..24f40802 100644 --- a/parser-specs/config.spec +++ b/parser-specs/config.spec @@ -18,6 +18,7 @@ state INITIAL: error -> '#' -> IGNORE_LINE 'set' -> IGNORE_LINE + 'set_from_resource' -> IGNORE_LINE bindtype = 'bindsym', 'bindcode', 'bind' -> BINDING 'bar' -> BARBRACE 'font' -> FONT diff --git a/src/config_parser.c b/src/config_parser.c index b197eb22..5b5e2363 100644 --- a/src/config_parser.c +++ b/src/config_parser.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "all.h" @@ -42,6 +43,8 @@ #define y(x, ...) yajl_gen_##x(command_output.json_gen, ##__VA_ARGS__) #define ystr(str) yajl_gen_string(command_output.json_gen, (unsigned char *)str, strlen(str)) +xcb_xrm_database_t *database = NULL; + #ifndef TEST_PARSER pid_t config_error_nagbar_pid = -1; static struct context *context; @@ -811,18 +814,80 @@ void start_config_error_nagbar(const char *configpath, bool has_errors) { free(pageraction); } +/* + * Inserts or updates a variable assignment depending on whether it already exists. + * + */ +static void upsert_variable(struct variables_head *variables, char *key, char *value) { + struct Variable *current; + SLIST_FOREACH(current, variables, variables) { + if (strcmp(current->key, key) != 0) { + continue; + } + + DLOG("Updated variable: %s = %s -> %s\n", key, current->value, value); + FREE(current->value); + current->value = sstrdup(value); + return; + } + + DLOG("Defined new variable: %s = %s\n", key, value); + struct Variable *new = scalloc(1, sizeof(struct Variable)); + struct Variable *test = NULL, *loc = NULL; + new->key = sstrdup(key); + 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) { + if (strlen(new->key) >= strlen(test->key)) + break; + loc = test; + } + + if (loc == NULL) { + SLIST_INSERT_HEAD(variables, new, variables); + } else { + SLIST_INSERT_AFTER(loc, new, variables); + } +} + +static char *get_resource(char *name) { + if (conn == NULL) { + return NULL; + } + + /* Load the resource database lazily. */ + if (database == NULL) { + database = xcb_xrm_database_from_default(conn); + + if (database == NULL) { + ELOG("Failed to open the resource database.\n"); + + /* Load an empty database so we don't keep trying to load the + * default database over and over again. */ + database = xcb_xrm_database_from_string(""); + + return NULL; + } + } + + char *resource; + xcb_xrm_resource_get_string(database, name, NULL, &resource); + return resource; +} + /* * Parses the given file by first replacing the variables, then calling * parse_config and possibly launching i3-nagbar. * */ bool parse_file(const char *f, bool use_nagbar) { - SLIST_HEAD(variables_head, Variable) variables = SLIST_HEAD_INITIALIZER(&variables); + struct variables_head variables = SLIST_HEAD_INITIALIZER(&variables); int fd; struct stat stbuf; char *buf; FILE *fstr; - char buffer[4096], key[512], value[512], *continuation = NULL; + char buffer[4096], key[512], value[4096], *continuation = NULL; if ((fd = open(f, O_RDONLY)) == -1) die("Could not open configuration file: %s\n", strerror(errno)); @@ -848,8 +913,9 @@ bool parse_file(const char *f, bool use_nagbar) { } /* sscanf implicitly strips whitespace. */ - const bool skip_line = (sscanf(buffer, "%511s %511[^\n]", key, value) < 1 || strlen(key) < 3); + const bool skip_line = (sscanf(buffer, "%511s %4095[^\n]", key, value) < 1 || strlen(key) < 3); const bool comment = (key[0] == '#'); + value[4095] = '\n'; continuation = strstr(buffer, "\\\n"); if (continuation) { @@ -868,49 +934,55 @@ bool parse_file(const char *f, bool use_nagbar) { } if (strcasecmp(key, "set") == 0) { - if (value[0] != '$') { + char v_key[512]; + char v_value[4096]; + + if (sscanf(value, "%511s %4095[^\n]", v_key, v_value) < 1) { + ELOG("Failed to parse variable specification '%s', skipping it.\n", value); + continue; + } + + if (v_key[0] != '$') { ELOG("Malformed variable assignment, name has to start with $\n"); continue; } - /* get key/value for this variable */ - char *v_key = value, *v_value; - if (strstr(value, " ") == NULL && strstr(value, "\t") == NULL) { - ELOG("Malformed variable assignment, need a value\n"); + upsert_variable(&variables, v_key, v_value); + continue; + } else if (strcasecmp(key, "set_from_resource") == 0) { + char res_name[512]; + char v_key[512]; + char fallback[4096]; + + if (sscanf(value, "%511s %511s %4095[^\n]", v_key, res_name, fallback) < 1) { + ELOG("Failed to parse resource specification '%s', skipping it.\n", value); continue; } - if (!(v_value = strstr(value, " "))) - v_value = strstr(value, "\t"); - - *(v_value++) = '\0'; - while (*v_value == '\t' || *v_value == ' ') - v_value++; - - struct Variable *new = scalloc(1, sizeof(struct Variable)); - struct Variable *test = NULL, *loc = NULL; - new->key = sstrdup(v_key); - new->value = sstrdup(v_value); - /* ensure that the correct variable is matched in case of one being - * the prefix of another */ - SLIST_FOREACH(test, &variables, variables) { - if (strlen(new->key) >= strlen(test->key)) - break; - loc = test; + if (v_key[0] != '$') { + ELOG("Malformed variable assignment, name has to start with $\n"); + continue; } - if (loc == NULL) { - SLIST_INSERT_HEAD(&variables, new, variables); - } else { - SLIST_INSERT_AFTER(loc, new, variables); + char *res_value = get_resource(res_name); + if (res_value == NULL) { + DLOG("Could not get resource '%s', using fallback '%s'.\n", res_name, fallback); + res_value = sstrdup(fallback); } - DLOG("Got new variable %s = %s\n", v_key, v_value); + upsert_variable(&variables, v_key, res_value); + FREE(res_value); continue; } } fclose(fstr); + if (database != NULL) { + xcb_xrm_database_free(database); + /* Explicitly set the database to NULL again in case the config gets reloaded. */ + database = NULL; + } + /* For every custom variable, see how often it occurs in the file and * how much extra bytes it requires when replaced. */ struct Variable *current, *nearest; diff --git a/src/i3.mk b/src/i3.mk index ed8e3ae9..6cb4abf4 100644 --- a/src/i3.mk +++ b/src/i3.mk @@ -5,8 +5,8 @@ CLEAN_TARGETS += clean-i3 i3_SOURCES := $(filter-out $(i3_SOURCES_GENERATED),$(wildcard src/*.c)) i3_HEADERS_CMDPARSER := $(wildcard include/GENERATED_*.h) i3_HEADERS := $(filter-out $(i3_HEADERS_CMDPARSER),$(wildcard include/*.h)) -i3_CFLAGS = $(XKB_COMMON_CFLAGS) $(XKB_COMMON_X11_CFLAGS) $(XCB_CFLAGS) $(XCB_KBD_CFLAGS) $(XCB_WM_CFLAGS) $(XCB_CURSOR_CFLAGS) $(PANGO_CFLAGS) $(YAJL_CFLAGS) $(LIBEV_CFLAGS) $(PCRE_CFLAGS) $(LIBSN_CFLAGS) -i3_LIBS = $(XKB_COMMON_LIBS) $(XKB_COMMON_X11_LIBS) $(XCB_LIBS) $(XCB_XKB_LIBS) $(XCB_KBD_LIBS) $(XCB_WM_LIBS) $(XCB_CURSOR_LIBS) $(PANGO_LIBS) $(YAJL_LIBS) $(LIBEV_LIBS) $(PCRE_LIBS) $(LIBSN_LIBS) -lm -lpthread +i3_CFLAGS = $(XKB_COMMON_CFLAGS) $(XKB_COMMON_X11_CFLAGS) $(XCB_CFLAGS) $(XCB_KBD_CFLAGS) $(XCB_WM_CFLAGS) $(XCB_CURSOR_CFLAGS) $(XCB_XRM_CFLAGS) $(PANGO_CFLAGS) $(YAJL_CFLAGS) $(LIBEV_CFLAGS) $(PCRE_CFLAGS) $(LIBSN_CFLAGS) +i3_LIBS = $(XKB_COMMON_LIBS) $(XKB_COMMON_X11_LIBS) $(XCB_LIBS) $(XCB_XKB_LIBS) $(XCB_KBD_LIBS) $(XCB_WM_LIBS) $(XCB_CURSOR_LIBS) $(XCB_XRM_LIBS) $(PANGO_LIBS) $(YAJL_LIBS) $(LIBEV_LIBS) $(PCRE_LIBS) $(LIBSN_LIBS) -lm -lpthread # When using clang, we use pre-compiled headers to speed up the build. With # gcc, this actually makes the build slower. diff --git a/testcases/t/201-config-parser.t b/testcases/t/201-config-parser.t index e8835005..bcccc5a2 100644 --- a/testcases/t/201-config-parser.t +++ b/testcases/t/201-config-parser.t @@ -441,7 +441,7 @@ client.focused #4c7899 #285577 #ffffff #2e9ef4 EOT my $expected_all_tokens = <<'EOT'; -ERROR: CONFIG: Expected one of these tokens: , '#', 'set', 'bindsym', 'bindcode', 'bind', 'bar', 'font', 'mode', 'floating_minimum_size', 'floating_maximum_size', 'floating_modifier', 'default_orientation', 'workspace_layout', 'new_window', 'new_float', 'hide_edge_borders', 'for_window', 'assign', 'no_focus', 'focus_follows_mouse', 'mouse_warping', 'force_focus_wrapping', 'force_xinerama', 'force-xinerama', 'workspace_auto_back_and_forth', 'fake_outputs', 'fake-outputs', 'force_display_urgency_hint', 'focus_on_window_activation', 'show_marks', 'workspace', 'ipc_socket', 'ipc-socket', 'restart_state', 'popup_during_fullscreen', 'exec_always', 'exec', 'client.background', 'client.focused_inactive', 'client.focused', 'client.unfocused', 'client.urgent', 'client.placeholder' +ERROR: CONFIG: Expected one of these tokens: , '#', 'set', 'set_from_resource', 'bindsym', 'bindcode', 'bind', 'bar', 'font', 'mode', 'floating_minimum_size', 'floating_maximum_size', 'floating_modifier', 'default_orientation', 'workspace_layout', 'new_window', 'new_float', 'hide_edge_borders', 'for_window', 'assign', 'no_focus', 'focus_follows_mouse', 'mouse_warping', 'force_focus_wrapping', 'force_xinerama', 'force-xinerama', 'workspace_auto_back_and_forth', 'fake_outputs', 'fake-outputs', 'force_display_urgency_hint', 'focus_on_window_activation', 'show_marks', 'workspace', 'ipc_socket', 'ipc-socket', 'restart_state', 'popup_during_fullscreen', 'exec_always', 'exec', 'client.background', 'client.focused_inactive', 'client.focused', 'client.unfocused', 'client.urgent', 'client.placeholder' EOT my $expected_end = <<'EOT'; diff --git a/testcases/t/532-xresources.t b/testcases/t/532-xresources.t new file mode 100644 index 00000000..438fad20 --- /dev/null +++ b/testcases/t/532-xresources.t @@ -0,0 +1,64 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Please read the following documents before working on tests: +# • http://build.i3wm.org/docs/testsuite.html +# (or docs/testsuite) +# +# • http://build.i3wm.org/docs/lib-i3test.html +# (alternatively: perldoc ./testcases/lib/i3test.pm) +# +# • http://build.i3wm.org/docs/ipc.html +# (or docs/ipc) +# +# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf +# (unless you are already familiar with Perl) +# +# Tests for using X resources in the config. +# Ticket: #2130 +use i3test i3_autostart => 0; +use X11::XCB qw(PROP_MODE_REPLACE); + +sub get_marks { + return i3(get_socket_path())->get_marks->recv; +} + +my $config = <change_property( + PROP_MODE_REPLACE, + $x->get_root_window(), + $x->atom(name => 'RESOURCE_MANAGER')->id, + $x->atom(name => 'STRING')->id, + 32, + length('*mark: works'), + '*mark: works'); +$x->flush; + +my $pid = launch_with_config($config); + +open_window(wm_class => 'worksforme'); +sync_with_i3; +is_deeply(get_marks(), [ 'works' ], 'the resource has loaded correctly'); + +cmd 'kill'; + +open_window(wm_class => 'doesnotworkforme'); +sync_with_i3; +is_deeply(get_marks(), [ 'none' ], 'the resource fallback was used'); + +exit_gracefully($pid); + +done_testing; diff --git a/travis/travis-base-ubuntu-386.Dockerfile b/travis/travis-base-ubuntu-386.Dockerfile index b1ee1c0c..ae6b7c82 100644 --- a/travis/travis-base-ubuntu-386.Dockerfile +++ b/travis/travis-base-ubuntu-386.Dockerfile @@ -27,3 +27,14 @@ COPY debian/control /usr/src/i3-debian-packaging/control RUN linux32 apt-get update && \ DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ rm -rf /var/lib/apt/lists/* + +# Install xcb-util-xrm. This is a workaround until it is available in the +# distribution packages. +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xutils-dev +RUN git clone --recursive https://github.com/Airblader/xcb-util-xrm.git && \ + cd xcb-util-xrm && \ + ./autogen.sh --prefix=/usr && \ + make && \ + make install && \ + cd - diff --git a/travis/travis-base-ubuntu.Dockerfile b/travis/travis-base-ubuntu.Dockerfile index e76229eb..62b81283 100644 --- a/travis/travis-base-ubuntu.Dockerfile +++ b/travis/travis-base-ubuntu.Dockerfile @@ -28,3 +28,14 @@ COPY debian/control /usr/src/i3-debian-packaging/control RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ rm -rf /var/lib/apt/lists/* + +# Install xcb-util-xrm. This is a workaround until it is available in the +# distribution packages. +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xutils-dev +RUN git clone --recursive https://github.com/Airblader/xcb-util-xrm.git && \ + cd xcb-util-xrm && \ + ./autogen.sh --prefix=/usr && \ + make && \ + make install && \ + cd - From 4bec3b9d24fe0bd7bab4792497bbd02bffaa6620 Mon Sep 17 00:00:00 2001 From: Julien Lequertier Date: Tue, 10 May 2016 20:27:20 +0200 Subject: [PATCH 047/150] Smart option added to hide_edge_borders config param (#2191) (#2191) Use case: * When managing multiple terminals in a workspace, the borders makes it easier to know where the focus is, but when there is only one it's obvious where the focus is. * When there's only a web browser for example, the borders are actually counter- productive since it makes clicking a side scrollbar or a tab a bit harder (if I smash my cursor to the side or the top of the workspace, I have to move it in the other direction by just a few pixels to be able to grab it) Behaviour: * No borders when there's a single window in a workspace * Borders when there are multiple windows in a workspace fixes #2188 --- docs/userguide | 6 +- include/con.h | 7 ++ include/config.h | 2 +- include/data.h | 6 ++ parser-specs/config.spec | 4 +- src/con.c | 29 ++++++ src/config_directives.c | 16 ++-- testcases/t/201-config-parser.t | 4 +- testcases/t/263-edge-borders.t | 159 ++++++++++++++++++++++++++++++++ 9 files changed, 220 insertions(+), 13 deletions(-) create mode 100644 testcases/t/263-edge-borders.t diff --git a/docs/userguide b/docs/userguide index d9cfc642..9abdd5b0 100644 --- a/docs/userguide +++ b/docs/userguide @@ -610,11 +610,13 @@ new_window pixel 3 You can hide container borders adjacent to the screen edges using +hide_edge_borders+. This is useful if you are using scrollbars, or do not want -to waste even two pixels in displayspace. Default is none. +to waste even two pixels in displayspace. The "smart" setting hides borders on +workspaces with only one window visible, but keeps them on workspaces with +multiple windows visible. Default is none. *Syntax*: ----------------------------------------------- -hide_edge_borders none|vertical|horizontal|both +hide_edge_borders none|vertical|horizontal|both|smart ----------------------------------------------- *Example*: diff --git a/include/con.h b/include/con.h index 7fa7facf..73ae0f38 100644 --- a/include/con.h +++ b/include/con.h @@ -200,6 +200,13 @@ Con *con_for_window(Con *con, i3Window *window, Match **store_match); */ int con_num_children(Con *con); +/** + * Returns the number of visible non-floating children of this container. + * For example, if the container contains a hsplit which has two children, + * this will return 2 instead of 1. + */ +int con_num_visible_children(Con *con); + /** * Count the number of windows (i.e., leaf containers). * diff --git a/include/config.h b/include/config.h index acdd2c89..699cc882 100644 --- a/include/config.h +++ b/include/config.h @@ -125,7 +125,7 @@ struct Config { * This is useful if you are reaching scrollbar on the edge of the * screen or do not want to waste a single pixel of displayspace. * By default, this is disabled. */ - adjacent_t hide_edge_borders; + hide_edge_borders_mode_t hide_edge_borders; /** By default, a workspace bar is drawn at the bottom of the screen. * If you want to have a more fancy bar, it is recommended to replace diff --git a/include/data.h b/include/data.h index 3a059e7b..88ed6879 100644 --- a/include/data.h +++ b/include/data.h @@ -75,6 +75,12 @@ typedef enum { ADJ_NONE = 0, ADJ_UPPER_SCREEN_EDGE = (1 << 2), ADJ_LOWER_SCREEN_EDGE = (1 << 4) } adjacent_t; +typedef enum { HEBM_NONE = ADJ_NONE, + HEBM_VERTICAL = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE, + HEBM_HORIZONTAL = ADJ_UPPER_SCREEN_EDGE | ADJ_LOWER_SCREEN_EDGE, + HEBM_BOTH = HEBM_VERTICAL | HEBM_HORIZONTAL, + HEBM_SMART = (1 << 5) } hide_edge_borders_mode_t; + typedef enum { MM_REPLACE, MM_ADD } mark_mode_t; diff --git a/parser-specs/config.spec b/parser-specs/config.spec index 24f40802..eeafaac8 100644 --- a/parser-specs/config.spec +++ b/parser-specs/config.spec @@ -122,10 +122,10 @@ state NEW_WINDOW_PIXELS_PX: end -> call cfg_new_window($windowtype, $border, &width) -# hide_edge_borders +# hide_edge_borders # also hide_edge_borders for compatibility state HIDE_EDGE_BORDERS: - hide_borders = 'none', 'vertical', 'horizontal', 'both' + hide_borders = 'none', 'vertical', 'horizontal', 'both', 'smart' -> call cfg_hide_edge_borders($hide_borders) hide_borders = '1', 'yes', 'true', 'on', 'enable', 'active' -> call cfg_hide_edge_borders($hide_borders) diff --git a/src/con.c b/src/con.c index 2c637a1f..dbb6d601 100644 --- a/src/con.c +++ b/src/con.c @@ -727,6 +727,29 @@ int con_num_children(Con *con) { return children; } +/** + * Returns the number of visible non-floating children of this container. + * For example, if the container contains a hsplit which has two children, + * this will return 2 instead of 1. + */ +int con_num_visible_children(Con *con) { + if (con == NULL) + return 0; + + int children = 0; + Con *current = NULL; + TAILQ_FOREACH(current, &(con->nodes_head), nodes) { + /* Visible leaf nodes are a child. */ + if (!con_is_hidden(current) && con_is_leaf(current)) + children++; + /* All other containers need to be recursed. */ + else + children += con_num_visible_children(current); + } + + return children; +} + /* * Count the number of windows (i.e., leaf containers). * @@ -1444,6 +1467,12 @@ Con *con_descend_direction(Con *con, direction_t direction) { * */ Rect con_border_style_rect(Con *con) { + if (config.hide_edge_borders == HEBM_SMART && con_num_visible_children(con_get_workspace(con)) <= 1) { + if (!con_is_floating(con)) { + return (Rect){0, 0, 0, 0}; + } + } + adjacent_t borders_to_hide = ADJ_NONE; int border_width = con->current_border_width; DLOG("The border width for con is set to: %d\n", con->current_border_width); diff --git a/src/config_directives.c b/src/config_directives.c index ec99321a..05c19c70 100644 --- a/src/config_directives.c +++ b/src/config_directives.c @@ -223,18 +223,20 @@ CFGFUN(new_window, const char *windowtype, const char *border, const long width) } CFGFUN(hide_edge_borders, const char *borders) { - if (strcmp(borders, "vertical") == 0) - config.hide_edge_borders = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE; + if (strcmp(borders, "smart") == 0) + config.hide_edge_borders = HEBM_SMART; + else if (strcmp(borders, "vertical") == 0) + config.hide_edge_borders = HEBM_VERTICAL; else if (strcmp(borders, "horizontal") == 0) - config.hide_edge_borders = ADJ_UPPER_SCREEN_EDGE | ADJ_LOWER_SCREEN_EDGE; + config.hide_edge_borders = HEBM_HORIZONTAL; else if (strcmp(borders, "both") == 0) - config.hide_edge_borders = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE | ADJ_UPPER_SCREEN_EDGE | ADJ_LOWER_SCREEN_EDGE; + config.hide_edge_borders = HEBM_BOTH; else if (strcmp(borders, "none") == 0) - config.hide_edge_borders = ADJ_NONE; + config.hide_edge_borders = HEBM_NONE; else if (eval_boolstr(borders)) - config.hide_edge_borders = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE; + config.hide_edge_borders = HEBM_VERTICAL; else - config.hide_edge_borders = ADJ_NONE; + config.hide_edge_borders = HEBM_NONE; } CFGFUN(focus_follows_mouse, const char *value) { diff --git a/testcases/t/201-config-parser.t b/testcases/t/201-config-parser.t index bcccc5a2..d3da4235 100644 --- a/testcases/t/201-config-parser.t +++ b/testcases/t/201-config-parser.t @@ -286,6 +286,7 @@ hide_edge_borders none hide_edge_borders vertical hide_edge_borders horizontal hide_edge_borders both +hide_edge_borders smart EOT $expected = <<'EOT'; @@ -293,6 +294,7 @@ cfg_hide_edge_borders(none) cfg_hide_edge_borders(vertical) cfg_hide_edge_borders(horizontal) cfg_hide_edge_borders(both) +cfg_hide_edge_borders(smart) EOT is(parser_calls($config), @@ -464,7 +466,7 @@ client.focused #4c7899 #285577 #ffffff #2e9ef4 EOT $expected = <<'EOT'; -ERROR: CONFIG: Expected one of these tokens: 'none', 'vertical', 'horizontal', 'both', '1', 'yes', 'true', 'on', 'enable', 'active' +ERROR: CONFIG: Expected one of these tokens: 'none', 'vertical', 'horizontal', 'both', 'smart', '1', 'yes', 'true', 'on', 'enable', 'active' ERROR: CONFIG: (in file ) ERROR: CONFIG: Line 1: hide_edge_borders FOOBAR ERROR: CONFIG: ^^^^^^ diff --git a/testcases/t/263-edge-borders.t b/testcases/t/263-edge-borders.t new file mode 100644 index 00000000..0d14c65c --- /dev/null +++ b/testcases/t/263-edge-borders.t @@ -0,0 +1,159 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Please read the following documents before working on tests: +# • http://build.i3wm.org/docs/testsuite.html +# (or docs/testsuite) +# +# • http://build.i3wm.org/docs/lib-i3test.html +# (alternatively: perldoc ./testcases/lib/i3test.pm) +# +# • http://build.i3wm.org/docs/ipc.html +# (or docs/ipc) +# +# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf +# (unless you are already familiar with Perl) +# +# Tests that the hide_edge_borders smart option works +# Ticket: #2188 + +use i3test i3_autostart => 0; + +#################################################################### +# 1: check that the borders are present on a floating windows +##################################################################### + +my $config = <{floating_nodes}}; +ok(@floating == 1, 'one floating container opened'); +is($floating[0]->{nodes}[0]->{current_border_width}, 2, 'floating current border width set to 2'); +is($floatwindow->rect->width, $floating[0]->{rect}->{width} - 2*2, 'floating border width 2'); + +exit_gracefully($pid); + +##################################################################### +# 2: check that the borders are present on a workspace with two tiled +# windows visible +##################################################################### + +$config = <{nodes}}; +ok(@tiled == 2, 'two tiled container opened'); +is($tiled[0]->{current_border_width}, 2, 'first tiled current border width set to 2'); +is($tilewindow->rect->width, $tiled[0]->{rect}->{width} - 2*2, 'first tiled border width 2'); +is($tiled[1]->{current_border_width}, 2, 'second tiled current border width set to 2'); +is($tilewindow2->rect->width, $tiled[1]->{rect}->{width} - 2*2, 'second tiled border width 2'); + +exit_gracefully($pid); + +##################################################################### +# 3: check that the borders are hidden on a workspace with one tiled +# window visible +##################################################################### + +$config = <{nodes}}; +ok(@tiled == 1, 'one tiled container opened'); +is($tiled[0]->{current_border_width}, 2, 'tiled current border width set to 2'); +is($tilewindow->rect->width, $tiled[0]->{rect}->{width} - 2*0, 'single tiled border width 0'); + +exit_gracefully($pid); + +##################################################################### +# 4: check that the borders are present on a workspace with two tiled +# windows visible, recursively +##################################################################### + +$config = < back to one container'); + +cmd 'focus parent'; +my $tilewindow3 = open_window; +ok(@{get_ws_content($tmp)} == 2, 'after split & new window, two containers'); + +$wscontent = get_ws($tmp); + +@tiled = @{$wscontent->{nodes}}; +ok(@tiled == 2, 'two tiled container opened in another container'); +is($tiled[0]->{current_border_width}, -1, 'first tiled current border width set to -1'); +is($tilewindow->rect->width, $tiled[0]->{rect}->{width} - 2*2, 'first tiled border width 2'); +is($tiled[1]->{current_border_width}, 2, 'second tiled current border width set to 2'); +is($tilewindow2->rect->width, $tiled[1]->{rect}->{width} - 2*2, 'second tiled border width 2'); + +exit_gracefully($pid); + +done_testing; From f5945b7c6ec11dd8f7a27e2f908ed00b1d8ff3a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 11 May 2016 20:11:04 +0200 Subject: [PATCH 048/150] Split list of command / config directives in tests. (#2345) This makes adding new directives less prone to merge conflicts. --- testcases/t/187-commands-parser.t | 57 ++++++++++++++++--------------- testcases/t/201-config-parser.t | 48 ++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 31 deletions(-) diff --git a/testcases/t/187-commands-parser.t b/testcases/t/187-commands-parser.t index e3481b0a..73c443f9 100644 --- a/testcases/t/187-commands-parser.t +++ b/testcases/t/187-commands-parser.t @@ -144,34 +144,35 @@ is(parser_calls("\nworkspace test"), ################################################################################ is(parser_calls('unknown_literal'), - "ERROR: Expected one of these tokens: , '[', " . - "'move', " . - "'exec', " . - "'exit', " . - "'restart', " . - "'reload', " . - "'shmlog', " . - "'debuglog', " . - "'border', " . - "'layout', " . - "'append_layout', " . - "'workspace', " . - "'focus', " . - "'kill', " . - "'open', " . - "'fullscreen', " . - "'sticky', " . - "'split', " . - "'floating', " . - "'mark', " . - "'unmark', " . - "'resize', " . - "'rename', " . - "'nop', " . - "'scratchpad', " . - "'title_format', " . - "'mode', " . - "'bar'\n" . + "ERROR: Expected one of these tokens: , '[', '" . join("', '", qw( + move + exec + exit + restart + reload + shmlog + debuglog + border + layout + append_layout + workspace + focus + kill + open + fullscreen + sticky + split + floating + mark + unmark + resize + rename + nop + scratchpad + title_format + mode + bar + )) . "'\n" . "ERROR: Your command: unknown_literal\n" . "ERROR: ^^^^^^^^^^^^^^^", 'error for unknown literal ok'); diff --git a/testcases/t/201-config-parser.t b/testcases/t/201-config-parser.t index d3da4235..d92d3b20 100644 --- a/testcases/t/201-config-parser.t +++ b/testcases/t/201-config-parser.t @@ -442,9 +442,51 @@ hide_edge_border both client.focused #4c7899 #285577 #ffffff #2e9ef4 EOT -my $expected_all_tokens = <<'EOT'; -ERROR: CONFIG: Expected one of these tokens: , '#', 'set', 'set_from_resource', 'bindsym', 'bindcode', 'bind', 'bar', 'font', 'mode', 'floating_minimum_size', 'floating_maximum_size', 'floating_modifier', 'default_orientation', 'workspace_layout', 'new_window', 'new_float', 'hide_edge_borders', 'for_window', 'assign', 'no_focus', 'focus_follows_mouse', 'mouse_warping', 'force_focus_wrapping', 'force_xinerama', 'force-xinerama', 'workspace_auto_back_and_forth', 'fake_outputs', 'fake-outputs', 'force_display_urgency_hint', 'focus_on_window_activation', 'show_marks', 'workspace', 'ipc_socket', 'ipc-socket', 'restart_state', 'popup_during_fullscreen', 'exec_always', 'exec', 'client.background', 'client.focused_inactive', 'client.focused', 'client.unfocused', 'client.urgent', 'client.placeholder' -EOT +my $expected_all_tokens = "ERROR: CONFIG: Expected one of these tokens: , '#', '" . join("', '", qw( + set + set_from_resource + bindsym + bindcode + bind + bar + font + mode + floating_minimum_size + floating_maximum_size + floating_modifier + default_orientation + workspace_layout + new_window + new_float + hide_edge_borders + for_window + assign + no_focus + focus_follows_mouse + mouse_warping + force_focus_wrapping + force_xinerama + force-xinerama + workspace_auto_back_and_forth + fake_outputs + fake-outputs + force_display_urgency_hint + focus_on_window_activation + show_marks + workspace + ipc_socket + ipc-socket + restart_state + popup_during_fullscreen + exec_always + exec + client.background + client.focused_inactive + client.focused + client.unfocused + client.urgent + client.placeholder + )) . "'\n"; my $expected_end = <<'EOT'; ERROR: CONFIG: (in file ) From 9409c2b2e5fafb67b9a853c7bbc802702c6ab7d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 11 May 2016 20:11:35 +0200 Subject: [PATCH 049/150] Don't trigger binding on window border click unless --border is given. (#2349) Prior to this commit a binding specifying only --whole-window would trigger even when clicking on the window border. However, this should only happen if --border is specified. fixes #2348 --- src/click.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/click.c b/src/click.c index a670120f..788c10f2 100644 --- a/src/click.c +++ b/src/click.c @@ -187,11 +187,10 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod * default behavior. */ if (dest == CLICK_DECORATION || dest == CLICK_INSIDE || dest == CLICK_BORDER) { Binding *bind = get_binding_from_xcb_event((xcb_generic_event_t *)event); - /* clicks over a window decoration will always trigger the binding and - * clicks on the inside of the window will only trigger a binding if - * the --whole-window flag was given for the binding. */ - if (bind && ((dest == CLICK_DECORATION || bind->whole_window) || - (dest == CLICK_BORDER && bind->border))) { + + if (bind != NULL && (dest == CLICK_DECORATION || + (dest == CLICK_INSIDE && bind->whole_window) || + (dest == CLICK_BORDER && bind->border))) { CommandResult *result = run_binding(bind, con); /* ASYNC_POINTER eats the event */ From 8dbdcde9a6fbc0cf04c4a2843af3b3e5f2ac3fc9 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 24 May 2016 20:07:01 +0200 Subject: [PATCH 050/150] travis: ubuntu: remove libxcb-xrm-dev from Build-Deps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s installed separately. This should fix the failing travis build. --- travis/travis-base-ubuntu-386.Dockerfile | 1 + travis/travis-base-ubuntu.Dockerfile | 1 + 2 files changed, 2 insertions(+) diff --git a/travis/travis-base-ubuntu-386.Dockerfile b/travis/travis-base-ubuntu-386.Dockerfile index ae6b7c82..4f11d02d 100644 --- a/travis/travis-base-ubuntu-386.Dockerfile +++ b/travis/travis-base-ubuntu-386.Dockerfile @@ -25,6 +25,7 @@ RUN linux32 apt-get update && \ # Install i3 build dependencies. COPY debian/control /usr/src/i3-debian-packaging/control RUN linux32 apt-get update && \ + sed -i '/^\s*libxcb-xrm-dev/d' /usr/src/i3-debian-packaging/control && \ DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ rm -rf /var/lib/apt/lists/* diff --git a/travis/travis-base-ubuntu.Dockerfile b/travis/travis-base-ubuntu.Dockerfile index 62b81283..2606f977 100644 --- a/travis/travis-base-ubuntu.Dockerfile +++ b/travis/travis-base-ubuntu.Dockerfile @@ -26,6 +26,7 @@ RUN apt-get update && \ # Install i3 build dependencies. COPY debian/control /usr/src/i3-debian-packaging/control RUN apt-get update && \ + sed -i '/^\s*libxcb-xrm-dev/d' /usr/src/i3-debian-packaging/control && \ DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ rm -rf /var/lib/apt/lists/* From a24a048cc92fa31ee20638772b8333f8a8535625 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 24 May 2016 20:21:08 +0200 Subject: [PATCH 051/150] travis: ubuntu: install ca-certificates to make git clone work --- travis/travis-base-ubuntu-386.Dockerfile | 1 + travis/travis-base-ubuntu.Dockerfile | 1 + 2 files changed, 2 insertions(+) diff --git a/travis/travis-base-ubuntu-386.Dockerfile b/travis/travis-base-ubuntu-386.Dockerfile index 4f11d02d..f6a502d6 100644 --- a/travis/travis-base-ubuntu-386.Dockerfile +++ b/travis/travis-base-ubuntu-386.Dockerfile @@ -26,6 +26,7 @@ RUN linux32 apt-get update && \ COPY debian/control /usr/src/i3-debian-packaging/control RUN linux32 apt-get update && \ sed -i '/^\s*libxcb-xrm-dev/d' /usr/src/i3-debian-packaging/control && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ca-certificates && \ DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ rm -rf /var/lib/apt/lists/* diff --git a/travis/travis-base-ubuntu.Dockerfile b/travis/travis-base-ubuntu.Dockerfile index 2606f977..0ea680a9 100644 --- a/travis/travis-base-ubuntu.Dockerfile +++ b/travis/travis-base-ubuntu.Dockerfile @@ -27,6 +27,7 @@ RUN apt-get update && \ COPY debian/control /usr/src/i3-debian-packaging/control RUN apt-get update && \ sed -i '/^\s*libxcb-xrm-dev/d' /usr/src/i3-debian-packaging/control && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ca-certificates && \ DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ rm -rf /var/lib/apt/lists/* From d08b0c428b57a8d76c2f863b1a5b25099ea5a62d Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 24 May 2016 22:04:26 +0200 Subject: [PATCH 052/150] travis: ubuntu: install autoconf (for autoreconf) --- travis/travis-base-ubuntu-386.Dockerfile | 3 +-- travis/travis-base-ubuntu.Dockerfile | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/travis/travis-base-ubuntu-386.Dockerfile b/travis/travis-base-ubuntu-386.Dockerfile index f6a502d6..c708e70e 100644 --- a/travis/travis-base-ubuntu-386.Dockerfile +++ b/travis/travis-base-ubuntu-386.Dockerfile @@ -26,14 +26,13 @@ RUN linux32 apt-get update && \ COPY debian/control /usr/src/i3-debian-packaging/control RUN linux32 apt-get update && \ sed -i '/^\s*libxcb-xrm-dev/d' /usr/src/i3-debian-packaging/control && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ca-certificates && \ DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ rm -rf /var/lib/apt/lists/* # Install xcb-util-xrm. This is a workaround until it is available in the # distribution packages. RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xutils-dev + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xutils-dev ca-certificates autoconf RUN git clone --recursive https://github.com/Airblader/xcb-util-xrm.git && \ cd xcb-util-xrm && \ ./autogen.sh --prefix=/usr && \ diff --git a/travis/travis-base-ubuntu.Dockerfile b/travis/travis-base-ubuntu.Dockerfile index 0ea680a9..34847bd4 100644 --- a/travis/travis-base-ubuntu.Dockerfile +++ b/travis/travis-base-ubuntu.Dockerfile @@ -27,14 +27,13 @@ RUN apt-get update && \ COPY debian/control /usr/src/i3-debian-packaging/control RUN apt-get update && \ sed -i '/^\s*libxcb-xrm-dev/d' /usr/src/i3-debian-packaging/control && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ca-certificates && \ DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ rm -rf /var/lib/apt/lists/* # Install xcb-util-xrm. This is a workaround until it is available in the # distribution packages. RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xutils-dev + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xutils-dev ca-certificates autoconf RUN git clone --recursive https://github.com/Airblader/xcb-util-xrm.git && \ cd xcb-util-xrm && \ ./autogen.sh --prefix=/usr && \ From 57dc46b4ec7ee033bbb1554a2a6100e01c35d551 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 24 May 2016 22:39:18 +0200 Subject: [PATCH 053/150] travis: ubuntu: also install autotools-dev and automake --- travis/travis-base-ubuntu-386.Dockerfile | 2 +- travis/travis-base-ubuntu.Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/travis/travis-base-ubuntu-386.Dockerfile b/travis/travis-base-ubuntu-386.Dockerfile index c708e70e..487465be 100644 --- a/travis/travis-base-ubuntu-386.Dockerfile +++ b/travis/travis-base-ubuntu-386.Dockerfile @@ -32,7 +32,7 @@ RUN linux32 apt-get update && \ # Install xcb-util-xrm. This is a workaround until it is available in the # distribution packages. RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xutils-dev ca-certificates autoconf + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xutils-dev ca-certificates autoconf automake autotools-dev RUN git clone --recursive https://github.com/Airblader/xcb-util-xrm.git && \ cd xcb-util-xrm && \ ./autogen.sh --prefix=/usr && \ diff --git a/travis/travis-base-ubuntu.Dockerfile b/travis/travis-base-ubuntu.Dockerfile index 34847bd4..a3dab4ba 100644 --- a/travis/travis-base-ubuntu.Dockerfile +++ b/travis/travis-base-ubuntu.Dockerfile @@ -33,7 +33,7 @@ RUN apt-get update && \ # Install xcb-util-xrm. This is a workaround until it is available in the # distribution packages. RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xutils-dev ca-certificates autoconf + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xutils-dev ca-certificates autoconf automake autotools-dev RUN git clone --recursive https://github.com/Airblader/xcb-util-xrm.git && \ cd xcb-util-xrm && \ ./autogen.sh --prefix=/usr && \ From 8e125e98458015724d25081747e5da78a199d2f4 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 25 May 2016 07:49:14 +0200 Subject: [PATCH 054/150] travis: ubuntu: install libtool --- travis/travis-base-ubuntu-386.Dockerfile | 2 +- travis/travis-base-ubuntu.Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/travis/travis-base-ubuntu-386.Dockerfile b/travis/travis-base-ubuntu-386.Dockerfile index 487465be..bc92a695 100644 --- a/travis/travis-base-ubuntu-386.Dockerfile +++ b/travis/travis-base-ubuntu-386.Dockerfile @@ -32,7 +32,7 @@ RUN linux32 apt-get update && \ # Install xcb-util-xrm. This is a workaround until it is available in the # distribution packages. RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xutils-dev ca-certificates autoconf automake autotools-dev + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xutils-dev ca-certificates autoconf automake autotools-dev libtool RUN git clone --recursive https://github.com/Airblader/xcb-util-xrm.git && \ cd xcb-util-xrm && \ ./autogen.sh --prefix=/usr && \ diff --git a/travis/travis-base-ubuntu.Dockerfile b/travis/travis-base-ubuntu.Dockerfile index a3dab4ba..5b0f731a 100644 --- a/travis/travis-base-ubuntu.Dockerfile +++ b/travis/travis-base-ubuntu.Dockerfile @@ -33,7 +33,7 @@ RUN apt-get update && \ # Install xcb-util-xrm. This is a workaround until it is available in the # distribution packages. RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xutils-dev ca-certificates autoconf automake autotools-dev + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xutils-dev ca-certificates autoconf automake autotools-dev libtool RUN git clone --recursive https://github.com/Airblader/xcb-util-xrm.git && \ cd xcb-util-xrm && \ ./autogen.sh --prefix=/usr && \ From ef0a5b0534793c4027b93fb429192ed7db7d0f57 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 25 May 2016 08:23:45 +0200 Subject: [PATCH 055/150] travis: remove libxcb-xrm-dev from build-deps before dpkg-buildpackage --- travis/debian-build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/travis/debian-build.sh b/travis/debian-build.sh index dafa5d7d..655bd5c4 100755 --- a/travis/debian-build.sh +++ b/travis/debian-build.sh @@ -11,6 +11,7 @@ make dist mkdir -p "${DEST}" tar xf *.tar.bz2 -C "${DEST}" --strip-components=1 cp -r debian "${DEST}" +sed -i '/^\s*libxcb-xrm-dev/d' deb/ubuntu-*/DIST/debian/control || true cd "${DEST}" debchange -m -l+g$(git describe --tags) 'Automatically built' dpkg-buildpackage -b From 460e33a847db1911d3e46e5b9f9b6c77d0a1c9b4 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Thu, 26 May 2016 14:53:30 +0200 Subject: [PATCH 056/150] travis: ubuntu: install libxcb-xrm from our repository see #2363 --- travis/travis-base-ubuntu-386.Dockerfile | 17 ++++------------- travis/travis-base-ubuntu.Dockerfile | 17 ++++------------- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/travis/travis-base-ubuntu-386.Dockerfile b/travis/travis-base-ubuntu-386.Dockerfile index bc92a695..c20cc41d 100644 --- a/travis/travis-base-ubuntu-386.Dockerfile +++ b/travis/travis-base-ubuntu-386.Dockerfile @@ -24,18 +24,9 @@ RUN linux32 apt-get update && \ # Install i3 build dependencies. COPY debian/control /usr/src/i3-debian-packaging/control -RUN linux32 apt-get update && \ - sed -i '/^\s*libxcb-xrm-dev/d' /usr/src/i3-debian-packaging/control && \ +RUN echo 'deb http://dl.bintray.com/i3/i3-autobuild-ubuntu wily main' > /etc/apt/sources.list.d/i3-autobuild.list && \ + linux32 apt-get update && \ + linux32 apt-get --allow-unauthenticated install i3-autobuild-keyring && \ + linux32 apt-get update && \ DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ rm -rf /var/lib/apt/lists/* - -# Install xcb-util-xrm. This is a workaround until it is available in the -# distribution packages. -RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xutils-dev ca-certificates autoconf automake autotools-dev libtool -RUN git clone --recursive https://github.com/Airblader/xcb-util-xrm.git && \ - cd xcb-util-xrm && \ - ./autogen.sh --prefix=/usr && \ - make && \ - make install && \ - cd - diff --git a/travis/travis-base-ubuntu.Dockerfile b/travis/travis-base-ubuntu.Dockerfile index 5b0f731a..e060fe0f 100644 --- a/travis/travis-base-ubuntu.Dockerfile +++ b/travis/travis-base-ubuntu.Dockerfile @@ -25,18 +25,9 @@ RUN apt-get update && \ # Install i3 build dependencies. COPY debian/control /usr/src/i3-debian-packaging/control -RUN apt-get update && \ - sed -i '/^\s*libxcb-xrm-dev/d' /usr/src/i3-debian-packaging/control && \ +RUN echo 'deb http://dl.bintray.com/i3/i3-autobuild-ubuntu wily main' > /etc/apt/sources.list.d/i3-autobuild.list && \ + apt-get update && \ + apt-get --allow-unauthenticated install i3-autobuild-keyring && \ + apt-get update && \ DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ rm -rf /var/lib/apt/lists/* - -# Install xcb-util-xrm. This is a workaround until it is available in the -# distribution packages. -RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xutils-dev ca-certificates autoconf automake autotools-dev libtool -RUN git clone --recursive https://github.com/Airblader/xcb-util-xrm.git && \ - cd xcb-util-xrm && \ - ./autogen.sh --prefix=/usr && \ - make && \ - make install && \ - cd - From 54cacd58ffa3a52c5c006e57fb3d50b42a8fe80e Mon Sep 17 00:00:00 2001 From: Trevor Merrifield Date: Sat, 28 May 2016 10:44:20 -0400 Subject: [PATCH 057/150] Fix outdated documentation (#2362) --- docs/ipc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ipc b/docs/ipc index f6f6c928..033d5018 100644 --- a/docs/ipc +++ b/docs/ipc @@ -285,7 +285,7 @@ type (string):: Type of this container. Can be one of "root", "output", "con", "floating_con", "workspace" or "dockarea". border (string):: - Can be either "normal", "none" or "1pixel", depending on the + Can be either "normal", "none" or "pixel", depending on the container’s border style. current_border_width (integer):: Number of pixels of the border width. From 82dd59cb31f0e1a938ad222d1746b132d04d448b Mon Sep 17 00:00:00 2001 From: Zamarin Arthur Date: Tue, 31 May 2016 23:57:58 +0300 Subject: [PATCH 058/150] Added qterminal to i3-sensible-terminal (#2367) --- i3-sensible-terminal | 2 +- man/i3-sensible-terminal.man | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/i3-sensible-terminal b/i3-sensible-terminal index a1ada248..e57af8cb 100755 --- a/i3-sensible-terminal +++ b/i3-sensible-terminal @@ -8,7 +8,7 @@ # We welcome patches that add distribution-specific mechanisms to find the # preferred terminal emulator. On Debian, there is the x-terminal-emulator # symlink for example. -for terminal in "$TERMINAL" x-terminal-emulator urxvt rxvt termit terminator Eterm aterm xterm gnome-terminal roxterm xfce4-terminal termite lxterminal mate-terminal terminology st; do +for terminal in "$TERMINAL" x-terminal-emulator urxvt rxvt termit terminator Eterm aterm xterm gnome-terminal roxterm xfce4-terminal termite lxterminal mate-terminal terminology st qterminal; do if command -v "$terminal" > /dev/null 2>&1; then exec "$terminal" "$@" fi diff --git a/man/i3-sensible-terminal.man b/man/i3-sensible-terminal.man index b231f808..4e99f91e 100644 --- a/man/i3-sensible-terminal.man +++ b/man/i3-sensible-terminal.man @@ -38,6 +38,7 @@ It tries to start one of the following (in that order): * mate-terminal * terminology * st +* qterminal Please don’t complain about the order: If the user has any preference, they will have $TERMINAL set or modified their i3 configuration file. From 18d6a1bc767680f9ab0b0993b23b4cac6aabf926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Tue, 31 May 2016 22:58:23 +0200 Subject: [PATCH 059/150] Explicitly terminate fallback in set_from_resource. (#2366) --- src/config_parser.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/config_parser.c b/src/config_parser.c index 5b5e2363..2a884730 100644 --- a/src/config_parser.c +++ b/src/config_parser.c @@ -954,6 +954,14 @@ bool parse_file(const char *f, bool use_nagbar) { char v_key[512]; char fallback[4096]; + /* Ensure that this string is terminated. For example, a user might + * want a variable to be empty if the resource can't be found and + * uses + * set_from_resource $foo i3wm.foo + * Without explicitly terminating the string first, sscanf() will + * leave it uninitialized, causing garbage in the config.*/ + fallback[0] = '\0'; + if (sscanf(value, "%511s %511s %4095[^\n]", v_key, res_name, fallback) < 1) { ELOG("Failed to parse resource specification '%s', skipping it.\n", value); continue; From 7e2483edf783d1600ab60bb6d21071072d6a04d2 Mon Sep 17 00:00:00 2001 From: Christopher Zimmermann Date: Sat, 11 Jun 2016 12:58:16 +0200 Subject: [PATCH 060/150] Use 64 bit time_t --- src/startup.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/startup.c b/src/startup.c index b7950c20..2a6bc002 100644 --- a/src/startup.c +++ b/src/startup.c @@ -103,8 +103,8 @@ static int _prune_startup_sequences(void) { */ void startup_sequence_delete(struct Startup_Sequence *sequence) { assert(sequence != NULL); - DLOG("Deleting startup sequence %s, delete_at = %ld, current_time = %ld\n", - sequence->id, sequence->delete_at, time(NULL)); + DLOG("Deleting startup sequence %s, delete_at = %lld, current_time = %lld\n", + sequence->id, (long long)sequence->delete_at, (long long)time(NULL)); /* Unref the context, will be free()d */ sn_launcher_context_unref(sequence->context); @@ -239,8 +239,8 @@ void startup_monitor_event(SnMonitorEvent *event, void *userdata) { /* Mark the given sequence for deletion in 30 seconds. */ time_t current_time = time(NULL); sequence->delete_at = current_time + 30; - DLOG("Will delete startup sequence %s at timestamp %ld\n", - sequence->id, sequence->delete_at); + DLOG("Will delete startup sequence %s at timestamp %lld\n", + sequence->id, (long long)sequence->delete_at); if (_prune_startup_sequences() == 0) { DLOG("No more startup sequences running, changing root window cursor to default pointer.\n"); From fa12f67870476d73eaabf4d9a531c05537c83229 Mon Sep 17 00:00:00 2001 From: Christopher Zimmermann Date: Sat, 11 Jun 2016 14:47:17 +0200 Subject: [PATCH 061/150] Fix testsuite on OpenBSD OpenBSD perl forks for glob(). Therefore attach SIGCHLD handler as late as possible. --- testcases/lib/StartXServer.pm | 18 +++++++++--------- testcases/t/180-fd-leaks.t | 5 +++++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/testcases/lib/StartXServer.pm b/testcases/lib/StartXServer.pm index 86a37d92..d3042c07 100644 --- a/testcases/lib/StartXServer.pm +++ b/testcases/lib/StartXServer.pm @@ -69,15 +69,6 @@ sub start_xserver { my @displays = (); my @childpids = (); - $SIG{CHLD} = sub { - my $child = waitpid -1, POSIX::WNOHANG; - @pids = grep { $_ != $child } @pids; - return unless @pids == 0; - print STDERR "All X server processes died.\n"; - print STDERR "Use ./complete-run.pl --parallel 1 --keep-xserver-output\n"; - exit 1; - }; - # Yeah, I know it’s non-standard, but Perl’s POSIX module doesn’t have # _SC_NPROCESSORS_CONF. my $num_cores; @@ -101,6 +92,15 @@ sub start_xserver { say "Starting $parallel Xephyr instances, starting at :$displaynum..."; + $SIG{CHLD} = sub { + my $child = waitpid -1, POSIX::WNOHANG; + @pids = grep { $_ != $child } @pids; + return unless @pids == 0; + print STDERR "All X server processes died.\n"; + print STDERR "Use ./complete-run.pl --parallel 1 --keep-xserver-output\n"; + exit 1; + }; + my @sockets_waiting; for (1 .. $parallel) { my $socket = fork_xserver($keep_xserver_output, $displaynum, diff --git a/testcases/t/180-fd-leaks.t b/testcases/t/180-fd-leaks.t index 454bfe7d..16272d31 100644 --- a/testcases/t/180-fd-leaks.t +++ b/testcases/t/180-fd-leaks.t @@ -20,6 +20,9 @@ use i3test; use POSIX qw(mkfifo); use File::Temp qw(:POSIX tempfile); +SKIP: { +skip "Procfs not available on $^O", 1 if $^O eq 'openbsd'; + my $i3 = i3(get_socket_path()); my $tmp = tmpnam(); @@ -59,4 +62,6 @@ for my $fd (keys %fds) { is(scalar keys %fds, 0, 'No file descriptors leaked'); +} + done_testing; From 87e90229bc90ef700f9c7b123fca65d89fe7b0dc Mon Sep 17 00:00:00 2001 From: Christopher Zimmermann Date: Sat, 11 Jun 2016 14:40:40 +0200 Subject: [PATCH 062/150] Always use socket activation it neither depends on systemd nor on any linuxism. --- src/sd-daemon.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/sd-daemon.c b/src/sd-daemon.c index f0b5ca05..dc33b2e9 100644 --- a/src/sd-daemon.c +++ b/src/sd-daemon.c @@ -45,9 +45,6 @@ #include "sd-daemon.h" int sd_listen_fds(int unset_environment) { -#if defined(DISABLE_SYSTEMD) || !defined(__linux__) - return 0; -#else int r, fd; const char *e; char *p = NULL; @@ -121,7 +118,6 @@ finish: } return r; -#endif } int sd_is_fifo(int fd, const char *path) { From 1322af1e4f94a3771905a72fe417c807bf84c2c6 Mon Sep 17 00:00:00 2001 From: Christopher Zimmermann Date: Sat, 11 Jun 2016 13:05:29 +0200 Subject: [PATCH 063/150] Don't use pthread on OpenBSD since OpenBSD pthread does not support pthread_condattr_setpshared(). This patch could also stay in the OpenBSD ports tree or depend on a configure test macro rather than defined __OpenBSD__. --- i3-dump-log/main.c | 31 +++++++++++++++++++++++++------ include/shmlog.h | 4 ++++ src/i3.mk | 5 ++++- src/log.c | 6 ++++++ 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/i3-dump-log/main.c b/i3-dump-log/main.c index 9d4eefc7..d9b0613c 100644 --- a/i3-dump-log/main.c +++ b/i3-dump-log/main.c @@ -28,8 +28,10 @@ #include "shmlog.h" #include -static uint32_t offset_next_write, - wrap_count; +#if !defined(__OpenBSD__) +static uint32_t offset_next_write; +#endif +static uint32_t wrap_count; static i3_shmlog_header *header; static char *logbuffer, @@ -57,17 +59,26 @@ static void print_till_end(void) { int main(int argc, char *argv[]) { int o, option_index = 0; - bool verbose = false, - follow = false; + bool verbose = false; +#if !defined(__OpenBSD__) + bool follow = false; +#endif static struct option long_options[] = { {"version", no_argument, 0, 'v'}, {"verbose", no_argument, 0, 'V'}, +#if !defined(__OpenBSD__) {"follow", no_argument, 0, 'f'}, +#endif {"help", no_argument, 0, 'h'}, - {0, 0, 0, 0}}; + {0, 0, 0, 0} + }; +#if !defined(__OpenBSD__) char *options_string = "s:vfVh"; +#else + char *options_string = "vVh"; +#endif while ((o = getopt_long(argc, argv, options_string, long_options, &option_index)) != -1) { if (o == 'v') { @@ -75,11 +86,17 @@ int main(int argc, char *argv[]) { return 0; } else if (o == 'V') { verbose = true; +#if !defined(__OpenBSD__) } else if (o == 'f') { follow = true; +#endif } else if (o == 'h') { printf("i3-dump-log " I3_VERSION "\n"); - printf("i3-dump-log [-f] [-s ]\n"); +#if !defined(__OpenBSD__) + printf("i3-dump-log [-fhVv]\n"); +#else + printf("i3-dump-log [-hVv]\n"); +#endif return 0; } } @@ -162,6 +179,7 @@ int main(int argc, char *argv[]) { walk = logbuffer + sizeof(i3_shmlog_header); print_till_end(); +#if !defined(__OpenBSD__) if (follow) { /* 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 @@ -177,6 +195,7 @@ int main(int argc, char *argv[]) { } } } +#endif return 0; } diff --git a/include/shmlog.h b/include/shmlog.h index 01fea8b4..0216c8d6 100644 --- a/include/shmlog.h +++ b/include/shmlog.h @@ -11,7 +11,9 @@ #pragma once #include +#if !defined(__OpenBSD__) #include +#endif /* Default shmlog size if not set by user. */ extern const int default_shmlog_size; @@ -37,8 +39,10 @@ typedef struct i3_shmlog_header { * and don’t matter — clients use an equality check (==). */ uint32_t wrap_count; +#if !defined(__OpenBSD__) /* pthread condvar which will be broadcasted whenever there is a new * message in the log. i3-dump-log uses this to implement -f (follow, like * tail -f) in an efficient way. */ pthread_cond_t condvar; +#endif } i3_shmlog_header; diff --git a/src/i3.mk b/src/i3.mk index 6cb4abf4..de747826 100644 --- a/src/i3.mk +++ b/src/i3.mk @@ -6,7 +6,10 @@ i3_SOURCES := $(filter-out $(i3_SOURCES_GENERATED),$(wildcard src/*.c) i3_HEADERS_CMDPARSER := $(wildcard include/GENERATED_*.h) i3_HEADERS := $(filter-out $(i3_HEADERS_CMDPARSER),$(wildcard include/*.h)) i3_CFLAGS = $(XKB_COMMON_CFLAGS) $(XKB_COMMON_X11_CFLAGS) $(XCB_CFLAGS) $(XCB_KBD_CFLAGS) $(XCB_WM_CFLAGS) $(XCB_CURSOR_CFLAGS) $(XCB_XRM_CFLAGS) $(PANGO_CFLAGS) $(YAJL_CFLAGS) $(LIBEV_CFLAGS) $(PCRE_CFLAGS) $(LIBSN_CFLAGS) -i3_LIBS = $(XKB_COMMON_LIBS) $(XKB_COMMON_X11_LIBS) $(XCB_LIBS) $(XCB_XKB_LIBS) $(XCB_KBD_LIBS) $(XCB_WM_LIBS) $(XCB_CURSOR_LIBS) $(XCB_XRM_LIBS) $(PANGO_LIBS) $(YAJL_LIBS) $(LIBEV_LIBS) $(PCRE_LIBS) $(LIBSN_LIBS) -lm -lpthread +i3_LIBS = $(XKB_COMMON_LIBS) $(XKB_COMMON_X11_LIBS) $(XCB_LIBS) $(XCB_XKB_LIBS) $(XCB_KBD_LIBS) $(XCB_WM_LIBS) $(XCB_CURSOR_LIBS) $(XCB_XRM_LIBS) $(PANGO_LIBS) $(YAJL_LIBS) $(LIBEV_LIBS) $(PCRE_LIBS) $(LIBSN_LIBS) -lm +ifneq ($(UNAME),OpenBSD) +i3_LIBS += -lpthread +endif # When using clang, we use pre-compiled headers to speed up the build. With # gcc, this actually makes the build slower. diff --git a/src/log.c b/src/log.c index e8a08b53..e9a1160d 100644 --- a/src/log.c +++ b/src/log.c @@ -20,7 +20,9 @@ #include #include #include +#if !defined(__OpenBSD__) #include +#endif #include "util.h" #include "log.h" @@ -157,11 +159,13 @@ void open_logbuffer(void) { header = (i3_shmlog_header *)logbuffer; +#if !defined(__OpenBSD__) pthread_condattr_t cond_attr; pthread_condattr_init(&cond_attr); if (pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED) != 0) fprintf(stderr, "pthread_condattr_setpshared() failed, i3-dump-log -f will not work!\n"); pthread_cond_init(&(header->condvar), &cond_attr); +#endif logwalk = logbuffer + sizeof(i3_shmlog_header); loglastwrap = logbuffer + logbuffer_size; @@ -277,8 +281,10 @@ static void vlog(const bool print, const char *fmt, va_list args) { store_log_markers(); +#if !defined(__OpenBSD__) /* Wake up all (i3-dump-log) processes waiting for condvar. */ pthread_cond_broadcast(&(header->condvar)); +#endif if (print) fwrite(message, len, 1, stdout); From b1d70f25b3f22027959d60e24f57b8f965fdd757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 15 Jun 2016 22:25:22 +0200 Subject: [PATCH 064/150] Introduced a new GET_BINDING_MODES message type and reply. (#2376) This type dumps all currently configured binding modes. fixes #2375 --- docs/ipc | 13 +++++++++++++ i3-msg/main.c | 4 +++- include/i3/ipc.h | 20 ++++---------------- man/i3-msg.man | 3 +++ src/ipc.c | 25 ++++++++++++++++++++++++- 5 files changed, 47 insertions(+), 18 deletions(-) diff --git a/docs/ipc b/docs/ipc index 033d5018..ddadabc4 100644 --- a/docs/ipc +++ b/docs/ipc @@ -80,6 +80,8 @@ GET_BAR_CONFIG (6):: GET_VERSION (7):: Gets the version of i3. The reply will be a JSON-encoded dictionary with the major, minor, patch and human-readable version. +GET_BINDING_MODES (8):: + Gets a list of currently configured binding modes. So, a typical message could look like this: -------------------------------------------------- @@ -137,6 +139,8 @@ BAR_CONFIG (6):: Reply to the GET_BAR_CONFIG message. VERSION (7):: Reply to the GET_VERSION message. +BINDING_MODES (8):: + Reply to the GET_BINDING_MODES message. === COMMAND reply @@ -604,6 +608,15 @@ loaded_config_file_name (string):: } ------------------- +=== BINDING_MODES reply + +The reply consists of an array of all currently configured binding modes. + +*Example:* +--------------------- +["default", "resize"] +--------------------- + == Events [[events]] diff --git a/i3-msg/main.c b/i3-msg/main.c index 36691cae..658c33b4 100644 --- a/i3-msg/main.c +++ b/i3-msg/main.c @@ -161,11 +161,13 @@ int main(int argc, char *argv[]) { message_type = I3_IPC_MESSAGE_TYPE_GET_MARKS; else if (strcasecmp(optarg, "get_bar_config") == 0) 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_version") == 0) message_type = I3_IPC_MESSAGE_TYPE_GET_VERSION; else { printf("Unknown message type\n"); - printf("Known types: command, get_workspaces, get_outputs, get_tree, get_marks, get_bar_config, get_version\n"); + printf("Known types: command, get_workspaces, get_outputs, get_tree, get_marks, get_bar_config, get_binding_modes, get_version\n"); exit(EXIT_FAILURE); } } else if (o == 'q') { diff --git a/include/i3/ipc.h b/include/i3/ipc.h index 8912bf13..98ac35b0 100644 --- a/include/i3/ipc.h +++ b/include/i3/ipc.h @@ -51,34 +51,22 @@ typedef struct i3_ipc_header { /** Request the i3 version */ #define I3_IPC_MESSAGE_TYPE_GET_VERSION 7 +/** Request a list of configured binding modes. */ +#define I3_IPC_MESSAGE_TYPE_GET_BINDING_MODES 8 + /* * Messages from i3 to clients * */ - -/** Command reply type */ #define I3_IPC_REPLY_TYPE_COMMAND 0 - -/** Workspaces reply type */ #define I3_IPC_REPLY_TYPE_WORKSPACES 1 - -/** Subscription reply type */ #define I3_IPC_REPLY_TYPE_SUBSCRIBE 2 - -/** Outputs reply type */ #define I3_IPC_REPLY_TYPE_OUTPUTS 3 - -/** Tree reply type */ #define I3_IPC_REPLY_TYPE_TREE 4 - -/** Marks reply type */ #define I3_IPC_REPLY_TYPE_MARKS 5 - -/** Bar config reply type */ #define I3_IPC_REPLY_TYPE_BAR_CONFIG 6 - -/** i3 version reply type */ #define I3_IPC_REPLY_TYPE_VERSION 7 +#define I3_IPC_REPLY_TYPE_BINDING_MODES 8 /* * Events from i3 to clients. Events have the first bit set high. diff --git a/man/i3-msg.man b/man/i3-msg.man index 000d9bf2..e81a94ab 100644 --- a/man/i3-msg.man +++ b/man/i3-msg.man @@ -62,6 +62,9 @@ get_bar_config:: Gets the configuration (as JSON map) of the workspace bar with the given ID. If no ID is provided, an array with all configured bar IDs is returned instead. +get_binding_modes:: +Gets a list of configured binding modes. + get_version:: Gets the version of i3. The reply will be a JSON-encoded dictionary with the major, minor, patch and human-readable version. diff --git a/src/ipc.c b/src/ipc.c index 2bd5f59d..a6c45ed1 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -958,6 +958,28 @@ IPC_HANDLER(get_bar_config) { y(free); } +/* + * Returns a list of configured binding modes + * + */ +IPC_HANDLER(get_binding_modes) { + yajl_gen gen = ygenalloc(); + + y(array_open); + struct Mode *mode; + SLIST_FOREACH(mode, &modes, modes) { + ystr(mode->name); + } + y(array_close); + + const unsigned char *payload; + ylength length; + y(get_buf, &payload, &length); + + ipc_send_message(fd, length, I3_IPC_REPLY_TYPE_BINDING_MODES, payload); + y(free); +} + /* * Callback for the YAJL parser (will be called when a string is parsed). * @@ -1034,7 +1056,7 @@ IPC_HANDLER(subscribe) { /* The index of each callback function corresponds to the numeric * value of the message type (see include/i3/ipc.h) */ -handler_t handlers[8] = { +handler_t handlers[9] = { handle_command, handle_get_workspaces, handle_subscribe, @@ -1043,6 +1065,7 @@ handler_t handlers[8] = { handle_get_marks, handle_get_bar_config, handle_get_version, + handle_get_binding_modes, }; /* From 45012189bcb67ba7652d2ea25a3e03cd74a796e7 Mon Sep 17 00:00:00 2001 From: yshui Date: Wed, 22 Jun 2016 02:39:25 -0400 Subject: [PATCH 065/150] Handle _MOTIF_WM_HINTS changes (#2384) --- src/handlers.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/handlers.c b/src/handlers.c index 2d18cbbd..991761fc 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -1171,6 +1171,38 @@ static bool handle_class_change(void *data, xcb_connection_t *conn, uint8_t stat return true; } +/* + * 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; + } + + border_style_t motif_border_style; + window_update_motif_hints(con->window, prop, &motif_border_style); + + if (motif_border_style != con->border_style) { + DLOG("Update border style of con %p to %d\n", con, motif_border_style); + con_set_border_style(con, motif_border_style, con->current_border_width); + + x_push_changes(croot); + } + + return true; +} + /* * Handles the _NET_WM_STRUT_PARTIAL property for allocating space for dock clients. * @@ -1272,7 +1304,8 @@ static struct property_handler_t property_handlers[] = { {0, 128, handle_windowrole_change}, {0, 128, handle_class_change}, {0, UINT_MAX, handle_strut_partial_change}, - {0, UINT_MAX, handle_window_type}}; + {0, UINT_MAX, handle_window_type}, + {0, 5 * sizeof(uint64_t), handle_motif_hints_change}}; #define NUM_HANDLERS (sizeof(property_handlers) / sizeof(struct property_handler_t)) /* @@ -1293,6 +1326,7 @@ 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; } static void property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom) { From 3ffa88e54a8b610a78d4036922d2b71302cb37d3 Mon Sep 17 00:00:00 2001 From: yshui Date: Sat, 25 Jun 2016 15:35:36 -0400 Subject: [PATCH 066/150] Don't change border style if BS_NORMAL is requested in motif hints (#2386) Fixes #2385 --- src/handlers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/handlers.c b/src/handlers.c index 991761fc..68fba0c4 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -1193,7 +1193,7 @@ static bool handle_motif_hints_change(void *data, xcb_connection_t *conn, uint8_ border_style_t motif_border_style; window_update_motif_hints(con->window, prop, &motif_border_style); - if (motif_border_style != con->border_style) { + if (motif_border_style != con->border_style && motif_border_style != BS_NORMAL) { DLOG("Update border style of con %p to %d\n", con, motif_border_style); con_set_border_style(con, motif_border_style, con->current_border_width); From bccd702e857067e4942f7eb23682744e484e3a14 Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Tue, 19 Jul 2016 14:28:42 -0400 Subject: [PATCH 067/150] Add uxterm to terminal list (#2397) --- i3-sensible-terminal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i3-sensible-terminal b/i3-sensible-terminal index e57af8cb..4ef1c75f 100755 --- a/i3-sensible-terminal +++ b/i3-sensible-terminal @@ -8,7 +8,7 @@ # We welcome patches that add distribution-specific mechanisms to find the # preferred terminal emulator. On Debian, there is the x-terminal-emulator # symlink for example. -for terminal in "$TERMINAL" x-terminal-emulator urxvt rxvt termit terminator Eterm aterm xterm gnome-terminal roxterm xfce4-terminal termite lxterminal mate-terminal terminology st qterminal; do +for terminal in "$TERMINAL" x-terminal-emulator urxvt rxvt termit terminator Eterm aterm uxterm xterm gnome-terminal roxterm xfce4-terminal termite lxterminal mate-terminal terminology st qterminal; do if command -v "$terminal" > /dev/null 2>&1; then exec "$terminal" "$@" fi From 85bb32409f974bbc85ed82900c4c4cc9a70f7424 Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Sat, 30 Jul 2016 13:30:25 -0400 Subject: [PATCH 068/150] Update manpages (#2404) --- man/i3-sensible-editor.man | 1 + man/i3-sensible-terminal.man | 1 + 2 files changed, 2 insertions(+) diff --git a/man/i3-sensible-editor.man b/man/i3-sensible-editor.man index 19b0f3a5..bfc5c5c6 100644 --- a/man/i3-sensible-editor.man +++ b/man/i3-sensible-editor.man @@ -20,6 +20,7 @@ It tries to start one of the following (in that order): * $VISUAL * $EDITOR * nano +* nvim * vim * vi * emacs diff --git a/man/i3-sensible-terminal.man b/man/i3-sensible-terminal.man index 4e99f91e..b830cd09 100644 --- a/man/i3-sensible-terminal.man +++ b/man/i3-sensible-terminal.man @@ -29,6 +29,7 @@ It tries to start one of the following (in that order): * terminator * Eterm * aterm +* uxterm * xterm * gnome-terminal * roxterm From afb90a0f9706d2800b0a3f8646f35b9e4d90b38b Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 2 Aug 2016 19:31:23 +0200 Subject: [PATCH 069/150] remove superfluous check for input_type This condition is already enforced in grab_all_keys(). --- src/bindings.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/bindings.c b/src/bindings.c index 759cfff9..ed6ce608 100644 --- a/src/bindings.c +++ b/src/bindings.c @@ -99,9 +99,6 @@ Binding *configure_binding(const char *bindtype, const char *modifiers, const ch } static void grab_keycode_for_binding(xcb_connection_t *conn, Binding *bind, uint32_t keycode) { - if (bind->input_type != B_KEYBOARD) - return; - /* Grab the key in all combinations */ #define GRAB_KEY(modifier) \ do { \ From 0239c4b6dab32c8760ff700a56fe9851f726928a Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 2 Aug 2016 19:33:26 +0200 Subject: [PATCH 070/150] move xkb_current_group check into own function This is a no-op refactoring. --- src/bindings.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/bindings.c b/src/bindings.c index ed6ce608..ee65a3c2 100644 --- a/src/bindings.c +++ b/src/bindings.c @@ -98,22 +98,32 @@ Binding *configure_binding(const char *bindtype, const char *modifiers, const ch return new_binding; } +static bool binding_in_current_group(const Binding *bind) { + /* If no bits are set, the binding should be installed in every group. */ + if ((bind->event_state_mask >> 16) == I3_XKB_GROUP_MASK_ANY) + return true; + switch (xkb_current_group) { + case XCB_XKB_GROUP_1: + return ((bind->event_state_mask >> 16) & I3_XKB_GROUP_MASK_1); + case XCB_XKB_GROUP_2: + return ((bind->event_state_mask >> 16) & I3_XKB_GROUP_MASK_2); + case XCB_XKB_GROUP_3: + return ((bind->event_state_mask >> 16) & I3_XKB_GROUP_MASK_3); + case XCB_XKB_GROUP_4: + return ((bind->event_state_mask >> 16) & I3_XKB_GROUP_MASK_4); + default: + ELOG("BUG: xkb_current_group (= %d) outside of [XCB_XKB_GROUP_1..XCB_XKB_GROUP_4]\n", xkb_current_group); + return false; + } +} + static void grab_keycode_for_binding(xcb_connection_t *conn, Binding *bind, uint32_t keycode) { /* Grab the key in all combinations */ #define GRAB_KEY(modifier) \ do { \ xcb_grab_key(conn, 0, root, modifier, keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC); \ } while (0) - int mods = bind->event_state_mask; - if (((mods >> 16) & I3_XKB_GROUP_MASK_1) && xkb_current_group != XCB_XKB_GROUP_1) - return; - if (((mods >> 16) & I3_XKB_GROUP_MASK_2) && xkb_current_group != XCB_XKB_GROUP_2) - return; - if (((mods >> 16) & I3_XKB_GROUP_MASK_3) && xkb_current_group != XCB_XKB_GROUP_3) - return; - if (((mods >> 16) & I3_XKB_GROUP_MASK_4) && xkb_current_group != XCB_XKB_GROUP_4) - return; - mods &= 0xFFFF; + const int mods = (bind->event_state_mask & 0xFFFF); DLOG("Grabbing keycode %d with event state mask 0x%x (mods 0x%x)\n", keycode, bind->event_state_mask, mods); GRAB_KEY(mods); @@ -132,6 +142,9 @@ void grab_all_keys(xcb_connection_t *conn) { if (bind->input_type != B_KEYBOARD) continue; + if (!binding_in_current_group(bind)) + continue; + /* The easy case: the user specified a keycode directly. */ if (bind->keycode > 0) { grab_keycode_for_binding(conn, bind, bind->keycode); From 3bd5e6e5c81b448f9f0ac84454671a871fbfea66 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 2 Aug 2016 20:10:26 +0200 Subject: [PATCH 071/150] refactoring: store modifiers alongside translated keycodes This is a no-op refactoring in terms of functionality. related to #2346 --- include/data.h | 23 ++++++++----- src/bindings.c | 89 ++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 83 insertions(+), 29 deletions(-) diff --git a/include/data.h b/include/data.h index 88ed6879..9f835a23 100644 --- a/include/data.h +++ b/include/data.h @@ -243,6 +243,17 @@ struct regex { pcre_extra *extra; }; +/** + * Stores a resolved keycode (from a keysym), including the modifier mask. Will + * be passed to xcb_grab_key(). + * + */ +struct Binding_Keycode { + xcb_keycode_t keycode; + i3_event_state_mask_t modifiers; + TAILQ_ENTRY(Binding_Keycode) keycodes; +}; + /****************************************************************************** * Major types *****************************************************************************/ @@ -281,8 +292,6 @@ struct Binding { * title bar (default). */ bool whole_window; - uint32_t number_keycodes; - /** Keycode to bind */ uint32_t keycode; @@ -296,12 +305,10 @@ struct Binding { * if the keyboard mapping changes (using Xmodmap for example) */ char *symbol; - /** Only in use if symbol != NULL. Gets set to the value to which the - * symbol got translated when binding. Useful for unbinding and - * checking which binding was used when a key press event comes in. - * - * This is an array of number_keycodes size. */ - xcb_keycode_t *translated_to; + /** 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; /** Command, like in command mode */ char *command; diff --git a/src/bindings.c b/src/bindings.c index ee65a3c2..22870d3c 100644 --- a/src/bindings.c +++ b/src/bindings.c @@ -95,6 +95,8 @@ Binding *configure_binding(const char *bindtype, const char *modifiers, const ch struct Mode *mode = mode_from_name(modename, pango_markup); TAILQ_INSERT_TAIL(mode->bindings, new_binding, bindings); + TAILQ_INIT(&(new_binding->keycodes_head)); + return new_binding; } @@ -127,8 +129,11 @@ static void grab_keycode_for_binding(xcb_connection_t *conn, Binding *bind, uint DLOG("Grabbing keycode %d with event state mask 0x%x (mods 0x%x)\n", keycode, bind->event_state_mask, mods); GRAB_KEY(mods); + /* Also bind the key with active NumLock */ GRAB_KEY(mods | xcb_numlock_mask); + /* Also bind the key with active CapsLock */ GRAB_KEY(mods | XCB_MOD_MASK_LOCK); + /* Also bind the key with active NumLock+CapsLock */ GRAB_KEY(mods | xcb_numlock_mask | XCB_MOD_MASK_LOCK); } @@ -151,8 +156,13 @@ void grab_all_keys(xcb_connection_t *conn) { continue; } - for (uint32_t i = 0; i < bind->number_keycodes; i++) - grab_keycode_for_binding(conn, bind, bind->translated_to[i]); + struct Binding_Keycode *binding_keycode; + TAILQ_FOREACH(binding_keycode, &(bind->keycodes_head), keycodes) { + const int keycode = binding_keycode->keycode; + const int mods = (binding_keycode->modifiers & 0xFFFF); + DLOG("Grabbing keycode %d with mods %d\n", keycode, mods); + xcb_grab_key(conn, 0, root, mods, keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC); + } } } @@ -234,9 +244,15 @@ static Binding *get_binding(i3_event_state_mask_t state_filtered, bool is_releas * keycode */ if (input_type == B_KEYBOARD && bind->symbol != NULL) { xcb_keycode_t input_keycode = (xcb_keycode_t)input_code; - if (memmem(bind->translated_to, - bind->number_keycodes * sizeof(xcb_keycode_t), - &input_keycode, sizeof(xcb_keycode_t)) == NULL) + bool found_keycode = false; + struct Binding_Keycode *binding_keycode; + TAILQ_FOREACH(binding_keycode, &(bind->keycodes_head), keycodes) { + if (binding_keycode->keycode == input_keycode) { + found_keycode = true; + break; + } + } + if (!found_keycode) continue; } else { /* This case is easier: The user specified a keycode */ @@ -346,11 +362,27 @@ static void add_keycode_if_matches(struct xkb_keymap *keymap, xkb_keycode_t key, return; } Binding *bind = resolving->bind; - bind->number_keycodes++; - bind->translated_to = srealloc(bind->translated_to, - (sizeof(xcb_keycode_t) * - bind->number_keycodes)); - bind->translated_to[bind->number_keycodes - 1] = key; + +#define ADD_TRANSLATED_KEY(mods) \ + do { \ + struct Binding_Keycode *binding_keycode = smalloc(sizeof(struct Binding_Keycode)); \ + binding_keycode->modifiers = (mods); \ + binding_keycode->keycode = key; \ + TAILQ_INSERT_TAIL(&(bind->keycodes_head), binding_keycode, keycodes); \ + } while (0) + + ADD_TRANSLATED_KEY(bind->event_state_mask); + + /* Also bind the key with active NumLock */ + ADD_TRANSLATED_KEY(bind->event_state_mask | xcb_numlock_mask); + + /* Also bind the key with active CapsLock */ + ADD_TRANSLATED_KEY(bind->event_state_mask | XCB_MOD_MASK_LOCK); + + /* Also bind the key with active NumLock+CapsLock */ + ADD_TRANSLATED_KEY(bind->event_state_mask | xcb_numlock_mask | XCB_MOD_MASK_LOCK); + +#undef ADD_TRANSLATED_KEY } /* @@ -432,15 +464,21 @@ void translate_keysyms(void) { .xkb_state = dummy_state, .xkb_state_no_shift = dummy_state_no_shift, }; - FREE(bind->translated_to); - bind->number_keycodes = 0; + while (!TAILQ_EMPTY(&(bind->keycodes_head))) { + struct Binding_Keycode *first = TAILQ_FIRST(&(bind->keycodes_head)); + TAILQ_REMOVE(&(bind->keycodes_head), first, keycodes); + FREE(first); + } xkb_keymap_key_for_each(xkb_keymap, add_keycode_if_matches, &resolving); char *keycodes = sstrdup(""); - for (uint32_t n = 0; n < bind->number_keycodes; n++) { + int num_keycodes = 0; + struct Binding_Keycode *binding_keycode; + TAILQ_FOREACH(binding_keycode, &(bind->keycodes_head), keycodes) { char *tmp; - sasprintf(&tmp, "%s %d", keycodes, bind->translated_to[n]); + sasprintf(&tmp, "%s %d", keycodes, binding_keycode->keycode); free(keycodes); keycodes = tmp; + num_keycodes++; /* check for duplicate bindings */ Binding *check; @@ -449,8 +487,8 @@ void translate_keysyms(void) { continue; if (check->symbol != NULL) continue; - if (check->keycode != bind->translated_to[n] || - check->event_state_mask != bind->event_state_mask || + if (check->keycode != binding_keycode->keycode || + check->event_state_mask != binding_keycode->modifiers || check->release != bind->release) continue; has_errors = true; @@ -458,7 +496,7 @@ void translate_keysyms(void) { } } DLOG("state=0x%x, cfg=\"%s\", sym=0x%x → keycodes%s (%d)\n", - bind->event_state_mask, bind->symbol, keysym, keycodes, bind->number_keycodes); + bind->event_state_mask, bind->symbol, keysym, keycodes, num_keycodes); free(keycodes); } @@ -626,10 +664,14 @@ static Binding *binding_copy(Binding *bind) { ret->symbol = sstrdup(bind->symbol); if (bind->command != NULL) ret->command = sstrdup(bind->command); - if (bind->translated_to != NULL) { - ret->translated_to = smalloc(sizeof(xcb_keycode_t) * bind->number_keycodes); - memcpy(ret->translated_to, bind->translated_to, sizeof(xcb_keycode_t) * bind->number_keycodes); + TAILQ_INIT(&(ret->keycodes_head)); + struct Binding_Keycode *binding_keycode; + 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); } + return ret; } @@ -641,8 +683,13 @@ void binding_free(Binding *bind) { return; } + while (!TAILQ_EMPTY(&(bind->keycodes_head))) { + struct Binding_Keycode *first = TAILQ_FIRST(&(bind->keycodes_head)); + TAILQ_REMOVE(&(bind->keycodes_head), first, keycodes); + FREE(first); + } + FREE(bind->symbol); - FREE(bind->translated_to); FREE(bind->command); FREE(bind); } From d77d40173aae250d2e5ba86a8bce7a6e857cbc67 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 2 Aug 2016 20:23:53 +0200 Subject: [PATCH 072/150] Only add NumLock fallback where necessary. Previously, we always discarded the NumLock bit when looking up key bindings for key press events, and we always grabbed every keycode with and without the NumLock modifier. With this commit, the NumLock bit is no longer discarded: since the previous commit 3bd5e6e5c81b448f9f0ac84454671a871fbfea66 we can correctly look up key bindings with/without the NumLock bit, as both variants are stored in |keycodes_head|. Further, before adding the NumLock fallback (resulting in grabbing the keycode with the NumLock modifier), we now check whether the key has the same meaning when NumLock is enabled. This correctly distinguishes the KP_End vs. KP_1 case, i.e. one can now use the following key bindings: # No longer accidentally triggered when pressing KP_1. bindsym KP_End nop KP_End # Properly distinguished now: bindsym KP_End nop KP_End bindsym Mod2+KP_1 nop KP_1 fixes #2346 --- src/bindings.c | 50 +++++++++-- testcases/t/264-keypress-numlock.t | 138 +++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 8 deletions(-) create mode 100644 testcases/t/264-keypress-numlock.t diff --git a/src/bindings.c b/src/bindings.c index 22870d3c..e0b70b6c 100644 --- a/src/bindings.c +++ b/src/bindings.c @@ -295,9 +295,9 @@ Binding *get_binding_from_xcb_event(xcb_generic_event_t *event) { const uint16_t event_state = ((xcb_key_press_event_t *)event)->state; const uint16_t event_detail = ((xcb_key_press_event_t *)event)->detail; - /* Remove the numlock bit */ - i3_event_state_mask_t state_filtered = event_state & ~(xcb_numlock_mask | XCB_MOD_MASK_LOCK); - DLOG("(removed numlock, state = 0x%x)\n", state_filtered); + /* Remove the CapsLock bit */ + i3_event_state_mask_t state_filtered = event_state & ~XCB_MOD_MASK_LOCK; + DLOG("(removed capslock, state = 0x%x)\n", state_filtered); /* Transform the keyboard_group from bit 13 and bit 14 into an * i3_xkb_group_mask_t, so that get_binding() can just bitwise AND the * configured bindings against |state_filtered|. @@ -338,6 +338,9 @@ struct resolve { /* Like |xkb_state|, just without the shift modifier, if shift was specified. */ struct xkb_state *xkb_state_no_shift; + + /* Like |xkb_state|, but with NumLock. */ + struct xkb_state *xkb_state_numlock; }; /* @@ -373,14 +376,28 @@ static void add_keycode_if_matches(struct xkb_keymap *keymap, xkb_keycode_t key, ADD_TRANSLATED_KEY(bind->event_state_mask); - /* Also bind the key with active NumLock */ - ADD_TRANSLATED_KEY(bind->event_state_mask | xcb_numlock_mask); - /* Also bind the key with active CapsLock */ ADD_TRANSLATED_KEY(bind->event_state_mask | XCB_MOD_MASK_LOCK); - /* Also bind the key with active NumLock+CapsLock */ - ADD_TRANSLATED_KEY(bind->event_state_mask | xcb_numlock_mask | XCB_MOD_MASK_LOCK); + /* If this binding is not explicitly for NumLock, check whether we need to + * add a fallback. */ + if ((bind->event_state_mask & xcb_numlock_mask) != xcb_numlock_mask) { + /* Check whether the keycode results in the same keysym when NumLock is + * active. If so, grab the key with NumLock as well, so that users don’t + * need to duplicate every key binding with an additional Mod2 specified. + */ + xkb_keysym_t sym_numlock = xkb_state_key_get_one_sym(resolving->xkb_state_numlock, key); + if (sym_numlock == resolving->keysym) { + /* Also bind the key with active NumLock */ + ADD_TRANSLATED_KEY(bind->event_state_mask | xcb_numlock_mask); + + /* Also bind the key with active NumLock+CapsLock */ + ADD_TRANSLATED_KEY(bind->event_state_mask | xcb_numlock_mask | XCB_MOD_MASK_LOCK); + } else { + DLOG("Skipping automatic numlock fallback, key %d resolves to 0x%x with unmlock\n", + key, sym_numlock); + } + } #undef ADD_TRANSLATED_KEY } @@ -402,6 +419,12 @@ void translate_keysyms(void) { return; } + struct xkb_state *dummy_state_numlock = xkb_state_new(xkb_keymap); + if (dummy_state_numlock == NULL) { + ELOG("Could not create XKB state, cannot translate keysyms.\n"); + return; + } + bool has_errors = false; Binding *bind; TAILQ_FOREACH(bind, bindings, bindings) { @@ -458,11 +481,21 @@ void translate_keysyms(void) { 0 /* xkb_layout_index_t latched_group, */, group /* xkb_layout_index_t locked_group, */); + (void)xkb_state_update_mask( + dummy_state_numlock, + (bind->event_state_mask & 0x1FFF) | xcb_numlock_mask /* xkb_mod_mask_t base_mods, */, + 0 /* xkb_mod_mask_t latched_mods, */, + 0 /* xkb_mod_mask_t locked_mods, */, + 0 /* xkb_layout_index_t base_group, */, + 0 /* xkb_layout_index_t latched_group, */, + group /* xkb_layout_index_t locked_group, */); + struct resolve resolving = { .bind = bind, .keysym = keysym, .xkb_state = dummy_state, .xkb_state_no_shift = dummy_state_no_shift, + .xkb_state_numlock = dummy_state_numlock, }; while (!TAILQ_EMPTY(&(bind->keycodes_head))) { struct Binding_Keycode *first = TAILQ_FIRST(&(bind->keycodes_head)); @@ -502,6 +535,7 @@ void translate_keysyms(void) { xkb_state_unref(dummy_state); xkb_state_unref(dummy_state_no_shift); + xkb_state_unref(dummy_state_numlock); if (has_errors) { start_config_error_nagbar(current_configpath, true); diff --git a/testcases/t/264-keypress-numlock.t b/testcases/t/264-keypress-numlock.t new file mode 100644 index 00000000..84db0e3c --- /dev/null +++ b/testcases/t/264-keypress-numlock.t @@ -0,0 +1,138 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Please read the following documents before working on tests: +# • http://build.i3wm.org/docs/testsuite.html +# (or docs/testsuite) +# +# • http://build.i3wm.org/docs/lib-i3test.html +# (alternatively: perldoc ./testcases/lib/i3test.pm) +# +# • http://build.i3wm.org/docs/ipc.html +# (or docs/ipc) +# +# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf +# (unless you are already familiar with Perl) +# +# Verifies that one can bind on numpad keys in different numlock states. +# Ticket: #2346 +# Bug still in: 4.12-78-g85bb324 +use i3test i3_autostart => 0; +use i3test::XTEST; +use ExtUtils::PkgConfig; + +SKIP: { + skip "libxcb-xkb too old (need >= 1.11)", 1 unless + ExtUtils::PkgConfig->atleast_version('xcb-xkb', '1.11'); + +my $config = < Date: Wed, 13 Apr 2016 15:53:15 +0000 Subject: [PATCH 073/150] Hex in struct Colorpixel.hex to contiguous memory No reason for hex not to be of a constant size, and no reason to introduce a cache miss by allocating it separated from the rest of the structure. --- libi3/get_colorpixel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi3/get_colorpixel.c b/libi3/get_colorpixel.c index a0a9e345..218f82e6 100644 --- a/libi3/get_colorpixel.c +++ b/libi3/get_colorpixel.c @@ -13,7 +13,7 @@ #include "libi3.h" struct Colorpixel { - char *hex; + char hex[8]; uint32_t pixel; SLIST_ENTRY(Colorpixel) @@ -74,7 +74,7 @@ uint32_t get_colorpixel(const char *hex) { /* Store the result in the cache */ struct Colorpixel *cache_pixel = scalloc(1, sizeof(struct Colorpixel)); - cache_pixel->hex = sstrdup(hex); + strncpy(cache_pixel->hex, hex, 8); cache_pixel->pixel = pixel; SLIST_INSERT_HEAD(&(colorpixels), cache_pixel, colorpixels); From 96704b2fc037f2b7906184d8580226a1e2611ae4 Mon Sep 17 00:00:00 2001 From: EvilPudding Date: Fri, 15 Apr 2016 13:24:03 +0000 Subject: [PATCH 074/150] Leaving the last byte in Colorpixel.hex NULL Added explicit assignment of last byte to the null character, for appearence's sake. --- libi3/get_colorpixel.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libi3/get_colorpixel.c b/libi3/get_colorpixel.c index 218f82e6..dc6d7748 100644 --- a/libi3/get_colorpixel.c +++ b/libi3/get_colorpixel.c @@ -74,7 +74,10 @@ uint32_t get_colorpixel(const char *hex) { /* Store the result in the cache */ struct Colorpixel *cache_pixel = scalloc(1, sizeof(struct Colorpixel)); - strncpy(cache_pixel->hex, hex, 8); + + strncpy(cache_pixel->hex, hex, 7); + cache_pixel->hex[7] = '\0'; + cache_pixel->pixel = pixel; SLIST_INSERT_HEAD(&(colorpixels), cache_pixel, colorpixels); From b668d62cfcd04a3a0ea1da5ad06a2e57187f6058 Mon Sep 17 00:00:00 2001 From: eplanet Date: Sat, 13 Aug 2016 22:46:27 +0200 Subject: [PATCH 075/150] Deleting VERSION and extracting it from I3_VERSION instead (#2419) --- Makefile | 2 -- VERSION | 1 - common.mk | 4 ++-- release.sh | 3 +-- 4 files changed, 3 insertions(+), 7 deletions(-) delete mode 100644 VERSION diff --git a/Makefile b/Makefile index d62db5d0..c08f2777 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,6 @@ install: $(INSTALL_TARGETS) store_git_version: echo -n ${I3_VERSION} > I3_VERSION - echo -n ${VERSION} > VERSION dist: distclean [ ! -d i3-${VERSION} ] || rm -rf i3-${VERSION} @@ -53,7 +52,6 @@ dist: distclean mkdir i3-${VERSION}/i3-input find i3-input -maxdepth 1 -type f \( -name "*.c" -or -name "*.mk" -or -name "*.h" -or -name "Makefile" \) -exec cp '{}' i3-${VERSION}/i3-input \; cp I3_VERSION i3-${VERSION}/I3_VERSION - cp VERSION i3-${VERSION}/VERSION # Pre-generate a manpage to allow distributors to skip this step and save some dependencies $(MAKE) mans cp man/*.1 i3-${VERSION}/man/ diff --git a/VERSION b/VERSION deleted file mode 100644 index f5885845..00000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -4.12 diff --git a/common.mk b/common.mk index 0215d35b..e99f93c8 100644 --- a/common.mk +++ b/common.mk @@ -21,8 +21,8 @@ endif # In dist and snapshot tarballs, use the I3_VERSION and VERSION files. Otherwise use git information. ifeq ($(wildcard .git),) # not in git repository - VERSION := '$(shell [ -f $(TOPDIR)/VERSION ] && cat $(TOPDIR)/VERSION)' - I3_VERSION := '$(shell [ -f $(TOPDIR)/I3_VERSION ] && cat $(TOPDIR)/I3_VERSION)' + VERSION := $(shell [ -f $(TOPDIR)/I3_VERSION ] && cat $(TOPDIR)/I3_VERSION | cut -d '-' -f 1) + I3_VERSION := $(shell [ -f $(TOPDIR)/I3_VERSION ] && cat $(TOPDIR)/I3_VERSION) else VERSION := $(shell git describe --tags --abbrev=0) I3_VERSION := '$(shell git describe --tags --always) ($(shell git log --pretty=format:%cd --date=short -n1), branch \"$(shell git describe --tags --always --all | sed s:heads/::)\")' diff --git a/release.sh b/release.sh index 61b3c444..cc59d6a2 100755 --- a/release.sh +++ b/release.sh @@ -56,9 +56,8 @@ cp "${STARTDIR}/RELEASE-NOTES-${RELEASE_VERSION}" "RELEASE-NOTES-${RELEASE_VERSI git add RELEASE-NOTES-${RELEASE_VERSION} git rm RELEASE-NOTES-${PREVIOUS_VERSION} sed -i "s,[^<]*,${RELEASE_VERSION},g" man/asciidoc.conf -echo "${RELEASE_VERSION}" > VERSION echo "${RELEASE_VERSION} ($(date +%F))" > I3_VERSION -git add VERSION I3_VERSION +git add I3_VERSION git commit -a -m "release i3 ${RELEASE_VERSION}" git tag "${RELEASE_VERSION}" -m "release i3 ${RELEASE_VERSION}" --sign --local-user=0x4AC8EE1D From d9797488539dc82ffe88b641588379c82c3dd1c6 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Sat, 9 Jul 2016 12:56:06 +0200 Subject: [PATCH 076/150] traverse numbered workspaces in correct order --- src/workspace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/workspace.c b/src/workspace.c index f8d15ba1..b0d59773 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -544,7 +544,7 @@ Con *workspace_next(void) { NODES_FOREACH(output_get_content(output)) { if (child->type != CT_WORKSPACE) continue; - if (!first) + if (!first || (child->num != -1 && child->num < first->num)) first = child; if (!first_opposite && child->num == -1) first_opposite = child; @@ -610,7 +610,7 @@ Con *workspace_prev(void) { NODES_FOREACH_REVERSE(output_get_content(output)) { if (child->type != CT_WORKSPACE) continue; - if (!last) + if (!last || (child->num != -1 && last->num < child->num)) last = child; if (!first_opposite && child->num == -1) first_opposite = child; From 5d6d974c661438c0d6f8cbe51da63de623d5bd4b Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Sun, 31 Jul 2016 19:27:02 +0200 Subject: [PATCH 077/150] remove goto statement remove goto statement to similarize workspace_next and workspace_prev --- src/workspace.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/workspace.c b/src/workspace.c index b0d59773..e6a156cd 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -596,7 +596,7 @@ Con *workspace_prev(void) { found_current = true; } else if (child->num == -1 && found_current) { prev = child; - goto workspace_prev_end; + return prev; } } } @@ -628,7 +628,6 @@ Con *workspace_prev(void) { if (!prev) prev = first_opposite ? first_opposite : last; -workspace_prev_end: return prev; } From 930733f35242cc69a8cc7b133d23d8a9f094bfce Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Sun, 31 Jul 2016 19:28:04 +0200 Subject: [PATCH 078/150] enhance test 528 Enhancing test 528 to test workspace_next and workspace_prev - Adding tests for worksace_prev - Mixing workspace distribution over outputs --- testcases/t/528-workspace-next-prev.t | 130 +++++++++++++------------- 1 file changed, 66 insertions(+), 64 deletions(-) diff --git a/testcases/t/528-workspace-next-prev.t b/testcases/t/528-workspace-next-prev.t index 79e83a07..1a83de23 100644 --- a/testcases/t/528-workspace-next-prev.t +++ b/testcases/t/528-workspace-next-prev.t @@ -31,6 +31,17 @@ sub assert_next { is(focused_ws, $expected, "workspace $expected focused"); } +sub assert_prev { + my ($expected) = @_; + + cmd 'workspace prev'; + # We need to sync after changing focus to a different output to wait for the + # EnterNotify to be processed, otherwise it will be processed at some point + # later in time and mess up our subsequent tests. + sync_with_i3; + + is(focused_ws, $expected, "workspace $expected focused"); +} my $config = <root->warp_pointer(0, 0); sync_with_i3; -cmd 'workspace A'; -# ensure workspace A stays open -open_window; - -cmd 'workspace B'; -# ensure workspace B stays open -open_window; - -cmd 'workspace D'; -# ensure workspace D stays open -open_window; - -cmd 'workspace E'; -# ensure workspace E stays open -open_window; +################################################################################ +# Setup workspaces so that they stay open (with an empty container). +# open_window ensures, this +# +# numbered named +# output 1 (left) : 1, 2, 3, 6, 7, B, F, C +# output 2 (right): 4, 5, A, D, E +# +################################################################################ cmd 'focus output right'; +cmd 'workspace A'; open_window; +cmd 'workspace D'; open_window; +cmd 'workspace 4'; open_window; +cmd 'workspace 5'; open_window; +cmd 'workspace E'; open_window; -cmd 'workspace 1'; -# ensure workspace 1 stays open -open_window; - -cmd 'workspace 2'; -# ensure workspace 2 stays open -open_window; - -cmd 'workspace 3'; -# ensure workspace 3 stays open -open_window; - -cmd 'workspace 4'; -# ensure workspace 4 stays open -open_window; - -cmd 'workspace 5'; -# ensure workspace 5 stays open -open_window; - -cmd 'workspace C'; -# ensure workspace C stays open -open_window; - -cmd 'workspace F'; -# ensure workspace F stays open -open_window; - -cmd 'focus output right'; +cmd 'focus output left'; +cmd 'workspace 1'; open_window; +cmd 'workspace 2'; open_window; +cmd 'workspace B'; open_window; +cmd 'workspace 3'; open_window; +cmd 'workspace F'; open_window; +cmd 'workspace 6'; open_window; +cmd 'workspace C'; open_window; +cmd 'workspace 7'; open_window; ################################################################################ # Use workspace next and verify the correct order. +# numbered -> numerical sort +# named -> sort by creation time ################################################################################ +cmd 'workspace 1'; +is(focused_ws, '1', 'back on workspace 1'); -# The current order should be: -# output 1: A, B, D, E -# output 2: 1, 2, 3, 4, 5, C, F - -cmd 'workspace A'; -is(focused_ws, 'A', 'back on workspace A'); - -assert_next('B'); -assert_next('D'); -assert_next('E'); -assert_next('C'); -assert_next('F'); -assert_next('1'); assert_next('2'); assert_next('3'); assert_next('4'); assert_next('5'); -assert_next('A'); +assert_next('6'); +assert_next('7'); + assert_next('B'); +assert_next('F'); +assert_next('C'); +assert_next('A'); +assert_next('D'); +assert_next('E'); +assert_next('1'); + +cmd 'workspace 1'; +is(focused_ws, '1', 'back on workspace 1'); + +assert_prev('E'); +assert_prev('D'); +assert_prev('A'); +assert_prev('C'); +assert_prev('F'); +assert_prev('B'); + +assert_prev('7'); +assert_prev('6'); +assert_prev('5'); +assert_prev('4'); +assert_prev('3'); +assert_prev('2'); +assert_prev('1'); + exit_gracefully($pid); From e35aff5cb9fc577c1016d9c847e5e9bbddc3a888 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Sun, 31 Jul 2016 19:50:01 +0200 Subject: [PATCH 079/150] fix transition from named to numbered workspace --- src/workspace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/workspace.c b/src/workspace.c index e6a156cd..0c80f69f 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -525,7 +525,7 @@ Con *workspace_next(void) { continue; if (!first) first = child; - if (!first_opposite && child->num != -1) + if (!first_opposite || (child->num != -1 && child->num < first_opposite->num)) first_opposite = child; if (child == current) { found_current = true; @@ -590,7 +590,7 @@ Con *workspace_prev(void) { continue; if (!last) last = child; - if (!first_opposite && child->num != -1) + if (!first_opposite || (child->num != -1 && child->num > first_opposite->num)) first_opposite = child; if (child == current) { found_current = true; From 7a94dfd11de1d2fb2d4b8470d7a142b9fb82fcc2 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Thu, 4 Aug 2016 16:18:02 +0200 Subject: [PATCH 080/150] add additional reversed testcase --- .../t/528-workspace-next-prev-reversed.t | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 testcases/t/528-workspace-next-prev-reversed.t diff --git a/testcases/t/528-workspace-next-prev-reversed.t b/testcases/t/528-workspace-next-prev-reversed.t new file mode 100644 index 00000000..00a9bbe4 --- /dev/null +++ b/testcases/t/528-workspace-next-prev-reversed.t @@ -0,0 +1,129 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Please read the following documents before working on tests: +# • http://build.i3wm.org/docs/testsuite.html +# (or docs/testsuite) +# +# • http://build.i3wm.org/docs/lib-i3test.html +# (alternatively: perldoc ./testcases/lib/i3test.pm) +# +# • http://build.i3wm.org/docs/ipc.html +# (or docs/ipc) +# +# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf +# (unless you are already familiar with Perl) +# +# Tests whether 'workspace next' works correctly. +# +use List::Util qw(first); +use i3test i3_autostart => 0; + +sub assert_next { + my ($expected) = @_; + + cmd 'workspace next'; + # We need to sync after changing focus to a different output to wait for the + # EnterNotify to be processed, otherwise it will be processed at some point + # later in time and mess up our subsequent tests. + sync_with_i3; + + is(focused_ws, $expected, "workspace $expected focused"); +} + +sub assert_prev { + my ($expected) = @_; + + cmd 'workspace prev'; + # We need to sync after changing focus to a different output to wait for the + # EnterNotify to be processed, otherwise it will be processed at some point + # later in time and mess up our subsequent tests. + sync_with_i3; + + is(focused_ws, $expected, "workspace $expected focused"); +} + +my $config = <root->warp_pointer(0, 0); +sync_with_i3; + +################################################################################ +# Setup workspaces so that they stay open (with an empty container). +# open_window ensures, this +# +# numbered named +# output 1 (left) : 1, 2, 3, 6, 7, B, F, C +# output 2 (right): 4, 5, A, D, E +# +################################################################################ + +cmd 'focus output left'; +cmd 'workspace A'; open_window; +cmd 'workspace D'; open_window; +cmd 'workspace 4'; open_window; +cmd 'workspace 5'; open_window; +cmd 'workspace E'; open_window; + +cmd 'focus output right'; +cmd 'workspace 1'; open_window; +cmd 'workspace 2'; open_window; +cmd 'workspace B'; open_window; +cmd 'workspace 3'; open_window; +cmd 'workspace F'; open_window; +cmd 'workspace 6'; open_window; +cmd 'workspace C'; open_window; +cmd 'workspace 7'; open_window; + +################################################################################ +# Use workspace next and verify the correct order. +# numbered -> numerical sort +# named -> sort by creation time +################################################################################ +cmd 'workspace 1'; +is(focused_ws, '1', 'back on workspace 1'); + +assert_next('2'); +assert_next('3'); +assert_next('4'); +assert_next('5'); +assert_next('6'); +assert_next('7'); + +assert_next('B'); +assert_next('F'); +assert_next('C'); +assert_next('A'); +assert_next('D'); +assert_next('E'); +assert_next('1'); + +cmd 'workspace 1'; +is(focused_ws, '1', 'back on workspace 1'); + +assert_prev('E'); +assert_prev('D'); +assert_prev('A'); +assert_prev('C'); +assert_prev('F'); +assert_prev('B'); + +assert_prev('7'); +assert_prev('6'); +assert_prev('5'); +assert_prev('4'); +assert_prev('3'); +assert_prev('2'); +assert_prev('1'); + + +exit_gracefully($pid); + +done_testing; From fac57699b4d416cfcbaaaba22bbbeac65e157cbd Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 4 Sep 2016 21:08:21 +0200 Subject: [PATCH 081/150] Bugfix: avoid setting urgency hint on content container and above fixes #2098 (I _think_) --- src/con.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/con.c b/src/con.c index dbb6d601..124d24ea 100644 --- a/src/con.c +++ b/src/con.c @@ -1948,6 +1948,13 @@ bool con_has_urgent_child(Con *con) { void con_update_parents_urgency(Con *con) { Con *parent = con->parent; + /* Urgency hints should not be set on any container higher up in the + * hierarchy than the workspace level. Unfortunately, since the content + * container has type == CT_CON, that’s not easy to verify in the loop + * below, so we need another condition to catch that case: */ + if (con->type == CT_WORKSPACE) + return; + bool new_urgency_value = con->urgent; while (parent && parent->type != CT_WORKSPACE && parent->type != CT_DOCKAREA) { if (new_urgency_value) { From f62eb9f533a32622fa1cfe13526c33e4e35eb872 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 5 Sep 2016 08:19:02 +0200 Subject: [PATCH 082/150] Bugfix: re-add single quotes around I3_VERSION Without single quotes, the version is not passed correctly to the compiler, and building Debian packages fails. related to #2437 --- common.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.mk b/common.mk index e99f93c8..b9569ca7 100644 --- a/common.mk +++ b/common.mk @@ -22,7 +22,7 @@ endif ifeq ($(wildcard .git),) # not in git repository VERSION := $(shell [ -f $(TOPDIR)/I3_VERSION ] && cat $(TOPDIR)/I3_VERSION | cut -d '-' -f 1) - I3_VERSION := $(shell [ -f $(TOPDIR)/I3_VERSION ] && cat $(TOPDIR)/I3_VERSION) + I3_VERSION := '$(shell [ -f $(TOPDIR)/I3_VERSION ] && cat $(TOPDIR)/I3_VERSION)' else VERSION := $(shell git describe --tags --abbrev=0) I3_VERSION := '$(shell git describe --tags --always) ($(shell git log --pretty=format:%cd --date=short -n1), branch \"$(shell git describe --tags --always --all | sed s:heads/::)\")' From 6584f70d28a91bd9cd2108b1caad3ae5b1b9fa16 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 5 Sep 2016 08:42:34 +0200 Subject: [PATCH 083/150] =?UTF-8?q?travis:=20work=20around=20asan=20broken?= =?UTF-8?q?-ness=20with=20libc=20=E2=89=A5=202.24?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes #2437 --- travis/run-tests.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/travis/run-tests.sh b/travis/run-tests.sh index 3ab3df4d..7bf4b039 100755 --- a/travis/run-tests.sh +++ b/travis/run-tests.sh @@ -4,6 +4,23 @@ set -e set -x cd testcases + +# TODO: remove this workaround once https://bugs.debian.org/836723 is fixed +# Found at https://llvm.org/bugs/show_bug.cgi?id=27310#c8: +cat >fixasan.c < Date: Mon, 5 Sep 2016 08:55:26 +0200 Subject: [PATCH 084/150] travis: only enable asan workaround for clang (breaks gcc) fixes #2437 --- travis/run-tests.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/travis/run-tests.sh b/travis/run-tests.sh index 7bf4b039..d8a40d77 100755 --- a/travis/run-tests.sh +++ b/travis/run-tests.sh @@ -7,7 +7,9 @@ cd testcases # TODO: remove this workaround once https://bugs.debian.org/836723 is fixed # Found at https://llvm.org/bugs/show_bug.cgi?id=27310#c8: -cat >fixasan.c <fixasan.c < Date: Mon, 5 Sep 2016 09:01:41 +0200 Subject: [PATCH 085/150] travis: pass through CC to run-tests fixes #2437 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4951fe64..f8a3de6f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,7 @@ script: - 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 -e CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Werror" ${BASENAME} make all mans -j ASAN=1 - 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 ${BASENAME} ./travis/run-tests.sh + - docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 -e CC ${BASENAME} ./travis/run-tests.sh - ./travis/skip-pkg.sh || docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/debian-build.sh deb/debian-amd64/DIST - ./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 From 5ca7d4b2226f4cdd40b661a0bc2585cc87518f9c Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 12 Sep 2016 12:01:12 +0200 Subject: [PATCH 086/150] expose binding pointer in debug messages This makes it a bit easier to match up the different messages to the configured binding. --- src/bindings.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/bindings.c b/src/bindings.c index e0b70b6c..9bac68d6 100644 --- a/src/bindings.c +++ b/src/bindings.c @@ -57,7 +57,7 @@ Binding *configure_binding(const char *bindtype, const char *modifiers, const ch const char *release, const char *border, const char *whole_window, const char *command, const char *modename, bool pango_markup) { Binding *new_binding = scalloc(1, sizeof(Binding)); - DLOG("bindtype %s, modifiers %s, input code %s, release %s\n", bindtype, modifiers, input_code, release); + DLOG("Binding %p bindtype %s, modifiers %s, input code %s, release %s\n", new_binding, bindtype, modifiers, input_code, release); new_binding->release = (release != NULL ? B_UPON_KEYRELEASE : B_UPON_KEYPRESS); new_binding->border = (border != NULL); new_binding->whole_window = (whole_window != NULL); @@ -126,8 +126,8 @@ static void grab_keycode_for_binding(xcb_connection_t *conn, Binding *bind, uint xcb_grab_key(conn, 0, root, modifier, keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC); \ } while (0) const int mods = (bind->event_state_mask & 0xFFFF); - DLOG("Grabbing keycode %d with event state mask 0x%x (mods 0x%x)\n", - keycode, bind->event_state_mask, mods); + DLOG("Binding %p Grabbing keycode %d with event state mask 0x%x (mods 0x%x)\n", + bind, keycode, bind->event_state_mask, mods); GRAB_KEY(mods); /* Also bind the key with active NumLock */ GRAB_KEY(mods | xcb_numlock_mask); @@ -160,7 +160,7 @@ void grab_all_keys(xcb_connection_t *conn) { TAILQ_FOREACH(binding_keycode, &(bind->keycodes_head), keycodes) { const int keycode = binding_keycode->keycode; const int mods = (binding_keycode->modifiers & 0xFFFF); - DLOG("Grabbing keycode %d with mods %d\n", keycode, mods); + DLOG("Binding %p Grabbing keycode %d with mods %d\n", bind, keycode, mods); xcb_grab_key(conn, 0, root, mods, keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC); } } @@ -458,7 +458,9 @@ void translate_keysyms(void) { else if ((bind->event_state_mask >> 16) & I3_XKB_GROUP_MASK_4) group = XCB_XKB_GROUP_4; - DLOG("group = %d, event_state_mask = %d, &2 = %s, &3 = %s, &4 = %s\n", group, + DLOG("Binding %p group = %d, event_state_mask = %d, &2 = %s, &3 = %s, &4 = %s\n", + bind, + group, bind->event_state_mask, (bind->event_state_mask & I3_XKB_GROUP_MASK_2) ? "yes" : "no", (bind->event_state_mask & I3_XKB_GROUP_MASK_3) ? "yes" : "no", From 0469716fd6cbe22916b1f7a0cc8193f6025e8405 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 12 Sep 2016 12:05:38 +0200 Subject: [PATCH 087/150] Bugfix: compare all resolved modifier masks Before this commit, i3 only compared the user-specified modifiers and incorrectly ignored the resolved modifiers (such as the numlock fallback). While at it, also fix the testcase which treated numlock as a momentary modifier, whereas it really is a latched modifier. fixes #2418 --- src/bindings.c | 59 +++++++++++++++++------------- testcases/t/264-keypress-numlock.t | 46 +++++++++++++++++++---- 2 files changed, 71 insertions(+), 34 deletions(-) diff --git a/src/bindings.c b/src/bindings.c index 9bac68d6..db88aee3 100644 --- a/src/bindings.c +++ b/src/bindings.c @@ -188,6 +188,17 @@ void regrab_all_buttons(xcb_connection_t *conn) { xcb_ungrab_server(conn); } +static bool modifiers_match(const uint32_t modifiers_mask, const uint32_t modifiers_state) { + /* modifiers_mask is a special case: a value of 0 does not mean “match + * all”, but rather “match exactly when no modifiers are present”. */ + if (modifiers_mask == 0) { + /* Verify no modifiers are pressed. A bitwise AND would lead to + * false positives, see issue #2002. */ + return (modifiers_state == 0); + } + return ((modifiers_state & modifiers_mask) == modifiers_mask); +} + /* * Returns a pointer to the Binding with the specified modifiers and * keycode or NULL if no such binding exists. @@ -210,34 +221,15 @@ 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) { - const uint32_t xkb_group_mask = (bind->event_state_mask & 0xFFFF0000); - /* modifiers_mask is a special case: a value of 0 does not mean “match all”, - * but rather “match exactly when no modifiers are present”. */ - const uint32_t modifiers_mask = (bind->event_state_mask & 0x0000FFFF); - const bool groups_match = ((xkb_group_state & xkb_group_mask) == xkb_group_mask); - bool mods_match; - if (modifiers_mask == 0) { - /* Verify no modifiers are pressed. A bitwise AND would lead to - * false positives, see issue #2002. */ - mods_match = (modifiers_state == 0); - } else { - mods_match = ((modifiers_state & modifiers_mask) == modifiers_mask); - } - const bool state_matches = (groups_match && mods_match); - - DLOG("binding groups_match = %s, mods_match = %s, state_matches = %s\n", - (groups_match ? "yes" : "no"), - (mods_match ? "yes" : "no"), - (state_matches ? "yes" : "no")); - /* First compare the state_filtered (unless this is a - * B_UPON_KEYRELEASE_IGNORE_MODS binding and this is a KeyRelease - * event) */ if (bind->input_type != input_type) continue; - if (!state_matches && - (bind->release != B_UPON_KEYRELEASE_IGNORE_MODS || - !is_release)) + + const uint32_t xkb_group_mask = (bind->event_state_mask & 0xFFFF0000); + const bool groups_match = ((xkb_group_state & xkb_group_mask) == xkb_group_mask); + if (!groups_match) { + DLOG("skipping binding %p because XKB groups do not match\n", bind); continue; + } /* For keyboard bindings where a symbol was specified by the user, we * need to look in the array of translated keycodes for the event’s @@ -247,7 +239,11 @@ static Binding *get_binding(i3_event_state_mask_t state_filtered, bool is_releas bool found_keycode = false; struct Binding_Keycode *binding_keycode; TAILQ_FOREACH(binding_keycode, &(bind->keycodes_head), keycodes) { - if (binding_keycode->keycode == input_keycode) { + const uint32_t modifiers_mask = (binding_keycode->modifiers & 0x0000FFFF); + const bool mods_match = modifiers_match(modifiers_mask, modifiers_state); + DLOG("binding_keycode->modifiers = %d, modifiers_mask = %d, modifiers_state = %d, mods_match = %s\n", + binding_keycode->modifiers, modifiers_mask, modifiers_state, (mods_match ? "yes" : "no")); + if (binding_keycode->keycode == input_keycode && mods_match) { found_keycode = true; break; } @@ -255,6 +251,17 @@ static Binding *get_binding(i3_event_state_mask_t state_filtered, bool is_releas if (!found_keycode) continue; } else { + const uint32_t modifiers_mask = (bind->event_state_mask & 0x0000FFFF); + const bool mods_match = modifiers_match(modifiers_mask, modifiers_state); + DLOG("binding mods_match = %s\n", (mods_match ? "yes" : "no")); + /* First compare the state_filtered (unless this is a + * B_UPON_KEYRELEASE_IGNORE_MODS binding and this is a KeyRelease + * event) */ + if (!mods_match && + (bind->release != B_UPON_KEYRELEASE_IGNORE_MODS || + !is_release)) + continue; + /* This case is easier: The user specified a keycode */ if (bind->keycode != input_code) continue; diff --git a/testcases/t/264-keypress-numlock.t b/testcases/t/264-keypress-numlock.t index 84db0e3c..4f255b78 100644 --- a/testcases/t/264-keypress-numlock.t +++ b/testcases/t/264-keypress-numlock.t @@ -35,6 +35,9 @@ bindsym KP_End nop KP_End # Binding which should work with numlock and without. bindsym Mod4+a nop a + +# Binding which should work with numlock and without, see issue #2418. +bindsym Escape nop Escape EOT my $pid = launch_with_config($config); @@ -52,10 +55,12 @@ is(listen_for_binding( is(listen_for_binding( sub { - xtest_key_press(77); # Num_Lock + xtest_key_press(77); # enable Num_Lock + xtest_key_release(77); # enable Num_Lock xtest_key_press(87); # KP_1 xtest_key_release(87); # KP_1 - xtest_key_release(77); # Num_Lock + xtest_key_press(77); # disable Num_Lock + xtest_key_release(77); # disable Num_Lock }, ), 'KP_1', @@ -74,20 +79,43 @@ is(listen_for_binding( is(listen_for_binding( sub { - xtest_key_press(77); # Num_Lock + xtest_key_press(77); # enable Num_Lock + xtest_key_release(77); # enable Num_Lock xtest_key_press(133); # Super_L xtest_key_press(38); # a xtest_key_release(38); # a xtest_key_release(133); # Super_L - xtest_key_release(77); # Num_Lock + xtest_key_press(77); # disable Num_Lock + xtest_key_release(77); # disable Num_Lock }, ), 'a', 'triggered the "a" keybinding'); +is(listen_for_binding( + sub { + xtest_key_press(9); # Escape + xtest_key_release(9); # Escape + }, + ), + 'Escape', + 'triggered the "Escape" keybinding'); + +is(listen_for_binding( + sub { + xtest_key_press(77); # enable Num_Lock + xtest_key_release(77); # enable Num_Lock + xtest_key_press(9); # Escape + xtest_key_release(9); # Escape + xtest_key_press(77); # disable Num_Lock + xtest_key_release(77); # disable Num_Lock + }, + ), + 'Escape', + 'triggered the "Escape" keybinding'); sync_with_i3; -is(scalar @i3test::XTEST::binding_events, 4, 'Received exactly 4 binding events'); +is(scalar @i3test::XTEST::binding_events, 6, 'Received exactly 4 binding events'); exit_gracefully($pid); @@ -117,10 +145,12 @@ is(listen_for_binding( is(listen_for_binding( sub { - xtest_key_press(77); # Num_Lock + xtest_key_press(77); # enable Num_Lock + xtest_key_release(77); # enable Num_Lock xtest_key_press(87); # KP_1 xtest_key_release(87); # KP_1 - xtest_key_release(77); # Num_Lock + xtest_key_press(77); # disable Num_Lock + xtest_key_release(77); # disable Num_Lock }, ), 'timeout', @@ -129,7 +159,7 @@ is(listen_for_binding( # TODO: This test does not verify that i3 does _NOT_ grab keycode 87 with Mod2. sync_with_i3; -is(scalar @i3test::XTEST::binding_events, 5, 'Received exactly 5 binding events'); +is(scalar @i3test::XTEST::binding_events, 7, 'Received exactly 5 binding events'); exit_gracefully($pid); From b00d36fca5839094c3a1ce48ab788fe3e2da67d0 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 12 Sep 2016 12:10:59 +0200 Subject: [PATCH 088/150] t/264-keypress-numlock: add a test covering shift related to #2418 --- testcases/t/264-keypress-numlock.t | 33 ++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/testcases/t/264-keypress-numlock.t b/testcases/t/264-keypress-numlock.t index 4f255b78..fa9caa61 100644 --- a/testcases/t/264-keypress-numlock.t +++ b/testcases/t/264-keypress-numlock.t @@ -38,6 +38,9 @@ bindsym Mod4+a nop a # Binding which should work with numlock and without, see issue #2418. bindsym Escape nop Escape + +# Binding which should work with numlock and without, see issue #2418. +bindsym Shift+Escape nop Shift+Escape EOT my $pid = launch_with_config($config); @@ -114,8 +117,34 @@ is(listen_for_binding( 'Escape', 'triggered the "Escape" keybinding'); +is(listen_for_binding( + sub { + xtest_key_press(50); # Shift_L + xtest_key_press(9); # Escape + xtest_key_release(9); # Escape + xtest_key_release(50); # Shift_L + }, + ), + 'Shift+Escape', + 'triggered the "Escape" keybinding'); + +is(listen_for_binding( + sub { + xtest_key_press(77); # enable Num_Lock + xtest_key_release(77); # enable Num_Lock + xtest_key_press(50); # Shift_L + xtest_key_press(9); # Escape + xtest_key_release(9); # Escape + xtest_key_release(50); # Shift_L + xtest_key_press(77); # disable Num_Lock + xtest_key_release(77); # disable Num_Lock + }, + ), + 'Shift+Escape', + 'triggered the "Escape" keybinding'); + sync_with_i3; -is(scalar @i3test::XTEST::binding_events, 6, 'Received exactly 4 binding events'); +is(scalar @i3test::XTEST::binding_events, 8, 'Received exactly 8 binding events'); exit_gracefully($pid); @@ -159,7 +188,7 @@ is(listen_for_binding( # TODO: This test does not verify that i3 does _NOT_ grab keycode 87 with Mod2. sync_with_i3; -is(scalar @i3test::XTEST::binding_events, 7, 'Received exactly 5 binding events'); +is(scalar @i3test::XTEST::binding_events, 9, 'Received exactly 9 binding events'); exit_gracefully($pid); From 2244c843a8cc4055dabb314f8547e34b1269b8b3 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 12 Sep 2016 12:57:13 +0200 Subject: [PATCH 089/150] =?UTF-8?q?Bugfix:=20don=E2=80=99t=20trigger=20unr?= =?UTF-8?q?elated=20key=20bindings=20for=20--release=20bindings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes #2442 --- src/bindings.c | 9 ++++++++- testcases/t/258-keypress-release.t | 30 +++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/bindings.c b/src/bindings.c index db88aee3..463a4f62 100644 --- a/src/bindings.c +++ b/src/bindings.c @@ -271,8 +271,15 @@ static Binding *get_binding(i3_event_state_mask_t state_filtered, bool is_releas * user pressed. We therefore mark it as B_UPON_KEYRELEASE_IGNORE_MODS * for later, so that the user can release the modifiers before the * actual key or button and the release event will still be matched. */ - if (bind->release == B_UPON_KEYRELEASE && !is_release) + if (bind->release == B_UPON_KEYRELEASE && !is_release) { bind->release = B_UPON_KEYRELEASE_IGNORE_MODS; + DLOG("marked bind %p as B_UPON_KEYRELEASE_IGNORE_MODS\n", bind); + /* The correct binding has been found, so abort the search, but + * also don’t return this binding, since it should not be executed + * yet (only when the keys are released). */ + bind = TAILQ_END(bindings); + break; + } /* Check if the binding is for a press or a release event */ if ((bind->release == B_UPON_KEYPRESS && is_release) || diff --git a/testcases/t/258-keypress-release.t b/testcases/t/258-keypress-release.t index 4c2775b6..b0d77858 100644 --- a/testcases/t/258-keypress-release.t +++ b/testcases/t/258-keypress-release.t @@ -33,6 +33,10 @@ font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 bindsym Print nop Print bindsym --release Control+Print nop Control+Print + +# see issue #2442 +bindsym Mod1+b nop Mod1+b +bindsym --release Mod1+Shift+b nop Mod1+Shift+b release EOT my $pid = launch_with_config($config); @@ -59,8 +63,32 @@ is(listen_for_binding( 'Control+Print', 'triggered the "Control+Print" keybinding'); +is(listen_for_binding( + sub { + xtest_key_press(64); # Alt_L + xtest_key_press(56); # b + xtest_key_release(56); # b + xtest_key_release(64); # Alt_L + }, + ), + 'Mod1+b', + 'triggered the "Mod1+b" keybinding'); + +is(listen_for_binding( + sub { + xtest_key_press(64); # Alt_L + xtest_key_press(50); # Shift_L + xtest_key_press(56); # b + xtest_key_release(56); # b + xtest_key_release(50); # Shift_L + xtest_key_release(64); # Alt_L + }, + ), + 'Mod1+Shift+b release', + 'triggered the "Mod1+Shift+b" release keybinding'); + sync_with_i3; -is(scalar @i3test::XTEST::binding_events, 2, 'Received exactly 2 binding events'); +is(scalar @i3test::XTEST::binding_events, 4, 'Received exactly 4 binding events'); exit_gracefully($pid); From 02f206d816b68de0cb8a943ee32c41abefeb39d3 Mon Sep 17 00:00:00 2001 From: Nathan Schulte Date: Fri, 9 Sep 2016 16:57:28 -0500 Subject: [PATCH 090/150] fix typo in logging message --- src/bindings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings.c b/src/bindings.c index 463a4f62..ccd397f6 100644 --- a/src/bindings.c +++ b/src/bindings.c @@ -408,7 +408,7 @@ static void add_keycode_if_matches(struct xkb_keymap *keymap, xkb_keycode_t key, /* Also bind the key with active NumLock+CapsLock */ ADD_TRANSLATED_KEY(bind->event_state_mask | xcb_numlock_mask | XCB_MOD_MASK_LOCK); } else { - DLOG("Skipping automatic numlock fallback, key %d resolves to 0x%x with unmlock\n", + DLOG("Skipping automatic numlock fallback, key %d resolves to 0x%x with numlock\n", key, sym_numlock); } } From 41ce596a943713d0000ed7914f7058d72a55afc2 Mon Sep 17 00:00:00 2001 From: Nathan Schulte Date: Fri, 9 Sep 2016 16:57:04 -0500 Subject: [PATCH 091/150] fix bindsyms with Shift, given NumLock tweaks --- src/bindings.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/bindings.c b/src/bindings.c index ccd397f6..7a056adf 100644 --- a/src/bindings.c +++ b/src/bindings.c @@ -355,6 +355,9 @@ struct resolve { /* Like |xkb_state|, but with NumLock. */ struct xkb_state *xkb_state_numlock; + + /* Like |xkb_state|, but with NumLock, just without the shift modifier, if shift was specified. */ + struct xkb_state *xkb_state_numlock_no_shift; }; /* @@ -401,7 +404,8 @@ static void add_keycode_if_matches(struct xkb_keymap *keymap, xkb_keycode_t key, * need to duplicate every key binding with an additional Mod2 specified. */ xkb_keysym_t sym_numlock = xkb_state_key_get_one_sym(resolving->xkb_state_numlock, key); - if (sym_numlock == resolving->keysym) { + xkb_keysym_t sym_numlock_no_shift = xkb_state_key_get_one_sym(resolving->xkb_state_numlock_no_shift, key); + if (sym_numlock == resolving->keysym || sym_numlock_no_shift == resolving->keysym) { /* Also bind the key with active NumLock */ ADD_TRANSLATED_KEY(bind->event_state_mask | xcb_numlock_mask); @@ -439,6 +443,12 @@ void translate_keysyms(void) { return; } + struct xkb_state *dummy_state_numlock_no_shift = xkb_state_new(xkb_keymap); + if (dummy_state_numlock_no_shift == NULL) { + ELOG("Could not create XKB state, cannot translate keysyms.\n"); + return; + } + bool has_errors = false; Binding *bind; TAILQ_FOREACH(bind, bindings, bindings) { @@ -506,12 +516,22 @@ void translate_keysyms(void) { 0 /* xkb_layout_index_t latched_group, */, group /* xkb_layout_index_t locked_group, */); + (void)xkb_state_update_mask( + dummy_state_numlock_no_shift, + ((bind->event_state_mask & 0x1FFF) | xcb_numlock_mask) ^ XCB_KEY_BUT_MASK_SHIFT /* xkb_mod_mask_t base_mods, */, + 0 /* xkb_mod_mask_t latched_mods, */, + 0 /* xkb_mod_mask_t locked_mods, */, + 0 /* xkb_layout_index_t base_group, */, + 0 /* xkb_layout_index_t latched_group, */, + group /* xkb_layout_index_t locked_group, */); + struct resolve resolving = { .bind = bind, .keysym = keysym, .xkb_state = dummy_state, .xkb_state_no_shift = dummy_state_no_shift, .xkb_state_numlock = dummy_state_numlock, + .xkb_state_numlock_no_shift = dummy_state_numlock_no_shift, }; while (!TAILQ_EMPTY(&(bind->keycodes_head))) { struct Binding_Keycode *first = TAILQ_FIRST(&(bind->keycodes_head)); @@ -552,6 +572,7 @@ void translate_keysyms(void) { xkb_state_unref(dummy_state); xkb_state_unref(dummy_state_no_shift); xkb_state_unref(dummy_state_numlock); + xkb_state_unref(dummy_state_numlock_no_shift); if (has_errors) { start_config_error_nagbar(current_configpath, true); From 555f458d7ad4d1e558747669fd2d2036ffead1ee Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 12 Sep 2016 22:24:23 +0200 Subject: [PATCH 092/150] =?UTF-8?q?Bugfix:=20don=E2=80=99t=20apply=20shift?= =?UTF-8?q?+numlock=20fallback=20for=20keypad=20keys?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes #2418 --- src/bindings.c | 11 ++++++--- testcases/t/264-keypress-numlock.t | 38 ++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/bindings.c b/src/bindings.c index 7a056adf..eec821b6 100644 --- a/src/bindings.c +++ b/src/bindings.c @@ -368,6 +368,7 @@ struct resolve { */ static void add_keycode_if_matches(struct xkb_keymap *keymap, xkb_keycode_t key, void *data) { const struct resolve *resolving = data; + struct xkb_state *numlock_state = resolving->xkb_state_numlock; xkb_keysym_t sym = xkb_state_key_get_one_sym(resolving->xkb_state, key); if (sym != resolving->keysym) { /* Check if Shift was specified, and try resolving the symbol without @@ -377,6 +378,11 @@ static void add_keycode_if_matches(struct xkb_keymap *keymap, xkb_keycode_t key, return; if (xkb_state_key_get_level(resolving->xkb_state, key, layout) > 1) return; + /* Skip the Shift fallback for keypad keys, otherwise one cannot bind + * KP_1 independent of KP_End. */ + if (sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_Equal) + return; + numlock_state = resolving->xkb_state_numlock_no_shift; sym = xkb_state_key_get_one_sym(resolving->xkb_state_no_shift, key); if (sym != resolving->keysym) return; @@ -403,9 +409,8 @@ static void add_keycode_if_matches(struct xkb_keymap *keymap, xkb_keycode_t key, * active. If so, grab the key with NumLock as well, so that users don’t * need to duplicate every key binding with an additional Mod2 specified. */ - xkb_keysym_t sym_numlock = xkb_state_key_get_one_sym(resolving->xkb_state_numlock, key); - xkb_keysym_t sym_numlock_no_shift = xkb_state_key_get_one_sym(resolving->xkb_state_numlock_no_shift, key); - if (sym_numlock == resolving->keysym || sym_numlock_no_shift == resolving->keysym) { + xkb_keysym_t sym_numlock = xkb_state_key_get_one_sym(numlock_state, key); + if (sym_numlock == resolving->keysym) { /* Also bind the key with active NumLock */ ADD_TRANSLATED_KEY(bind->event_state_mask | xcb_numlock_mask); diff --git a/testcases/t/264-keypress-numlock.t b/testcases/t/264-keypress-numlock.t index fa9caa61..45ec7e88 100644 --- a/testcases/t/264-keypress-numlock.t +++ b/testcases/t/264-keypress-numlock.t @@ -41,6 +41,9 @@ bindsym Escape nop Escape # Binding which should work with numlock and without, see issue #2418. bindsym Shift+Escape nop Shift+Escape + +# Binding which should work with numlock and without, see issue #2418. +bindsym Mod1+Shift+q nop Mod1+Shift+q EOT my $pid = launch_with_config($config); @@ -143,8 +146,39 @@ is(listen_for_binding( 'Shift+Escape', 'triggered the "Escape" keybinding'); +is(listen_for_binding( + sub { + xtest_key_press(50); # Shift_L + xtest_key_press(64); # Alt_L + xtest_key_press(24); # q + xtest_key_release(24); # q + xtest_key_release(64); # Alt_L + xtest_key_release(50); # Shift_L + }, + ), + 'Mod1+Shift+q', + 'triggered the "Mod1+Shift+q" keybinding'); + + +is(listen_for_binding( + sub { + xtest_key_press(77); # enable Num_Lock + xtest_key_release(77); # enable Num_Lock + xtest_key_press(50); # Shift_L + xtest_key_press(64); # Alt_L + xtest_key_press(24); # q + xtest_key_release(24); # q + xtest_key_release(64); # Alt_L + xtest_key_release(50); # Shift_L + xtest_key_press(77); # disable Num_Lock + xtest_key_release(77); # disable Num_Lock + }, + ), + 'Mod1+Shift+q', + 'triggered the "Mod1+Shift+q" keybinding'); + sync_with_i3; -is(scalar @i3test::XTEST::binding_events, 8, 'Received exactly 8 binding events'); +is(scalar @i3test::XTEST::binding_events, 10, 'Received exactly 10 binding events'); exit_gracefully($pid); @@ -188,7 +222,7 @@ is(listen_for_binding( # TODO: This test does not verify that i3 does _NOT_ grab keycode 87 with Mod2. sync_with_i3; -is(scalar @i3test::XTEST::binding_events, 9, 'Received exactly 9 binding events'); +is(scalar @i3test::XTEST::binding_events, 11, 'Received exactly 11 binding events'); exit_gracefully($pid); From d48c9b1e337a3eb663c6f0f8af28c3b52f405ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 14 Sep 2016 09:13:17 +0200 Subject: [PATCH 093/150] Fix colormap handling for containers. (#2450) This commit correctly handles colormaps by * Using the static default colormap we determine on startup if the con has the corresponding depth. This avoids creating pointless colormaps. * Not freeing the default colormap to not have stray colormaps on containers. This fixes an issue with certain programs such as xwd. * Creating a custom colormap when necessary and freeing it when the container is killed. fixes #2435 --- include/data.h | 3 +++ src/x.c | 22 +++++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/include/data.h b/include/data.h index 9f835a23..247cd3c5 100644 --- a/include/data.h +++ b/include/data.h @@ -699,4 +699,7 @@ struct Con { /* Depth of the container window */ uint16_t depth; + + /* The colormap for this con if a custom one is used. */ + xcb_colormap_t colormap; }; diff --git a/src/x.c b/src/x.c index 6fd3297a..f3e02fa4 100644 --- a/src/x.c +++ b/src/x.c @@ -105,11 +105,18 @@ void x_con_init(Con *con) { uint32_t mask = 0; uint32_t values[5]; - /* For custom visuals, we need to create a colormap before creating - * this window. It will be freed directly after creating the window. */ xcb_visualid_t visual = get_visualid_by_depth(con->depth); - xcb_colormap_t win_colormap = xcb_generate_id(conn); - xcb_create_colormap_checked(conn, XCB_COLORMAP_ALLOC_NONE, win_colormap, root, visual); + xcb_colormap_t win_colormap; + if (con->depth != root_depth) { + /* We need to create a custom colormap. */ + win_colormap = xcb_generate_id(conn); + xcb_create_colormap(conn, XCB_COLORMAP_ALLOC_NONE, win_colormap, root, visual); + con->colormap = win_colormap; + } else { + /* Use the default colormap. */ + win_colormap = colormap; + con->colormap = XCB_NONE; + } /* We explicitly set a background color and border color (even though we * don’t even have a border) because the X11 server requires us to when @@ -144,9 +151,6 @@ void x_con_init(Con *con) { (strlen("i3-frame") + 1) * 2, "i3-frame\0i3-frame\0"); - if (win_colormap != XCB_NONE) - xcb_free_colormap(conn, win_colormap); - struct con_state *state = scalloc(1, sizeof(struct con_state)); state->id = con->frame.id; state->mapped = false; @@ -229,6 +233,10 @@ void x_move_win(Con *src, Con *dest) { void x_con_kill(Con *con) { con_state *state; + if (con->colormap != XCB_NONE) { + xcb_free_colormap(conn, con->colormap); + } + draw_util_surface_free(conn, &(con->frame)); draw_util_surface_free(conn, &(con->frame_buffer)); xcb_destroy_window(conn, con->frame.id); From 5594139676125716defd7b44f5ea10efd3781203 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 14 Sep 2016 09:19:25 +0200 Subject: [PATCH 094/150] Eliminate once-used check_error utility function --- include/util.h | 8 -------- src/main.c | 6 +++++- src/util.c | 14 -------------- 3 files changed, 5 insertions(+), 23 deletions(-) diff --git a/include/util.h b/include/util.h index 28655178..9915c1a8 100644 --- a/include/util.h +++ b/include/util.h @@ -98,14 +98,6 @@ bool update_if_necessary(uint32_t *destination, const uint32_t new_value); */ void exec_i3_utility(char *name, char *argv[]); -/** - * Checks a generic cookie for errors and quits with the given message if - * there was an error. - * - */ -void check_error(xcb_connection_t *conn, xcb_void_cookie_t cookie, - char *err_message); - /** * Checks if the given path exists by calling stat(). * diff --git a/src/main.c b/src/main.c index 8bbd23ba..367ebac1 100644 --- a/src/main.c +++ b/src/main.c @@ -538,7 +538,11 @@ int main(int argc, char *argv[]) { xcb_void_cookie_t cookie; cookie = xcb_change_window_attributes_checked(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){ROOT_EVENT_MASK}); - check_error(conn, cookie, "Another window manager seems to be running"); + xcb_generic_error_t *error = xcb_request_check(conn, cookie); + if (error != NULL) { + ELOG("Another window manager seems to be running (X error %d)\n", error->error_code); + return 1; + } xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(conn, gcookie, NULL); if (greply == NULL) { diff --git a/src/util.c b/src/util.c index 53f78d72..d19f8c5e 100644 --- a/src/util.c +++ b/src/util.c @@ -145,20 +145,6 @@ void exec_i3_utility(char *name, char *argv[]) { _exit(2); } -/* - * Checks a generic cookie for errors and quits with the given message if there - * was an error. - * - */ -void check_error(xcb_connection_t *conn, xcb_void_cookie_t cookie, char *err_message) { - xcb_generic_error_t *error = xcb_request_check(conn, cookie); - if (error != NULL) { - fprintf(stderr, "ERROR: %s (X error %d)\n", err_message, error->error_code); - xcb_disconnect(conn); - exit(-1); - } -} - /* * Checks if the given path exists by calling stat(). * From b850cfba4d4ce9f5dda5613c6d197648e7e65401 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 14 Sep 2016 09:22:06 +0200 Subject: [PATCH 095/150] Fix memleaks by avoiding _checked variants when discarding the result Thanks psychon for pointing this out in https://github.com/i3/i3/pull/2450#discussion_r78560433! --- src/main.c | 2 +- src/x.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.c b/src/main.c index 367ebac1..5362d077 100644 --- a/src/main.c +++ b/src/main.c @@ -826,7 +826,7 @@ int main(int argc, char *argv[]) { (uint32_t[]){XCB_GX_COPY, ~0, XCB_FILL_STYLE_SOLID, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS}); xcb_copy_area(conn, root->root, pixmap, gc, 0, 0, 0, 0, width, height); - xcb_change_window_attributes_checked(conn, root->root, XCB_CW_BACK_PIXMAP, (uint32_t[]){pixmap}); + xcb_change_window_attributes(conn, root->root, XCB_CW_BACK_PIXMAP, (uint32_t[]){pixmap}); xcb_flush(conn); xcb_free_gc(conn, gc); xcb_free_pixmap(conn, pixmap); diff --git a/src/x.c b/src/x.c index f3e02fa4..9a387749 100644 --- a/src/x.c +++ b/src/x.c @@ -789,7 +789,7 @@ void x_push_node(Con *con) { int width = MAX((int32_t)rect.width, 1); int height = MAX((int32_t)rect.height, 1); - xcb_create_pixmap_checked(conn, win_depth, con->frame_buffer.id, con->frame.id, width, height); + xcb_create_pixmap(conn, win_depth, con->frame_buffer.id, con->frame.id, width, height); draw_util_surface_init(conn, &(con->frame_buffer), con->frame_buffer.id, get_visualtype_by_id(get_visualid_by_depth(win_depth)), width, height); From 14f49aa6d36d70e15c03052d47ccbcb096e4dbca Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 24 Sep 2016 08:16:02 -0700 Subject: [PATCH 096/150] travis/cleanup-bintray: use dpkg --compare-versions (#2453) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …instead of lexicographically sorting strings, which fails for the following situation: 4.12-96-g086276b 4.12-97-g59c070b 4.12-108-gb850cfb This bug resulted in new packages being built and uploaded, then immediately deleted. Thanks to eeemsi for reporting the issue. --- travis/cleanup-bintray.pl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/travis/cleanup-bintray.pl b/travis/cleanup-bintray.pl index 296ae388..e89efb1b 100755 --- a/travis/cleanup-bintray.pl +++ b/travis/cleanup-bintray.pl @@ -25,7 +25,9 @@ my $client = HTTP::Tiny->new( my $resp = $client->get($apiurl); die "Getting versions failed: HTTP status $resp->{status} (content: $resp->{content})" unless $resp->{success}; my $decoded = decode_json($resp->{content}); -my @versions = reverse sort @{$decoded->{versions}}; +my @versions = reverse sort { + (system("/usr/bin/dpkg", "--compare-versions", "$a", "gt", "$b") == 0) ? 1 : -1 +} @{$decoded->{versions}}; # Keep the most recent 5 versions. splice(@versions, 0, 5); From 9bf346c7a00f0783e3754d45dda331ff91ec9a64 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 24 Sep 2016 09:48:32 -0700 Subject: [PATCH 097/150] Remove compatibility definitions for xcb-util < 0.3.8 (#2473) Even Debian oldstable has xcb-util 0.3.8. --- common.mk | 9 ++---- i3-config-wizard/i3-config-wizard.mk | 2 +- i3-dump-log/i3-dump-log.mk | 2 +- i3-input/i3-input.mk | 2 +- i3-msg/i3-msg.mk | 2 +- i3-nagbar/i3-nagbar.mk | 2 +- i3bar/i3bar.mk | 2 +- i3bar/include/xcb.h | 4 --- i3bar/src/xcb.c | 4 --- include/all.h | 5 --- include/xcb_compat.h | 47 ---------------------------- libi3/libi3.mk | 2 +- src/i3.mk | 14 ++++----- 13 files changed, 16 insertions(+), 81 deletions(-) delete mode 100644 include/xcb_compat.h diff --git a/common.mk b/common.mk index b9569ca7..2bd879d4 100644 --- a/common.mk +++ b/common.mk @@ -93,15 +93,10 @@ XCB_CFLAGS := $(call cflags_for_lib, xcb) XCB_CFLAGS += $(call cflags_for_lib, xcb-event) XCB_LIBS := $(call ldflags_for_lib, xcb,xcb) XCB_LIBS += $(call ldflags_for_lib, xcb-event,xcb-event) -ifeq ($(shell $(PKG_CONFIG) --exists xcb-util 2>/dev/null || echo 1),1) -XCB_CFLAGS += $(call cflags_for_lib, xcb-atom) -XCB_CFLAGS += $(call cflags_for_lib, xcb-aux) -XCB_LIBS += $(call ldflags_for_lib, xcb-atom,xcb-atom) -XCB_LIBS += $(call ldflags_for_lib, xcb-aux,xcb-aux) -XCB_CPPFLAGS+= -DXCB_COMPAT -else XCB_CFLAGS += $(call cflags_for_lib, xcb-util) XCB_LIBS += $(call ldflags_for_lib, xcb-util) +ifneq ($(shell $(PKG_CONFIG) --atleast-version=0.3.8 xcb-util 2>/dev/null && echo 1),1) +$(error "xcb-util >= 0.3.8 not found") endif XCB_XKB_LIBS := $(call ldflags_for_lib, xcb-xkb,xcb-xkb) diff --git a/i3-config-wizard/i3-config-wizard.mk b/i3-config-wizard/i3-config-wizard.mk index 900893f5..2a761433 100644 --- a/i3-config-wizard/i3-config-wizard.mk +++ b/i3-config-wizard/i3-config-wizard.mk @@ -12,7 +12,7 @@ i3_config_wizard_OBJECTS := $(i3_config_wizard_SOURCES:.c=.o) i3-config-wizard/%.o: i3-config-wizard/%.c $(i3_config_wizard_HEADERS) i3-config-parser.stamp echo "[i3-config-wizard] CC $<" - $(CC) $(I3_CPPFLAGS) $(XCB_CPPFLAGS) $(CPPFLAGS) $(i3_config_wizard_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< + $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_config_wizard_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< i3-config-wizard/i3-config-wizard: libi3.a $(i3_config_wizard_OBJECTS) echo "[i3-config-wizard] Link i3-config-wizard" diff --git a/i3-dump-log/i3-dump-log.mk b/i3-dump-log/i3-dump-log.mk index 7e5d4499..09a793f5 100644 --- a/i3-dump-log/i3-dump-log.mk +++ b/i3-dump-log/i3-dump-log.mk @@ -12,7 +12,7 @@ i3_dump_log_OBJECTS := $(i3_dump_log_SOURCES:.c=.o) i3-dump-log/%.o: i3-dump-log/%.c $(i3_dump_log_HEADERS) echo "[i3-dump-log] CC $<" - $(CC) $(I3_CPPFLAGS) $(XCB_CPPFLAGS) $(CPPFLAGS) $(i3_dump_log_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< + $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_dump_log_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< i3-dump-log/i3-dump-log: libi3.a $(i3_dump_log_OBJECTS) echo "[i3-dump-log] Link i3-dump-log" diff --git a/i3-input/i3-input.mk b/i3-input/i3-input.mk index be3e2833..2b1f451e 100644 --- a/i3-input/i3-input.mk +++ b/i3-input/i3-input.mk @@ -12,7 +12,7 @@ i3_input_OBJECTS := $(i3_input_SOURCES:.c=.o) i3-input/%.o: i3-input/%.c $(i3_input_HEADERS) echo "[i3-input] CC $<" - $(CC) $(I3_CPPFLAGS) $(XCB_CPPFLAGS) $(CPPFLAGS) $(i3_input_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< + $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_input_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< i3-input/i3-input: libi3.a $(i3_input_OBJECTS) echo "[i3-input] Link i3-input" diff --git a/i3-msg/i3-msg.mk b/i3-msg/i3-msg.mk index 277c43e7..dfba4d2c 100644 --- a/i3-msg/i3-msg.mk +++ b/i3-msg/i3-msg.mk @@ -12,7 +12,7 @@ i3_msg_OBJECTS := $(i3_msg_SOURCES:.c=.o) i3-msg/%.o: i3-msg/%.c $(i3_msg_HEADERS) echo "[i3-msg] CC $<" - $(CC) $(I3_CPPFLAGS) $(XCB_CPPFLAGS) $(CPPFLAGS) $(i3_msg_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< + $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_msg_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< i3-msg/i3-msg: libi3.a $(i3_msg_OBJECTS) echo "[i3-msg] Link i3-msg" diff --git a/i3-nagbar/i3-nagbar.mk b/i3-nagbar/i3-nagbar.mk index b10e389e..564a7bc2 100644 --- a/i3-nagbar/i3-nagbar.mk +++ b/i3-nagbar/i3-nagbar.mk @@ -12,7 +12,7 @@ i3_nagbar_OBJECTS := $(i3_nagbar_SOURCES:.c=.o) i3-nagbar/%.o: i3-nagbar/%.c $(i3_nagbar_HEADERS) echo "[i3-nagbar] CC $<" - $(CC) $(I3_CPPFLAGS) $(XCB_CPPFLAGS) $(CPPFLAGS) $(i3_nagbar_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< + $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_nagbar_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< i3-nagbar/i3-nagbar: libi3.a $(i3_nagbar_OBJECTS) echo "[i3-nagbar] Link i3-nagbar" diff --git a/i3bar/i3bar.mk b/i3bar/i3bar.mk index 5aed1902..114e9314 100644 --- a/i3bar/i3bar.mk +++ b/i3bar/i3bar.mk @@ -12,7 +12,7 @@ i3bar_OBJECTS := $(i3bar_SOURCES:.c=.o) i3bar/src/%.o: i3bar/src/%.c $(i3bar_HEADERS) echo "[i3bar] CC $<" - $(CC) $(I3_CPPFLAGS) $(XCB_CPPFLAGS) $(CPPFLAGS) $(i3bar_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -Ii3bar/include -c -o $@ $< + $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3bar_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -Ii3bar/include -c -o $@ $< i3bar/i3bar: libi3.a $(i3bar_OBJECTS) echo "[i3bar] Link i3bar" diff --git a/i3bar/include/xcb.h b/i3bar/include/xcb.h index 03bfc51e..e5af39fa 100644 --- a/i3bar/include/xcb.h +++ b/i3bar/include/xcb.h @@ -12,10 +12,6 @@ #include //#include "outputs.h" -#ifdef XCB_COMPAT -#define XCB_ATOM_CARDINAL CARDINAL -#endif - #define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0 #define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1 #define SYSTEM_TRAY_REQUEST_DOCK 0 diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 9bf36187..d44da458 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -13,10 +13,6 @@ #include #include -#ifdef XCB_COMPAT -#include "xcb_compat.h" -#endif - #include #include #include diff --git a/include/all.h b/include/all.h index 85397d59..e39e27b9 100644 --- a/include/all.h +++ b/include/all.h @@ -38,11 +38,6 @@ #include #include -/* Contains compatibility definitions for old libxcb versions */ -#ifdef XCB_COMPAT -#include "xcb_compat.h" -#endif - #include "data.h" #include "util.h" #include "ipc.h" diff --git a/include/xcb_compat.h b/include/xcb_compat.h deleted file mode 100644 index 066d834a..00000000 --- a/include/xcb_compat.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * vim:ts=4:sw=4:expandtab - * - * i3 - an improved dynamic tiling window manager - * © 2009 Michael Stapelberg and contributors (see also: LICENSE) - * - * xcb_compat.h: uses #define to create aliases for xcb functions which got - * renamed. Makes the code work with >= 0.3.8 xcb-util and - * older versions. - * - */ -#pragma once - -#define xcb_icccm_get_wm_protocols_reply_t xcb_get_wm_protocols_reply_t -#define xcb_icccm_get_wm_protocols xcb_get_wm_protocols -#define xcb_icccm_get_wm_protocols_unchecked xcb_get_wm_protocols_unchecked -#define xcb_icccm_get_wm_protocols_reply xcb_get_wm_protocols_reply -#define xcb_icccm_get_wm_protocols_reply_wipe xcb_get_wm_protocols_reply_wipe -#define XCB_ICCCM_WM_STATE_NORMAL XCB_WM_STATE_NORMAL -#define XCB_ICCCM_WM_STATE_WITHDRAWN XCB_WM_STATE_WITHDRAWN -#define xcb_icccm_get_wm_size_hints_from_reply xcb_get_wm_size_hints_from_reply -#define xcb_icccm_get_wm_size_hints_reply xcb_get_wm_size_hints_reply -#define xcb_icccm_get_wm_normal_hints xcb_get_wm_normal_hints -#define xcb_icccm_get_wm_normal_hints_reply xcb_get_wm_normal_hints_reply -#define xcb_icccm_get_wm_normal_hints_unchecked xcb_get_wm_normal_hints_unchecked -#define XCB_ICCCM_SIZE_HINT_P_MIN_SIZE XCB_SIZE_HINT_P_MIN_SIZE -#define XCB_ICCCM_SIZE_HINT_P_MAX_SIZE XCB_SIZE_HINT_P_MAX_SIZE -#define XCB_ICCCM_SIZE_HINT_P_RESIZE_INC XCB_SIZE_HINT_P_RESIZE_INC -#define XCB_ICCCM_SIZE_HINT_BASE_SIZE XCB_SIZE_HINT_BASE_SIZE -#define XCB_ICCCM_SIZE_HINT_P_ASPECT XCB_SIZE_HINT_P_ASPECT -#define xcb_icccm_wm_hints_t xcb_wm_hints_t -#define xcb_icccm_get_wm_hints xcb_get_wm_hints -#define xcb_icccm_get_wm_hints_from_reply xcb_get_wm_hints_from_reply -#define xcb_icccm_get_wm_hints_reply xcb_get_wm_hints_reply -#define xcb_icccm_get_wm_hints_unchecked xcb_get_wm_hints_unchecked -#define xcb_icccm_wm_hints_get_urgency xcb_wm_hints_get_urgency -#define xcb_icccm_get_wm_transient_for_from_reply xcb_get_wm_transient_for_from_reply - -#define XCB_ATOM_CARDINAL CARDINAL -#define XCB_ATOM_WINDOW WINDOW -#define XCB_ATOM_WM_TRANSIENT_FOR WM_TRANSIENT_FOR -#define XCB_ATOM_WM_NAME WM_NAME -#define XCB_ATOM_WM_CLASS WM_CLASS -#define XCB_ATOM_WM_HINTS WM_HINTS -#define XCB_ATOM_ATOM ATOM -#define XCB_ATOM_WM_NORMAL_HINTS WM_NORMAL_HINTS -#define XCB_ATOM_STRING STRING diff --git a/libi3/libi3.mk b/libi3/libi3.mk index 965e3e49..d313a44e 100644 --- a/libi3/libi3.mk +++ b/libi3/libi3.mk @@ -10,7 +10,7 @@ libi3_OBJECTS := $(libi3_SOURCES:.c=.o) libi3/%.o: libi3/%.c $(libi3_HEADERS) echo "[libi3] CC $<" - $(CC) $(I3_CPPFLAGS) $(XCB_CPPFLAGS) $(CPPFLAGS) $(libi3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< + $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(libi3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< libi3.a: $(libi3_OBJECTS) echo "[libi3] AR libi3.a" diff --git a/src/i3.mk b/src/i3.mk index de747826..de3f6845 100644 --- a/src/i3.mk +++ b/src/i3.mk @@ -33,33 +33,33 @@ canonical_path := ../$(shell basename $(shell pwd -P)) include/all.h.pch: $(i3_HEADERS) echo "[i3] PCH all.h" - $(CC) $(I3_CPPFLAGS) $(XCB_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -x c-header include/all.h -o include/all.h.pch + $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -x c-header include/all.h -o include/all.h.pch src/version.o: src/version.c LAST_VERSION $(i3_HEADERS_DEP) echo "[i3] CC $<" - $(CC) $(I3_CPPFLAGS) $(XCB_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) $(PCH_FLAGS) -c -o $@ ${canonical_path}/$< + $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) $(PCH_FLAGS) -c -o $@ ${canonical_path}/$< src/%.o: src/%.c $(i3_HEADERS_DEP) echo "[i3] CC $<" - $(CC) $(I3_CPPFLAGS) $(XCB_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) $(PCH_FLAGS) -c -o $@ ${canonical_path}/$< + $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) $(PCH_FLAGS) -c -o $@ ${canonical_path}/$< test-tools: test.commands_parser test.config_parser test.commands_parser: src/commands_parser.c $(i3_HEADERS_DEP) i3-command-parser.stamp libi3.a echo "[i3] Link test.commands_parser" - $(CC) $(I3_CPPFLAGS) $(XCB_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) $(I3_LDFLAGS) $(LDFLAGS) -DTEST_PARSER -g -o test.commands_parser $< $(LIBS) $(i3_LIBS) + $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) $(I3_LDFLAGS) $(LDFLAGS) -DTEST_PARSER -g -o test.commands_parser $< $(LIBS) $(i3_LIBS) test.config_parser: src/config_parser.c $(i3_HEADERS_DEP) i3-config-parser.stamp libi3.a echo "[i3] Link test.config_parser" - $(CC) $(I3_CPPFLAGS) $(XCB_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) $(I3_LDFLAGS) $(LDFLAGS) -DTEST_PARSER -g -o test.config_parser $< $(LIBS) $(i3_LIBS) + $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) $(I3_LDFLAGS) $(LDFLAGS) -DTEST_PARSER -g -o test.config_parser $< $(LIBS) $(i3_LIBS) src/commands_parser.o: src/commands_parser.c $(i3_HEADERS_DEP) i3-command-parser.stamp echo "[i3] CC $<" - $(CC) $(I3_CPPFLAGS) $(XCB_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ ${canonical_path}/$< + $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ ${canonical_path}/$< src/config_parser.o: src/config_parser.c $(i3_HEADERS_DEP) i3-config-parser.stamp echo "[i3] CC $<" - $(CC) $(I3_CPPFLAGS) $(XCB_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ ${canonical_path}/$< + $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ ${canonical_path}/$< i3-command-parser.stamp: generate-command-parser.pl parser-specs/commands.spec echo "[i3] Generating command parser" From d4bf7b94d41010a315177f123df9cf7d8ccf6d8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 24 Sep 2016 19:53:02 +0200 Subject: [PATCH 098/150] Fix link in the documentation. (#2462) This replaces the dead pull request #2242. Thanks to @pniederlag for noticing the issue and providing the original PR. --- docs/userguide | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/userguide b/docs/userguide index 9abdd5b0..9472fdd7 100644 --- a/docs/userguide +++ b/docs/userguide @@ -2088,6 +2088,7 @@ See <> for how to move a container/workspace to a different RandR output. [[move_to_outputs]] +[[_moving_containers_workspaces_to_randr_outputs]] === Moving containers/workspaces to RandR outputs To move a container to another RandR output (addressed by names like +LVDS1+ or @@ -2572,7 +2573,7 @@ have more than one monitor: track of which window you put where. Thus, you can use vim-like marks to quickly switch between windows. See <>. 4. For information on how to move existing workspaces between monitors, - see <<_moving_containers_workspaces_to_randr_outputs>>. + see <>. == i3 and the rest of your software world From 23ee16077a7e419ec6fc2c995d6e8f273a8238ca Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 24 Sep 2016 12:24:47 -0700 Subject: [PATCH 099/150] travis: build ubuntu packages for xenial, not wily (#2474) The extra rm command when configuring the repository is necessary because of https://bugs.debian.org/838779. --- travis/bintray-autobuild-ubuntu.json | 4 ++-- travis/travis-base-ubuntu-386.Dockerfile | 5 +++-- travis/travis-base-ubuntu.Dockerfile | 5 +++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/travis/bintray-autobuild-ubuntu.json b/travis/bintray-autobuild-ubuntu.json index 2ceef7d4..79bd50c5 100644 --- a/travis/bintray-autobuild-ubuntu.json +++ b/travis/bintray-autobuild-ubuntu.json @@ -15,7 +15,7 @@ { "includePattern": "deb/ubuntu-amd64/(.*\\.deb)$", "matrixParams": { - "deb_distribution": "wily", + "deb_distribution": "xenial", "deb_component": "main", "deb_architecture": "amd64" }, @@ -24,7 +24,7 @@ { "includePattern": "deb/ubuntu-i386/(.*\\.deb)$", "matrixParams": { - "deb_distribution": "wily", + "deb_distribution": "xenial", "deb_component": "main", "deb_architecture": "i386" }, diff --git a/travis/travis-base-ubuntu-386.Dockerfile b/travis/travis-base-ubuntu-386.Dockerfile index c20cc41d..65f123c8 100644 --- a/travis/travis-base-ubuntu-386.Dockerfile +++ b/travis/travis-base-ubuntu-386.Dockerfile @@ -1,7 +1,7 @@ # vim:ft=Dockerfile # Same as travis-base.Dockerfile, but without the test suite dependencies since # we only build Debian packages on Ubuntu i386, we don’t run the tests. -FROM i386/ubuntu:wily +FROM i386/ubuntu:xenial RUN echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup # Paper over occasional network flakiness of some mirrors. @@ -24,9 +24,10 @@ RUN linux32 apt-get update && \ # Install i3 build dependencies. COPY debian/control /usr/src/i3-debian-packaging/control -RUN echo 'deb http://dl.bintray.com/i3/i3-autobuild-ubuntu wily main' > /etc/apt/sources.list.d/i3-autobuild.list && \ +RUN echo 'deb http://dl.bintray.com/i3/i3-autobuild-ubuntu xenial main' > /etc/apt/sources.list.d/i3-autobuild.list && \ linux32 apt-get update && \ linux32 apt-get --allow-unauthenticated install i3-autobuild-keyring && \ + rm -f /var/lib/apt/lists/dl.bintray.com_i3_i3-autobuild-ubuntu_* && \ linux32 apt-get update && \ DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ rm -rf /var/lib/apt/lists/* diff --git a/travis/travis-base-ubuntu.Dockerfile b/travis/travis-base-ubuntu.Dockerfile index e060fe0f..ab474691 100644 --- a/travis/travis-base-ubuntu.Dockerfile +++ b/travis/travis-base-ubuntu.Dockerfile @@ -1,7 +1,7 @@ # vim:ft=Dockerfile # Same as travis-base.Dockerfile, but without the test suite dependencies since # we only build Debian packages on Ubuntu, we don’t run the tests. -FROM ubuntu:wily +FROM ubuntu:xenial RUN echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup # Paper over occasional network flakiness of some mirrors. @@ -25,9 +25,10 @@ RUN apt-get update && \ # Install i3 build dependencies. COPY debian/control /usr/src/i3-debian-packaging/control -RUN echo 'deb http://dl.bintray.com/i3/i3-autobuild-ubuntu wily main' > /etc/apt/sources.list.d/i3-autobuild.list && \ +RUN echo 'deb http://dl.bintray.com/i3/i3-autobuild-ubuntu xenial main' > /etc/apt/sources.list.d/i3-autobuild.list && \ apt-get update && \ apt-get --allow-unauthenticated install i3-autobuild-keyring && \ + rm -f /var/lib/apt/lists/dl.bintray.com_i3_i3-autobuild-ubuntu_* && \ apt-get update && \ DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ rm -rf /var/lib/apt/lists/* From 655ed0ba27b262fe6bd3d308df37f79e3c10d7c9 Mon Sep 17 00:00:00 2001 From: koebi Date: Mon, 26 Sep 2016 17:01:30 +0200 Subject: [PATCH 100/150] fix i3bar crashing when I3SOCK present (#2471) When I3SOCK is present, socket_path might be a pointer to an environment variable, which cannot be free'd in line 157. This commit duplicates the string if I3SOCK is present, thus making socket_path a free-able pointer again. --- i3bar/src/main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/i3bar/src/main.c b/i3bar/src/main.c index 3b5d7546..14e42a2b 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -93,6 +93,9 @@ int main(int argc, char **argv) { int opt; int option_index = 0; char *socket_path = getenv("I3SOCK"); + if (socket_path != NULL) { + socket_path = sstrdup(socket_path); + } char *i3_default_sock_path = "/tmp/i3-ipc.sock"; /* Initialize the standard config to use 0 as default */ From 1437271e6568ab627536d85babd7a9f9f2fe7ae3 Mon Sep 17 00:00:00 2001 From: johannes karoff Date: Mon, 26 Sep 2016 18:45:58 +0200 Subject: [PATCH 101/150] do not match docks in config and command criteria (#2340) --- src/ipc.c | 2 +- src/load_layout.c | 1 + src/match.c | 3 +- src/restore_layout.c | 1 + testcases/t/264-dock-criteria.t | 71 +++++++++++++++++++++++++++++++++ 5 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 testcases/t/264-dock-criteria.t diff --git a/src/ipc.c b/src/ipc.c index a6c45ed1..bf529b17 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -480,7 +480,7 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) { if (match->restart_mode) continue; y(map_open); - if (match->dock != -1) { + if (match->dock != M_DONTCHECK) { ystr("dock"); y(integer, match->dock); ystr("insert_where"); diff --git a/src/load_layout.c b/src/load_layout.c index 863770b7..a3b44756 100644 --- a/src/load_layout.c +++ b/src/load_layout.c @@ -48,6 +48,7 @@ static int json_start_map(void *ctx) { LOG("creating new swallow\n"); current_swallow = smalloc(sizeof(Match)); match_init(current_swallow); + current_swallow->dock = M_DONTCHECK; TAILQ_INSERT_TAIL(&(json_node->swallow_head), current_swallow, matches); swallow_is_empty = true; } else { diff --git a/src/match.c b/src/match.c index d072b85f..ba87eb23 100644 --- a/src/match.c +++ b/src/match.c @@ -27,7 +27,6 @@ */ void match_init(Match *match) { memset(match, 0, sizeof(Match)); - match->dock = M_DONTCHECK; match->urgent = U_DONTCHECK; /* we use this as the placeholder value for "not set". */ match->window_type = UINT32_MAX; @@ -53,7 +52,7 @@ bool match_is_empty(Match *match) { match->id == XCB_NONE && match->window_type == UINT32_MAX && match->con_id == NULL && - match->dock == -1 && + match->dock == M_NODOCK && match->floating == M_ANY); } diff --git a/src/restore_layout.c b/src/restore_layout.c index 7e1b78ae..da018b9e 100644 --- a/src/restore_layout.c +++ b/src/restore_layout.c @@ -240,6 +240,7 @@ static void open_placeholder_window(Con *con) { /* create temporary id swallow to match the placeholder */ Match *temp_id = smalloc(sizeof(Match)); match_init(temp_id); + temp_id->dock = M_DONTCHECK; temp_id->id = placeholder; TAILQ_INSERT_HEAD(&(con->swallow_head), temp_id, matches); } diff --git a/testcases/t/264-dock-criteria.t b/testcases/t/264-dock-criteria.t new file mode 100644 index 00000000..cbbdeb0f --- /dev/null +++ b/testcases/t/264-dock-criteria.t @@ -0,0 +1,71 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Please read the following documents before working on tests: +# • http://build.i3wm.org/docs/testsuite.html +# (or docs/testsuite) +# +# • http://build.i3wm.org/docs/lib-i3test.html +# (alternatively: perldoc ./testcases/lib/i3test.pm) +# +# • http://build.i3wm.org/docs/ipc.html +# (or docs/ipc) +# +# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf +# (unless you are already familiar with Perl) +# +# Verifies that command or config criteria does not match dock clients +# Bug still in: 4.12-38-ge690e3d +use i3test i3_autostart => 0; + +my $config = < $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), + wm_class => "x" +}); + +is(get_dock_clients, 1, "created one docked client"); +is_num_children($ws, 0, 'no container on the current workspace'); + +cmd '[class="^x$"] move workspace current'; + +does_i3_live +is(get_dock_clients, 1, "one docked client after move"); +is_num_children($ws, 0, 'no container on the current workspace'); + +cmd '[class="^x$"] fullscreen'; + +does_i3_live +is(get_dock_clients, 1, "one docked client after fullscreen"); +is_num_children($ws, 0, 'no container on the current workspace'); + +cmd '[class="^x$"] kill'; + +does_i3_live +is(get_dock_clients, 1, "one docked client after kill"); +is_num_children($ws, 0, 'no container on the current workspace'); + + +## config criteria should not match dock windows +open_window({ + window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), + wm_class => "dock" +}); + +does_i3_live +is(get_dock_clients, 2, "created second docked client"); +is_num_children($ws, 0, 'no container on the current workspace'); + + +exit_gracefully($pid); +done_testing; From cb1fcfed6a918eba985530a262916b1b6a17f9b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Fri, 23 Sep 2016 15:09:49 +0200 Subject: [PATCH 102/150] Use Xft.dpi for DPI if available. fixes #2465 --- i3-config-wizard/i3-config-wizard.mk | 4 +- i3-input/i3-input.mk | 4 +- i3-nagbar/i3-nagbar.mk | 4 +- i3bar/i3bar.mk | 4 +- include/libi3.h | 7 ++++ libi3/dpi.c | 57 +++++++++++++++++++++++++++- libi3/libi3.mk | 2 +- src/main.c | 7 ++-- 8 files changed, 75 insertions(+), 14 deletions(-) diff --git a/i3-config-wizard/i3-config-wizard.mk b/i3-config-wizard/i3-config-wizard.mk index 2a761433..9c01cdb6 100644 --- a/i3-config-wizard/i3-config-wizard.mk +++ b/i3-config-wizard/i3-config-wizard.mk @@ -4,8 +4,8 @@ CLEAN_TARGETS += clean-i3-config-wizard i3_config_wizard_SOURCES := $(wildcard i3-config-wizard/*.c) i3_config_wizard_HEADERS := $(wildcard i3-config-wizard/*.h) -i3_config_wizard_CFLAGS = $(XCB_CFLAGS) $(XCB_KBD_CFLAGS) $(PANGO_CFLAGS) $(XKB_COMMON_CFLAGS) $(XKB_COMMON_X11_CFLAGS) -i3_config_wizard_LIBS = $(XCB_LIBS) $(XCB_KBD_LIBS) $(PANGO_LIBS) $(XKB_COMMON_LIBS) $(XKB_COMMON_X11_LIBS) +i3_config_wizard_CFLAGS = $(XCB_CFLAGS) $(XCB_KBD_CFLAGS) $(PANGO_CFLAGS) $(XCB_XRM_CFLAGS) $(XKB_COMMON_CFLAGS) $(XKB_COMMON_X11_CFLAGS) +i3_config_wizard_LIBS = $(XCB_LIBS) $(XCB_KBD_LIBS) $(PANGO_LIBS) $(XCB_XRM_LIBS) $(XKB_COMMON_LIBS) $(XKB_COMMON_X11_LIBS) i3_config_wizard_OBJECTS := $(i3_config_wizard_SOURCES:.c=.o) diff --git a/i3-input/i3-input.mk b/i3-input/i3-input.mk index 2b1f451e..ce36f932 100644 --- a/i3-input/i3-input.mk +++ b/i3-input/i3-input.mk @@ -4,8 +4,8 @@ CLEAN_TARGETS += clean-i3-input i3_input_SOURCES := $(wildcard i3-input/*.c) i3_input_HEADERS := $(wildcard i3-input/*.h) -i3_input_CFLAGS = $(XCB_CFLAGS) $(XCB_KBD_CFLAGS) $(PANGO_CFLAGS) -i3_input_LIBS = $(XCB_LIBS) $(XCB_KBD_LIBS) $(PANGO_LIBS) +i3_input_CFLAGS = $(XCB_CFLAGS) $(XCB_KBD_CFLAGS) $(PANGO_CFLAGS) $(XCB_XRM_CFLAGS) +i3_input_LIBS = $(XCB_LIBS) $(XCB_KBD_LIBS) $(PANGO_LIBS) $(XCB_XRM_LIBS) i3_input_OBJECTS := $(i3_input_SOURCES:.c=.o) diff --git a/i3-nagbar/i3-nagbar.mk b/i3-nagbar/i3-nagbar.mk index 564a7bc2..c6c7a2ef 100644 --- a/i3-nagbar/i3-nagbar.mk +++ b/i3-nagbar/i3-nagbar.mk @@ -4,8 +4,8 @@ CLEAN_TARGETS += clean-i3-nagbar i3_nagbar_SOURCES := $(wildcard i3-nagbar/*.c) i3_nagbar_HEADERS := $(wildcard i3-nagbar/*.h) -i3_nagbar_CFLAGS = $(XCB_CFLAGS) $(XCB_CURSOR_CFLAGS) $(XCB_WM_CFLAGS) $(PANGO_CFLAGS) -i3_nagbar_LIBS = $(XCB_LIBS) $(XCB_CURSOR_LIBS) $(XCB_WM_LIBS) $(PANGO_LIBS) +i3_nagbar_CFLAGS = $(XCB_CFLAGS) $(XCB_CURSOR_CFLAGS) $(XCB_WM_CFLAGS) $(PANGO_CFLAGS) $(XCB_XRM_CFLAGS) +i3_nagbar_LIBS = $(XCB_LIBS) $(XCB_CURSOR_LIBS) $(XCB_WM_LIBS) $(PANGO_LIBS) $(XCB_XRM_LIBS) i3_nagbar_OBJECTS := $(i3_nagbar_SOURCES:.c=.o) diff --git a/i3bar/i3bar.mk b/i3bar/i3bar.mk index 114e9314..03c607dd 100644 --- a/i3bar/i3bar.mk +++ b/i3bar/i3bar.mk @@ -4,8 +4,8 @@ CLEAN_TARGETS += clean-i3bar i3bar_SOURCES := $(wildcard i3bar/src/*.c) i3bar_HEADERS := $(wildcard i3bar/include/*.h) -i3bar_CFLAGS = $(XCB_CFLAGS) $(XCB_CURSOR_CFLAGS) $(PANGO_CFLAGS) $(YAJL_CFLAGS) $(LIBEV_CFLAGS) -i3bar_LIBS = $(XCB_LIBS) $(XCB_CURSOR_LIBS) $(PANGO_LIBS) $(YAJL_LIBS) $(LIBEV_LIBS) $(XCB_XKB_LIBS) +i3bar_CFLAGS = $(XCB_CFLAGS) $(XCB_CURSOR_CFLAGS) $(PANGO_CFLAGS) $(XCB_XRM_CFLAGS) $(YAJL_CFLAGS) $(LIBEV_CFLAGS) +i3bar_LIBS = $(XCB_LIBS) $(XCB_CURSOR_LIBS) $(PANGO_LIBS) $(XCB_XRM_LIBS) $(YAJL_LIBS) $(LIBEV_LIBS) $(XCB_XKB_LIBS) i3bar_OBJECTS := $(i3bar_SOURCES:.c=.o) diff --git a/include/libi3.h b/include/libi3.h index da5ad891..c1fe770b 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -470,6 +470,13 @@ char *get_process_filename(const char *prefix); */ char *get_exe_path(const char *argv0); +/** + * Initialize the DPI setting. + * This will use the 'Xft.dpi' X resource if available and fall back to + * guessing the correct value otherwise. + */ +void init_dpi(void); + /** * Convert a logical amount of pixels (e.g. 2 pixels on a “standard” 96 DPI * screen) to a corresponding amount of physical pixels on a standard or retina diff --git a/libi3/dpi.c b/libi3/dpi.c index 897e6e40..f105ef9a 100644 --- a/libi3/dpi.c +++ b/libi3/dpi.c @@ -7,6 +7,61 @@ */ #include "libi3.h" #include +#include +#include + +static long dpi; + +static long init_dpi_fallback(void) { + return (double)root_screen->height_in_pixels * 25.4 / (double)root_screen->height_in_millimeters; +} + +/* + * Initialize the DPI setting. + * This will use the 'Xft.dpi' X resource if available and fall back to + * guessing the correct value otherwise. + */ +void init_dpi(void) { + xcb_xrm_database_t *database = NULL; + + if (conn == NULL) { + goto init_dpi_end; + } + + database = xcb_xrm_database_from_default(conn); + if (database == NULL) { + ELOG("Failed to open the resource database.\n"); + goto init_dpi_end; + } + + char *resource; + xcb_xrm_resource_get_string(database, "Xft.dpi", NULL, &resource); + if (resource == NULL) { + DLOG("Resource Xft.dpi not specified, skipping.\n"); + goto init_dpi_end; + } + + char *endptr; + dpi = strtol(resource, &endptr, 10); + if (dpi == LONG_MAX || dpi == LONG_MIN || dpi < 0 || *endptr != '\0' || endptr == resource) { + ELOG("Xft.dpi = %s is an invalid number and couldn't be parsed.\n", resource); + dpi = 0; + goto init_dpi_end; + } + + DLOG("Found Xft.dpi = %ld.\n", dpi); + +init_dpi_end: + if (database != NULL) { + xcb_xrm_database_free(database); + } + + if (dpi == 0) { + DLOG("Using fallback for calculating DPI.\n"); + dpi = init_dpi_fallback(); + DLOG("Using dpi = %ld\n", dpi); + } +} /* * Convert a logical amount of pixels (e.g. 2 pixels on a “standard” 96 DPI @@ -21,8 +76,6 @@ int logical_px(const int logical) { return logical; } - const int dpi = (double)root_screen->height_in_pixels * 25.4 / - (double)root_screen->height_in_millimeters; /* There are many misconfigurations out there, i.e. systems with screens * whose dpi is in fact higher than 96 dpi, but not significantly higher, * so software was never adapted. We could tell people to reconfigure their diff --git a/libi3/libi3.mk b/libi3/libi3.mk index d313a44e..16e1f149 100644 --- a/libi3/libi3.mk +++ b/libi3/libi3.mk @@ -2,7 +2,7 @@ CLEAN_TARGETS += clean-libi3 libi3_SOURCES := $(wildcard libi3/*.c) libi3_HEADERS := $(wildcard libi3/*.h) -libi3_CFLAGS = $(PANGO_CFLAGS) +libi3_CFLAGS = $(PANGO_CFLAGS) $(XCB_XRM_CFLAGS) libi3_LIBS = libi3_OBJECTS := $(libi3_SOURCES:.c=.o) diff --git a/src/main.c b/src/main.c index 5362d077..96eab671 100644 --- a/src/main.c +++ b/src/main.c @@ -503,10 +503,11 @@ int main(int argc, char *argv[]) { visual_type = get_visualtype(root_screen); } + init_dpi(); + DLOG("root_depth = %d, visual_id = 0x%08x.\n", root_depth, visual_type->visual_id); - DLOG("root_screen->height_in_pixels = %d, root_screen->height_in_millimeters = %d, dpi = %d\n", - root_screen->height_in_pixels, root_screen->height_in_millimeters, - (int)((double)root_screen->height_in_pixels * 25.4 / (double)root_screen->height_in_millimeters)); + DLOG("root_screen->height_in_pixels = %d, root_screen->height_in_millimeters = %d\n", + root_screen->height_in_pixels, root_screen->height_in_millimeters); DLOG("One logical pixel corresponds to %d physical pixels on this display.\n", logical_px(1)); xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(conn, root); From 889d0abe8f397da9a39db9566e34cdfbb37d01fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 24 Sep 2016 23:48:33 +0200 Subject: [PATCH 103/150] Set $HOME for tests. We add $HOME to the environment variables we define for a test case in order to redirect it from the user's actual home directory. This is necessary because xcb-util-xrm will fall back to $HOME/.Xresources when determining the DPI. If a user has this set to, e.g., 192 on their machine, this would break tests. Since tests shouldn't rely on the system they run in, we redirect the home directory altogether to simulate a clean slate. relates to #2465 --- testcases/lib/TestWorker.pm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/testcases/lib/TestWorker.pm b/testcases/lib/TestWorker.pm index 140537d4..6371591f 100644 --- a/testcases/lib/TestWorker.pm +++ b/testcases/lib/TestWorker.pm @@ -112,8 +112,9 @@ sub worker_wait { $test->failure_output(\*STDERR); $test->todo_output(\*STDOUT); - @ENV{qw(DISPLAY TESTNAME OUTDIR VALGRIND STRACE XTRACE COVERAGE RESTART)} - = ($self->{display}, + @ENV{qw(HOME DISPLAY TESTNAME OUTDIR VALGRIND STRACE XTRACE COVERAGE RESTART)} + = ($outdir, + $self->{display}, basename($file), $outdir, $options->{valgrind}, From 47b84ca5ed0773896c69cc2b217845ed0c80e999 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 26 Sep 2016 17:26:37 +0200 Subject: [PATCH 104/150] travis-base.Dockerfile: depend on perl, not perl-modules As per the package description, perl-modules is an implementation detail and packages should depend on perl instead. --- travis/travis-base.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis/travis-base.Dockerfile b/travis/travis-base.Dockerfile index 0861b26a..85fa2752 100644 --- a/travis/travis-base.Dockerfile +++ b/travis/travis-base.Dockerfile @@ -19,7 +19,7 @@ RUN apt-get update && \ dpkg-dev devscripts git equivs \ clang clang-format-3.5 \ lintian \ - libanyevent-perl libanyevent-i3-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-modules 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 libanyevent-i3-perl && \ + libanyevent-perl libanyevent-i3-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 libanyevent-i3-perl && \ rm -rf /var/lib/apt/lists/* # Install i3 build dependencies. From 8f9138fbad1e88490a2f2ca83987a01d925e39a5 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 26 Sep 2016 17:29:27 +0200 Subject: [PATCH 105/150] t/158-wm_take_focus.t: avoid shift on scalars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This feature is forbidden in Perl ≥ 5.24: Experimental shift on scalar is now forbidden at ./t/158-wm_take_focus.t line 94, near ");" --- testcases/t/158-wm_take_focus.t | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/testcases/t/158-wm_take_focus.t b/testcases/t/158-wm_take_focus.t index b8dae3b1..5d481924 100644 --- a/testcases/t/158-wm_take_focus.t +++ b/testcases/t/158-wm_take_focus.t @@ -56,7 +56,8 @@ subtest 'Window without WM_TAKE_FOCUS', sub { ok(!recv_take_focus($window), 'did not receive ClientMessage'); - my $con = shift get_ws_content($ws); + my ($nodes) = get_ws_content($ws); + my $con = shift @$nodes; ok($con->{focused}, 'con is focused'); done_testing; @@ -91,7 +92,8 @@ subtest 'Window with WM_TAKE_FOCUS and without InputHint', sub { ok(!recv_take_focus($window), 'did not receive ClientMessage'); - my $con = shift get_ws_content($ws); + my ($nodes) = get_ws_content($ws); + my $con = shift @$nodes; ok($con->{focused}, 'con is focused'); done_testing; @@ -111,7 +113,8 @@ subtest 'Window with WM_TAKE_FOCUS and unspecified InputHint', sub { ok(!recv_take_focus($window), 'did not receive ClientMessage'); - my $con = shift get_ws_content($ws); + my ($nodes) = get_ws_content($ws); + my $con = shift @$nodes; ok($con->{focused}, 'con is focused'); done_testing; From b638ce2e4cd10910c4b47f4cb843f76c8a3522ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Tue, 27 Sep 2016 03:31:16 +0200 Subject: [PATCH 106/150] Check output crossing on ENTER_NOTIFY to dockarea. (#2477) When receiving an ENTER_NOTIFY event on a dock client we returned as to not focus the dock client (cf. #321 and #323). However, we still need to check for crossing output boundaries and if that happened focus the new output. Otherwise it can happen that the cursor is on a different output than the focused output. When opening a window, this would open it on the old output and then warp the mouse there. This effect will be even worse if the window is immediately moved with 'move position mouse' as the window will end up in its correct position on the new output and the cursor warped to the old output. relates to #2081 --- src/handlers.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/handlers.c b/src/handlers.c index 68fba0c4..8a84f335 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -148,18 +148,15 @@ static void handle_enter_notify(xcb_enter_notify_event_t *event) { enter_child = true; } - /* If not, then the user moved their cursor to the root window. In that case, we adjust c_ws */ - if (con == NULL) { + /* If we cannot find the container, the user moved their cursor to the root + * window. In this case and if they used it to a dock, we need to focus the + * workspace on the correct output. */ + if (con == NULL || con->parent->type == CT_DOCKAREA) { DLOG("Getting screen at %d x %d\n", event->root_x, event->root_y); check_crossing_screen_boundary(event->root_x, event->root_y); return; } - if (con->parent->type == CT_DOCKAREA) { - DLOG("Ignoring, this is a dock client\n"); - return; - } - /* see if the user entered the window on a certain window decoration */ layout_t layout = (enter_child ? con->parent->layout : con->layout); if (layout == L_DEFAULT) { From f4f9b7102d9f19e7cf8f5d255c067cd332491676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Tue, 27 Sep 2016 03:32:05 +0200 Subject: [PATCH 107/150] Handle _NET_ACTIVE_WINDOW for scratchpad windows. (#2458) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We call scratchpad_show() on _NET_ACTIVE_WINDOW requests if the request came from a pager. This is consistent with the i3 »focus« command because we assume the user requested to see the window, so we do the only sensible thing. fixes #2455 --- src/handlers.c | 18 +++++++++++++----- testcases/t/195-net-active-window.t | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/handlers.c b/src/handlers.c index 8a84f335..bd391176 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -713,14 +713,13 @@ static void handle_client_message(xcb_client_message_event_t *event) { } Con *ws = con_get_workspace(con); - if (ws == NULL) { DLOG("Window is not being managed, ignoring _NET_ACTIVE_WINDOW\n"); return; } - if (con_is_internal(ws)) { - DLOG("Workspace is internal, ignoring _NET_ACTIVE_WINDOW\n"); + if (con_is_internal(ws) && ws != workspace_get("__i3_scratch", NULL)) { + DLOG("Workspace is internal but not scratchpad, ignoring _NET_ACTIVE_WINDOW\n"); return; } @@ -729,10 +728,19 @@ static void handle_client_message(xcb_client_message_event_t *event) { /* Always focus the con if it is from a pager, because this is most * likely from some user action */ DLOG("This request came from a pager. Focusing con = %p\n", con); - workspace_show(ws); - con_focus(con); + + if (con_is_internal(ws)) { + scratchpad_show(con); + } else { + workspace_show(ws); + con_focus(con); + } } else { /* Request is from an application. */ + if (con_is_internal(ws)) { + DLOG("Ignoring request to make con = %p active because it's on an internal workspace.\n", con); + return; + } if (config.focus_on_window_activation == FOWA_FOCUS || (config.focus_on_window_activation == FOWA_SMART && workspace_is_visible(ws))) { DLOG("Focusing con = %p\n", con); diff --git a/testcases/t/195-net-active-window.t b/testcases/t/195-net-active-window.t index 032e5452..804a7add 100644 --- a/testcases/t/195-net-active-window.t +++ b/testcases/t/195-net-active-window.t @@ -39,6 +39,7 @@ sub send_net_active_window { 0; $x->send_event(0, $x->get_root_window(), X11::XCB::EVENT_MASK_SUBSTRUCTURE_REDIRECT, $msg); + sync_with_i3; } sub get_net_active_window { @@ -131,6 +132,23 @@ send_net_active_window($scratch->id); is($x->input_focus, $win3->id, 'window 3 still focused'); +################################################################################ +# A scratchpad window should be shown if _NET_ACTIVE_WINDOW from a pager +# is received. +################################################################################ + +my $scratch = open_window; + +is($x->input_focus, $scratch->id, 'to-scratchpad window has focus'); + +cmd 'move scratchpad'; + +is($x->input_focus, $win3->id, 'focus reverted to window 3'); + +send_net_active_window($scratch->id, 'pager'); + +is($x->input_focus, $scratch->id, 'scratchpad window is shown'); + ################################################################################ # Verify that the _NET_ACTIVE_WINDOW property is updated on the root window # correctly. From c93056b2d892b094926d9536583201f0f90baea6 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 26 Sep 2016 19:04:13 -0700 Subject: [PATCH 108/150] Unconditionally depend on libpcre >= 8.10 (#2472) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Even Debian oldstable has 8.30, so let’s get rid of conditional compilation where we don’t actually need it. --- common.mk | 4 ++-- debian/control | 2 +- src/regex.c | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/common.mk b/common.mk index 2bd879d4..7df415eb 100644 --- a/common.mk +++ b/common.mk @@ -135,8 +135,8 @@ LIBEV_LIBS := $(call ldflags_for_lib, libev,ev) # libpcre PCRE_CFLAGS := $(call cflags_for_lib, libpcre) -ifeq ($(shell $(PKG_CONFIG) --atleast-version=8.10 libpcre 2>/dev/null && echo 1),1) -I3_CPPFLAGS += -DPCRE_HAS_UCP=1 +ifneq ($(shell $(PKG_CONFIG) --atleast-version=8.10 libpcre 2>/dev/null && echo 1),1) +$(error "libpcre >= 8.10 not found") endif PCRE_LIBS := $(call ldflags_for_lib, libpcre,pcre) diff --git a/debian/control b/debian/control index 6b1530b8..c1e655d8 100644 --- a/debian/control +++ b/debian/control @@ -20,7 +20,7 @@ Build-Depends: debhelper (>= 9), pkg-config, libev-dev (>= 1:4.04), libyajl-dev (>= 2.0.4), - libpcre3-dev, + libpcre3-dev (>= 1:8.10), libstartup-notification0-dev (>= 0.10), libcairo2-dev, libpango1.0-dev, diff --git a/src/regex.c b/src/regex.c index 24846981..12c0b67f 100644 --- a/src/regex.c +++ b/src/regex.c @@ -28,11 +28,9 @@ struct regex *regex_new(const char *pattern) { struct regex *re = scalloc(1, sizeof(struct regex)); re->pattern = sstrdup(pattern); int options = PCRE_UTF8; -#ifdef PCRE_HAS_UCP /* We use PCRE_UCP so that \B, \b, \D, \d, \S, \s, \W, \w and some POSIX * character classes play nicely with Unicode */ options |= PCRE_UCP; -#endif while (!(re->regex = pcre_compile2(pattern, options, &errorcode, &error, &offset, NULL))) { /* If the error is that PCRE was not compiled with UTF-8 support we * disable it and try again */ From a15ce8cb8dddf118ed27deb79eb5d1b4103e8303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Tue, 27 Sep 2016 07:39:17 +0200 Subject: [PATCH 109/150] Assign the sticky value for _NET_WM_DESKTOP on scratchpad windows. (#2457) fixes #2456 --- src/ewmh.c | 23 ++++++++++++++++------- src/manage.c | 5 ++++- testcases/t/529-net-wm-desktop.t | 20 ++++++++++++++++++++ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/ewmh.c b/src/ewmh.c index c4ae844e..5459c7e9 100644 --- a/src/ewmh.c +++ b/src/ewmh.c @@ -124,11 +124,13 @@ void ewmh_update_desktop_viewport(void) { } static void ewmh_update_wm_desktop_recursively(Con *con, const uint32_t desktop) { - /* Recursively call this to descend through the entire subtree. */ Con *child; + + /* Recursively call this to descend through the entire subtree. */ 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) { @@ -139,8 +141,6 @@ static void ewmh_update_wm_desktop_recursively(Con *con, const uint32_t desktop) if (!con_has_managed_window(con)) return; - const xcb_window_t window = con->window->id; - uint32_t wm_desktop = desktop; /* Sticky windows are only actually sticky when they are floating or inside * a floating container. This is technically still slightly wrong, since @@ -151,11 +151,20 @@ static void ewmh_update_wm_desktop_recursively(Con *con, const uint32_t desktop) wm_desktop = NET_WM_DESKTOP_ALL; } + /* If the window is on the scratchpad we assign the sticky value to it + * since showing it works on any workspace. We cannot remove the property + * as per specification. */ + Con *ws = con_get_workspace(con); + if (ws != NULL && con_is_internal(ws)) { + wm_desktop = NET_WM_DESKTOP_ALL; + } + /* If this is the cached value, we don't need to do anything. */ if (con->window->wm_desktop == wm_desktop) return; con->window->wm_desktop = wm_desktop; + const xcb_window_t window = con->window->id; if (wm_desktop != NET_WM_DESKTOP_NONE) { DLOG("Setting _NET_WM_DESKTOP = %d for window 0x%08x.\n", wm_desktop, window); xcb_change_property(conn, XCB_PROP_MODE_REPLACE, window, A__NET_WM_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, &wm_desktop); @@ -179,11 +188,11 @@ void ewmh_update_wm_desktop(void) { TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { Con *workspace; TAILQ_FOREACH(workspace, &(output_get_content(output)->nodes_head), nodes) { - if (con_is_internal(workspace)) - continue; - ewmh_update_wm_desktop_recursively(workspace, desktop); - ++desktop; + + if (!con_is_internal(workspace)) { + ++desktop; + } } } } diff --git a/src/manage.c b/src/manage.c index 37d50e7b..bbd84007 100644 --- a/src/manage.c +++ b/src/manage.c @@ -430,7 +430,10 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki if (xcb_reply_contains_atom(state_reply, A__NET_WM_STATE_STICKY)) nc->sticky = true; - if (cwindow->wm_desktop == NET_WM_DESKTOP_ALL) { + /* We ignore the hint for an internal workspace because windows in the + * scratchpad also have this value, but upon restarting i3 we don't want + * them to become sticky windows. */ + if (cwindow->wm_desktop == NET_WM_DESKTOP_ALL && !con_is_internal(ws)) { DLOG("This window has _NET_WM_DESKTOP = 0xFFFFFFFF. Will float it and make it sticky.\n"); nc->sticky = true; want_floating = true; diff --git a/testcases/t/529-net-wm-desktop.t b/testcases/t/529-net-wm-desktop.t index f6a3b218..8f2df735 100644 --- a/testcases/t/529-net-wm-desktop.t +++ b/testcases/t/529-net-wm-desktop.t @@ -345,6 +345,26 @@ is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated'); kill_windows; exit_gracefully($pid); +############################################################################### +# _NET_WM_DESKTOP is updated when a window is moved to the scratchpad. +############################################################################### + +$pid = launch_with_config($config); + +cmd 'workspace 0'; +$con = open_window; +cmd 'floating enable'; +is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)'); + +cmd 'move scratchpad'; +is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated'); + +cmd 'scratchpad show'; +is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)'); + +kill_windows; +exit_gracefully($pid); + ############################################################################### done_testing; From 0e73a6e9e7dcc0a01b8666f85bc279a72f7c5936 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 27 Sep 2016 12:57:00 -0700 Subject: [PATCH 110/150] Remove conditional compilation for cairo/pangocairo (#2480) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We strive to avoid conditional compilation in i3 as much as possible. cairo and pangocairo have been around long enough in the versions that we need that it’s time to unconditionally depend on them. Also update DEPENDS with the last-known-good-versions while at it. --- DEPENDS | 18 +++++++++--------- common.mk | 5 ++--- debian/control | 2 +- include/libi3.h | 10 ---------- libi3/draw_util.c | 37 ------------------------------------- libi3/font.c | 22 ---------------------- libi3/string.c | 6 ------ src/util.c | 2 -- 8 files changed, 12 insertions(+), 90 deletions(-) diff --git a/DEPENDS b/DEPENDS index 227aaec3..167827ff 100644 --- a/DEPENDS +++ b/DEPENDS @@ -7,25 +7,25 @@ ┌──────────────┬────────┬────────┬───────────────────────────────────────────────────────────┐ │ dependency │ min. │ lkgv │ URL │ ├──────────────┼────────┼────────┼───────────────────────────────────────────────────────────┤ -│ pkg-config │ 0.25 │ 0.28 │ http://pkgconfig.freedesktop.org/ │ -│ libxcb │ 1.1.93 │ 1.11 │ http://xcb.freedesktop.org/dist/ │ +│ pkg-config │ 0.25 │ 0.29 │ http://pkgconfig.freedesktop.org/ │ +│ libxcb │ 1.1.93 │ 1.12 │ http://xcb.freedesktop.org/dist/ │ │ xcb-util │ 0.3.3 │ 0.4.1 │ http://xcb.freedesktop.org/dist/ │ -│ xkbcommon │ 0.4.0 │ 0.5.0 │ http://xkbcommon.org/ │ -│ xkbcommon-x11│ 0.4.0 │ 0.5.0 │ http://xkbcommon.org/ │ -│ util-cursor³⁴│ 0.0.99 │ 0.1.2 │ http://xcb.freedesktop.org/dist/ │ +│ xkbcommon │ 0.4.0 │ 0.6.1 │ http://xkbcommon.org/ │ +│ xkbcommon-x11│ 0.4.0 │ 0.6.1 │ http://xkbcommon.org/ │ +│ util-cursor³⁴│ 0.0.99 │ 0.1.3 │ http://xcb.freedesktop.org/dist/ │ │ util-wm⁴ │ 0.3.8 │ 0.3.8 │ http://xcb.freedesktop.org/dist/ │ │ util-keysyms⁴│ 0.3.8 │ 0.4.0 │ http://xcb.freedesktop.org/dist/ │ │ util-xrm⁴ │ 1.0.0 │ 1.0.0 │ https://github.com/Airblader/xcb-util-xrm │ │ libev │ 4.0 │ 4.19 │ http://libev.schmorp.de/ │ │ yajl │ 2.0.1 │ 2.1.0 │ http://lloyd.github.com/yajl/ │ -│ asciidoc │ 8.3.0 │ 8.6.8 │ http://www.methods.co.nz/asciidoc/ │ +│ asciidoc │ 8.3.0 │ 8.6.9 │ http://www.methods.co.nz/asciidoc/ │ │ xmlto │ 0.0.23 │ 0.0.23 │ http://www.methods.co.nz/asciidoc/ │ │ Pod::Simple² │ 3.22 │ 3.22 │ http://search.cpan.org/~dwheeler/Pod-Simple-3.23/ │ │ docbook-xml │ 4.5 │ 4.5 │ http://www.methods.co.nz/asciidoc/ │ -│ PCRE │ 8.12 │ 8.35 │ http://www.pcre.org/ │ +│ PCRE │ 8.12 │ 8.38 │ http://www.pcre.org/ │ │ libsn¹ │ 0.10 │ 0.12 │ http://freedesktop.org/wiki/Software/startup-notification │ -│ pango │ 1.30.0 | 1.36.8 │ http://www.pango.org/ │ -│ cairo │ 1.14.4 │ 1.14.4 │ http://cairographics.org/ │ +│ pango │ 1.30.0 | 1.40.1 │ http://www.pango.org/ │ +│ cairo │ 1.14.4 │ 1.14.6 │ http://cairographics.org/ │ └──────────────┴────────┴────────┴───────────────────────────────────────────────────────────┘ ¹ libsn = libstartup-notification ² Pod::Simple is a Perl module required for converting the testsuite diff --git a/common.mk b/common.mk index 7df415eb..6032ce6c 100644 --- a/common.mk +++ b/common.mk @@ -147,9 +147,8 @@ LIBSN_LIBS := $(call ldflags_for_lib, libstartup-notification-1.0,startup-noti # Pango PANGO_CFLAGS := $(call cflags_for_lib, cairo) PANGO_CFLAGS += $(call cflags_for_lib, pangocairo) -I3_CPPFLAGS += -DPANGO_SUPPORT=1 -ifeq ($(shell $(PKG_CONFIG) --atleast-version=1.14.4 cairo 2>/dev/null && echo 1),1) -I3_CPPFLAGS += -DCAIRO_SUPPORT=1 +ifneq ($(shell $(PKG_CONFIG) --atleast-version=1.14.4 cairo 2>/dev/null && echo 1),1) +$(error "cairo >= 1.14.4 missing") endif PANGO_LIBS := $(call ldflags_for_lib, cairo) PANGO_LIBS += $(call ldflags_for_lib, pangocairo) diff --git a/debian/control b/debian/control index c1e655d8..5fa675c1 100644 --- a/debian/control +++ b/debian/control @@ -22,7 +22,7 @@ Build-Depends: debhelper (>= 9), libyajl-dev (>= 2.0.4), libpcre3-dev (>= 1:8.10), libstartup-notification0-dev (>= 0.10), - libcairo2-dev, + libcairo2-dev (>= 1.14.4), libpango1.0-dev, libpod-simple-perl Standards-Version: 3.9.7 diff --git a/include/libi3.h b/include/libi3.h index c1fe770b..5123ce01 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -17,12 +17,8 @@ #include #include -#if PANGO_SUPPORT #include -#endif -#if CAIRO_SUPPORT #include -#endif #define DEFAULT_DIR_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) @@ -73,10 +69,8 @@ struct Font { xcb_charinfo_t *table; } xcb; -#if PANGO_SUPPORT /** The pango font description */ PangoFontDescription *pango_desc; -#endif } specific; }; @@ -525,7 +519,6 @@ typedef struct placeholder_t { */ char *format_placeholders(char *format, placeholder_t *placeholders, int num); -#if CAIRO_SUPPORT /* We need to flush cairo surfaces twice to avoid an assertion bug. See #1989 * and https://bugs.freedesktop.org/show_bug.cgi?id=92455. */ #define CAIRO_SURFACE_FLUSH(surface) \ @@ -533,7 +526,6 @@ char *format_placeholders(char *format, placeholder_t *placeholders, int num); cairo_surface_flush(surface); \ cairo_surface_flush(surface); \ } while (0) -#endif /* A wrapper grouping an XCB drawable and both a graphics context * and the corresponding cairo objects representing it. */ @@ -549,14 +541,12 @@ typedef struct surface_t { int width; int height; -#if CAIRO_SUPPORT /* A cairo surface representing the drawable. */ cairo_surface_t *surface; /* The cairo object representing the drawable. In general, * this is what one should use for any drawing operation. */ cairo_t *cr; -#endif } surface_t; /** diff --git a/libi3/draw_util.c b/libi3/draw_util.c index b69d51b4..56b1bce8 100644 --- a/libi3/draw_util.c +++ b/libi3/draw_util.c @@ -11,9 +11,7 @@ #include #include #include -#if CAIRO_SUPPORT #include -#endif #include "libi3.h" @@ -50,10 +48,8 @@ void draw_util_surface_init(xcb_connection_t *conn, surface_t *surface, xcb_draw ELOG("Could not create graphical context. Error code: %d. Please report this bug.\n", error->error_code); } -#if CAIRO_SUPPORT surface->surface = cairo_xcb_surface_create(conn, surface->id, surface->visual_type, width, height); surface->cr = cairo_create(surface->surface); -#endif } /* @@ -62,7 +58,6 @@ void draw_util_surface_init(xcb_connection_t *conn, surface_t *surface, xcb_draw */ void draw_util_surface_free(xcb_connection_t *conn, surface_t *surface) { xcb_free_gc(conn, surface->gc); -#if CAIRO_SUPPORT cairo_surface_destroy(surface->surface); cairo_destroy(surface->cr); @@ -71,7 +66,6 @@ void draw_util_surface_free(xcb_connection_t *conn, surface_t *surface) { * when setting the border of a window to none and then closing it. */ surface->surface = NULL; surface->cr = NULL; -#endif } /* @@ -81,9 +75,7 @@ void draw_util_surface_free(xcb_connection_t *conn, surface_t *surface) { void draw_util_surface_set_size(surface_t *surface, int width, int height) { surface->width = width; surface->height = height; -#if CAIRO_SUPPORT cairo_xcb_surface_set_size(surface->surface, width, height); -#endif } /* @@ -121,13 +113,7 @@ color_t draw_util_hex_to_color(const char *color) { static void draw_util_set_source_color(xcb_connection_t *conn, surface_t *surface, color_t color) { RETURN_UNLESS_SURFACE_INITIALIZED(surface); -#if CAIRO_SUPPORT cairo_set_source_rgba(surface->cr, color.red, color.green, color.blue, color.alpha); -#else - uint32_t colorpixel = color.colorpixel; - xcb_change_gc(conn, surface->gc, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, - (uint32_t[]){colorpixel, colorpixel}); -#endif } /** @@ -139,18 +125,14 @@ static void draw_util_set_source_color(xcb_connection_t *conn, surface_t *surfac void draw_util_text(i3String *text, surface_t *surface, color_t fg_color, color_t bg_color, int x, int y, int max_width) { RETURN_UNLESS_SURFACE_INITIALIZED(surface); -#if CAIRO_SUPPORT /* Flush any changes before we draw the text as this might use XCB directly. */ CAIRO_SURFACE_FLUSH(surface->surface); -#endif set_font_colors(surface->gc, fg_color, bg_color); draw_text(text, surface->id, surface->gc, surface->visual_type, x, y, max_width); -#if CAIRO_SUPPORT /* Notify cairo that we (possibly) used another way to draw on the surface. */ cairo_surface_mark_dirty(surface->surface); -#endif } /** @@ -162,7 +144,6 @@ void draw_util_text(i3String *text, surface_t *surface, color_t fg_color, color_ void draw_util_rectangle(xcb_connection_t *conn, surface_t *surface, color_t color, double x, double y, double w, double h) { RETURN_UNLESS_SURFACE_INITIALIZED(surface); -#if CAIRO_SUPPORT cairo_save(surface->cr); /* Using the SOURCE operator will copy both color and alpha information directly @@ -179,12 +160,6 @@ void draw_util_rectangle(xcb_connection_t *conn, surface_t *surface, color_t col CAIRO_SURFACE_FLUSH(surface->surface); cairo_restore(surface->cr); -#else - draw_util_set_source_color(conn, surface, color); - - xcb_rectangle_t rect = {x, y, w, h}; - xcb_poly_fill_rectangle(conn, surface->id, surface->gc, 1, &rect); -#endif } /** @@ -194,7 +169,6 @@ void draw_util_rectangle(xcb_connection_t *conn, surface_t *surface, color_t col void draw_util_clear_surface(xcb_connection_t *conn, surface_t *surface, color_t color) { RETURN_UNLESS_SURFACE_INITIALIZED(surface); -#if CAIRO_SUPPORT cairo_save(surface->cr); /* Using the SOURCE operator will copy both color and alpha information directly @@ -210,12 +184,6 @@ void draw_util_clear_surface(xcb_connection_t *conn, surface_t *surface, color_t CAIRO_SURFACE_FLUSH(surface->surface); cairo_restore(surface->cr); -#else - draw_util_set_source_color(conn, surface, color); - - xcb_rectangle_t rect = {0, 0, surface->width, surface->height}; - xcb_poly_fill_rectangle(conn, surface->id, surface->gc, 1, &rect); -#endif } /** @@ -227,7 +195,6 @@ void draw_util_copy_surface(xcb_connection_t *conn, surface_t *src, surface_t *d RETURN_UNLESS_SURFACE_INITIALIZED(src); RETURN_UNLESS_SURFACE_INITIALIZED(dest); -#if CAIRO_SUPPORT cairo_save(dest->cr); /* Using the SOURCE operator will copy both color and alpha information directly @@ -245,8 +212,4 @@ void draw_util_copy_surface(xcb_connection_t *conn, surface_t *src, surface_t *d CAIRO_SURFACE_FLUSH(dest->surface); cairo_restore(dest->cr); -#else - xcb_copy_area(conn, src->id, dest->id, dest->gc, (int16_t)src_x, (int16_t)src_y, - (int16_t)dest_x, (int16_t)dest_y, (uint16_t)width, (uint16_t)height); -#endif } diff --git a/libi3/font.c b/libi3/font.c index 00e7dfb3..7c305e25 100644 --- a/libi3/font.c +++ b/libi3/font.c @@ -13,15 +13,12 @@ #include #include -#if PANGO_SUPPORT #include -#endif #include "libi3.h" static const i3Font *savedFont = NULL; -#if PANGO_SUPPORT static xcb_visualtype_t *root_visual_type; static double pango_font_red; static double pango_font_green; @@ -166,7 +163,6 @@ static int predict_text_width_pango(const char *text, size_t text_len, bool pang return width; } -#endif /* * Loads a font for usage, also getting its metrics. If fallback is true, @@ -187,7 +183,6 @@ i3Font load_font(const char *pattern, const bool fallback) { return font; } -#if PANGO_SUPPORT /* Try to load a pango font if specified */ if (strlen(pattern) > strlen("pango:") && !strncmp(pattern, "pango:", strlen("pango:"))) { const char *font_pattern = pattern + strlen("pango:"); @@ -202,7 +197,6 @@ i3Font load_font(const char *pattern, const bool fallback) { return font; } } -#endif /* Send all our requests first */ font.specific.xcb.id = xcb_generate_id(conn); @@ -297,12 +291,10 @@ void free_font(void) { free(savedFont->specific.xcb.info); break; } -#if PANGO_SUPPORT case FONT_TYPE_PANGO: /* Free the font description */ pango_font_description_free(savedFont->specific.pango_desc); break; -#endif default: assert(false); break; @@ -329,14 +321,12 @@ void set_font_colors(xcb_gcontext_t gc, color_t foreground, color_t background) xcb_change_gc(conn, gc, mask, values); break; } -#if PANGO_SUPPORT case FONT_TYPE_PANGO: /* Save the foreground font */ pango_font_red = foreground.red; pango_font_green = foreground.green; pango_font_blue = foreground.blue; break; -#endif default: assert(false); break; @@ -348,11 +338,7 @@ void set_font_colors(xcb_gcontext_t gc, color_t foreground, color_t background) * */ bool font_is_pango(void) { -#if PANGO_SUPPORT return savedFont->type == FONT_TYPE_PANGO; -#else - return false; -#endif } static int predict_text_width_xcb(const xcb_char2b_t *text, size_t text_len); @@ -397,11 +383,9 @@ static void draw_text_xcb(const xcb_char2b_t *text, size_t text_len, xcb_drawabl void draw_text(i3String *text, xcb_drawable_t drawable, xcb_gcontext_t gc, xcb_visualtype_t *visual, int x, int y, int max_width) { assert(savedFont != NULL); -#if PANGO_SUPPORT if (visual == NULL) { visual = root_visual_type; } -#endif switch (savedFont->type) { case FONT_TYPE_NONE: @@ -411,13 +395,11 @@ void draw_text(i3String *text, xcb_drawable_t drawable, xcb_gcontext_t gc, draw_text_xcb(i3string_as_ucs2(text), i3string_get_num_glyphs(text), drawable, gc, x, y, max_width); break; -#if PANGO_SUPPORT case FONT_TYPE_PANGO: /* Render the text using Pango */ draw_text_pango(i3string_as_utf8(text), i3string_get_num_bytes(text), drawable, visual, x, y, max_width, i3string_is_markup(text)); return; -#endif default: assert(false); } @@ -450,13 +432,11 @@ void draw_text_ascii(const char *text, xcb_drawable_t drawable, } break; } -#if PANGO_SUPPORT case FONT_TYPE_PANGO: /* Render the text using Pango */ draw_text_pango(text, strlen(text), drawable, root_visual_type, x, y, max_width, false); return; -#endif default: assert(false); } @@ -547,12 +527,10 @@ int predict_text_width(i3String *text) { return 0; case FONT_TYPE_XCB: return predict_text_width_xcb(i3string_as_ucs2(text), i3string_get_num_glyphs(text)); -#if PANGO_SUPPORT case FONT_TYPE_PANGO: /* Calculate extents using Pango */ return predict_text_width_pango(i3string_as_utf8(text), i3string_get_num_bytes(text), i3string_is_markup(text)); -#endif default: assert(false); return 0; diff --git a/libi3/string.c b/libi3/string.c index 328b41c0..19039a23 100644 --- a/libi3/string.c +++ b/libi3/string.c @@ -13,9 +13,7 @@ #include #include -#if PANGO_SUPPORT #include -#endif #include "libi3.h" @@ -192,15 +190,11 @@ void i3string_set_markup(i3String *str, bool pango_markup) { * Escape pango markup characters in the given string. */ i3String *i3string_escape_markup(i3String *str) { -#if PANGO_SUPPORT const char *text = i3string_as_utf8(str); char *escaped = g_markup_escape_text(text, -1); i3String *result = i3string_from_utf8(escaped); free(escaped); return result; -#else - return str; -#endif } /* diff --git a/src/util.c b/src/util.c index d19f8c5e..15796d88 100644 --- a/src/util.c +++ b/src/util.c @@ -327,12 +327,10 @@ char *pango_escape_markup(char *input) { if (!font_is_pango()) return input; -#if PANGO_SUPPORT char *escaped = g_markup_escape_text(input, -1); FREE(input); return escaped; -#endif } /* From 6a8fb69eff913e4ebb9a07cb2f77f59320d93805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Wed, 28 Sep 2016 04:04:00 +0200 Subject: [PATCH 111/150] Added new criteria 'tiling' / 'floating'. (#2481) These criteria allow selecting only windows in a specific mode, i.e., tiling and floating, respectively. fixes #2406 --- docs/userguide | 7 +++++++ include/data.h | 6 +++--- parser-specs/commands.spec | 2 ++ parser-specs/config.spec | 2 ++ src/match.c | 28 +++++++++++++++++++++++++++- testcases/t/165-for_window.t | 27 +++++++++++++++++++++++++++ 6 files changed, 68 insertions(+), 4 deletions(-) diff --git a/docs/userguide b/docs/userguide index 9472fdd7..93c54467 100644 --- a/docs/userguide +++ b/docs/userguide @@ -1679,6 +1679,9 @@ bindsym $mod+x [class="Firefox" window_role="About"] kill # enable floating mode and move container to workspace 4 for_window [class="^evil-app$"] floating enable, move container to workspace 4 + +# move all floating windows to the scratchpad +bindsym $mod+x [floating] move scratchpad ------------------------------------ The criteria which are currently implemented are: @@ -1721,6 +1724,10 @@ con_id:: Compares the i3-internal container ID, which you can get via the IPC interface. Handy for scripting. Use the special value +\_\_focused__+ to match only the currently focused window. +floating:: + Only matches floating windows. This criterion requires no value. +tiling:: + Only matches tiling windows. This criterion requires no value. The criteria +class+, +instance+, +role+, +title+, +workspace+ and +mark+ are actually regular expressions (PCRE). See +pcresyntax(3)+ or +perldoc perlre+ for diff --git a/include/data.h b/include/data.h index 247cd3c5..70edd222 100644 --- a/include/data.h +++ b/include/data.h @@ -474,9 +474,9 @@ struct Match { M_DOCK_BOTTOM = 3 } dock; xcb_window_t id; - enum { M_ANY = 0, - M_TILING, - M_FLOATING } floating; + enum { WM_ANY = 0, + WM_TILING, + WM_FLOATING } window_mode; Con *con_id; /* Where the window looking for a match should be inserted: diff --git a/parser-specs/commands.spec b/parser-specs/commands.spec index ec7fbabf..d4b3dbc6 100644 --- a/parser-specs/commands.spec +++ b/parser-specs/commands.spec @@ -53,6 +53,8 @@ state CRITERIA: ctype = 'title' -> CRITERION ctype = 'urgent' -> CRITERION ctype = 'workspace' -> CRITERION + ctype = 'tiling', 'floating' + -> call cmd_criteria_add($ctype, NULL); CRITERIA ']' -> call cmd_criteria_match_windows(); INITIAL state CRITERION: diff --git a/parser-specs/config.spec b/parser-specs/config.spec index eeafaac8..90296819 100644 --- a/parser-specs/config.spec +++ b/parser-specs/config.spec @@ -173,6 +173,8 @@ state CRITERIA: ctype = 'title' -> CRITERION ctype = 'urgent' -> CRITERION ctype = 'workspace' -> CRITERION + ctype = 'tiling', 'floating' + -> call cfg_criteria_add($ctype, NULL); CRITERIA ']' -> call cfg_criteria_pop_state() diff --git a/src/match.c b/src/match.c index ba87eb23..ac9ddaf9 100644 --- a/src/match.c +++ b/src/match.c @@ -28,6 +28,7 @@ void match_init(Match *match) { memset(match, 0, sizeof(Match)); match->urgent = U_DONTCHECK; + match->window_mode = WM_ANY; /* we use this as the placeholder value for "not set". */ match->window_type = UINT32_MAX; } @@ -53,7 +54,7 @@ bool match_is_empty(Match *match) { match->window_type == UINT32_MAX && match->con_id == NULL && match->dock == M_NODOCK && - match->floating == M_ANY); + match->window_mode == WM_ANY); } /* @@ -243,6 +244,21 @@ bool match_matches_window(Match *match, i3Window *window) { } } + if (match->window_mode != WM_ANY) { + 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; + } + + LOG("window_mode matches\n"); + } + return true; } @@ -384,5 +400,15 @@ void match_parse_property(Match *match, const char *ctype, const char *cvalue) { return; } + if (strcmp(ctype, "tiling") == 0) { + match->window_mode = WM_TILING; + return; + } + + if (strcmp(ctype, "floating") == 0) { + match->window_mode = WM_FLOATING; + return; + } + ELOG("Unknown criterion: %s\n", ctype); } diff --git a/testcases/t/165-for_window.t b/testcases/t/165-for_window.t index 025fe21c..bc3df114 100644 --- a/testcases/t/165-for_window.t +++ b/testcases/t/165-for_window.t @@ -459,6 +459,33 @@ is_deeply($nodes[0]->{nodes}[0]->{marks}, [ 'triggered' ], "mark set for workspa exit_gracefully($pid); +############################################################## +# 13: check that the tiling / floating criteria work. +############################################################## + +$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 +EOT + +$pid = launch_with_config($config); +$tmp = fresh_workspace; + +open_window; +open_floating_window; + +@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"); + +@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"); + +exit_gracefully($pid); + ############################################################## done_testing; From c71f6f8f7c314434f790162a155f910c01233e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Fri, 30 Sep 2016 17:28:02 +0200 Subject: [PATCH 112/150] Implement special value 'current' for output. (#2483) This commit introduces the special 'current' value for outputs in both of * move con to output current * move workspace to output current fixes #2357 --- docs/userguide | 8 ++--- include/output.h | 6 ++++ src/commands.c | 15 ++------- src/move.c | 3 +- src/output.c | 37 +++++++++++++++------- src/workspace.c | 11 ++----- testcases/t/504-move-workspace-to-output.t | 25 ++++++++++++--- 7 files changed, 63 insertions(+), 42 deletions(-) diff --git a/docs/userguide b/docs/userguide index 93c54467..ae741b69 100644 --- a/docs/userguide +++ b/docs/userguide @@ -2103,10 +2103,10 @@ To move a container to another RandR output (addressed by names like +LVDS1+ or +right+, +up+ or +down+), there are two commands: *Syntax*: ----------------------------------------------------- -move container to output left|right|down|up| -move workspace to output left|right|down|up| ----------------------------------------------------- +------------------------------------------------------------ +move container to output left|right|down|up|current| +move workspace to output left|right|down|up|current| +------------------------------------------------------------ *Examples*: -------------------------------------------------------- diff --git a/include/output.h b/include/output.h index 8299a19b..03a4fbcf 100644 --- a/include/output.h +++ b/include/output.h @@ -22,6 +22,12 @@ Con *output_get_content(Con *output); */ Output *get_output_from_string(Output *current_output, const char *output_str); +/** + * Returns the output for the given con. + * + */ +Output *get_output_for_con(Con *con); + /** * Iterates over all outputs and pushes sticky windows to the currently visible * workspace on that output. diff --git a/src/commands.c b/src/commands.c index 403c3b3a..58641d6a 100644 --- a/src/commands.c +++ b/src/commands.c @@ -87,17 +87,6 @@ static bool definitelyGreaterThan(float a, float b, float epsilon) { return (a - b) > ((fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon); } -/* - * Returns the output containing the given container. - */ -static Output *get_output_of_con(Con *con) { - Con *output_con = con_get_output(con); - Output *output = get_output_by_name(output_con->name); - assert(output != NULL); - - return output; -} - /* * Checks whether we switched to a new workspace and returns false in that case, * signaling that further workspace switching should be done by the calling function @@ -1036,7 +1025,7 @@ void cmd_move_con_to_output(I3_CMD, const char *name) { TAILQ_FOREACH(current, &owindows, owindows) { DLOG("matching: %p / %s\n", current->con, current->con->name); - Output *current_output = get_output_of_con(current->con); + Output *current_output = get_output_for_con(current->con); assert(current_output != NULL); Output *output = get_output_from_string(current_output, name); @@ -1648,7 +1637,7 @@ void cmd_focus_output(I3_CMD, const char *name) { Output *output; TAILQ_FOREACH(current, &owindows, owindows) - current_output = get_output_of_con(current->con); + current_output = get_output_for_con(current->con); assert(current_output != NULL); output = get_output_from_string(current_output, name); diff --git a/src/move.c b/src/move.c index 87f78ee3..25c658ce 100644 --- a/src/move.c +++ b/src/move.c @@ -101,8 +101,7 @@ static void attach_to_workspace(Con *con, Con *ws, direction_t direction) { */ static void move_to_output_directed(Con *con, direction_t direction) { Con *old_ws = con_get_workspace(con); - Con *current_output_con = con_get_output(con); - Output *current_output = get_output_by_name(current_output_con->name); + Output *current_output = get_output_for_con(con); Output *output = get_output_next(direction, current_output, CLOSEST_OUTPUT); if (!output) { diff --git a/src/output.c b/src/output.c index 62b146a7..1a9f6129 100644 --- a/src/output.c +++ b/src/output.c @@ -31,18 +31,33 @@ Con *output_get_content(Con *output) { * */ Output *get_output_from_string(Output *current_output, const char *output_str) { - Output *output; + if (strcasecmp(output_str, "current") == 0) { + return get_output_for_con(focused); + } else if (strcasecmp(output_str, "left") == 0) { + return get_output_next_wrap(D_LEFT, current_output); + } else if (strcasecmp(output_str, "right") == 0) { + return get_output_next_wrap(D_RIGHT, current_output); + } else if (strcasecmp(output_str, "up") == 0) { + return get_output_next_wrap(D_UP, current_output); + } else if (strcasecmp(output_str, "down") == 0) { + return get_output_next_wrap(D_DOWN, current_output); + } - if (strcasecmp(output_str, "left") == 0) - output = get_output_next_wrap(D_LEFT, current_output); - else if (strcasecmp(output_str, "right") == 0) - output = get_output_next_wrap(D_RIGHT, current_output); - else if (strcasecmp(output_str, "up") == 0) - output = get_output_next_wrap(D_UP, current_output); - else if (strcasecmp(output_str, "down") == 0) - output = get_output_next_wrap(D_DOWN, current_output); - else - output = get_output_by_name(output_str); + return get_output_by_name(output_str); +} + +Output *get_output_for_con(Con *con) { + Con *output_con = con_get_output(con); + if (output_con == NULL) { + ELOG("Could not get the output container for con = %p.\n", con); + return NULL; + } + + Output *output = get_output_by_name(output_con->name); + if (output == NULL) { + ELOG("Could not get output from name \"%s\".\n", output_con->name); + return NULL; + } return output; } diff --git a/src/workspace.c b/src/workspace.c index 0c80f69f..0da0a378 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -911,17 +911,12 @@ Con *workspace_encapsulate(Con *ws) { bool workspace_move_to_output(Con *ws, const char *name) { LOG("Trying to move workspace %p / %s to output \"%s\".\n", ws, ws->name, name); - Con *current_output_con = con_get_output(ws); - if (!current_output_con) { - ELOG("Could not get the output container for workspace %p / %s.\n", ws, ws->name); - return false; - } - - Output *current_output = get_output_by_name(current_output_con->name); - if (!current_output) { + Output *current_output = get_output_for_con(ws); + if (current_output == NULL) { ELOG("Cannot get current output. This is a bug in i3.\n"); return false; } + Output *output = get_output_from_string(current_output, name); if (!output) { ELOG("Could not get output from string \"%s\"\n", name); diff --git a/testcases/t/504-move-workspace-to-output.t b/testcases/t/504-move-workspace-to-output.t index efe0d6e7..c43b8b40 100644 --- a/testcases/t/504-move-workspace-to-output.t +++ b/testcases/t/504-move-workspace-to-output.t @@ -19,9 +19,6 @@ use List::Util qw(first); use i3test i3_autostart => 0; -# TODO: -# introduce 'move workspace 3 to output ' with synonym 'move workspace 3 to ' - # Ensure the pointer is at (0, 0) so that we really start on the first # (the left) workspace. $x->root->warp_pointer(0, 0); @@ -163,6 +160,26 @@ ok(!($empty_ws ~~ @$x0), 'empty_ws not on fake-0'); ok(!($empty_ws ~~ @$x1), 'empty_ws not on fake-1'); ok($other_output_ws ~~ @$x0, 'other_output_ws on fake-0'); -exit_gracefully($pid); +################################################################################ +# Verify that the special word 'current' can be used for the output. +################################################################################ +my $ws1 = fresh_workspace(output => 1); +open_window; +cmd 'mark marked'; + +my $ws0 = fresh_workspace(output => 0); + +($x0, $x1) = workspaces_per_screen(); +ok($ws0 ~~ @$x0, 'ws0 on fake-0'); +ok($ws1 ~~ @$x1, 'ws1 on fake-1'); + +cmd '[con_mark=marked] move workspace to output current'; + +($x0, $x1) = workspaces_per_screen(); +ok($ws1 ~~ @$x0, 'ws1 on fake-0'); + +################################################################################ + +exit_gracefully($pid); done_testing; From 6b3d8b9e8b45b999a7da19ef2c0831ec0e050530 Mon Sep 17 00:00:00 2001 From: Ferdinand Bachmann Date: Mon, 3 Oct 2016 14:53:56 +0200 Subject: [PATCH 113/150] Bugfix: NULL dereference when stickying _NET_WM_DESKTOP_ALL windows (#2488) In some cases, ws will be NULL here. Originally tested with "lemonbar" --- src/manage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/manage.c b/src/manage.c index bbd84007..fd9226e4 100644 --- a/src/manage.c +++ b/src/manage.c @@ -433,7 +433,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki /* We ignore the hint for an internal workspace because windows in the * scratchpad also have this value, but upon restarting i3 we don't want * them to become sticky windows. */ - if (cwindow->wm_desktop == NET_WM_DESKTOP_ALL && !con_is_internal(ws)) { + if (cwindow->wm_desktop == NET_WM_DESKTOP_ALL && (ws == NULL || !con_is_internal(ws))) { DLOG("This window has _NET_WM_DESKTOP = 0xFFFFFFFF. Will float it and make it sticky.\n"); nc->sticky = true; want_floating = true; From 3a359a024343f73cd39068c5d3d5ed5afd4883b0 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 3 Oct 2016 23:53:49 -0700 Subject: [PATCH 114/150] Remove extraneous newline when printing core_pattern (#2490) This was accidentally changed in commit 94a09b3cac98a3bc1ed580fce16aa9869f83bbaa --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 96eab671..9373445a 100644 --- a/src/main.c +++ b/src/main.c @@ -451,7 +451,7 @@ int main(int argc, char *argv[]) { memset(cwd, '\0', cwd_size); if (read(patternfd, cwd, cwd_size) > 0) /* a trailing newline is included in cwd */ - LOG("CORE DUMPS: Your core_pattern is: \"%s\".\n", cwd); + LOG("CORE DUMPS: Your core_pattern is: %s", cwd); close(patternfd); } free(cwd); From 3cba06f7b970d34b540c65e10c4cef8a8ced7e57 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 5 Oct 2016 09:46:33 -0700 Subject: [PATCH 115/150] Fix _i3_version debugging symbol (#2492) The idea was to ensure the symbol would always be present. For that, we need __attribute__((used)), not __attribute__((unused)). Further, ensure the variable has static storage, as the used attribute only applies to variables with static storage. See also http://stackoverflow.com/a/29545417/712014 --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 9373445a..f94a8941 100644 --- a/src/main.c +++ b/src/main.c @@ -189,7 +189,7 @@ static void handle_signal(int sig, siginfo_t *info, void *data) { int main(int argc, char *argv[]) { /* Keep a symbol pointing to the I3_VERSION string constant so that we have * it in gdb backtraces. */ - const char *_i3_version __attribute__((unused)) = i3_version; + static const char *_i3_version __attribute__((used)) = I3_VERSION; char *override_configpath = NULL; bool autostart = true; char *layout_path = NULL; From e82e26a24d22e2f92cd90d9547c213493e94ea63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Tue, 11 Oct 2016 20:46:25 +0200 Subject: [PATCH 116/150] Handle ResizeRequests for tray clients. (#2495) Some tray clients such as VLC use override_redirect on their tray window. As per specification this means i3bar won't receive a ConfigureRequest, but instead a ResizeRequest will be triggered. If not selected, the X server will simply confirm the request which leads to a broken tray window size. This commit selects and handles the event just like a configure request is handled. fixes #2494 --- i3bar/src/xcb.c | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index d44da458..32187445 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -685,15 +685,17 @@ static void handle_client_message(xcb_client_message_event_t *event) { if (op == SYSTEM_TRAY_REQUEST_DOCK) { xcb_window_t client = event->data.data32[2]; - /* Listen for PropertyNotify events to get the most recent value of - * the XEMBED_MAPPED atom, also listen for UnmapNotify events */ mask = XCB_CW_EVENT_MASK; - values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE | - XCB_EVENT_MASK_STRUCTURE_NOTIFY; - xcb_change_window_attributes(xcb_connection, - client, - mask, - values); + + /* Needed to get the most recent value of XEMBED_MAPPED. */ + values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE; + /* Needed for UnmapNotify events. */ + values[0] |= XCB_EVENT_MASK_STRUCTURE_NOTIFY; + /* Needed because some tray applications (e.g., VLC) use + * override_redirect which causes no ConfigureRequest to be sent. */ + values[0] |= XCB_EVENT_MASK_RESIZE_REDIRECT; + + xcb_change_window_attributes(xcb_connection, client, mask, values); /* Request the _XEMBED_INFO property. The XEMBED specification * (which is referred by the tray specification) says this *has* to @@ -1004,13 +1006,11 @@ static void handle_property_notify(xcb_property_notify_event_t *event) { } /* - * Handle ConfigureRequests by denying them and sending the client a - * ConfigureNotify with its actual size. + * If a tray client attempts to change its size we deny the request and respond + * by telling it its actual size. * */ -static void handle_configure_request(xcb_configure_request_event_t *event) { - DLOG("ConfigureRequest for window = %08x\n", event->window); - +static void handle_configuration_change(xcb_window_t window) { trayclient *trayclient; i3_output *output; SLIST_FOREACH(output, outputs, slist) { @@ -1023,7 +1023,7 @@ static void handle_configure_request(xcb_configure_request_event_t *event) { continue; clients++; - if (trayclient->win != event->window) + if (trayclient->win != window) continue; xcb_rectangle_t rect; @@ -1033,7 +1033,7 @@ static void handle_configure_request(xcb_configure_request_event_t *event) { rect.height = icon_size; DLOG("This is a tray window. x = %d\n", rect.x); - fake_configure_notify(xcb_connection, rect, event->window, 0); + fake_configure_notify(xcb_connection, rect, window, 0); return; } } @@ -1041,6 +1041,16 @@ static void handle_configure_request(xcb_configure_request_event_t *event) { DLOG("WARNING: Could not find corresponding tray window.\n"); } +static void handle_configure_request(xcb_configure_request_event_t *event) { + DLOG("ConfigureRequest for window = %08x\n", event->window); + handle_configuration_change(event->window); +} + +static void handle_resize_request(xcb_resize_request_event_t *event) { + DLOG("ResizeRequest for window = %08x\n", event->window); + handle_configuration_change(event->window); +} + /* * This function is called immediately before the main loop locks. We flush xcb * then (and only then) @@ -1166,6 +1176,9 @@ void xcb_chk_cb(struct ev_loop *loop, ev_check *watcher, int revents) { case XCB_CONFIGURE_REQUEST: /* ConfigureRequest, sent by a tray child */ handle_configure_request((xcb_configure_request_event_t *)event); + case XCB_RESIZE_REQUEST: + /* ResizeRequest sent by a tray child using override_redirect. */ + handle_resize_request((xcb_resize_request_event_t *)event); break; } free(event); From 83452a3472c48898552fac18d729f6a215e43063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Tue, 18 Oct 2016 08:29:31 +0200 Subject: [PATCH 117/150] Disable pango markup for plain-text input in i3bar. (#2505) fixes #2498 --- i3bar/src/child.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 3570dde9..1b2dc94c 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -359,11 +359,13 @@ static void read_flat_input(char *buffer, int length) { I3STRING_FREE(first->full_text); /* Remove the trailing newline and terminate the string at the same * time. */ - if (buffer[length - 1] == '\n' || buffer[length - 1] == '\r') + if (buffer[length - 1] == '\n' || buffer[length - 1] == '\r') { buffer[length - 1] = '\0'; - else + } else { buffer[length] = '\0'; - first->full_text = i3string_from_markup(buffer); + } + + first->full_text = i3string_from_utf8(buffer); } static bool read_json_input(unsigned char *input, int length) { From e51a89e84259e854756a20f6367299eee1612da9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Tue, 18 Oct 2016 08:32:41 +0200 Subject: [PATCH 118/150] Implement new window::mark IPC event. (#2503) This introduces a new type of 'window' event sent wit change:mark whenever a mark on a window changes. fixes #2501 --- docs/ipc | 17 ++++----- src/con.c | 5 +++ testcases/t/265-ipc-mark.t | 70 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 testcases/t/265-ipc-mark.t diff --git a/docs/ipc b/docs/ipc index ddadabc4..fda289a0 100644 --- a/docs/ipc +++ b/docs/ipc @@ -754,14 +754,15 @@ defines whether pango markup shall be used for displaying this mode. This event consists of a single serialized map containing a property +change (string)+ which indicates the type of the change -* +new+ - the window has become managed by i3 -* +close+ - the window has closed -* +focus+ - the window has received input focus -* +title+ - the window's title has changed -* +fullscreen_mode+ - the window has entered or exited fullscreen mode -* +move+ - the window has changed its position in the tree -* +floating+ - the window has transitioned to or from floating -* +urgent+ - the window has become urgent or lost its urgent status +* +new+ – the window has become managed by i3 +* +close+ – the window has closed +* +focus+ – the window has received input focus +* +title+ – the window's title has changed +* +fullscreen_mode+ – the window has entered or exited fullscreen mode +* +move+ – the window has changed its position in the tree +* +floating+ – the window has transitioned to or from floating +* +urgent+ – the window has become urgent or lost its urgent status +* +mark+ – a mark has been added to or removed from the window Additionally a +container (object)+ field will be present, which consists of the window's parent container. Be aware that for the "new" event, the diff --git a/src/con.c b/src/con.c index 124d24ea..a104028b 100644 --- a/src/con.c +++ b/src/con.c @@ -617,6 +617,7 @@ void con_mark(Con *con, const char *mark, mark_mode_t mode) { mark_t *new = scalloc(1, sizeof(mark_t)); new->name = sstrdup(mark); TAILQ_INSERT_TAIL(&(con->marks_head), new, marks); + ipc_send_window_event("mark", con); con->mark_changed = true; } @@ -645,6 +646,8 @@ void con_unmark(Con *con, const char *name) { FREE(mark->name); TAILQ_REMOVE(&(current->marks_head), mark, marks); FREE(mark); + + ipc_send_window_event("mark", current); } current->mark_changed = true; @@ -668,6 +671,8 @@ void con_unmark(Con *con, const char *name) { FREE(mark->name); TAILQ_REMOVE(&(current->marks_head), mark, marks); FREE(mark); + + ipc_send_window_event("mark", current); break; } } diff --git a/testcases/t/265-ipc-mark.t b/testcases/t/265-ipc-mark.t new file mode 100644 index 00000000..c0e12215 --- /dev/null +++ b/testcases/t/265-ipc-mark.t @@ -0,0 +1,70 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Please read the following documents before working on tests: +# • http://build.i3wm.org/docs/testsuite.html +# (or docs/testsuite) +# +# • http://build.i3wm.org/docs/lib-i3test.html +# (alternatively: perldoc ./testcases/lib/i3test.pm) +# +# • http://build.i3wm.org/docs/ipc.html +# (or docs/ipc) +# +# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf +# (unless you are already familiar with Perl) +# +# Tests for the window::mark IPC event. +# Ticket: #2501 +use i3test; + +my ($i3, $timer, $event, $mark); + +$i3 = i3(get_socket_path()); +$i3->connect()->recv; + +$i3->subscribe({ + window => sub { + my ($event) = @_; + return unless defined $mark; + return unless $event->{change} eq 'mark'; + + $mark->send($event); + } +})->recv; + +$timer = AnyEvent->timer( + after => 0.5, + cb => sub { + $mark->send(0); + } +); + +############################################################################### +# Marking a container triggers a 'mark' event. +############################################################################### +fresh_workspace; +open_window; + +$mark = AnyEvent->condvar; +cmd 'mark x'; + +$event = $mark->recv; +ok($event, 'window::mark event has been received'); + +############################################################################### +# Unmarking a container triggers a 'mark' event. +############################################################################### +fresh_workspace; +open_window; +cmd 'mark x'; + +$mark = AnyEvent->condvar; +cmd 'unmark x'; + +$event = $mark->recv; +ok($event, 'window::mark event has been received'); + +############################################################################### + +done_testing; From 6b89690a3f923fbd5b7b3988ed7a8934af6038df Mon Sep 17 00:00:00 2001 From: Peder Stray Date: Wed, 19 Oct 2016 08:41:10 +0200 Subject: [PATCH 119/150] Add "output" to IPC events referencing a container (#2489) Add the property "output" to all IPC events that has an output container as a parent, making it easier to keep track of such things. fixes #2478 --- src/ipc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ipc.c b/src/ipc.c index bf529b17..ddc09294 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -294,6 +294,11 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) { ystr("focused"); y(bool, (con == focused)); + if (con->type != CT_ROOT && con->type != CT_OUTPUT) { + ystr("output"); + ystr(con_get_output(con)->name); + } + ystr("layout"); switch (con->layout) { case L_DEFAULT: From 4d66841811250814cfe5d9ca9f9371ed09901487 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 7 Oct 2016 13:35:06 +0200 Subject: [PATCH 120/150] check vasprintf return code --- i3bar/src/child.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 3570dde9..295eb76f 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -105,7 +105,9 @@ __attribute__((format(printf, 1, 2))) static void set_statusline_error(const cha char *message; va_list args; va_start(args, format); - (void)vasprintf(&message, format, args); + if (vasprintf(&message, format, args) == -1) { + return; + } struct status_block *err_block = scalloc(1, sizeof(struct status_block)); err_block->full_text = i3string_from_utf8("Error: "); From ea0b5dd335e7b40bd8077e05ecfa21107a8fa3d0 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 7 Oct 2016 13:36:45 +0200 Subject: [PATCH 121/150] Ensure error message is included when bailing out --- testcases/t/175-startup-notification.t | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testcases/t/175-startup-notification.t b/testcases/t/175-startup-notification.t index b27bed53..4456b1d0 100644 --- a/testcases/t/175-startup-notification.t +++ b/testcases/t/175-startup-notification.t @@ -192,7 +192,7 @@ is_num_children($third_ws, 2, 'two containers on the third workspace'); # environment variable. ###################################################################### -mkfifo($tmp, 0600) or BAIL_OUT "Could not create FIFO in $tmp"; +mkfifo($tmp, 0600) or BAIL_OUT "Could not create FIFO in $tmp: $!"; cmd qq|exec --no-startup-id echo \$DESKTOP_STARTUP_ID >$tmp|; @@ -208,7 +208,7 @@ is($startup_id, '', 'startup_id empty'); # 4) same thing, but with double quotes in exec ###################################################################### -mkfifo($tmp, 0600) or BAIL_OUT "Could not create FIFO in $tmp"; +mkfifo($tmp, 0600) or BAIL_OUT "Could not create FIFO in $tmp: $!"; cmd qq|exec --no-startup-id "echo \$DESKTOP_STARTUP_ID >$tmp"|; From 4e9925de7300997567d6621c8466d5b62b974021 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 7 Oct 2016 13:33:58 +0200 Subject: [PATCH 122/150] rename config.h to configuration.h This is a preparation step for the next commit. --- i3bar/include/common.h | 2 +- i3bar/include/{config.h => configuration.h} | 0 include/all.h | 2 +- include/{config.h => configuration.h} | 2 +- include/ipc.h | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename i3bar/include/{config.h => configuration.h} (100%) rename include/{config.h => configuration.h} (99%) diff --git a/i3bar/include/common.h b/i3bar/include/common.h index 0d46ab6a..c6bb0dba 100644 --- a/i3bar/include/common.h +++ b/i3bar/include/common.h @@ -85,6 +85,6 @@ TAILQ_HEAD(statusline_head, status_block) statusline_head; #include "mode.h" #include "trayclients.h" #include "xcb.h" -#include "config.h" +#include "configuration.h" #include "libi3.h" #include "parse_json_header.h" diff --git a/i3bar/include/config.h b/i3bar/include/configuration.h similarity index 100% rename from i3bar/include/config.h rename to i3bar/include/configuration.h diff --git a/include/all.h b/include/all.h index e39e27b9..b323f863 100644 --- a/include/all.h +++ b/include/all.h @@ -51,7 +51,7 @@ #include "click.h" #include "key_press.h" #include "floating.h" -#include "config.h" +#include "configuration.h" #include "handlers.h" #include "randr.h" #include "xinerama.h" diff --git a/include/config.h b/include/configuration.h similarity index 99% rename from include/config.h rename to include/configuration.h index 699cc882..ced104b6 100644 --- a/include/config.h +++ b/include/configuration.h @@ -4,7 +4,7 @@ * i3 - an improved dynamic tiling window manager * © 2009 Michael Stapelberg and contributors (see also: LICENSE) * - * include/config.h: Contains all structs/variables for the configurable + * include/configuration.h: Contains all structs/variables for the configurable * part of i3 as well as functions handling the configuration file (calling * the parser (src/config_parse.c) with the correct path, switching key * bindings mode). diff --git a/include/ipc.h b/include/ipc.h index e1c18816..a9323751 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -16,7 +16,7 @@ #include "data.h" #include "tree.h" -#include "config.h" +#include "configuration.h" #include "i3/ipc.h" From 4a52a7e9fb6fb2e1f0256b2e086cfa313f411cd8 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 7 Oct 2016 13:48:26 +0200 Subject: [PATCH 123/150] Switch to autotools (GNU build system) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit probably comes as a surprise to some, given that one of i3’s explicitly stated goals used to be “Do not use programs such as autoconf/automake for configuration and creating unreadable/broken makefiles”. I phrased this goal over 7 years ago, based largely on a grudge that I inherited, which — as I’ve realized in the meantime — was largely held against FOSS in general, and not actually nuanced criticism of autotools. In the meantime, I have come to realize that the knee-jerk reaction of “I could do this better!” (i.e. writing our own build system in this particular case) is usually misguided, and nowadays I strongly suggest trying hard to fix the existing system for the benefit of all existing and future users. Further, I recently got to experience the other side of the coin, as I packaged a new version of FreeRADIUS for Debian, which at the time of writing used autoconf in combination with boilermake, a custom make-based build system that only FreeRADIUS uses. Understanding the build system enough to fix issues and enable parallel compilation took me an entire day. That time is time which potentially every downstream maintainer needs to invest, and the resulting knowledge cannot be applied to any other project. Hence, I believe it’s a good idea switch i3 to autotools. Yes, it might be that particular features were easier to implement/understand in our custom Makefiles, and there might be individuals who have an easier time reading through our custom Makefiles than learning autotools. All of these considerations are outweighed by the benefits we get from using the same build system as literally thousands of other FOSS software packages. Aside from these somewhat philosophical considerations, there’s also practical improvements which this change brings us. See the “changes” section below. ┌──────────────────────────────────────────────────────────────────────────────┐ │ new workflow │ └──────────────────────────────────────────────────────────────────────────────┘ You can now build i3 like you build any other software package which uses autotools. Here’s a memory refresher: 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.) ┌──────────────────────────────────────────────────────────────────────────────┐ │ recommended reading │ └──────────────────────────────────────────────────────────────────────────────┘ I very much recommend reading “A Practitioner's Guide to GNU Autoconf, Automake, and Libtool” by John Calcote (https://www.nostarch.com/autotools.htm). That book is from 2010 and, AFAICT, is the most up to date comprehensive description of autotools. Do not read older documentation. In particular, if a document you’re reading mentions configure.in (deprecated filename) or recursive make (now considered harmful), it’s likely outdated. ┌──────────────────────────────────────────────────────────────────────────────┐ │ changes │ └──────────────────────────────────────────────────────────────────────────────┘ This commit implements the following new functionality/changes in behavior: • 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 let me know. • “make check” runs the i3 testsuite. You can still use ./testcases/complete-run.pl to get the interactive progress output. • “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” 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. • 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 simplicitly. Maybe we can re-add it later. • coverage reports are now generated using “make check-code-coverage”, which requires specifying --enable-code-coverage when calling configure. ┌──────────────────────────────────────────────────────────────────────────────┐ │ build system feature parity/testing │ └──────────────────────────────────────────────────────────────────────────────┘ In addition to what’s described above, I tested the following features: • “make install” installs the same files (plus documentation and manpages) cd i3-old && make install PREFIX=/tmp/inst/old cd i3-new && ./configure --prefix=/tmp/inst/new cd /tmp/inst (cd old && for f in $(find); do [ -e "../new/$f" ] || echo "$f missing"; done) • make dist generates a tarball which includes the same files cd i3-old && make dist cd i3-new/x86_64-pc-linux-gnu && make dist colordiff -u <(tar tf i3-old/i3-4.12.tar.bz2 | sort) \ <(tar tf i3-new/x86_64-pc-linux-gnu/i3-4.12.tar.gz | sort) There are some expected differences: • Some files have been renamed (e.g. the new etc/ and share/ subdirectories) • Some files will now be generated at build-time, so only their corresponding .in file is shipped (e.g. testcases/complete-run.pl) • The generated parser files are shipped in the dist tarball (they only depend on the parser-specs/* files, not on the target system) • autotools infrastructure is shipped (e.g. “configure”, “missing”, etc.) • DLOG and ELOG statements still produce the same file name in logfiles • Listing source code in gdb still works. • gdb backtraces contain the i3- path component • release.sh still works • version embedding 1. git checkout shows “4.12-136-gf720023 (2016-10-10, branch "autotools")” 2. tarball of a git version shows “4.12-non-git” 3. release tarball shows 4.13 • debug mode is enabled by default for non-release builds • enabling verbose builds via V=1 ┌──────────────────────────────────────────────────────────────────────────────┐ │ speed │ └──────────────────────────────────────────────────────────────────────────────┘ There is no noticeable difference in compilation speed itself (of binaries, documentation and manpages): i3-old $ time make all docs mans -j8 make all docs mans -j8 28.92s user 2.15s system 640% cpu 4.852 total i3-new $ time make -j8 make -j8 27.08s user 1.92s system 620% cpu 4.669 total In terms of one-time costs: configuring the build system (../configure) takes about 2.7s on my machine, generating the build system (autoreconf -fi) takes about 3.1s on my machine. ┌──────────────────────────────────────────────────────────────────────────────┐ │ m4 macros │ └──────────────────────────────────────────────────────────────────────────────┘ All files in m4/ have been copied from the autoconf-archive package in version b6aeb1988f4b6c78bf39d97b6c4f6e1d594d59b9 and should be updated whenever they change. This commit has been tested with autoconf 2.69 and automake 1.15. --- Makefile | 70 ---- Makefile.am | 560 +++++++++++++++++++++++++++ common.mk | 218 ----------- configure.ac | 164 ++++++++ docs/Makefile | 7 - docs/docs.mk | 46 --- i3-config-wizard/Makefile | 10 - i3-config-wizard/i3-config-wizard.mk | 28 -- i3-dump-log/Makefile | 10 - i3-dump-log/i3-dump-log.mk | 28 -- i3-input/Makefile | 10 - i3-input/i3-input.mk | 28 -- i3-msg/Makefile | 10 - i3-msg/i3-msg.mk | 28 -- i3-nagbar/Makefile | 10 - i3-nagbar/i3-nagbar.mk | 28 -- i3bar/Makefile | 10 - i3bar/i3bar.mk | 28 -- libi3/Makefile | 7 - libi3/libi3.mk | 21 - m4/ax_append_flag.m4 | 71 ++++ m4/ax_cflags_warn_all.m4 | 122 ++++++ m4/ax_check_compile_flag.m4 | 74 ++++ m4/ax_check_enable_debug.m4 | 124 ++++++ m4/ax_check_gnu_make.m4 | 84 ++++ m4/ax_check_link_flag.m4 | 74 ++++ m4/ax_code_coverage.m4 | 273 +++++++++++++ m4/ax_configure_args.m4 | 70 ++++ m4/ax_enable_builddir.m4 | 302 +++++++++++++++ m4/ax_extend_srcdir.m4 | 86 ++++ m4/ax_pthread.m4 | 485 +++++++++++++++++++++++ m4/ax_require_defined.m4 | 37 ++ m4/ax_sanitizers.m4 | 130 +++++++ man/Makefile | 7 - man/man.mk | 42 -- src/Makefile | 10 - src/i3.mk | 102 ----- 37 files changed, 2656 insertions(+), 758 deletions(-) delete mode 100644 Makefile create mode 100644 Makefile.am delete mode 100644 common.mk create mode 100644 configure.ac delete mode 100644 docs/Makefile delete mode 100644 docs/docs.mk delete mode 100644 i3-config-wizard/Makefile delete mode 100644 i3-config-wizard/i3-config-wizard.mk delete mode 100644 i3-dump-log/Makefile delete mode 100644 i3-dump-log/i3-dump-log.mk delete mode 100644 i3-input/Makefile delete mode 100644 i3-input/i3-input.mk delete mode 100644 i3-msg/Makefile delete mode 100644 i3-msg/i3-msg.mk delete mode 100644 i3-nagbar/Makefile delete mode 100644 i3-nagbar/i3-nagbar.mk delete mode 100644 i3bar/Makefile delete mode 100644 i3bar/i3bar.mk delete mode 100644 libi3/Makefile delete mode 100644 libi3/libi3.mk create mode 100644 m4/ax_append_flag.m4 create mode 100644 m4/ax_cflags_warn_all.m4 create mode 100644 m4/ax_check_compile_flag.m4 create mode 100644 m4/ax_check_enable_debug.m4 create mode 100644 m4/ax_check_gnu_make.m4 create mode 100644 m4/ax_check_link_flag.m4 create mode 100644 m4/ax_code_coverage.m4 create mode 100644 m4/ax_configure_args.m4 create mode 100644 m4/ax_enable_builddir.m4 create mode 100644 m4/ax_extend_srcdir.m4 create mode 100644 m4/ax_pthread.m4 create mode 100644 m4/ax_require_defined.m4 create mode 100644 m4/ax_sanitizers.m4 delete mode 100644 man/Makefile delete mode 100644 man/man.mk delete mode 100644 src/Makefile delete mode 100644 src/i3.mk diff --git a/Makefile b/Makefile deleted file mode 100644 index c08f2777..00000000 --- a/Makefile +++ /dev/null @@ -1,70 +0,0 @@ -TOPDIR=$(shell pwd) - -include $(TOPDIR)/common.mk - -SUBDIRS:= - -ALL_TARGETS = -INSTALL_TARGETS = -CLEAN_TARGETS = -DISTCLEAN_TARGETS = - -all: real-all - -include libi3/libi3.mk -include src/i3.mk -include i3-config-wizard/i3-config-wizard.mk -include i3-msg/i3-msg.mk -include i3-input/i3-input.mk -include i3-nagbar/i3-nagbar.mk -include i3bar/i3bar.mk -include i3-dump-log/i3-dump-log.mk -include docs/docs.mk -include man/man.mk - -# Update $(TOPDIR)/LAST_VERSION if it differs from $I3_VERSION -CACHED_VERSION := '$(shell [ -f $(TOPDIR)/LAST_VERSION ] && cat $(TOPDIR)/LAST_VERSION)' -ifneq ($(CACHED_VERSION),$(I3_VERSION)) -$(shell echo -n ${I3_VERSION} > $(TOPDIR)/LAST_VERSION) -endif - -real-all: $(ALL_TARGETS) - -install: $(INSTALL_TARGETS) - -store_git_version: - echo -n ${I3_VERSION} > I3_VERSION - -dist: distclean - [ ! -d i3-${VERSION} ] || rm -rf i3-${VERSION} - [ ! -e i3-${VERSION}.tar.bz2 ] || rm i3-${VERSION}.tar.bz2 - mkdir i3-${VERSION} - cp i3-migrate-config-to-v4 i3-save-tree generate-command-parser.pl i3-sensible-* i3-dmenu-desktop i3.config.keycodes DEPENDS LICENSE PACKAGE-MAINTAINER RELEASE-NOTES-${VERSION} i3.config i3.xsession.desktop i3-with-shmlog.xsession.desktop i3.applications.desktop pseudo-doc.doxygen common.mk Makefile i3-${VERSION} - cp -r src libi3 i3-msg i3-nagbar i3-config-wizard i3bar i3-dump-log include man parser-specs testcases i3-${VERSION} - # Only copy toplevel documentation (important stuff) - mkdir i3-${VERSION}/docs - # Pre-generate documentation - $(MAKE) docs - # Cleanup τεχ output files - find docs -regex ".*\.\(aux\|out\|log\|toc\|bm\|dvi\|log\)" -exec rm '{}' \; - find docs -maxdepth 1 -type f ! \( -name "*.xcf" -or -name "*.svg" \) -exec cp '{}' i3-${VERSION}/docs \; - # Only copy source code from i3-input - mkdir i3-${VERSION}/i3-input - find i3-input -maxdepth 1 -type f \( -name "*.c" -or -name "*.mk" -or -name "*.h" -or -name "Makefile" \) -exec cp '{}' i3-${VERSION}/i3-input \; - cp I3_VERSION i3-${VERSION}/I3_VERSION - # Pre-generate a manpage to allow distributors to skip this step and save some dependencies - $(MAKE) mans - cp man/*.1 i3-${VERSION}/man/ - tar cfj i3-${VERSION}.tar.bz2 i3-${VERSION} - rm -rf i3-${VERSION} - -clean: $(CLEAN_TARGETS) - (which lcov >/dev/null 2>&1 && lcov -d . --zerocounters) || true - -distclean: clean $(DISTCLEAN_TARGETS) - -coverage: - rm -f /tmp/i3-coverage.info - rm -rf /tmp/i3-coverage - lcov -d . -b . --capture -o /tmp/i3-coverage.info - genhtml -o /tmp/i3-coverage/ /tmp/i3-coverage.info diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..7bba241b --- /dev/null +++ b/Makefile.am @@ -0,0 +1,560 @@ +@CODE_COVERAGE_RULES@ + +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 + +check_SCRIPTS = \ + testcases/complete-run.pl + +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=) \ + 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 \ + DEPENDS \ + I3_VERSION \ + LICENSE \ + PACKAGE-MAINTAINER \ + RELEASE-NOTES-4.12 \ + 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_srcdir)/man/asciidoc.conf -o $@ $< + +$(pod_MANS): man/%.1: % man/$(dirstamp) + $(AM_V_GEN) @PATH_POD2MAN@ --utf8 $< > $@ +else +asciidoc_MANS = +endif + +AM_CPPFLAGS = \ + -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) \ + $(XCB_CFLAGS) \ + $(XCB_UTIL_CFLAGS) \ + $(XCB_UTIL_XRM_CFLAGS) \ + $(YAJL_CFLAGS) \ + $(PANGOCAIRO_CFLAGS) + +libi3_LIBS = \ + $(top_builddir)/libi3.a \ + $(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/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) \ + $(libi3_CFLAGS) + +i3_nagbar_i3_nagbar_LDADD = \ + $(libi3_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) \ + $(XKBCOMMON_CFLAGS) + +i3_config_wizard_i3_config_wizard_LDADD = \ + $(libi3_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_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/debug.h \ + include/display_version.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/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/debug.c \ + src/display_version.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/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 $@ + +CLEANFILES = \ + i3-command-parser.stamp \ + i3-config-parser.stamp diff --git a/common.mk b/common.mk deleted file mode 100644 index 6032ce6c..00000000 --- a/common.mk +++ /dev/null @@ -1,218 +0,0 @@ -UNAME=$(shell uname) -DEBUG=1 -ASAN=0 -INSTALL=install -LN=ln -PKG_CONFIG=pkg-config -ifndef PREFIX - PREFIX=/usr -endif -ifndef EXEC_PREFIX - EXEC_PREFIX=$(PREFIX) -endif -ifndef SYSCONFDIR - ifeq ($(PREFIX),/usr) - SYSCONFDIR=/etc - else - SYSCONFDIR=$(PREFIX)/etc - endif -endif - -# In dist and snapshot tarballs, use the I3_VERSION and VERSION files. Otherwise use git information. -ifeq ($(wildcard .git),) - # not in git repository - VERSION := $(shell [ -f $(TOPDIR)/I3_VERSION ] && cat $(TOPDIR)/I3_VERSION | cut -d '-' -f 1) - I3_VERSION := '$(shell [ -f $(TOPDIR)/I3_VERSION ] && cat $(TOPDIR)/I3_VERSION)' -else - VERSION := $(shell git describe --tags --abbrev=0) - I3_VERSION := '$(shell git describe --tags --always) ($(shell git log --pretty=format:%cd --date=short -n1), branch \"$(shell git describe --tags --always --all | sed s:heads/::)\")' -endif - -MAJOR_VERSION := $(shell echo ${VERSION} | cut -d '.' -f 1) -MINOR_VERSION := $(shell echo ${VERSION} | cut -d '.' -f 2) -PATCH_VERSION := $(shell echo ${VERSION} | cut -d '.' -f 3) -ifeq (${PATCH_VERSION},) -PATCH_VERSION := 0 -endif - -## Generic flags - -# Default CFLAGS that users should be able to override -ifeq ($(DEBUG),1) -# Extended debugging flags, macros shall be available in gcc -CFLAGS ?= -pipe -gdwarf-2 -g3 -else -CFLAGS ?= -pipe -O2 -freorder-blocks-and-partition -endif - -ifeq ($(ASAN),1) -CFLAGS += -fsanitize=address -DI3_ASAN_ENABLED -LDFLAGS += -fsanitize=address -endif - -# Default LDFLAGS that users should be able to override -LDFLAGS ?= $(as_needed_LDFLAG) - -# Common CFLAGS for all i3 related binaries -I3_CFLAGS = -std=c99 -I3_CFLAGS += -Wall -# unused-function, unused-label, unused-variable are turned on by -Wall -# We don’t want unused-parameter because of the use of many callbacks -I3_CFLAGS += -Wunused-value -I3_CFLAGS += -Iinclude - -I3_CPPFLAGS = -DI3_VERSION=\"${I3_VERSION}\" -I3_CPPFLAGS += -DMAJOR_VERSION=${MAJOR_VERSION} -I3_CPPFLAGS += -DMINOR_VERSION=${MINOR_VERSION} -I3_CPPFLAGS += -DPATCH_VERSION=${PATCH_VERSION} -I3_CPPFLAGS += -DSYSCONFDIR=\"${SYSCONFDIR}\" -I3_CPPFLAGS += -DI3__FILE__=__FILE__ - - -## Libraries flags - -ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null 1>/dev/null || echo 1),1) -$(error "pkg-config was not found") -endif - -# An easier way to get CFLAGS and LDFLAGS falling back in case there's -# no pkg-config support for certain libraries. -# -# NOTE that you must not use a blank after comma when calling this: -# $(call ldflags_for_lib name, fallback) # bad -# $(call ldflags_for_lib name,fallback) # good -# Otherwise, the compiler will get -l foo instead of -lfoo -# -# We redirect stderr to /dev/null because pkg-config prints an error if support -# for gnome-config was enabled but gnome-config is not actually installed. -cflags_for_lib = $(shell $(PKG_CONFIG) --silence-errors --cflags $(1) 2>/dev/null) -ldflags_for_lib = $(shell $(PKG_CONFIG) --exists 2>/dev/null $(1) && $(PKG_CONFIG) --libs $(1) 2>/dev/null || echo -l$(2)) - -# XCB common stuff -XCB_CFLAGS := $(call cflags_for_lib, xcb) -XCB_CFLAGS += $(call cflags_for_lib, xcb-event) -XCB_LIBS := $(call ldflags_for_lib, xcb,xcb) -XCB_LIBS += $(call ldflags_for_lib, xcb-event,xcb-event) -XCB_CFLAGS += $(call cflags_for_lib, xcb-util) -XCB_LIBS += $(call ldflags_for_lib, xcb-util) -ifneq ($(shell $(PKG_CONFIG) --atleast-version=0.3.8 xcb-util 2>/dev/null && echo 1),1) -$(error "xcb-util >= 0.3.8 not found") -endif -XCB_XKB_LIBS := $(call ldflags_for_lib, xcb-xkb,xcb-xkb) - -# XCB keyboard stuff -XCB_KBD_CFLAGS := $(call cflags_for_lib, xcb-keysyms) -XCB_KBD_LIBS := $(call ldflags_for_lib, xcb-keysyms,xcb-keysyms) - -# XCB WM stuff -XCB_WM_CFLAGS := $(call cflags_for_lib, xcb-icccm) -XCB_WM_CFLAGS += $(call cflags_for_lib, xcb-xinerama) -XCB_WM_CFLAGS += $(call cflags_for_lib, xcb-randr) -XCB_WM_LIBS := $(call ldflags_for_lib, xcb-icccm,xcb-icccm) -XCB_WM_LIBS += $(call ldflags_for_lib, xcb-xinerama,xcb-xinerama) -XCB_WM_LIBS += $(call ldflags_for_lib, xcb-randr,xcb-randr) - -# XCB cursor -XCB_CURSOR_CFLAGS := $(call cflags_for_lib, xcb-cursor) -XCB_CURSOR_LIBS := $(call ldflags_for_lib, xcb-cursor,xcb-cursor) - -XKB_COMMON_CFLAGS := $(call cflags_for_lib, xkbcommon,xkbcommon) -XKB_COMMON_LIBS := $(call ldflags_for_lib, xkbcommon,xkbcommon) -XKB_COMMON_X11_CFLAGS := $(call cflags_for_lib, xkbcommon-x11,xkbcommon-x11) -XKB_COMMON_X11_LIBS := $(call ldflags_for_lib, xkbcommon-x11,xkbcommon-x11) - -# XCB xrm -XCB_XRM_CFLAGS := $(call cflags_for_lib, xcb-xrm) -XCB_XRM_LIBS := $(call ldflags_for_lib, xcb-xrm,xcb-xrm) - -# yajl -YAJL_CFLAGS := $(call cflags_for_lib, yajl) -YAJL_LIBS := $(call ldflags_for_lib, yajl,yajl) - -#libev -LIBEV_CFLAGS := $(call cflags_for_lib, libev) -LIBEV_LIBS := $(call ldflags_for_lib, libev,ev) - -# libpcre -PCRE_CFLAGS := $(call cflags_for_lib, libpcre) -ifneq ($(shell $(PKG_CONFIG) --atleast-version=8.10 libpcre 2>/dev/null && echo 1),1) -$(error "libpcre >= 8.10 not found") -endif -PCRE_LIBS := $(call ldflags_for_lib, libpcre,pcre) - -# startup-notification -LIBSN_CFLAGS := $(call cflags_for_lib, libstartup-notification-1.0) -LIBSN_LIBS := $(call ldflags_for_lib, libstartup-notification-1.0,startup-notification-1) - -# Pango -PANGO_CFLAGS := $(call cflags_for_lib, cairo) -PANGO_CFLAGS += $(call cflags_for_lib, pangocairo) -ifneq ($(shell $(PKG_CONFIG) --atleast-version=1.14.4 cairo 2>/dev/null && echo 1),1) -$(error "cairo >= 1.14.4 missing") -endif -PANGO_LIBS := $(call ldflags_for_lib, cairo) -PANGO_LIBS += $(call ldflags_for_lib, pangocairo) - -# libi3 -LIBS = -L$(TOPDIR) -li3 -lm - -## Platform-specific flags - -# Please test if -Wl,--as-needed works on your platform and send me a patch. -# it is known not to work on Darwin (Mac OS X) -ifneq (,$(filter Linux GNU GNU/%, $(UNAME))) -as_needed_LDFLAG = -Wl,--as-needed -endif - -ifeq ($(UNAME),NetBSD) -# We need -idirafter instead of -I to prefer the system’s iconv over GNU libiconv -I3_CFLAGS += -idirafter /usr/pkg/include -I3_LDFLAGS += -Wl,-rpath,/usr/local/lib -Wl,-rpath,/usr/pkg/lib -endif - -ifeq ($(UNAME),OpenBSD) -I3_CFLAGS += -I${X11BASE}/include -LIBS += -liconv -I3_LDFLAGS += -L${X11BASE}/lib -endif - -ifeq ($(UNAME),FreeBSD) -LIBS += -liconv -endif - -ifeq ($(UNAME),Darwin) -LIBS += -liconv -else ifneq ($(UNAME),OpenBSD) -# Darwin (Mac OS X) and OpenBSD do not have librt -LIBS += -lrt -endif - -ifeq ($(UNAME),SunOS) -LIBS += -lsocket -liconv -lgen -endif - -ifneq (,$(filter Linux GNU GNU/%, $(UNAME))) -I3_CPPFLAGS += -D_GNU_SOURCE -endif - - -ifeq ($(COVERAGE),1) -I3_CFLAGS += -fprofile-arcs -ftest-coverage -LIBS += -lgcov -endif - -V ?= 0 -ifeq ($(V),0) -# Don’t print command lines which are run -.SILENT: - -# echo-ing vars -V_ASCIIDOC = echo ASCIIDOC $@; -V_POD2HTML = echo POD2HTML $@; -V_POD2MAN = echo POD2MAN $@; -V_A2X = echo A2X $@; -endif - -# Always remake the following targets -.PHONY: install clean dist distclean - diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000..573261f5 --- /dev/null +++ b/configure.ac @@ -0,0 +1,164 @@ +# -*- Autoconf -*- +# Run autoreconf -fi to generate a configure script from this file. + +AC_PREREQ([2.69]) +AC_INIT([i3], [4.12], [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]) + +# 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 -d ${srcdir}/.git], + [ + VERSION="$(git describe --tags --abbrev=0)" + I3_VERSION="$(git describe --tags --always) ($(git log --pretty=format:%cd --date=short -n1), branch \\\"$(git 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="$(cat ${srcdir}/I3_VERSION)" + is_release="$(grep -q non-git ${srcdir}/I3_VERSION && echo no || echo yes)" + ]) +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 + +AC_DEFINE_UNQUOTED(SYSCONFDIR, "`eval echo $sysconfdir`", [Location of system configuration files]) + +# 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 strndup strrchr strspn strstr strtol strtoul], , [AC_MSG_FAILURE([cannot find the $ac_func function, which i3 requires])]) + +# 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]) + +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]) +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]) + +# Checks for programs. +AC_PROG_AWK +AC_PROG_CPP +AC_PROG_INSTALL +AC_PROG_MAKE_SET +AC_PROG_RANLIB +AC_PROG_LN_S + +AC_PATH_PROG([PATH_ASCIIDOC], [asciidoc]) +AC_PATH_PROG([PATH_XMLTO], [xmlto]) +AC_PATH_PROG([PATH_POD2MAN], [pod2man]) + +AM_CONDITIONAL([BUILD_MANS], [test x$PATH_ASCIIDOC != x && test x$PATH_XMLTO != x && test x$PATH_POD2MAN != x]) +AM_CONDITIONAL([BUILD_DOCS], [test x$PATH_ASCIIDOC != x]) + +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]) +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 + +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/docs/Makefile b/docs/Makefile deleted file mode 100644 index d6e670c9..00000000 --- a/docs/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: - $(MAKE) -C .. docs - -clean: - $(MAKE) -C .. clean-docs - -.PHONY: all clean diff --git a/docs/docs.mk b/docs/docs.mk deleted file mode 100644 index 050df97d..00000000 --- a/docs/docs.mk +++ /dev/null @@ -1,46 +0,0 @@ -DISTCLEAN_TARGETS += clean-docs - -# To pass additional parameters for asciidoc -ASCIIDOC = asciidoc -I3POD2HTML = ./docs/i3-pod2html - -ASCIIDOC_NOTOC_TARGETS = \ - docs/debugging.html - -ASCIIDOC_TOC_TARGETS = \ - 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 - -ASCIIDOC_TARGETS = \ - $(ASCIIDOC_TOC_TARGETS) \ - $(ASCIIDOC_NOTOC_TARGETS) - -ASCIIDOC_CALL = $(V_ASCIIDOC)$(ASCIIDOC) -n $(ASCIIDOC_FLAGS) -o $@ $< -ASCIIDOC_TOC_CALL = $(V_ASCIIDOC)$(ASCIIDOC) -a toc -n $(ASCIIDOC_FLAGS) -o $@ $< - -POD2HTML_TARGETS = \ - docs/lib-i3test.html \ - docs/lib-i3test-test.html - -docs/lib-i3test.html: testcases/lib/i3test.pm - $(V_POD2HTML)$(I3POD2HTML) $< $@ - -docs/lib-i3test-test.html: testcases/lib/i3test/Test.pm - $(V_POD2HTML)$(I3POD2HTML) $< $@ - -docs: $(ASCIIDOC_TARGETS) $(POD2HTML_TARGETS) - -$(ASCIIDOC_TOC_TARGETS): docs/%.html: docs/% - $(ASCIIDOC_TOC_CALL) - -$(ASCIIDOC_NOTOC_TARGETS): docs/%.html: docs/% - $(ASCIIDOC_CALL) - -clean-docs: - rm -f $(ASCIIDOC_TARGETS) $(POD2HTML_TARGETS) diff --git a/i3-config-wizard/Makefile b/i3-config-wizard/Makefile deleted file mode 100644 index d5ac18c6..00000000 --- a/i3-config-wizard/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -all: - $(MAKE) -C .. i3-config-wizard/i3-config-wizard - -install: - $(MAKE) -C .. install-i3-config-wizard - -clean: - $(MAKE) -C .. clean-i3-config-wizard - -.PHONY: all install clean diff --git a/i3-config-wizard/i3-config-wizard.mk b/i3-config-wizard/i3-config-wizard.mk deleted file mode 100644 index 9c01cdb6..00000000 --- a/i3-config-wizard/i3-config-wizard.mk +++ /dev/null @@ -1,28 +0,0 @@ -ALL_TARGETS += i3-config-wizard/i3-config-wizard -INSTALL_TARGETS += install-i3-config-wizard -CLEAN_TARGETS += clean-i3-config-wizard - -i3_config_wizard_SOURCES := $(wildcard i3-config-wizard/*.c) -i3_config_wizard_HEADERS := $(wildcard i3-config-wizard/*.h) -i3_config_wizard_CFLAGS = $(XCB_CFLAGS) $(XCB_KBD_CFLAGS) $(PANGO_CFLAGS) $(XCB_XRM_CFLAGS) $(XKB_COMMON_CFLAGS) $(XKB_COMMON_X11_CFLAGS) -i3_config_wizard_LIBS = $(XCB_LIBS) $(XCB_KBD_LIBS) $(PANGO_LIBS) $(XCB_XRM_LIBS) $(XKB_COMMON_LIBS) $(XKB_COMMON_X11_LIBS) - -i3_config_wizard_OBJECTS := $(i3_config_wizard_SOURCES:.c=.o) - - -i3-config-wizard/%.o: i3-config-wizard/%.c $(i3_config_wizard_HEADERS) i3-config-parser.stamp - echo "[i3-config-wizard] CC $<" - $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_config_wizard_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< - -i3-config-wizard/i3-config-wizard: libi3.a $(i3_config_wizard_OBJECTS) - echo "[i3-config-wizard] Link i3-config-wizard" - $(CC) $(I3_LDFLAGS) $(LDFLAGS) -o $@ $(filter-out libi3.a,$^) $(LIBS) $(i3_config_wizard_LIBS) - -install-i3-config-wizard: i3-config-wizard/i3-config-wizard - echo "[i3-config-wizard] Install" - $(INSTALL) -d -m 0755 $(DESTDIR)$(EXEC_PREFIX)/bin - $(INSTALL) -m 0755 i3-config-wizard/i3-config-wizard $(DESTDIR)$(EXEC_PREFIX)/bin/ - -clean-i3-config-wizard: - echo "[i3-config-wizard] Clean" - rm -f $(i3_config_wizard_OBJECTS) $(i3_config_wizard_SOURCES_GENERATED) i3-config-wizard/i3-config-wizard i3-config-wizard/cfgparse.* diff --git a/i3-dump-log/Makefile b/i3-dump-log/Makefile deleted file mode 100644 index 2b9e4fe9..00000000 --- a/i3-dump-log/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -all: - $(MAKE) -C .. i3-dump-log/i3-dump-log - -install: - $(MAKE) -C .. install-i3-dump-log - -clean: - $(MAKE) -C .. clean-i3-dump-log - -.PHONY: all install clean diff --git a/i3-dump-log/i3-dump-log.mk b/i3-dump-log/i3-dump-log.mk deleted file mode 100644 index 09a793f5..00000000 --- a/i3-dump-log/i3-dump-log.mk +++ /dev/null @@ -1,28 +0,0 @@ -ALL_TARGETS += i3-dump-log/i3-dump-log -INSTALL_TARGETS += install-i3-dump-log -CLEAN_TARGETS += clean-i3-dump-log - -i3_dump_log_SOURCES := $(wildcard i3-dump-log/*.c) -i3_dump_log_HEADERS := $(wildcard i3-dump-log/*.h) -i3_dump_log_CFLAGS = $(XCB_CFLAGS) $(PANGO_CFLAGS) -i3_dump_log_LIBS = $(XCB_LIBS) - -i3_dump_log_OBJECTS := $(i3_dump_log_SOURCES:.c=.o) - - -i3-dump-log/%.o: i3-dump-log/%.c $(i3_dump_log_HEADERS) - echo "[i3-dump-log] CC $<" - $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_dump_log_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< - -i3-dump-log/i3-dump-log: libi3.a $(i3_dump_log_OBJECTS) - echo "[i3-dump-log] Link i3-dump-log" - $(CC) $(I3_LDFLAGS) $(LDFLAGS) -o $@ $(filter-out libi3.a,$^) $(LIBS) $(i3_dump_log_LIBS) - -install-i3-dump-log: i3-dump-log/i3-dump-log - echo "[i3-dump-log] Install" - $(INSTALL) -d -m 0755 $(DESTDIR)$(EXEC_PREFIX)/bin - $(INSTALL) -m 0755 i3-dump-log/i3-dump-log $(DESTDIR)$(EXEC_PREFIX)/bin/ - -clean-i3-dump-log: - echo "[i3-dump-log] Clean" - rm -f $(i3_dump_log_OBJECTS) i3-dump-log/i3-dump-log diff --git a/i3-input/Makefile b/i3-input/Makefile deleted file mode 100644 index e1c8eae5..00000000 --- a/i3-input/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -all: - $(MAKE) -C .. i3-input/i3-input - -install: - $(MAKE) -C .. install-i3-input - -clean: - $(MAKE) -C .. clean-i3-input - -.PHONY: all install clean diff --git a/i3-input/i3-input.mk b/i3-input/i3-input.mk deleted file mode 100644 index ce36f932..00000000 --- a/i3-input/i3-input.mk +++ /dev/null @@ -1,28 +0,0 @@ -ALL_TARGETS += i3-input/i3-input -INSTALL_TARGETS += install-i3-input -CLEAN_TARGETS += clean-i3-input - -i3_input_SOURCES := $(wildcard i3-input/*.c) -i3_input_HEADERS := $(wildcard i3-input/*.h) -i3_input_CFLAGS = $(XCB_CFLAGS) $(XCB_KBD_CFLAGS) $(PANGO_CFLAGS) $(XCB_XRM_CFLAGS) -i3_input_LIBS = $(XCB_LIBS) $(XCB_KBD_LIBS) $(PANGO_LIBS) $(XCB_XRM_LIBS) - -i3_input_OBJECTS := $(i3_input_SOURCES:.c=.o) - - -i3-input/%.o: i3-input/%.c $(i3_input_HEADERS) - echo "[i3-input] CC $<" - $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_input_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< - -i3-input/i3-input: libi3.a $(i3_input_OBJECTS) - echo "[i3-input] Link i3-input" - $(CC) $(I3_LDFLAGS) $(LDFLAGS) -o $@ $(filter-out libi3.a,$^) $(LIBS) $(i3_input_LIBS) - -install-i3-input: i3-input/i3-input - echo "[i3-input] Install" - $(INSTALL) -d -m 0755 $(DESTDIR)$(EXEC_PREFIX)/bin - $(INSTALL) -m 0755 i3-input/i3-input $(DESTDIR)$(EXEC_PREFIX)/bin/ - -clean-i3-input: - echo "[i3-input] Clean" - rm -f $(i3_input_OBJECTS) i3-input/i3-input diff --git a/i3-msg/Makefile b/i3-msg/Makefile deleted file mode 100644 index fedb31e7..00000000 --- a/i3-msg/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -all: - $(MAKE) -C .. i3-msg/i3-msg - -install: - $(MAKE) -C .. install-i3-msg - -clean: - $(MAKE) -C .. clean-i3-msg - -.PHONY: all install clean diff --git a/i3-msg/i3-msg.mk b/i3-msg/i3-msg.mk deleted file mode 100644 index dfba4d2c..00000000 --- a/i3-msg/i3-msg.mk +++ /dev/null @@ -1,28 +0,0 @@ -ALL_TARGETS += i3-msg/i3-msg -INSTALL_TARGETS += install-i3-msg -CLEAN_TARGETS += clean-i3-msg - -i3_msg_SOURCES := $(wildcard i3-msg/*.c) -i3_msg_HEADERS := $(wildcard i3-msg/*.h) -i3_msg_CFLAGS = $(XCB_CFLAGS) $(PANGO_CFLAGS) $(YAJL_CFLAGS) -i3_msg_LIBS = $(XCB_LIBS) $(YAJL_LIBS) - -i3_msg_OBJECTS := $(i3_msg_SOURCES:.c=.o) - - -i3-msg/%.o: i3-msg/%.c $(i3_msg_HEADERS) - echo "[i3-msg] CC $<" - $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_msg_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< - -i3-msg/i3-msg: libi3.a $(i3_msg_OBJECTS) - echo "[i3-msg] Link i3-msg" - $(CC) $(I3_LDFLAGS) $(LDFLAGS) -o $@ $(filter-out libi3.a,$^) $(LIBS) $(i3_msg_LIBS) - -install-i3-msg: i3-msg/i3-msg - echo "[i3-msg] Install" - $(INSTALL) -d -m 0755 $(DESTDIR)$(EXEC_PREFIX)/bin - $(INSTALL) -m 0755 i3-msg/i3-msg $(DESTDIR)$(EXEC_PREFIX)/bin/ - -clean-i3-msg: - echo "[i3-msg] Clean" - rm -f $(i3_msg_OBJECTS) i3-msg/i3-msg diff --git a/i3-nagbar/Makefile b/i3-nagbar/Makefile deleted file mode 100644 index 12748e21..00000000 --- a/i3-nagbar/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -all: - $(MAKE) -C .. i3-nagbar/i3-nagbar - -install: - $(MAKE) -C .. install-i3-nagbar - -clean: - $(MAKE) -C .. clean-i3-nagbar - -.PHONY: all install clean diff --git a/i3-nagbar/i3-nagbar.mk b/i3-nagbar/i3-nagbar.mk deleted file mode 100644 index c6c7a2ef..00000000 --- a/i3-nagbar/i3-nagbar.mk +++ /dev/null @@ -1,28 +0,0 @@ -ALL_TARGETS += i3-nagbar/i3-nagbar -INSTALL_TARGETS += install-i3-nagbar -CLEAN_TARGETS += clean-i3-nagbar - -i3_nagbar_SOURCES := $(wildcard i3-nagbar/*.c) -i3_nagbar_HEADERS := $(wildcard i3-nagbar/*.h) -i3_nagbar_CFLAGS = $(XCB_CFLAGS) $(XCB_CURSOR_CFLAGS) $(XCB_WM_CFLAGS) $(PANGO_CFLAGS) $(XCB_XRM_CFLAGS) -i3_nagbar_LIBS = $(XCB_LIBS) $(XCB_CURSOR_LIBS) $(XCB_WM_LIBS) $(PANGO_LIBS) $(XCB_XRM_LIBS) - -i3_nagbar_OBJECTS := $(i3_nagbar_SOURCES:.c=.o) - - -i3-nagbar/%.o: i3-nagbar/%.c $(i3_nagbar_HEADERS) - echo "[i3-nagbar] CC $<" - $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_nagbar_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< - -i3-nagbar/i3-nagbar: libi3.a $(i3_nagbar_OBJECTS) - echo "[i3-nagbar] Link i3-nagbar" - $(CC) $(I3_LDFLAGS) $(LDFLAGS) -o $@ $(filter-out libi3.a,$^) $(LIBS) $(i3_nagbar_LIBS) - -install-i3-nagbar: i3-nagbar/i3-nagbar - echo "[i3-nagbar] Install" - $(INSTALL) -d -m 0755 $(DESTDIR)$(EXEC_PREFIX)/bin - $(INSTALL) -m 0755 i3-nagbar/i3-nagbar $(DESTDIR)$(EXEC_PREFIX)/bin/ - -clean-i3-nagbar: - echo "[i3-nagbar] Clean" - rm -f $(i3_nagbar_OBJECTS) i3-nagbar/i3-nagbar diff --git a/i3bar/Makefile b/i3bar/Makefile deleted file mode 100644 index cd23cd81..00000000 --- a/i3bar/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -all: - $(MAKE) -C .. i3bar/i3bar - -install: - $(MAKE) -C .. install-i3bar - -clean: - $(MAKE) -C .. clean-i3bar - -.PHONY: all install clean diff --git a/i3bar/i3bar.mk b/i3bar/i3bar.mk deleted file mode 100644 index 03c607dd..00000000 --- a/i3bar/i3bar.mk +++ /dev/null @@ -1,28 +0,0 @@ -ALL_TARGETS += i3bar/i3bar -INSTALL_TARGETS += install-i3bar -CLEAN_TARGETS += clean-i3bar - -i3bar_SOURCES := $(wildcard i3bar/src/*.c) -i3bar_HEADERS := $(wildcard i3bar/include/*.h) -i3bar_CFLAGS = $(XCB_CFLAGS) $(XCB_CURSOR_CFLAGS) $(PANGO_CFLAGS) $(XCB_XRM_CFLAGS) $(YAJL_CFLAGS) $(LIBEV_CFLAGS) -i3bar_LIBS = $(XCB_LIBS) $(XCB_CURSOR_LIBS) $(PANGO_LIBS) $(XCB_XRM_LIBS) $(YAJL_LIBS) $(LIBEV_LIBS) $(XCB_XKB_LIBS) - -i3bar_OBJECTS := $(i3bar_SOURCES:.c=.o) - - -i3bar/src/%.o: i3bar/src/%.c $(i3bar_HEADERS) - echo "[i3bar] CC $<" - $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3bar_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -Ii3bar/include -c -o $@ $< - -i3bar/i3bar: libi3.a $(i3bar_OBJECTS) - echo "[i3bar] Link i3bar" - $(CC) $(I3_LDFLAGS) $(LDFLAGS) -o $@ $(filter-out libi3.a,$^) $(LIBS) $(i3bar_LIBS) - -install-i3bar: i3bar/i3bar - echo "[i3bar] Install" - $(INSTALL) -d -m 0755 $(DESTDIR)$(EXEC_PREFIX)/bin - $(INSTALL) -m 0755 i3bar/i3bar $(DESTDIR)$(EXEC_PREFIX)/bin/ - -clean-i3bar: - echo "[i3bar] Clean" - rm -f $(i3bar_OBJECTS) i3bar/i3bar diff --git a/libi3/Makefile b/libi3/Makefile deleted file mode 100644 index 2c2f68ad..00000000 --- a/libi3/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: - $(MAKE) -C .. libi3.a - -clean: - $(MAKE) -C .. clean-libi3 - -.PHONY: all clean diff --git a/libi3/libi3.mk b/libi3/libi3.mk deleted file mode 100644 index 16e1f149..00000000 --- a/libi3/libi3.mk +++ /dev/null @@ -1,21 +0,0 @@ -CLEAN_TARGETS += clean-libi3 - -libi3_SOURCES := $(wildcard libi3/*.c) -libi3_HEADERS := $(wildcard libi3/*.h) -libi3_CFLAGS = $(PANGO_CFLAGS) $(XCB_XRM_CFLAGS) -libi3_LIBS = - -libi3_OBJECTS := $(libi3_SOURCES:.c=.o) - - -libi3/%.o: libi3/%.c $(libi3_HEADERS) - echo "[libi3] CC $<" - $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(libi3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ $< - -libi3.a: $(libi3_OBJECTS) - echo "[libi3] AR libi3.a" - $(AR) rcs $@ $^ $(libi3_LIBS) - -clean-libi3: - echo "[libi3] Clean" - rm -f $(libi3_OBJECTS) libi3/libi3.a libi3.a diff --git a/m4/ax_append_flag.m4 b/m4/ax_append_flag.m4 new file mode 100644 index 00000000..08f2e07e --- /dev/null +++ b/m4/ax_append_flag.m4 @@ -0,0 +1,71 @@ +# =========================================================================== +# 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 +# Copyright (c) 2011 Maarten Bosmans +# +# 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 . +# +# 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 new file mode 100644 index 00000000..1f077992 --- /dev/null +++ b/m4/ax_cflags_warn_all.m4 @@ -0,0 +1,122 @@ +# =========================================================================== +# 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 +# Copyright (c) 2010 Rhys Ulerich +# +# 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 . +# +# 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 new file mode 100644 index 00000000..ca363971 --- /dev/null +++ b/m4/ax_check_compile_flag.m4 @@ -0,0 +1,74 @@ +# =========================================================================== +# 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 +# Copyright (c) 2011 Maarten Bosmans +# +# 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 . +# +# 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 new file mode 100644 index 00000000..f99d75fe --- /dev/null +++ b/m4/ax_check_enable_debug.m4 @@ -0,0 +1,124 @@ +# =========================================================================== +# 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 +# Copyright (c) 2014, 2015 Philip Withnall +# +# 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 new file mode 100644 index 00000000..6762e9ed --- /dev/null +++ b/m4/ax_check_gnu_make.m4 @@ -0,0 +1,84 @@ +# =========================================================================== +# 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 +# Copyright (c) 2015 Enrico M. Crisostomo +# +# 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 new file mode 100644 index 00000000..eb01a6ce --- /dev/null +++ b/m4/ax_check_link_flag.m4 @@ -0,0 +1,74 @@ +# =========================================================================== +# 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 +# Copyright (c) 2011 Maarten Bosmans +# +# 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 . +# +# 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 new file mode 100644 index 00000000..6c985ebc --- /dev/null +++ b/m4/ax_code_coverage.m4 @@ -0,0 +1,273 @@ +# =========================================================================== +# 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 . + +#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" + + 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 new file mode 100644 index 00000000..0726b1bc --- /dev/null +++ b/m4/ax_configure_args.m4 @@ -0,0 +1,70 @@ +# =========================================================================== +# 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 +# +# 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 . +# +# 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 new file mode 100644 index 00000000..5f4ba327 --- /dev/null +++ b/m4/ax_enable_builddir.m4 @@ -0,0 +1,302 @@ +# =========================================================================== +# 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 +# Copyright (c) 2009 Alan Jenkins +# +# 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 . +# +# 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 new file mode 100644 index 00000000..a308d67d --- /dev/null +++ b/m4/ax_extend_srcdir.m4 @@ -0,0 +1,86 @@ +# =========================================================================== +# 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 +# +# 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 new file mode 100644 index 00000000..4c4051ea --- /dev/null +++ b/m4/ax_pthread.m4 @@ -0,0 +1,485 @@ +# =========================================================================== +# 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 +# Copyright (c) 2011 Daniel Richard G. +# +# 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 . +# +# 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 +# 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 ], + [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 ]], + [[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 new file mode 100644 index 00000000..cae11112 --- /dev/null +++ b/m4/ax_require_defined.m4 @@ -0,0 +1,37 @@ +# =========================================================================== +# 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 +# +# 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 new file mode 100644 index 00000000..836d4afd --- /dev/null +++ b/m4/ax_sanitizers.m4 @@ -0,0 +1,130 @@ +# =========================================================================== +# 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 option. +# +# SANITIZERS is a whitespace-separated list of sanitizers to offer via +# --enable--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 +# +# 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/man/Makefile b/man/Makefile deleted file mode 100644 index e4cee0cc..00000000 --- a/man/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: - $(MAKE) -C .. mans - -clean: - $(MAKE) -C .. clean-mans - -.PHONY: all clean diff --git a/man/man.mk b/man/man.mk deleted file mode 100644 index e0df386d..00000000 --- a/man/man.mk +++ /dev/null @@ -1,42 +0,0 @@ -DISTCLEAN_TARGETS += clean-mans - -A2X = a2x -POD2MAN = pod2man - -A2X_MAN_CALL = $(V_A2X)$(A2X) -f manpage --asciidoc-opts="-f man/asciidoc.conf" $(A2X_FLAGS) $< -POD2MAN_CALL = $(V_POD2MAN)$(POD2MAN) --utf8 $< > $@ - -MANS_ASCIIDOC = \ - 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 - -MANS_POD = \ - man/i3-dmenu-desktop.1 \ - man/i3-save-tree.1 - -MANS = \ - $(MANS_ASCIIDOC) \ - $(MANS_POD) - -mans: $(MANS) - -$(MANS_ASCIIDOC): %.1: %.man man/asciidoc.conf - $(A2X_MAN_CALL) - -$(MANS_POD): man/%.1: % - $(POD2MAN_CALL) - -clean-mans: - for file in $(notdir $(MANS)); \ - do \ - rm -f man/$${file} man/$${file%.*}.html man/$${file%.*}.xml; \ - done diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index 6a37f56c..00000000 --- a/src/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -all: - $(MAKE) -C .. i3 - -install: - $(MAKE) -C .. install-i3 - -clean: - $(MAKE) -C .. clean-i3 - -.PHONY: all install clean diff --git a/src/i3.mk b/src/i3.mk deleted file mode 100644 index de3f6845..00000000 --- a/src/i3.mk +++ /dev/null @@ -1,102 +0,0 @@ -ALL_TARGETS += i3 test-tools -INSTALL_TARGETS += install-i3 -CLEAN_TARGETS += clean-i3 - -i3_SOURCES := $(filter-out $(i3_SOURCES_GENERATED),$(wildcard src/*.c)) -i3_HEADERS_CMDPARSER := $(wildcard include/GENERATED_*.h) -i3_HEADERS := $(filter-out $(i3_HEADERS_CMDPARSER),$(wildcard include/*.h)) -i3_CFLAGS = $(XKB_COMMON_CFLAGS) $(XKB_COMMON_X11_CFLAGS) $(XCB_CFLAGS) $(XCB_KBD_CFLAGS) $(XCB_WM_CFLAGS) $(XCB_CURSOR_CFLAGS) $(XCB_XRM_CFLAGS) $(PANGO_CFLAGS) $(YAJL_CFLAGS) $(LIBEV_CFLAGS) $(PCRE_CFLAGS) $(LIBSN_CFLAGS) -i3_LIBS = $(XKB_COMMON_LIBS) $(XKB_COMMON_X11_LIBS) $(XCB_LIBS) $(XCB_XKB_LIBS) $(XCB_KBD_LIBS) $(XCB_WM_LIBS) $(XCB_CURSOR_LIBS) $(XCB_XRM_LIBS) $(PANGO_LIBS) $(YAJL_LIBS) $(LIBEV_LIBS) $(PCRE_LIBS) $(LIBSN_LIBS) -lm -ifneq ($(UNAME),OpenBSD) -i3_LIBS += -lpthread -endif - -# When using clang, we use pre-compiled headers to speed up the build. With -# gcc, this actually makes the build slower. -ifeq ($(CC),clang) -i3_HEADERS_DEP := $(i3_HEADERS) include/all.h.pch -PCH_FLAGS := -include include/all.h -else -i3_HEADERS_DEP := $(i3_HEADERS) -PCH_FLAGS := -endif - -i3_OBJECTS := $(i3_SOURCES_GENERATED:.c=.o) $(i3_SOURCES:.c=.o) - -# The basename/pwd calls are for canonicalizing the path: Instead -# of src/main.c, we will see something like ../i3-4.2/src/main.c in -# debugger backtraces, making it clearer which code belongs to i3 and -# which code doesn’t. -# We only do this for src/ since all the other subdirectories contain i3 in -# their name already. -canonical_path := ../$(shell basename $(shell pwd -P)) - -include/all.h.pch: $(i3_HEADERS) - echo "[i3] PCH all.h" - $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -x c-header include/all.h -o include/all.h.pch - -src/version.o: src/version.c LAST_VERSION $(i3_HEADERS_DEP) - echo "[i3] CC $<" - $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) $(PCH_FLAGS) -c -o $@ ${canonical_path}/$< - -src/%.o: src/%.c $(i3_HEADERS_DEP) - echo "[i3] CC $<" - $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) $(PCH_FLAGS) -c -o $@ ${canonical_path}/$< - -test-tools: test.commands_parser test.config_parser - -test.commands_parser: src/commands_parser.c $(i3_HEADERS_DEP) i3-command-parser.stamp libi3.a - echo "[i3] Link test.commands_parser" - $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) $(I3_LDFLAGS) $(LDFLAGS) -DTEST_PARSER -g -o test.commands_parser $< $(LIBS) $(i3_LIBS) - -test.config_parser: src/config_parser.c $(i3_HEADERS_DEP) i3-config-parser.stamp libi3.a - echo "[i3] Link test.config_parser" - $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) $(I3_LDFLAGS) $(LDFLAGS) -DTEST_PARSER -g -o test.config_parser $< $(LIBS) $(i3_LIBS) - -src/commands_parser.o: src/commands_parser.c $(i3_HEADERS_DEP) i3-command-parser.stamp - echo "[i3] CC $<" - $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ ${canonical_path}/$< - -src/config_parser.o: src/config_parser.c $(i3_HEADERS_DEP) i3-config-parser.stamp - echo "[i3] CC $<" - $(CC) $(I3_CPPFLAGS) $(CPPFLAGS) $(i3_CFLAGS) $(I3_CFLAGS) $(CFLAGS) -c -o $@ ${canonical_path}/$< - -i3-command-parser.stamp: generate-command-parser.pl parser-specs/commands.spec - echo "[i3] Generating command parser" - (cd $(TOPDIR)/include; ../generate-command-parser.pl --input=../parser-specs/commands.spec --prefix=command) - touch $@ - -i3-config-parser.stamp: generate-command-parser.pl parser-specs/config.spec - echo "[i3] Generating config parser" - (cd $(TOPDIR)/include; ../generate-command-parser.pl --input=../parser-specs/config.spec --prefix=config) - touch $@ - -i3: libi3.a $(i3_OBJECTS) - echo "[i3] Link i3" - $(CC) $(CFLAGS) $(I3_LDFLAGS) $(LDFLAGS) -o $@ $(filter-out libi3.a,$^) $(LIBS) $(i3_LIBS) - -install-i3: i3 - echo "[i3] Install" - $(INSTALL) -d -m 0755 $(DESTDIR)$(EXEC_PREFIX)/bin - $(INSTALL) -d -m 0755 $(DESTDIR)$(SYSCONFDIR)/i3 - $(INSTALL) -d -m 0755 $(DESTDIR)$(EXEC_PREFIX)/include/i3 - $(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/share/xsessions - $(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/share/applications - $(INSTALL) -m 0755 i3 $(DESTDIR)$(EXEC_PREFIX)/bin/ - $(LN) -sf i3 $(DESTDIR)$(EXEC_PREFIX)/bin/i3-with-shmlog - $(INSTALL) -m 0755 i3-migrate-config-to-v4 $(DESTDIR)$(EXEC_PREFIX)/bin/ - $(INSTALL) -m 0755 i3-sensible-editor $(DESTDIR)$(EXEC_PREFIX)/bin/ - $(INSTALL) -m 0755 i3-sensible-pager $(DESTDIR)$(EXEC_PREFIX)/bin/ - $(INSTALL) -m 0755 i3-sensible-terminal $(DESTDIR)$(EXEC_PREFIX)/bin/ - $(INSTALL) -m 0755 i3-save-tree $(DESTDIR)$(EXEC_PREFIX)/bin/ - $(INSTALL) -m 0755 i3-dmenu-desktop $(DESTDIR)$(EXEC_PREFIX)/bin/ - test -e $(DESTDIR)$(SYSCONFDIR)/i3/config || $(INSTALL) -m 0644 i3.config $(DESTDIR)$(SYSCONFDIR)/i3/config - test -e $(DESTDIR)$(SYSCONFDIR)/i3/config.keycodes || $(INSTALL) -m 0644 i3.config.keycodes $(DESTDIR)$(SYSCONFDIR)/i3/config.keycodes - $(INSTALL) -m 0644 i3.xsession.desktop $(DESTDIR)$(PREFIX)/share/xsessions/i3.desktop - $(INSTALL) -m 0644 i3-with-shmlog.xsession.desktop $(DESTDIR)$(PREFIX)/share/xsessions/i3-with-shmlog.desktop - $(INSTALL) -m 0644 i3.applications.desktop $(DESTDIR)$(PREFIX)/share/applications/i3.desktop - $(INSTALL) -m 0644 include/i3/ipc.h $(DESTDIR)$(EXEC_PREFIX)/include/i3/ - -clean-i3: - echo "[i3] Clean" - rm -f $(i3_OBJECTS) $(i3_SOURCES_GENERATED) $(i3_HEADERS_CMDPARSER) include/loglevels.h loglevels.tmp include/all.h.pch i3-command-parser.stamp i3-config-parser.stamp i3 test.config_parser test.commands_parser src/*.gcno src/cfgparse.* src/cmdparse.* LAST_VERSION From 84e70a19a82eeed387160a75f4ca28717cd5db7a Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 10 Oct 2016 21:14:59 +0200 Subject: [PATCH 124/150] testsuite: use relative paths, set PATH to absolute path This approach works better with autotools, which supports the build directory being complete outside the source tree. --- .../{complete-run.pl => complete-run.pl.in} | 71 ++++++++----------- testcases/lib/SocketActivation.pm | 10 +-- testcases/lib/TestWorker.pm | 2 +- testcases/lib/{i3test.pm => i3test.pm.in} | 2 +- testcases/t/171-config-migrate.t | 2 +- testcases/t/187-commands-parser.t | 2 +- testcases/t/196-randr-output-names.t | 2 +- testcases/t/201-config-parser.t | 2 +- testcases/t/207-shmlog.t | 8 +-- testcases/t/235-check-config-no-x.t | 2 +- 10 files changed, 41 insertions(+), 62 deletions(-) rename testcases/{complete-run.pl => complete-run.pl.in} (89%) rename testcases/lib/{i3test.pm => i3test.pm.in} (99%) diff --git a/testcases/complete-run.pl b/testcases/complete-run.pl.in similarity index 89% rename from testcases/complete-run.pl rename to testcases/complete-run.pl.in index 14c0a15d..d872bda1 100755 --- a/testcases/complete-run.pl +++ b/testcases/complete-run.pl.in @@ -17,19 +17,8 @@ use TAP::Parser::Aggregator; use Time::HiRes qw(time); use IO::Handle; -my $dirname; - -BEGIN { - use File::Basename; - use Cwd qw(abs_path); - - # fileparse()[1] contains the directory portion of the specified path. - # See File::Basename(3p) for more details. - $dirname = (fileparse(abs_path($0)))[1]; -} - # these are shipped with the testsuite -use lib $dirname . 'lib'; +use lib qw(@abs_top_builddir@/testcases/lib @abs_top_srcdir@/testcases/lib); use i3test::Util qw(slurp); use StartXServer; use StatusLine; @@ -82,17 +71,15 @@ my $result = GetOptions( pod2usage(-verbose => 2, -exitcode => 0) if $help; -chdir $dirname or die "Could not chdir into $dirname"; - # Check for missing executables my @binaries = qw( - ../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 + @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 ); foreach my $binary (@binaries) { @@ -100,15 +87,16 @@ foreach my $binary (@binaries) { die "$binary is not an executable" unless -x $binary; } -if ($options{coverage}) { - qx(command -v lcov &> /dev/null); - die "Cannot find lcov needed for coverage testing." if $?; - qx(command -v genhtml &> /dev/null); - die "Cannot find genhtml needed for coverage testing." if $?; - - # clean out the counters that may be left over from previous tests. - qx(lcov -d ../ --zerocounters &> /dev/null); -} +$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}); qx(Xephyr -help 2>&1); die "Xephyr was not found in your path. Please install Xephyr (xserver-xephyr on Debian)." if $?; @@ -120,7 +108,17 @@ die "Xephyr was not found in your path. Please install Xephyr (xserver-xephyr on my @testfiles = @ARGV; # if no files were passed on command line, run all tests from t/ -@testfiles = if @testfiles == 0; +if (scalar @testfiles == 0) { + @testfiles = <@abs_top_srcdir@/testcases/t/*.t> if @testfiles == 0; +} else { + @testfiles = map { + # Fully qualify each specified file if necessary + if (! -e $_) { + $_ = "@abs_top_srcdir@/testcases/$_"; + } + $_ + } @testfiles; +} my $numtests = scalar @testfiles; @@ -251,17 +249,6 @@ if ($numtests == 1) { END { cleanup() } -if ($options{coverage}) { - print("\nGenerating test coverage report...\n"); - qx(lcov -d ../ -b ../ --capture -o latest/i3-coverage.info); - qx(genhtml -o latest/i3-coverage latest/i3-coverage.info); - if ($?) { - print("Could not generate test coverage html. Did you compile i3 with test coverage support?\n"); - } else { - print("Test coverage report generated in latest/i3-coverage\n"); - } -} - # Report logfiles that match “(Leak|Address)Sanitizer:”. my @logs_with_leaks; for my $log (<$outdir/i3-log-for-*>) { diff --git a/testcases/lib/SocketActivation.pm b/testcases/lib/SocketActivation.pm index b58707a4..53dbb3b6 100644 --- a/testcases/lib/SocketActivation.pm +++ b/testcases/lib/SocketActivation.pm @@ -62,14 +62,6 @@ sub activate_i3 { mkdir $ENV{XDG_RUNTIME_DIR}; } $ENV{DISPLAY} = $args{display}; - $ENV{PATH} = join(':', - '../i3-nagbar', - '../i3-msg', - '../i3-config-wizard', - '../i3bar', - '..', - $ENV{PATH} - ); # We are about to exec, but we did not modify $^F to include $socket # when creating the socket (because the file descriptor could have a @@ -96,7 +88,7 @@ sub activate_i3 { # the interactive signalhandler to make it crash immediately instead. # Also disable logging to SHM since we redirect the logs anyways. # Force Xinerama because we use Xdmx for multi-monitor tests. - my $i3cmd = abs_path("../i3") . q| --shmlog-size=0 --disable-signalhandler --force-xinerama|; + my $i3cmd = q|i3 --shmlog-size=0 --disable-signalhandler --force-xinerama|; if (!$args{validate_config}) { # We only set logging if i3 is actually started, but not if we only # validate the config file. This is to keep logging to a minimum as diff --git a/testcases/lib/TestWorker.pm b/testcases/lib/TestWorker.pm index 6371591f..aee994f7 100644 --- a/testcases/lib/TestWorker.pm +++ b/testcases/lib/TestWorker.pm @@ -125,7 +125,7 @@ sub worker_wait { package main; local $@; - do "./$file"; + do $file; $test->ok(undef, "$@") if $@; # XXX hack, we need to trigger the read watcher once more diff --git a/testcases/lib/i3test.pm b/testcases/lib/i3test.pm.in similarity index 99% rename from testcases/lib/i3test.pm rename to testcases/lib/i3test.pm.in index 98486122..f9f6e821 100644 --- a/testcases/lib/i3test.pm +++ b/testcases/lib/i3test.pm.in @@ -836,7 +836,7 @@ sub launch_with_config { if ($config ne '-default') { say $fh $config; } else { - open(my $conf_fh, '<', './i3-test.config') + open(my $conf_fh, '<', '@abs_top_srcdir@/testcases/i3-test.config') or $tester->BAIL_OUT("could not open default config: $!"); local $/; say $fh scalar <$conf_fh>; diff --git a/testcases/t/171-config-migrate.t b/testcases/t/171-config-migrate.t index d098ae58..5bd21128 100644 --- a/testcases/t/171-config-migrate.t +++ b/testcases/t/171-config-migrate.t @@ -29,7 +29,7 @@ sub migrate_config { print $fh $config; close($fh); - my $cmd = "sh -c 'exec " . abs_path("../i3-migrate-config-to-v4") . " --v3 <$tmpfile'"; + my $cmd = "sh -c 'exec i3-migrate-config-to-v4 --v3 <$tmpfile'"; return [ split /\n/, qx($cmd) ]; } diff --git a/testcases/t/187-commands-parser.t b/testcases/t/187-commands-parser.t index 73c443f9..dc5b67ed 100644 --- a/testcases/t/187-commands-parser.t +++ b/testcases/t/187-commands-parser.t @@ -25,7 +25,7 @@ sub parser_calls { # TODO: use a timeout, so that we can error out if it doesn’t terminate # TODO: better way of passing arguments - my $stdout = qx(../test.commands_parser '$command' 2>&1 >&-); + my $stdout = qx(test.commands_parser '$command' 2>&1 >&-); # Filter out all debugging output. my @lines = split("\n", $stdout); diff --git a/testcases/t/196-randr-output-names.t b/testcases/t/196-randr-output-names.t index e5049eb8..7c53732b 100644 --- a/testcases/t/196-randr-output-names.t +++ b/testcases/t/196-randr-output-names.t @@ -28,7 +28,7 @@ font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 workspace 2 output DVI-I_1/digital EOT -my $output = qx(../i3 -C -c $filename); +my $output = qx(i3 -C -c $filename); unlike($output, qr/ERROR/, 'no errors in i3 -C'); close($fh); diff --git a/testcases/t/201-config-parser.t b/testcases/t/201-config-parser.t index d92d3b20..6cd84b6f 100644 --- a/testcases/t/201-config-parser.t +++ b/testcases/t/201-config-parser.t @@ -25,7 +25,7 @@ sub parser_calls { my ($command) = @_; my $stdout; - run [ '../test.config_parser', $command ], + run [ 'test.config_parser', $command ], '>/dev/null', '2>', \$stdout; # TODO: use a timeout, so that we can error out if it doesn’t terminate diff --git a/testcases/t/207-shmlog.t b/testcases/t/207-shmlog.t index b63a7499..b6c6d776 100644 --- a/testcases/t/207-shmlog.t +++ b/testcases/t/207-shmlog.t @@ -33,7 +33,7 @@ my $pid = launch_with_config($config); my $stdout; my $stderr; -run [ '../i3-dump-log/i3-dump-log' ], +run [ 'i3-dump-log' ], '>', \$stdout, '2>', \$stderr; @@ -49,7 +49,7 @@ cmd 'shmlog on'; my $random_nop = mktemp('nop.XXXXXX'); cmd "nop $random_nop"; -run [ '../i3-dump-log/i3-dump-log' ], +run [ 'i3-dump-log' ], '>', \$stdout, '2>', \$stderr; @@ -62,7 +62,7 @@ like($stderr, qr#^$#, 'stderr empty'); cmd 'shmlog ' . (23 * 1024 * 1024); -run [ '../i3-dump-log/i3-dump-log' ], +run [ 'i3-dump-log' ], '>', \$stdout, '2>', \$stderr; @@ -75,7 +75,7 @@ like($stderr, qr#^$#, 'stderr empty'); cmd 'shmlog off'; -run [ '../i3-dump-log/i3-dump-log' ], +run [ 'i3-dump-log' ], '>', \$stdout, '2>', \$stderr; diff --git a/testcases/t/235-check-config-no-x.t b/testcases/t/235-check-config-no-x.t index ec17353e..5e87d992 100644 --- a/testcases/t/235-check-config-no-x.t +++ b/testcases/t/235-check-config-no-x.t @@ -26,7 +26,7 @@ sub check_config { my ($config) = @_; my ($fh, $tmpfile) = tempfile(UNLINK => 1); print $fh $config; - my $output = qx(DISPLAY= ../i3 -C -c $tmpfile 2>&1); + my $output = qx(DISPLAY= i3 -C -c $tmpfile 2>&1); my $retval = $?; $fh->flush; close($fh); From 567897bec6378cd771c8a554b33c0f068786e2ca Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 10 Oct 2016 21:16:09 +0200 Subject: [PATCH 125/150] Switch from I3__FILE__ to STRIPPED__FILE__ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …as we now use the m4/ax_extend_srcdir.m4 macro, which defines STRIPPED__FILE__ (the macro is not i3-specific). --- include/libi3.h | 2 +- include/log.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/libi3.h b/include/libi3.h index 5123ce01..0d9189f3 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -89,7 +89,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, I3__FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define DLOG(fmt, ...) debuglog("%s:%s:%d - " fmt, STRIPPED__FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) #endif /** diff --git a/include/log.h b/include/log.h index e7fc8acb..b683529c 100644 --- a/include/log.h +++ b/include/log.h @@ -27,7 +27,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, I3__FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define DLOG(fmt, ...) debuglog("%s:%s:%d - " fmt, STRIPPED__FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) extern char *errorfilename; extern char *shmlogname; From c2bd10c482173b72a74f568348305ea87d3b4dd9 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 11 Oct 2016 08:53:58 +0200 Subject: [PATCH 126/150] Move/rename config files/.desktop files into subdirs This makes it easier to install them with the correct name when using autotools. --- i3.config => etc/config | 0 i3.config.keycodes => etc/config.keycodes | 0 i3.applications.desktop => share/applications/i3.desktop | 0 .../xsessions/i3-with-shmlog.desktop | 0 i3.xsession.desktop => share/xsessions/i3.desktop | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename i3.config => etc/config (100%) rename i3.config.keycodes => etc/config.keycodes (100%) rename i3.applications.desktop => share/applications/i3.desktop (100%) rename i3-with-shmlog.xsession.desktop => share/xsessions/i3-with-shmlog.desktop (100%) rename i3.xsession.desktop => share/xsessions/i3.desktop (100%) diff --git a/i3.config b/etc/config similarity index 100% rename from i3.config rename to etc/config diff --git a/i3.config.keycodes b/etc/config.keycodes similarity index 100% rename from i3.config.keycodes rename to etc/config.keycodes diff --git a/i3.applications.desktop b/share/applications/i3.desktop similarity index 100% rename from i3.applications.desktop rename to share/applications/i3.desktop diff --git a/i3-with-shmlog.xsession.desktop b/share/xsessions/i3-with-shmlog.desktop similarity index 100% rename from i3-with-shmlog.xsession.desktop rename to share/xsessions/i3-with-shmlog.desktop diff --git a/i3.xsession.desktop b/share/xsessions/i3.desktop similarity index 100% rename from i3.xsession.desktop rename to share/xsessions/i3.desktop From f354f534357798eb3ba497b7143132f41ff090f6 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 11 Oct 2016 09:13:35 +0200 Subject: [PATCH 127/150] Ensure all *.[ch] files include config.h Including config.h is necessary to get e.g. the _GNU_SOURCE define and any other definitions that autoconf declares. Hence, config.h needs to be included as the first header in each file. This is done either via: 1. Including "common.h" (i3bar) 2. Including "libi3.h" 3. Including "all.h" (i3) 4. Including directly Also remove now-unused I3__FILE__, add copyright/license statement where missing and switch include/all.h to #pragma once. --- i3-config-wizard/main.c | 2 ++ i3-dump-log/main.c | 2 ++ i3-input/i3-input.h | 2 ++ i3-input/main.c | 4 ++-- i3-msg/main.c | 3 ++- i3-nagbar/i3-nagbar.h | 2 ++ i3-nagbar/main.c | 3 ++- i3bar/include/child.h | 2 ++ i3bar/include/common.h | 2 ++ i3bar/include/configuration.h | 2 ++ i3bar/include/ipc.h | 2 ++ i3bar/include/mode.h | 2 ++ i3bar/include/outputs.h | 2 ++ i3bar/include/parse_json_header.h | 2 ++ i3bar/include/util.h | 2 ++ i3bar/include/workspaces.h | 4 ++-- i3bar/include/xcb.h | 2 ++ i3bar/src/child.c | 4 ++-- i3bar/src/config.c | 4 ++-- i3bar/src/ipc.c | 4 ++-- i3bar/src/main.c | 4 ++-- i3bar/src/mode.c | 4 ++-- i3bar/src/outputs.c | 4 ++-- i3bar/src/parse_json_header.c | 4 ++-- i3bar/src/workspaces.c | 4 ++-- i3bar/src/xcb.c | 3 ++- include/all.h | 7 +++---- include/assignments.h | 2 ++ include/bindings.h | 2 ++ include/click.h | 2 ++ include/cmdparse.h | 2 ++ include/commands.h | 2 ++ include/commands_parser.h | 2 ++ include/con.h | 2 ++ include/config_directives.h | 2 ++ include/config_parser.h | 2 ++ include/configuration.h | 3 ++- include/data.h | 3 ++- include/debug.h | 2 ++ include/display_version.h | 2 ++ include/ewmh.h | 2 ++ include/fake_outputs.h | 2 ++ include/floating.h | 2 ++ include/handlers.h | 2 ++ include/i3.h | 2 ++ include/ipc.h | 2 ++ include/key_press.h | 2 ++ include/libi3.h | 2 ++ include/load_layout.h | 2 ++ include/log.h | 2 ++ include/main.h | 2 ++ include/manage.h | 2 ++ include/match.h | 2 ++ include/move.h | 2 ++ include/output.h | 2 ++ include/randr.h | 2 ++ include/regex.h | 2 ++ include/render.h | 2 ++ include/resize.h | 2 ++ include/restore_layout.h | 2 ++ include/scratchpad.h | 2 ++ include/shmlog.h | 2 ++ include/sighandler.h | 2 ++ include/startup.h | 2 ++ include/tree.h | 2 ++ include/util.h | 2 ++ include/window.h | 2 ++ include/workspace.h | 2 ++ include/x.h | 2 ++ include/xcb.h | 2 ++ include/xcursor.h | 2 ++ include/xinerama.h | 2 ++ include/yajl_utils.h | 2 ++ libi3/dpi.c | 1 + libi3/draw_util.c | 4 ++-- libi3/fake_configure_notify.c | 4 ++-- libi3/font.c | 4 ++-- libi3/format_placeholders.c | 4 ++-- libi3/get_colorpixel.c | 4 ++-- libi3/get_config_path.c | 1 + libi3/get_exe_path.c | 11 +++++++++-- libi3/get_mod_mask.c | 4 ++-- libi3/get_process_filename.c | 4 ++-- libi3/ipc_connect.c | 4 ++-- libi3/ipc_recv_message.c | 4 ++-- libi3/ipc_send_message.c | 4 ++-- libi3/is_debug_build.c | 9 +++++++++ libi3/mkdirp.c | 8 ++++++++ libi3/resolve_tilde.c | 2 +- libi3/root_atom_contents.c | 4 ++-- libi3/safewrappers.c | 4 ++-- libi3/string.c | 3 +-- libi3/strndup.c | 4 ++-- libi3/ucs2_conversion.c | 4 ++-- src/assignments.c | 2 -- src/click.c | 2 -- src/commands.c | 5 ++--- src/commands_parser.c | 6 ++---- src/con.c | 3 +-- src/config.c | 3 +-- src/config_directives.c | 6 ++---- src/config_parser.c | 6 ++---- src/debug.c | 4 ++-- src/display_version.c | 5 ++--- src/ewmh.c | 2 -- src/fake_outputs.c | 2 -- src/floating.c | 2 -- src/handlers.c | 2 -- src/ipc.c | 3 +-- src/key_press.c | 2 -- src/load_layout.c | 2 -- src/log.c | 4 ++-- src/main.c | 5 ++--- src/manage.c | 3 +-- src/match.c | 2 -- src/move.c | 2 -- src/output.c | 2 -- src/randr.c | 2 -- src/regex.c | 2 -- src/render.c | 2 -- src/resize.c | 2 -- src/restore_layout.c | 2 -- src/scratchpad.c | 2 -- src/sighandler.c | 2 -- src/startup.c | 3 +-- src/tree.c | 2 -- src/util.c | 2 -- src/version.c | 2 ++ src/window.c | 2 -- src/workspace.c | 2 -- src/x.c | 2 -- src/xcb.c | 2 -- src/xcursor.c | 4 ++-- src/xinerama.c | 2 -- 134 files changed, 230 insertions(+), 149 deletions(-) diff --git a/i3-config-wizard/main.c b/i3-config-wizard/main.c index 284f15fa..2bb43270 100644 --- a/i3-config-wizard/main.c +++ b/i3-config-wizard/main.c @@ -8,6 +8,8 @@ * keysyms. * */ +#include + #if defined(__FreeBSD__) #include #endif diff --git a/i3-dump-log/main.c b/i3-dump-log/main.c index d9b0613c..ec9e577d 100644 --- a/i3-dump-log/main.c +++ b/i3-dump-log/main.c @@ -7,6 +7,8 @@ * i3-dump-log/main.c: Dumps the i3 SHM log to stdout. * */ +#include + #include #include #include diff --git a/i3-input/i3-input.h b/i3-input/i3-input.h index fcf9edc3..d347506f 100644 --- a/i3-input/i3-input.h +++ b/i3-input/i3-input.h @@ -1,5 +1,7 @@ #pragma once +#include + #include #define die(...) errx(EXIT_FAILURE, __VA_ARGS__); diff --git a/i3-input/main.c b/i3-input/main.c index b467c4c3..97d574a2 100644 --- a/i3-input/main.c +++ b/i3-input/main.c @@ -8,6 +8,8 @@ * to i3. * */ +#include "libi3.h" + #include #include #include @@ -31,8 +33,6 @@ #include "i3-input.h" -#include "libi3.h" - /* IPC format string. %s will be replaced with what the user entered, then * the command will be sent to i3 */ static char *format; diff --git a/i3-msg/main.c b/i3-msg/main.c index 658c33b4..51612459 100644 --- a/i3-msg/main.c +++ b/i3-msg/main.c @@ -14,6 +14,8 @@ * Additionally, it’s even useful sometimes :-). * */ +#include "libi3.h" + #include #include #include @@ -34,7 +36,6 @@ #include #include -#include "libi3.h" #include static char *socket_path; diff --git a/i3-nagbar/i3-nagbar.h b/i3-nagbar/i3-nagbar.h index fc076d72..c5e94cc6 100644 --- a/i3-nagbar/i3-nagbar.h +++ b/i3-nagbar/i3-nagbar.h @@ -1,5 +1,7 @@ #pragma once +#include + #include #define die(...) errx(EXIT_FAILURE, __VA_ARGS__); diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c index 674fcb7d..2e9e77d4 100644 --- a/i3-nagbar/main.c +++ b/i3-nagbar/main.c @@ -8,6 +8,8 @@ * when the user has an error in their configuration file. * */ +#include "libi3.h" + #include #include #include @@ -30,7 +32,6 @@ #include #include -#include "libi3.h" #include "i3-nagbar.h" /** This is the equivalent of XC_left_ptr. I’m not sure why xcb doesn’t have a diff --git a/i3bar/include/child.h b/i3bar/include/child.h index 873a3465..0871c7f4 100644 --- a/i3bar/include/child.h +++ b/i3bar/include/child.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include #define STDIN_CHUNK_SIZE 1024 diff --git a/i3bar/include/common.h b/i3bar/include/common.h index c6bb0dba..0929e408 100644 --- a/i3bar/include/common.h +++ b/i3bar/include/common.h @@ -7,6 +7,8 @@ */ #pragma once +#include + #include #include #include diff --git a/i3bar/include/configuration.h b/i3bar/include/configuration.h index 2a059046..c7c1f5e2 100644 --- a/i3bar/include/configuration.h +++ b/i3bar/include/configuration.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include "common.h" typedef enum { diff --git a/i3bar/include/ipc.h b/i3bar/include/ipc.h index 686c0322..5056e5f3 100644 --- a/i3bar/include/ipc.h +++ b/i3bar/include/ipc.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include /* diff --git a/i3bar/include/mode.h b/i3bar/include/mode.h index 828d4906..5c87d904 100644 --- a/i3bar/include/mode.h +++ b/i3bar/include/mode.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include #include "common.h" diff --git a/i3bar/include/outputs.h b/i3bar/include/outputs.h index 63cfca7f..3067581d 100644 --- a/i3bar/include/outputs.h +++ b/i3bar/include/outputs.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include #include diff --git a/i3bar/include/parse_json_header.h b/i3bar/include/parse_json_header.h index 41e97de2..d834fe05 100644 --- a/i3bar/include/parse_json_header.h +++ b/i3bar/include/parse_json_header.h @@ -10,6 +10,8 @@ */ #pragma once +#include + #include /** diff --git a/i3bar/include/util.h b/i3bar/include/util.h index dfbfd6bf..3af79ed7 100644 --- a/i3bar/include/util.h +++ b/i3bar/include/util.h @@ -7,6 +7,8 @@ */ #pragma once +#include + #include "queue.h" /* Get the maximum/minimum of x and y */ diff --git a/i3bar/include/workspaces.h b/i3bar/include/workspaces.h index 5ed84de8..dde8b6e1 100644 --- a/i3bar/include/workspaces.h +++ b/i3bar/include/workspaces.h @@ -9,10 +9,10 @@ */ #pragma once -#include - #include "common.h" +#include + typedef struct i3_ws i3_ws; TAILQ_HEAD(ws_head, i3_ws); diff --git a/i3bar/include/xcb.h b/i3bar/include/xcb.h index e5af39fa..7783e877 100644 --- a/i3bar/include/xcb.h +++ b/i3bar/include/xcb.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include //#include "outputs.h" diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 295eb76f..1fd901ce 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -7,6 +7,8 @@ * child.c: Getting input for the statusline * */ +#include "common.h" + #include #include #include @@ -25,8 +27,6 @@ #include #include -#include "common.h" - /* Global variables for child_*() */ i3bar_child child; diff --git a/i3bar/src/config.c b/i3bar/src/config.c index 5c23bc78..d065ff4c 100644 --- a/i3bar/src/config.c +++ b/i3bar/src/config.c @@ -7,6 +7,8 @@ * config.c: Parses the configuration (received from i3). * */ +#include "common.h" + #include #include #include @@ -17,8 +19,6 @@ #include -#include "common.h" - static char *cur_key; static bool parsing_bindings; static bool parsing_tray_outputs; diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index 34898663..4a090ad7 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -7,6 +7,8 @@ * ipc.c: Communicating with i3 * */ +#include "common.h" + #include #include #include @@ -21,8 +23,6 @@ #include #endif -#include "common.h" - ev_io *i3_connection; const char *sock_path; diff --git a/i3bar/src/main.c b/i3bar/src/main.c index 14e42a2b..be684fc5 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -5,6 +5,8 @@ * © 2010 Axel Wagner and contributors (see also: LICENSE) * */ +#include "common.h" + #include #include #include @@ -15,8 +17,6 @@ #include #include -#include "common.h" - /* * Having verboselog(), errorlog() and debuglog() is necessary when using libi3. * diff --git a/i3bar/src/mode.c b/i3bar/src/mode.c index 3e52f0b1..17e7b97e 100644 --- a/i3bar/src/mode.c +++ b/i3bar/src/mode.c @@ -7,6 +7,8 @@ * mode.c: Handle mode event and show current binding mode in the bar * */ +#include "common.h" + #include #include #include @@ -14,8 +16,6 @@ #include #include -#include "common.h" - /* A datatype to pass through the callbacks to save the state */ struct mode_json_params { char *json; diff --git a/i3bar/src/outputs.c b/i3bar/src/outputs.c index b53d8cc8..480c00be 100644 --- a/i3bar/src/outputs.c +++ b/i3bar/src/outputs.c @@ -7,6 +7,8 @@ * outputs.c: Maintaining the outputs list * */ +#include "common.h" + #include #include #include @@ -15,8 +17,6 @@ #include #include -#include "common.h" - /* A datatype to pass through the callbacks to save the state */ struct outputs_json_params { struct outputs_head *outputs; diff --git a/i3bar/src/parse_json_header.c b/i3bar/src/parse_json_header.c index 1cd95106..3d4c2a67 100644 --- a/i3bar/src/parse_json_header.c +++ b/i3bar/src/parse_json_header.c @@ -8,6 +8,8 @@ * protocol version and features. * */ +#include "common.h" + #include #include #include @@ -25,8 +27,6 @@ #include #include -#include "common.h" - static enum { KEY_VERSION, KEY_STOP_SIGNAL, diff --git a/i3bar/src/workspaces.c b/i3bar/src/workspaces.c index 1187a946..23324989 100644 --- a/i3bar/src/workspaces.c +++ b/i3bar/src/workspaces.c @@ -7,6 +7,8 @@ * workspaces.c: Maintaining the workspace lists * */ +#include "common.h" + #include #include #include @@ -14,8 +16,6 @@ #include #include -#include "common.h" - /* A datatype to pass through the callbacks to save the state */ struct workspaces_json_params { struct ws_head *workspaces; diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 32187445..2715e447 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -7,6 +7,8 @@ * xcb.c: Communicating with X * */ +#include "common.h" + #include #include #include @@ -32,7 +34,6 @@ #include #endif -#include "common.h" #include "libi3.h" /** This is the equivalent of XC_left_ptr. I’m not sure why xcb doesn’t have a diff --git a/include/all.h b/include/all.h index b323f863..c26835b9 100644 --- a/include/all.h +++ b/include/all.h @@ -10,8 +10,9 @@ * compile-time. * */ -#ifndef I3_ALL_H -#define I3_ALL_H +#pragma once + +#include #include #include @@ -81,5 +82,3 @@ #include "display_version.h" #include "restore_layout.h" #include "main.h" - -#endif diff --git a/include/assignments.h b/include/assignments.h index 22ebafc3..a4dc766b 100644 --- a/include/assignments.h +++ b/include/assignments.h @@ -9,6 +9,8 @@ */ #pragma once +#include + /** * Checks the list of assignments for the given window and runs all matching * ones (unless they have already been run for this specific window). diff --git a/include/bindings.h b/include/bindings.h index d15598ea..0fcc4df4 100644 --- a/include/bindings.h +++ b/include/bindings.h @@ -9,6 +9,8 @@ */ #pragma once +#include + extern pid_t command_error_nagbar_pid; /** diff --git a/include/click.h b/include/click.h index 7ce80d97..0d57abf7 100644 --- a/include/click.h +++ b/include/click.h @@ -9,6 +9,8 @@ */ #pragma once +#include + /** * The button press X callback. This function determines whether the floating * modifier is pressed and where the user clicked (decoration, border, inside diff --git a/include/cmdparse.h b/include/cmdparse.h index 2ffa49b0..a2cbb17e 100644 --- a/include/cmdparse.h +++ b/include/cmdparse.h @@ -9,4 +9,6 @@ */ #pragma once +#include + char *parse_cmd(const char *new); diff --git a/include/commands.h b/include/commands.h index 9f83cb21..a57b2925 100644 --- a/include/commands.h +++ b/include/commands.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include "commands_parser.h" /** The beginning of the prototype for every cmd_ function. */ diff --git a/include/commands_parser.h b/include/commands_parser.h index 1acb7fae..88b3f6d0 100644 --- a/include/commands_parser.h +++ b/include/commands_parser.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include /* diff --git a/include/con.h b/include/con.h index 73ae0f38..0c532207 100644 --- a/include/con.h +++ b/include/con.h @@ -11,6 +11,8 @@ */ #pragma once +#include + /** * Create a new container (and attach it to the given parent, if not NULL). * This function only initializes the data structures. diff --git a/include/config_directives.h b/include/config_directives.h index bcbea111..7f1bfe4a 100644 --- a/include/config_directives.h +++ b/include/config_directives.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include "config_parser.h" /** diff --git a/include/config_parser.h b/include/config_parser.h index 2ba79a68..ace4041d 100644 --- a/include/config_parser.h +++ b/include/config_parser.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include SLIST_HEAD(variables_head, Variable); diff --git a/include/configuration.h b/include/configuration.h index ced104b6..b7cdc804 100644 --- a/include/configuration.h +++ b/include/configuration.h @@ -12,10 +12,11 @@ */ #pragma once +#include "libi3.h" + #include #include "queue.h" #include "i3.h" -#include "libi3.h" typedef struct Config Config; typedef struct Barconfig Barconfig; diff --git a/include/data.h b/include/data.h index 70edd222..a729b21e 100644 --- a/include/data.h +++ b/include/data.h @@ -9,6 +9,8 @@ */ #pragma once +#include "libi3.h" + #define SN_API_NOT_YET_FROZEN 1 #include @@ -17,7 +19,6 @@ #include #include -#include "libi3.h" #include "queue.h" /* diff --git a/include/debug.h b/include/debug.h index 3875ec6b..ab5f3808 100644 --- a/include/debug.h +++ b/include/debug.h @@ -10,4 +10,6 @@ */ #pragma once +#include + int handle_event(void *ignored, xcb_connection_t *c, xcb_generic_event_t *e); diff --git a/include/display_version.h b/include/display_version.h index b1a5a0e0..d8dac30b 100644 --- a/include/display_version.h +++ b/include/display_version.h @@ -9,6 +9,8 @@ */ #pragma once +#include + /** * Connects to i3 to find out the currently running version. Useful since it * might be different from the version compiled into this binary (maybe the diff --git a/include/ewmh.h b/include/ewmh.h index 2a55ab9f..545e3a6b 100644 --- a/include/ewmh.h +++ b/include/ewmh.h @@ -9,6 +9,8 @@ */ #pragma once +#include + /** * Updates _NET_CURRENT_DESKTOP with the current desktop number. * diff --git a/include/fake_outputs.h b/include/fake_outputs.h index 32b07fa9..27a0d41a 100644 --- a/include/fake_outputs.h +++ b/include/fake_outputs.h @@ -10,6 +10,8 @@ */ #pragma once +#include + /** * Creates outputs according to the given specification. * The specification must be in the format wxh+x+y, for example 1024x768+0+0, diff --git a/include/floating.h b/include/floating.h index e187b98f..babfafc9 100644 --- a/include/floating.h +++ b/include/floating.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include "tree.h" /** Callback for dragging */ diff --git a/include/handlers.h b/include/handlers.h index d80a24f8..1d5a3865 100644 --- a/include/handlers.h +++ b/include/handlers.h @@ -10,6 +10,8 @@ */ #pragma once +#include + #include extern int randr_base; diff --git a/include/i3.h b/include/i3.h index 254c4d23..4d13d448 100644 --- a/include/i3.h +++ b/include/i3.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include #include diff --git a/include/ipc.h b/include/ipc.h index a9323751..5c528a6d 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include #include #include diff --git a/include/key_press.h b/include/key_press.h index bbfec83b..8f23854b 100644 --- a/include/key_press.h +++ b/include/key_press.h @@ -9,6 +9,8 @@ */ #pragma once +#include + /** * There was a key press. We compare this key code with our bindings table and pass * the bound action to parse_command(). diff --git a/include/libi3.h b/include/libi3.h index 0d9189f3..11ca3127 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -10,6 +10,8 @@ */ #pragma once +#include + #include #include #include diff --git a/include/load_layout.h b/include/load_layout.h index f8b7da20..0dd81318 100644 --- a/include/load_layout.h +++ b/include/load_layout.h @@ -10,6 +10,8 @@ */ #pragma once +#include + typedef enum { // We could not determine the content of the JSON file. This typically // means it’s unreadable or contains garbage. diff --git a/include/log.h b/include/log.h index b683529c..5c530231 100644 --- a/include/log.h +++ b/include/log.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include #include diff --git a/include/main.h b/include/main.h index 1ce53954..1f213cce 100644 --- a/include/main.h +++ b/include/main.h @@ -9,6 +9,8 @@ */ #pragma once +#include + /** * Enable or disable the main X11 event handling function. * This is used by drag_pointer() which has its own, modal event handler, which diff --git a/include/manage.h b/include/manage.h index 520f0c06..55b0a85b 100644 --- a/include/manage.h +++ b/include/manage.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include "data.h" /** diff --git a/include/match.h b/include/match.h index 64a4f22b..4ff8c485 100644 --- a/include/match.h +++ b/include/match.h @@ -13,6 +13,8 @@ */ #pragma once +#include + /* * Initializes the Match data structure. This function is necessary because the * members representing boolean values (like dock) need to be initialized with diff --git a/include/move.h b/include/move.h index 7debcf28..64b12b80 100644 --- a/include/move.h +++ b/include/move.h @@ -9,6 +9,8 @@ */ #pragma once +#include + /** * Moves the given container in the given direction (TOK_LEFT, TOK_RIGHT, * TOK_UP, TOK_DOWN from cmdparse.l) diff --git a/include/output.h b/include/output.h index 03a4fbcf..b13c9728 100644 --- a/include/output.h +++ b/include/output.h @@ -9,6 +9,8 @@ */ #pragma once +#include + /** * Returns the output container below the given output container. * diff --git a/include/randr.h b/include/randr.h index 30dd955d..55068316 100644 --- a/include/randr.h +++ b/include/randr.h @@ -11,6 +11,8 @@ */ #pragma once +#include + #include "data.h" #include diff --git a/include/regex.h b/include/regex.h index 2e2f22fd..abda3cd7 100644 --- a/include/regex.h +++ b/include/regex.h @@ -9,6 +9,8 @@ */ #pragma once +#include + /** * Creates a new 'regex' struct containing the given pattern and a PCRE * compiled regular expression. Also, calls pcre_study because this regex will diff --git a/include/render.h b/include/render.h index d32f0310..750b7d31 100644 --- a/include/render.h +++ b/include/render.h @@ -10,6 +10,8 @@ */ #pragma once +#include + /* This is used to keep a state to pass around when rendering a con in render_con(). */ typedef struct render_params { /* A copy of the coordinates of the container which is being rendered. */ diff --git a/include/resize.h b/include/resize.h index 945678d9..7b33de90 100644 --- a/include/resize.h +++ b/include/resize.h @@ -9,6 +9,8 @@ */ #pragma once +#include + bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction); int resize_graphical_handler(Con *first, Con *second, orientation_t orientation, const xcb_button_press_event_t *event); diff --git a/include/restore_layout.h b/include/restore_layout.h index f952834c..98b257d9 100644 --- a/include/restore_layout.h +++ b/include/restore_layout.h @@ -10,6 +10,8 @@ */ #pragma once +#include + /** * Opens a separate connection to X11 for placeholder windows when restoring * layouts. This is done as a safety measure (users can xkill a placeholder diff --git a/include/scratchpad.h b/include/scratchpad.h index b385550c..241653c0 100644 --- a/include/scratchpad.h +++ b/include/scratchpad.h @@ -9,6 +9,8 @@ */ #pragma once +#include + /** * Moves the specified window to the __i3_scratch workspace, making it floating * and setting the appropriate scratchpad_state. diff --git a/include/shmlog.h b/include/shmlog.h index 0216c8d6..b90211ef 100644 --- a/include/shmlog.h +++ b/include/shmlog.h @@ -10,6 +10,8 @@ */ #pragma once +#include + #include #if !defined(__OpenBSD__) #include diff --git a/include/sighandler.h b/include/sighandler.h index 56680bc4..20ede4eb 100644 --- a/include/sighandler.h +++ b/include/sighandler.h @@ -11,6 +11,8 @@ */ #pragma once +#include + /** * Setup signal handlers to safely handle SIGSEGV and SIGFPE * diff --git a/include/startup.h b/include/startup.h index 9729cdc2..5da221e1 100644 --- a/include/startup.h +++ b/include/startup.h @@ -12,6 +12,8 @@ */ #pragma once +#include + #define SN_API_NOT_YET_FROZEN 1 #include diff --git a/include/tree.h b/include/tree.h index c64c173d..62461def 100644 --- a/include/tree.h +++ b/include/tree.h @@ -9,6 +9,8 @@ */ #pragma once +#include + extern Con *croot; /* TODO: i am not sure yet how much access to the focused container should * be permitted to source files */ diff --git a/include/util.h b/include/util.h index 9915c1a8..e5ba3341 100644 --- a/include/util.h +++ b/include/util.h @@ -10,6 +10,8 @@ */ #pragma once +#include + #include #include "data.h" diff --git a/include/window.h b/include/window.h index d0b97f1d..77e3f48f 100644 --- a/include/window.h +++ b/include/window.h @@ -9,6 +9,8 @@ */ #pragma once +#include + /** * Frees an i3Window and all its members. * diff --git a/include/workspace.h b/include/workspace.h index 8e5ff841..8d109e9e 100644 --- a/include/workspace.h +++ b/include/workspace.h @@ -10,6 +10,8 @@ */ #pragma once +#include + #include "data.h" #include "tree.h" #include "randr.h" diff --git a/include/x.h b/include/x.h index 39e0eb2f..3e81bc36 100644 --- a/include/x.h +++ b/include/x.h @@ -10,6 +10,8 @@ */ #pragma once +#include + /** Stores the X11 window ID of the currently focused window */ extern xcb_window_t focused_id; diff --git a/include/xcb.h b/include/xcb.h index b7eed2cb..94f2945d 100644 --- a/include/xcb.h +++ b/include/xcb.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include "data.h" #include "xcursor.h" diff --git a/include/xcursor.h b/include/xcursor.h index e0ee9813..804e1f84 100644 --- a/include/xcursor.h +++ b/include/xcursor.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include enum xcursor_cursor_t { diff --git a/include/xinerama.h b/include/xinerama.h index 936b9653..f01ee568 100644 --- a/include/xinerama.h +++ b/include/xinerama.h @@ -11,6 +11,8 @@ */ #pragma once +#include + #include "data.h" /** diff --git a/include/yajl_utils.h b/include/yajl_utils.h index 93c63d8f..6ab1ff1c 100644 --- a/include/yajl_utils.h +++ b/include/yajl_utils.h @@ -9,6 +9,8 @@ */ #pragma once +#include + #include #include #include diff --git a/libi3/dpi.c b/libi3/dpi.c index f105ef9a..a832a689 100644 --- a/libi3/dpi.c +++ b/libi3/dpi.c @@ -6,6 +6,7 @@ * */ #include "libi3.h" + #include #include #include diff --git a/libi3/draw_util.c b/libi3/draw_util.c index 56b1bce8..e471405b 100644 --- a/libi3/draw_util.c +++ b/libi3/draw_util.c @@ -6,6 +6,8 @@ * draw.c: Utility for drawing. * */ +#include "libi3.h" + #include #include #include @@ -13,8 +15,6 @@ #include #include -#include "libi3.h" - /* The default visual_type to use if none is specified when creating the surface. Must be defined globally. */ xcb_visualtype_t *visual_type; diff --git a/libi3/fake_configure_notify.c b/libi3/fake_configure_notify.c index 2c4d4559..145f4512 100644 --- a/libi3/fake_configure_notify.c +++ b/libi3/fake_configure_notify.c @@ -5,14 +5,14 @@ * © 2009 Michael Stapelberg and contributors (see also: LICENSE) * */ +#include "libi3.h" + #include #include #include #include -#include "libi3.h" - /* * Generates a configure_notify event and sends it to the given window * Applications need this to think they’ve configured themselves correctly. diff --git a/libi3/font.c b/libi3/font.c index 7c305e25..fa848481 100644 --- a/libi3/font.c +++ b/libi3/font.c @@ -5,6 +5,8 @@ * © 2009 Michael Stapelberg and contributors (see also: LICENSE) * */ +#include "libi3.h" + #include #include #include @@ -15,8 +17,6 @@ #include #include -#include "libi3.h" - static const i3Font *savedFont = NULL; static xcb_visualtype_t *root_visual_type; diff --git a/libi3/format_placeholders.c b/libi3/format_placeholders.c index c9cbbea4..59e94781 100644 --- a/libi3/format_placeholders.c +++ b/libi3/format_placeholders.c @@ -5,12 +5,12 @@ * © 2009 Michael Stapelberg and contributors (see also: LICENSE) * */ +#include "libi3.h" + #include #include #include -#include "libi3.h" - #ifndef STARTS_WITH #define STARTS_WITH(string, needle) (strncasecmp((string), (needle), strlen((needle))) == 0) #endif diff --git a/libi3/get_colorpixel.c b/libi3/get_colorpixel.c index dc6d7748..9bdd0a71 100644 --- a/libi3/get_colorpixel.c +++ b/libi3/get_colorpixel.c @@ -5,13 +5,13 @@ * © 2009 Michael Stapelberg and contributors (see also: LICENSE) * */ +#include "libi3.h" + #include #include #include #include "queue.h" -#include "libi3.h" - struct Colorpixel { char hex[8]; uint32_t pixel; diff --git a/libi3/get_config_path.c b/libi3/get_config_path.c index bad75c4d..c47e6dd8 100644 --- a/libi3/get_config_path.c +++ b/libi3/get_config_path.c @@ -6,6 +6,7 @@ * */ #include "libi3.h" + #include #include #include diff --git a/libi3/get_exe_path.c b/libi3/get_exe_path.c index ef8f23bc..b9d35ea1 100644 --- a/libi3/get_exe_path.c +++ b/libi3/get_exe_path.c @@ -1,3 +1,12 @@ +/* + * vim:ts=4:sw=4:expandtab + * + * i3 - an improved dynamic tiling window manager + * © 2009 Michael Stapelberg and contributors (see also: LICENSE) + * + */ +#include "libi3.h" + #include #include #include @@ -5,8 +14,6 @@ #include #include -#include "libi3.h" - /* * This function returns the absolute path to the executable it is running in. * diff --git a/libi3/get_mod_mask.c b/libi3/get_mod_mask.c index ac71e6b2..98031d4c 100644 --- a/libi3/get_mod_mask.c +++ b/libi3/get_mod_mask.c @@ -5,13 +5,13 @@ * © 2009 Michael Stapelberg and contributors (see also: LICENSE) * */ +#include "libi3.h" + #include #include #include #include -#include "libi3.h" - /* * All-in-one function which returns the modifier mask (XCB_MOD_MASK_*) for the * given keysymbol, for example for XCB_NUM_LOCK (usually configured to mod2). diff --git a/libi3/get_process_filename.c b/libi3/get_process_filename.c index a3dee9cd..7e2ecbd2 100644 --- a/libi3/get_process_filename.c +++ b/libi3/get_process_filename.c @@ -5,6 +5,8 @@ * © 2009 Michael Stapelberg and contributors (see also: LICENSE) * */ +#include "libi3.h" + #include #include #include @@ -17,8 +19,6 @@ #include #include -#include "libi3.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 f493b4f1..2e628342 100644 --- a/libi3/ipc_connect.c +++ b/libi3/ipc_connect.c @@ -5,6 +5,8 @@ * © 2009 Michael Stapelberg and contributors (see also: LICENSE) * */ +#include "libi3.h" + #include #include #include @@ -14,8 +16,6 @@ #include #include -#include "libi3.h" - /* * Connects to the i3 IPC socket and returns the file descriptor for the * socket. die()s if anything goes wrong. diff --git a/libi3/ipc_recv_message.c b/libi3/ipc_recv_message.c index 0ef4fced..16dda90d 100644 --- a/libi3/ipc_recv_message.c +++ b/libi3/ipc_recv_message.c @@ -5,6 +5,8 @@ * © 2009 Michael Stapelberg and contributors (see also: LICENSE) * */ +#include "libi3.h" + #include #include #include @@ -14,8 +16,6 @@ #include -#include "libi3.h" - /* * Reads a message from the given socket file descriptor and stores its length * (reply_length) as well as a pointer to its contents (reply). diff --git a/libi3/ipc_send_message.c b/libi3/ipc_send_message.c index a9ba3165..c2cc0127 100644 --- a/libi3/ipc_send_message.c +++ b/libi3/ipc_send_message.c @@ -5,6 +5,8 @@ * © 2009 Michael Stapelberg and contributors (see also: LICENSE) * */ +#include "libi3.h" + #include #include #include @@ -14,8 +16,6 @@ #include -#include "libi3.h" - /* * Formats a message (payload) of the given size and type and sends it to i3 via * the given socket file descriptor. diff --git a/libi3/is_debug_build.c b/libi3/is_debug_build.c index 3173c122..4e583622 100644 --- a/libi3/is_debug_build.c +++ b/libi3/is_debug_build.c @@ -1,3 +1,12 @@ +/* + * vim:ts=4:sw=4:expandtab + * + * i3 - an improved dynamic tiling window manager + * © 2009 Michael Stapelberg and contributors (see also: LICENSE) + * + */ +#include "libi3.h" + #include #include diff --git a/libi3/mkdirp.c b/libi3/mkdirp.c index c64b80a3..1fc8c346 100644 --- a/libi3/mkdirp.c +++ b/libi3/mkdirp.c @@ -1,4 +1,12 @@ +/* + * vim:ts=4:sw=4:expandtab + * + * i3 - an improved dynamic tiling window manager + * © 2009 Michael Stapelberg and contributors (see also: LICENSE) + * + */ #include "libi3.h" + #include #include #include diff --git a/libi3/resolve_tilde.c b/libi3/resolve_tilde.c index 7a4fb79b..51d642db 100644 --- a/libi3/resolve_tilde.c +++ b/libi3/resolve_tilde.c @@ -5,8 +5,8 @@ * © 2009 Michael Stapelberg and contributors (see also: LICENSE) * */ - #include "libi3.h" + #include #include #include diff --git a/libi3/root_atom_contents.c b/libi3/root_atom_contents.c index 8d26c307..d6394d4b 100644 --- a/libi3/root_atom_contents.c +++ b/libi3/root_atom_contents.c @@ -5,6 +5,8 @@ * © 2009 Michael Stapelberg and contributors (see also: LICENSE) * */ +#include "libi3.h" + #include #include #include @@ -15,8 +17,6 @@ #include #include -#include "libi3.h" - /* * Try to get the contents of the given atom (for example I3_SOCKET_PATH) from * the X11 root window and return NULL if it doesn’t work. diff --git a/libi3/safewrappers.c b/libi3/safewrappers.c index 0a233a12..94ad4ee6 100644 --- a/libi3/safewrappers.c +++ b/libi3/safewrappers.c @@ -5,6 +5,8 @@ * © 2009 Michael Stapelberg and contributors (see also: LICENSE) * */ +#include "libi3.h" + #include #include #include @@ -13,8 +15,6 @@ #include #include -#include "libi3.h" - /* * The s* functions (safe) are wrappers around malloc, strdup, …, which exits if one of * the called functions returns NULL, meaning that there is no more memory available diff --git a/libi3/string.c b/libi3/string.c index 19039a23..edd588da 100644 --- a/libi3/string.c +++ b/libi3/string.c @@ -9,14 +9,13 @@ * others want UTF-8 (Pango). * */ +#include "libi3.h" #include #include #include -#include "libi3.h" - struct _i3String { char *utf8; xcb_char2b_t *ucs2; diff --git a/libi3/strndup.c b/libi3/strndup.c index c4032dc5..e17f843c 100644 --- a/libi3/strndup.c +++ b/libi3/strndup.c @@ -5,11 +5,11 @@ * © 2009 Michael Stapelberg and contributors (see also: LICENSE) * */ +#include "libi3.h" + #include #include -#include "libi3.h" - #if defined(__APPLE__) /* diff --git a/libi3/ucs2_conversion.c b/libi3/ucs2_conversion.c index b583e32c..75cff78a 100644 --- a/libi3/ucs2_conversion.c +++ b/libi3/ucs2_conversion.c @@ -5,14 +5,14 @@ * © 2009 Michael Stapelberg and contributors (see also: LICENSE) * */ +#include "libi3.h" + #include #include #include #include #include -#include "libi3.h" - static iconv_t utf8_conversion_descriptor = (iconv_t)-1; static iconv_t ucs2_conversion_descriptor = (iconv_t)-1; diff --git a/src/assignments.c b/src/assignments.c index 6c563357..a0f5d5a7 100644 --- a/src/assignments.c +++ b/src/assignments.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "assignments.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/click.c b/src/click.c index 788c10f2..913741b4 100644 --- a/src/click.c +++ b/src/click.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "click.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/commands.c b/src/commands.c index 58641d6a..b91c71a4 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "commands.c" /* * vim:ts=4:sw=4:expandtab * @@ -9,6 +7,8 @@ * commands.c: all command functions (see commands_parser.c) * */ +#include "all.h" + #include #include #include @@ -17,7 +17,6 @@ #include #endif -#include "all.h" #include "shmlog.h" // Macros to make the YAJL API a bit easier to use. diff --git a/src/commands_parser.c b/src/commands_parser.c index cdd35e45..98f06659 100644 --- a/src/commands_parser.c +++ b/src/commands_parser.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "commands_parser.c" /* * vim:ts=4:sw=4:expandtab * @@ -25,6 +23,8 @@ * instead of actually calling any function). * */ +#include "all.h" + #include #include #include @@ -32,8 +32,6 @@ #include #include -#include "all.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) diff --git a/src/con.c b/src/con.c index 124d24ea..3c7c2186 100644 --- a/src/con.c +++ b/src/con.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "con.c" /* * vim:ts=4:sw=4:expandtab * @@ -12,6 +10,7 @@ * */ #include "all.h" + #include "yajl_utils.h" static void con_on_remove_child(Con *con); diff --git a/src/config.c b/src/config.c index c2824ca2..d4441d5d 100644 --- a/src/config.c +++ b/src/config.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "config.c" /* * vim:ts=4:sw=4:expandtab * @@ -11,6 +9,7 @@ * */ #include "all.h" + #include char *current_configpath = NULL; diff --git a/src/config_directives.c b/src/config_directives.c index 05c19c70..6b5464f1 100644 --- a/src/config_directives.c +++ b/src/config_directives.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "config_directives.c" /* * vim:ts=4:sw=4:expandtab * @@ -9,11 +7,11 @@ * config_directives.c: all config storing functions (see config_parser.c) * */ +#include "all.h" + #include #include -#include "all.h" - /******************************************************************************* * Criteria functions. ******************************************************************************/ diff --git a/src/config_parser.c b/src/config_parser.c index 2a884730..a8265869 100644 --- a/src/config_parser.c +++ b/src/config_parser.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "config_parser.c" /* * vim:ts=4:sw=4:expandtab * @@ -25,6 +23,8 @@ * nearest token. * */ +#include "all.h" + #include #include #include @@ -37,8 +37,6 @@ #include #include -#include "all.h" - // Macros to make the YAJL API a bit easier to use. #define y(x, ...) yajl_gen_##x(command_output.json_gen, ##__VA_ARGS__) #define ystr(str) yajl_gen_string(command_output.json_gen, (unsigned char *)str, strlen(str)) diff --git a/src/debug.c b/src/debug.c index bb880b2f..ea4ca997 100644 --- a/src/debug.c +++ b/src/debug.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "debug.c" /* * vim:ts=4:sw=4:expandtab * @@ -10,6 +8,8 @@ * events. This code is from xcb-util. * */ +#include + #include #include diff --git a/src/display_version.c b/src/display_version.c index c82610ed..0e650e81 100644 --- a/src/display_version.c +++ b/src/display_version.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "key_press.c" /* * vim:ts=4:sw=4:expandtab * @@ -10,6 +8,8 @@ * i3 --moreversion. * */ +#include "all.h" + #include #include #include @@ -17,7 +17,6 @@ #include #include #include -#include "all.h" static bool human_readable_key, loaded_config_file_name_key; static char *human_readable_version, *loaded_config_file_name; diff --git a/src/ewmh.c b/src/ewmh.c index 5459c7e9..f4bb049a 100644 --- a/src/ewmh.c +++ b/src/ewmh.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "ewmh.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/fake_outputs.c b/src/fake_outputs.c index 3df0e246..b898ce98 100644 --- a/src/fake_outputs.c +++ b/src/fake_outputs.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "fake_outputs.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/floating.c b/src/floating.c index e9c7a801..616602c0 100644 --- a/src/floating.c +++ b/src/floating.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "floating.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/handlers.c b/src/handlers.c index bd391176..7dfacef7 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "handlers.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/ipc.c b/src/ipc.c index bf529b17..73f8d8cb 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "ipc.c" /* * vim:ts=4:sw=4:expandtab * @@ -10,6 +8,7 @@ * */ #include "all.h" + #include "yajl_utils.h" #include diff --git a/src/key_press.c b/src/key_press.c index 6760e35b..d16174f8 100644 --- a/src/key_press.c +++ b/src/key_press.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "key_press.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/load_layout.c b/src/load_layout.c index a3b44756..7004a859 100644 --- a/src/load_layout.c +++ b/src/load_layout.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "load_layout.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/log.c b/src/log.c index e9a1160d..1c33649a 100644 --- a/src/log.c +++ b/src/log.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "log.c" /* * vim:ts=4:sw=4:expandtab * @@ -9,6 +7,8 @@ * log.c: Logging functions. * */ +#include + #include #include #include diff --git a/src/main.c b/src/main.c index f94a8941..4d9fd5a5 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "main.c" /* * vim:ts=4:sw=4:expandtab * @@ -9,6 +7,8 @@ * main.c: Initialization, main loop * */ +#include "all.h" + #include #include #include @@ -19,7 +19,6 @@ #include #include #include -#include "all.h" #include "shmlog.h" #include "sd-daemon.h" diff --git a/src/manage.c b/src/manage.c index fd9226e4..81ee16fd 100644 --- a/src/manage.c +++ b/src/manage.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "manage.c" /* * vim:ts=4:sw=4:expandtab * @@ -10,6 +8,7 @@ * */ #include "all.h" + #include "yajl_utils.h" #include diff --git a/src/match.c b/src/match.c index ac9ddaf9..4d87c560 100644 --- a/src/match.c +++ b/src/match.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "match.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/move.c b/src/move.c index 25c658ce..70c8c788 100644 --- a/src/move.c +++ b/src/move.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "move.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/output.c b/src/output.c index 1a9f6129..0f2bd617 100644 --- a/src/output.c +++ b/src/output.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "output.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/randr.c b/src/randr.c index 512e0d28..51255619 100644 --- a/src/randr.c +++ b/src/randr.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "randr.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/regex.c b/src/regex.c index 12c0b67f..296b91dd 100644 --- a/src/regex.c +++ b/src/regex.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "regex.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/render.c b/src/render.c index 7ee501f0..85548f26 100644 --- a/src/render.c +++ b/src/render.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "render.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/resize.c b/src/resize.c index 5d9eb2eb..f07fcec6 100644 --- a/src/resize.c +++ b/src/resize.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "resize.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/restore_layout.c b/src/restore_layout.c index da018b9e..131196e9 100644 --- a/src/restore_layout.c +++ b/src/restore_layout.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "restore_layout.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/scratchpad.c b/src/scratchpad.c index 6d83a558..9018ad3f 100644 --- a/src/scratchpad.c +++ b/src/scratchpad.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "scratchpad.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/sighandler.c b/src/sighandler.c index 400cd5a5..79f90d9a 100644 --- a/src/sighandler.c +++ b/src/sighandler.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "sighandler.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/startup.c b/src/startup.c index 2a6bc002..166842e0 100644 --- a/src/startup.c +++ b/src/startup.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "startup.c" /* * vim:ts=4:sw=4:expandtab * @@ -13,6 +11,7 @@ * */ #include "all.h" + #include "sd-daemon.h" #include diff --git a/src/tree.c b/src/tree.c index e848a6ac..6e128363 100644 --- a/src/tree.c +++ b/src/tree.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "tree.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/util.c b/src/util.c index 15796d88..cfe4c953 100644 --- a/src/util.c +++ b/src/util.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "util.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/version.c b/src/version.c index 6e385ada..1244711a 100644 --- a/src/version.c +++ b/src/version.c @@ -8,4 +8,6 @@ * and used dynamically without recompiling every object file. * */ +#include + const char *i3_version = I3_VERSION; diff --git a/src/window.c b/src/window.c index d10811f5..db6215d0 100644 --- a/src/window.c +++ b/src/window.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "window.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/workspace.c b/src/workspace.c index 0da0a378..d7f2ce7c 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "workspace.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/x.c b/src/x.c index 9a387749..8d7d3dd8 100644 --- a/src/x.c +++ b/src/x.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "x.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/xcb.c b/src/xcb.c index 630c68f9..900840a2 100644 --- a/src/xcb.c +++ b/src/xcb.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "xcb.c" /* * vim:ts=4:sw=4:expandtab * diff --git a/src/xcursor.c b/src/xcursor.c index 1e1e23b0..cbfe808b 100644 --- a/src/xcursor.c +++ b/src/xcursor.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "xcursor.c" /* * vim:ts=4:sw=4:expandtab * @@ -9,6 +7,8 @@ * xcursor.c: xcursor support for themed cursors. * */ +#include + #include #include diff --git a/src/xinerama.c b/src/xinerama.c index ddf98375..25bfa6b1 100644 --- a/src/xinerama.c +++ b/src/xinerama.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "xinerama.c" /* * vim:ts=4:sw=4:expandtab * From ca83fd566dfc7a1b86894ad481f346225ecc9fc3 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 11 Oct 2016 09:40:06 +0200 Subject: [PATCH 128/150] pull autotools.gitignore into .gitignore --- .gitignore | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/.gitignore b/.gitignore index 617421ac..c6fd81c8 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,30 @@ i3-command-parser.stamp i3-config-parser.stamp .clang_complete LAST_VERSION + +################################################################################ +# https://raw.githubusercontent.com/github/gitignore/master/Autotools.gitignore +################################################################################ + +# 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 From 8ab1bf6063dc9c6079ca544aeb05cc623b51553e Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 14 Oct 2016 09:16:08 +0200 Subject: [PATCH 129/150] Update debian/ for autotools --- debian/rules | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/debian/rules b/debian/rules index 843655ee..e119f260 100755 --- a/debian/rules +++ b/debian/rules @@ -4,14 +4,14 @@ export V:=1 export DEB_BUILD_MAINT_OPTIONS = hardening=+all -override_dh_auto_build: - dh_auto_build -- all docs mans - override_dh_installchangelogs: dh_installchangelogs RELEASE-NOTES-* override_dh_strip: dh_strip --dbg-package=i3-wm-dbg +override_dh_auto_test: + # TODO: enable tests + %: - dh $@ --parallel + dh $@ --parallel --builddirectory=build --with=autoreconf From 7b2d7344633bcfc138517bdd6676ea9a90048cdd Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 14 Oct 2016 09:51:07 +0200 Subject: [PATCH 130/150] Update release.sh for autotools --- release.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/release.sh b/release.sh index cc59d6a2..14f443f3 100755 --- a/release.sh +++ b/release.sh @@ -55,13 +55,18 @@ 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 sed -i "s,[^<]*,${RELEASE_VERSION},g" man/asciidoc.conf echo "${RELEASE_VERSION} ($(date +%F))" > I3_VERSION git add I3_VERSION git commit -a -m "release i3 ${RELEASE_VERSION}" git tag "${RELEASE_VERSION}" -m "release i3 ${RELEASE_VERSION}" --sign --local-user=0x4AC8EE1D -make dist +autoreconf -fi +mkdir build +(cd build && ../configure && make dist-bzip2 -j8) +cp build/i3-${RELEASE_VERSION}.tar.bz2 . echo "Differences in the release tarball file lists:" @@ -157,7 +162,7 @@ git add downloads/RELEASE-NOTES-${RELEASE_VERSION}.txt sed -i "s,

Documentation for i3 v[^<]*

,

Documentation for i3 v${RELEASE_VERSION}

,g" docs/index.html sed -i "s,[^<]*,${RELEASE_VERSION},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,,\n \n ${RELEASE_VERSION}\n i3-${RELEASE_VERSION}.tar.bz2\n $(ls -lh ../i3/i3-${RELEASE_VERSION}.tar.bz2 | awk -F " " {'print $5'} | sed 's/K$/ KiB/g')\n signature\n $(date +'%Y-%m-%d')\n release notes\n \n,g" downloads/index.html +sed -i "s,,\n \n ${RELEASE_VERSION}\n i3-${RELEASE_VERSION}.tar.bz2\n $(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')\n signature\n $(date +'%Y-%m-%d')\n release notes\n \n,g" downloads/index.html git commit -a -m "add ${RELEASE_VERSION} release" From cfe9824c1dcd3c23575a5dfa3a3983e83a338057 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 15 Oct 2016 17:39:14 +0200 Subject: [PATCH 131/150] =?UTF-8?q?Update=20PACKAGE-MAINTAINER=E2=80=99s?= =?UTF-8?q?=20compilation=20instructions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PACKAGE-MAINTAINER | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/PACKAGE-MAINTAINER b/PACKAGE-MAINTAINER index 5a922ee8..953fac53 100644 --- a/PACKAGE-MAINTAINER +++ b/PACKAGE-MAINTAINER @@ -23,14 +23,10 @@ x-terminal-emulator symlink in Debian, please use it in i3-sensible-terminal. On debian, compilation and installing the manpages looks like this: - # Compilation - $(MAKE) - $(MAKE) -C man - - # Installation - $(MAKE) DESTDIR=$(CURDIR)/debian/i3-wm/ install - mkdir -p $(CURDIR)/debian/i3-wm/usr/share/man/man1 - cp man/*.1 $(CURDIR)/debian/i3-wm/usr/share/man/man1 + autoreconf -fi + mkdir -p build && cd build + ../configure + make -j8 install 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 From 05e5901bcae1ceaec435936f0c056886ac3ed12d Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 16 Oct 2016 17:23:51 +0200 Subject: [PATCH 132/150] generate asciidoc.conf via autoconf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …instead of updating it in release.sh. --- Makefile.am | 4 ++-- configure.ac | 2 +- man/{asciidoc.conf => asciidoc.conf.in} | 2 +- release.sh | 1 - 4 files changed, 4 insertions(+), 5 deletions(-) rename man/{asciidoc.conf => asciidoc.conf.in} (87%) diff --git a/Makefile.am b/Makefile.am index 7bba241b..21f57e5b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -86,7 +86,7 @@ EXTRA_DIST = \ libi3/README \ $(asciidoc_MANS:.1=.man) \ $(asciidoc_MANS:.1=.man) \ - man/asciidoc.conf \ + man/asciidoc.conf.in \ DEPENDS \ I3_VERSION \ LICENSE \ @@ -200,7 +200,7 @@ $(asciidoc_MANS): man/%.1: man/%.xml man/$(dirstamp) @stamp='$@'; $(MKDIR_P) "$${stamp%/*}" man/%.xml: man/%.man man/asciidoc.conf man/$(dirstamp) - $(AM_V_GEN) @PATH_ASCIIDOC@ -d manpage -b docbook -f $(top_srcdir)/man/asciidoc.conf -o $@ $< + $(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 $< > $@ diff --git a/configure.ac b/configure.ac index 573261f5..01b4d309 100644 --- a/configure.ac +++ b/configure.ac @@ -118,7 +118,7 @@ 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]) +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 diff --git a/man/asciidoc.conf b/man/asciidoc.conf.in similarity index 87% rename from man/asciidoc.conf rename to man/asciidoc.conf.in index 11e76501..e9a9ea23 100644 --- a/man/asciidoc.conf +++ b/man/asciidoc.conf.in @@ -7,7 +7,7 @@ template::[header-declarations] {mantitle} {manvolnum} i3 -4.12 +@PACKAGE_VERSION@ i3 Manual diff --git a/release.sh b/release.sh index 14f443f3..9101332c 100755 --- a/release.sh +++ b/release.sh @@ -57,7 +57,6 @@ 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 -sed -i "s,[^<]*,${RELEASE_VERSION},g" man/asciidoc.conf echo "${RELEASE_VERSION} ($(date +%F))" > I3_VERSION git add I3_VERSION git commit -a -m "release i3 ${RELEASE_VERSION}" From ca98c7e614c35c64cf717eaa95ebe9dafa5b02c1 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 16 Oct 2016 18:03:09 +0200 Subject: [PATCH 133/150] Update travis for autotools --- .travis.yml | 2 +- Makefile.am | 3 +++ configure.ac | 1 + travis/check-spelling.pl | 16 ++++++++-------- travis/clang-analyze.sh | 4 ++-- travis/debian-build.sh | 9 ++++++--- travis/run-tests.sh | 6 +++--- 7 files changed, 24 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index f8a3de6f..f9744335 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,7 +32,7 @@ install: script: - docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/check-safe-wrappers.sh - docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/check-formatting.sh - - docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 -e CC -e CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Werror" ${BASENAME} make all mans -j ASAN=1 + - docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 -e CC ${BASENAME} /bin/sh -c 'autoreconf -fi && mkdir -p build && cd build && (../configure || (cat config.log; false)) && make -j CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Werror"' - docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/check-spelling.pl - docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 -e CC ${BASENAME} ./travis/run-tests.sh - ./travis/skip-pkg.sh || docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/debian-build.sh deb/debian-amd64/DIST diff --git a/Makefile.am b/Makefile.am index 21f57e5b..57d5b019 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,8 @@ @CODE_COVERAGE_RULES@ +echo-version: + @echo "@I3_VERSION@" + bin_PROGRAMS = \ i3 \ i3bar/i3bar \ diff --git a/configure.ac b/configure.ac index 01b4d309..3c47c6b5 100644 --- a/configure.ac +++ b/configure.ac @@ -35,6 +35,7 @@ AS_IF([test -d ${srcdir}/.git], I3_VERSION="$(cat ${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)" diff --git a/travis/check-spelling.pl b/travis/check-spelling.pl index 71feec31..6d070136 100755 --- a/travis/check-spelling.pl +++ b/travis/check-spelling.pl @@ -29,13 +29,13 @@ my $binary_spelling_exceptions = { 'betwen' => 1, # asan_flags.inc contains this spelling error. }; my @binaries = qw( - i3 - i3-config-wizard/i3-config-wizard - i3-dump-log/i3-dump-log - i3-input/i3-input - i3-msg/i3-msg - i3-nagbar/i3-nagbar - i3bar/i3bar + 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 ); for my $binary (@binaries) { check_spelling(slurp($binary), $binary_spelling_exceptions, sub { @@ -50,7 +50,7 @@ for my $binary (@binaries) { my $manpage_spelling_exceptions = { }; -for my $name (glob('man/*.1')) { +for my $name (glob('build/man/*.1')) { for my $line (split(/\n/, slurp($name))) { next if $line =~ /^\.\\\"/o; check_spelling($line, $manpage_spelling_exceptions, sub { diff --git a/travis/clang-analyze.sh b/travis/clang-analyze.sh index 05d54119..97c11fcc 100755 --- a/travis/clang-analyze.sh +++ b/travis/clang-analyze.sh @@ -3,7 +3,7 @@ set -e set -x -mkdir -p deb/DIST-clang +mkdir -p deb/DIST-clang/build tar xf *.tar.bz2 -C deb/DIST-clang --strip-components=1 -(cd deb/DIST-clang && scan-build -o ../CLANG --html-title="Analysis of i3 v$(git describe --tags)" make -j8) +(cd deb/DIST-clang/build && scan-build -o ../../CLANG ../configure && scan-build -o ../../CLANG --html-title="Analysis of i3 v$(git describe --tags)" make -j8) mv deb/CLANG/*/* deb/CLANG diff --git a/travis/debian-build.sh b/travis/debian-build.sh index 655bd5c4..9ce5a5af 100755 --- a/travis/debian-build.sh +++ b/travis/debian-build.sh @@ -5,12 +5,15 @@ set -x DEST=$1 -make store_git_version -make dist +mkdir -p build +cd build +../configure +make echo-version > ../I3_VERSION +make dist-bzip2 # unpack dist tarball mkdir -p "${DEST}" tar xf *.tar.bz2 -C "${DEST}" --strip-components=1 -cp -r debian "${DEST}" +cp -r ../debian "${DEST}" sed -i '/^\s*libxcb-xrm-dev/d' deb/ubuntu-*/DIST/debian/control || true cd "${DEST}" debchange -m -l+g$(git describe --tags) 'Automatically built' diff --git a/travis/run-tests.sh b/travis/run-tests.sh index d8a40d77..44df81d2 100755 --- a/travis/run-tests.sh +++ b/travis/run-tests.sh @@ -3,7 +3,7 @@ set -e set -x -cd testcases +cd build # TODO: remove this workaround once https://bugs.debian.org/836723 is fixed # Found at https://llvm.org/bugs/show_bug.cgi?id=27310#c8: @@ -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 ! xvfb-run ./complete-run.pl +if ! xvfb-run make check then - xvfb-run ./complete-run.pl --parallel=1 || (cat latest/complete-run.log; false) + xvfb-run ./testcases/complete-run.pl --parallel=1 || (cat latest/complete-run.log; false) fi From 8ddc18756c892b003ff93dbc531d51a6ebbfb3f0 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 25 Oct 2016 20:54:41 +0200 Subject: [PATCH 134/150] debian: add missing dh-autoreconf to Build-Depends (#2516) --- debian/control | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/control b/debian/control index 5fa675c1..e128a358 100644 --- a/debian/control +++ b/debian/control @@ -3,6 +3,7 @@ Section: x11 Priority: extra Maintainer: Michael Stapelberg Build-Depends: debhelper (>= 9), + dh-autoreconf, libx11-dev, libxcb-util0-dev (>= 0.3.8), libxcb-keysyms1-dev, From c3b5bb929ee585df6484830ccfe254a1f38d906f Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 25 Oct 2016 22:35:30 +0200 Subject: [PATCH 135/150] Bugfix: escape I3_VERSION when read from file (#2517) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I3_VERSION is used as string literal in config.h, i.e.: #define I3_VERSION … Where “…” is replaced with the contents of I3_VERSION. For our travis builds, we persist the version number to I3_VERSION, i.e.: $ cat I3_VERSION 4.12-150-g8ddc187 (2016-10-25, branch "next") Previously, config.h would end up with: #define I3_VERSION "4.12-150-g8ddc187 (2016-10-25, branch "next")" Note the unquoted double quotes around “next”, which are invalid in C string literals. Hence, this commit uses sed to escape double quotes, question marks and backslashes (see also http://stackoverflow.com/a/12208808/712014). The @<:@ and @:>@ quadrigraphs that m4 expands to [ and ], respectively, see also http://stackoverflow.com/a/2309394/712014 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 3c47c6b5..8829fed9 100644 --- a/configure.ac +++ b/configure.ac @@ -32,7 +32,7 @@ AS_IF([test -d ${srcdir}/.git], ], [ VERSION="$(cut -d '-' -f 1 ${srcdir}/I3_VERSION | cut -d ' ' -f 1)" - I3_VERSION="$(cat ${srcdir}/I3_VERSION)" + 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]) From 758fc7d33141fb0047c5b702429e33e120d33462 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 26 Oct 2016 08:46:26 +0200 Subject: [PATCH 136/150] travis/clang-analyze: look for dist tarball in build/ --- travis/clang-analyze.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis/clang-analyze.sh b/travis/clang-analyze.sh index 97c11fcc..5ef390d3 100755 --- a/travis/clang-analyze.sh +++ b/travis/clang-analyze.sh @@ -4,6 +4,6 @@ set -e set -x mkdir -p deb/DIST-clang/build -tar xf *.tar.bz2 -C deb/DIST-clang --strip-components=1 +tar xf build/*.tar.bz2 -C deb/DIST-clang --strip-components=1 (cd deb/DIST-clang/build && scan-build -o ../../CLANG ../configure && scan-build -o ../../CLANG --html-title="Analysis of i3 v$(git describe --tags)" make -j8) mv deb/CLANG/*/* deb/CLANG From b10eb0c3e6878b08b3b59f44f76e3847a64aab4f Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 26 Oct 2016 08:46:39 +0200 Subject: [PATCH 137/150] travis/docs.sh: call asciidoc directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …instead of the no longer existing docs-clean and docs targets. --- travis/docs.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/travis/docs.sh b/travis/docs.sh index 35bc12bb..d452e9b6 100755 --- a/travis/docs.sh +++ b/travis/docs.sh @@ -3,9 +3,14 @@ set -e set -x -make clean-docs docs ASCIIDOC="asciidoc -a linkcss -a stylesdir=http://i3wm.org/css -a scriptsdir=http://i3wm.org/js --backend=xhtml11 -f docs/asciidoc-git.conf" +for f in $(grep '\.html$' debian/i3-wm.docs | grep -v 'docs/refcard.html' | grep -v 'docs/lib-i3test') +do + asciidoc -a linkcss -a stylesdir=http://i3wm.org/css -a scriptsdir=http://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) do [ -f "$file" ] && asciidoc -a linkcss -a stylesdir=http://i3wm.org/css -a scriptsdir=http://i3wm.org/js --backend=xhtml11 -f docs/asciidoc-git.conf "$file" From 7ad5736875f0446bd66e8557add2a7d558143293 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 28 Oct 2016 23:41:13 +0200 Subject: [PATCH 138/150] travis: use correct path to debian packages (#2521) --- travis/bintray-autobuild-debian.json | 4 ++-- travis/bintray-autobuild-ubuntu.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/travis/bintray-autobuild-debian.json b/travis/bintray-autobuild-debian.json index 554d2b74..23fe6050 100644 --- a/travis/bintray-autobuild-debian.json +++ b/travis/bintray-autobuild-debian.json @@ -13,7 +13,7 @@ "files": [ { - "includePattern": "deb/debian-amd64/(.*\\.deb)$", + "includePattern": "build/deb/debian-amd64/(.*\\.deb)$", "matrixParams": { "deb_distribution": "sid", "deb_component": "main", @@ -22,7 +22,7 @@ "uploadPattern": "$1" }, { - "includePattern": "deb/debian-i386/(.*\\.deb)$", + "includePattern": "build/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 79bd50c5..948f3dc4 100644 --- a/travis/bintray-autobuild-ubuntu.json +++ b/travis/bintray-autobuild-ubuntu.json @@ -13,7 +13,7 @@ "files": [ { - "includePattern": "deb/ubuntu-amd64/(.*\\.deb)$", + "includePattern": "build/deb/ubuntu-amd64/(.*\\.deb)$", "matrixParams": { "deb_distribution": "xenial", "deb_component": "main", @@ -22,7 +22,7 @@ "uploadPattern": "$1" }, { - "includePattern": "deb/ubuntu-i386/(.*\\.deb)$", + "includePattern": "build/deb/ubuntu-i386/(.*\\.deb)$", "matrixParams": { "deb_distribution": "xenial", "deb_component": "main", From fea0bc1a454788a0a7db563ffb307bf8896fc0df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Thu, 3 Nov 2016 08:18:18 +0100 Subject: [PATCH 139/150] Fix memory leaks. (#2530) fixes #2529 --- i3-msg/main.c | 3 ++- src/main.c | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/i3-msg/main.c b/i3-msg/main.c index 51612459..915d326f 100644 --- a/i3-msg/main.c +++ b/i3-msg/main.c @@ -206,7 +206,7 @@ int main(int argc, char *argv[]) { } if (!payload) - payload = ""; + payload = sstrdup(""); int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0); if (sockfd == -1) @@ -221,6 +221,7 @@ int main(int argc, char *argv[]) { if (ipc_send_message(sockfd, strlen(payload), message_type, (uint8_t *)payload) == -1) err(EXIT_FAILURE, "IPC: write()"); + free(payload); if (quiet) return 0; diff --git a/src/main.c b/src/main.c index 4d9fd5a5..4737175b 100644 --- a/src/main.c +++ b/src/main.c @@ -403,12 +403,14 @@ int main(int argc, char *argv[]) { memset(&addr, 0, sizeof(struct sockaddr_un)); addr.sun_family = AF_LOCAL; strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1); + FREE(socket_path); if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) err(EXIT_FAILURE, "Could not connect to i3"); if (ipc_send_message(sockfd, strlen(payload), I3_IPC_MESSAGE_TYPE_COMMAND, (uint8_t *)payload) == -1) err(EXIT_FAILURE, "IPC: write()"); + FREE(payload); uint32_t reply_length; uint32_t reply_type; @@ -422,6 +424,7 @@ int main(int argc, char *argv[]) { if (reply_type != I3_IPC_MESSAGE_TYPE_COMMAND) errx(EXIT_FAILURE, "IPC: received reply of type %d but expected %d (COMMAND)", reply_type, I3_IPC_MESSAGE_TYPE_COMMAND); printf("%.*s\n", reply_length, reply); + FREE(reply); return 0; } From 454d0c4f0794933a966d5fda277200a50bc9ca70 Mon Sep 17 00:00:00 2001 From: Josh Rosso Date: Sat, 5 Nov 2016 03:32:16 -0700 Subject: [PATCH 140/150] Update config.keycodes link to proper location in user guide (#2537) Links to i3's config.keycodes in the User's guide navigates to a 404. This commit updates the reference to the `/etc/config.keycodes` file in GitHub. --- docs/userguide | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/userguide b/docs/userguide index ae741b69..acdc0a58 100644 --- a/docs/userguide +++ b/docs/userguide @@ -152,7 +152,7 @@ and move it to the wanted size. You can also use <> to define a mode for resizing via the keyboard. To see an example for this, look at the -https://github.com/i3/i3/blob/next/i3.config.keycodes[default config] provided +https://github.com/i3/i3/blob/next/etc/config.keycodes[default config] provided by i3. === Restarting i3 inplace @@ -181,7 +181,7 @@ can also do that by using the <>. Another way to resize floating windows using the mouse is to right-click on the titlebar and drag. For resizing floating windows with your keyboard, see the resizing binding mode -provided by the i3 https://github.com/i3/i3/blob/next/i3.config.keycodes[default config]. +provided by the i3 https://github.com/i3/i3/blob/next/etc/config.keycodes[default config]. Floating windows are always on top of tiling windows. @@ -2161,7 +2161,7 @@ floating containers. It is recommended to define bindings for resizing in a dedicated binding mode. See <> and the example in the i3 -https://github.com/i3/i3/blob/next/i3.config.keycodes[default config] for more +https://github.com/i3/i3/blob/next/etc/config.keycodes[default config] for more context. *Example*: From e48119adfef9527d4a10d4d5fa5cf9bea816bbf1 Mon Sep 17 00:00:00 2001 From: Jakub Wilk Date: Sat, 5 Nov 2016 11:32:40 +0100 Subject: [PATCH 141/150] Fix typo (#2536) --- docs/i3bar-protocol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/i3bar-protocol b/docs/i3bar-protocol index 0ad1967f..ebd3b83a 100644 --- a/docs/i3bar-protocol +++ b/docs/i3bar-protocol @@ -111,7 +111,7 @@ cont_signal:: processing. The default value (if none is specified) is SIGCONT. click_events:: - If specified and true i3bar will write a infinite array (same as above) + If specified and true i3bar will write an infinite array (same as above) to your stdin. === Blocks in detail From 9c6a21f2d42c14985c7f95d8a42253d98921d794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sun, 6 Nov 2016 17:14:37 +0100 Subject: [PATCH 142/150] Fix memory leak in i3-msg. (#2542) relates to #2541 --- i3-msg/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/i3-msg/main.c b/i3-msg/main.c index 915d326f..02e156a1 100644 --- a/i3-msg/main.c +++ b/i3-msg/main.c @@ -240,9 +240,10 @@ int main(int argc, char *argv[]) { /* For the reply of commands, have a look if that command was successful. * If not, nicely format the error message. */ if (reply_type == I3_IPC_MESSAGE_TYPE_COMMAND) { - yajl_handle handle; - handle = yajl_alloc(&reply_callbacks, NULL, NULL); + yajl_handle handle = yajl_alloc(&reply_callbacks, NULL, NULL); yajl_status state = yajl_parse(handle, (const unsigned char *)reply, reply_length); + yajl_free(handle); + switch (state) { case yajl_status_ok: break; From 841118e5f8b2456d61bbf3d0e65094fac3c935cc Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 7 Nov 2016 11:49:26 -0800 Subject: [PATCH 143/150] configure: add build directory to gitignore (#2543) --- configure.ac | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/configure.ac b/configure.ac index 8829fed9..9e61d997 100644 --- a/configure.ac +++ b/configure.ac @@ -146,6 +146,15 @@ else print_BUILD_MANS=no fi +git_dir=`git rev-parse --git-dir 2>/dev/null` +if test -n "$git_dir"; then + 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: From faa9915abc447ff5c6cb60854a284c152c556d91 Mon Sep 17 00:00:00 2001 From: Chih-Chyuan Hwang Date: Tue, 8 Nov 2016 16:56:46 +0800 Subject: [PATCH 144/150] Fix an use-after-free bug (#2522) Fix the issue #2421 (https://github.com/i3/i3/issues/2421). floating_enable() invokes tree_close_internal() to free con->parent. After con->parent is freed in tree_close_internal() but before con->parent is reassigned by the caller, con->parent may be dereferenced and causes i3 crash. The backtrace below is an example. The already-freed pointer is dereferenced again through the pointer "focused" in x_push_changes(). Reassign con->parent before calling tree_close_internal() to fix this use-after-free bug. 0x0000000000416372 in con_get_workspace (con=0x7ab9c0) at ../i3/src/con.c:375 0x0000000000416103 in con_has_managed_window (con=0x7ab9c0) at ../i3/src/con.c:266 0x000000000042b413 in x_push_changes (con=0x78d190) at ../i3/src/x.c:1132 0x0000000l0004533e8 in tree_render () at ../i3/src/tree.c:504 0x0000000000452b4f in tree_close_internal (con=0x7b67c0, kill_window=DONT_KILL_WINDOW, dont_kill_parent=false, force_set_focus=false) ../i3/src/tree.c:314 0x00000000004196f0 in con_on_remove_child (con=0x7b67c0) at ../i3/src/con.c:1801 0x0000000000452eb7 in tree_close_internal (con=0x783840, kill_window=DONT_KILL_WINDOW, dont_kill_parent=false, force_set_focus=false) ../i3/src/tree.c:364 0x0000000000431516 in floating_enable (con=0x7ab9c0, automatic=false) at ../i3/src/floating.c:183 0x0000000000431eed in toggle_floating_mode (con=0x7ab9c0, automatic=false) at ../i3/src/floating.c:379 0x0000000000420d92 in cmd_floating (current_match=0x679a20 , cmd_output=0x679aa0 , floating_mode=0x7ab8c0 "toggle") ../i3/src/commands.c:1088 0x000000000043e5ae in GENERATED_call (call_identifier=60, result=0x679aa0 ) at include/GENERATED_command_call.h:486 0x000000000043ee19 in next_state (token=0x675d70 ) at ../i3/src/commands_parser.c:187 0x000000000043f2fb in parse_command (input=0x7b4fe0 "floating toggle", gen=0x0) at ../i3/src/commands_parser.c:308 0x00000000004125f8 in run_binding (bind=0x784260, con=0x0) at ../i3/src/bindings.c:792 0x000000000042bace in handle_key_press (event=0x7a01a0) at ../i3/src/key_press.c:33 0x000000000044e6aa in handle_event (type=2, event=0x7a01a0) at ../i3/src/handlers.c:1420 0x0000000000439533 in xcb_check_cb (loop=0x7ffff532f8e0, w=0x68c140, revents=32768) at ../i3/src/main.c:133 0x00007ffff5125d73 in ev_invoke_pending () from /usr/lib/x86_64-linux-gnu/libev.so.4 0x00007ffff51293de in ev_run () from /usr/lib/x86_64-linux-gnu/libev.so.4 0x0000000000439418 in ev_loop (loop=0x7ffff532f8e0, flags=0) at /usr/include/ev.h:835 0x000000000043d51d in main (argc=3, argv=0x7fffffffe0a8) at ../i3/src/main.c:913 --- src/floating.c | 10 ++++++++-- src/randr.c | 6 ++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/floating.c b/src/floating.c index 616602c0..0a8b6957 100644 --- a/src/floating.c +++ b/src/floating.c @@ -178,7 +178,10 @@ void floating_enable(Con *con, bool automatic) { if ((con->parent->type == CT_CON || con->parent->type == CT_FLOATING_CON) && con_num_children(con->parent) == 0) { DLOG("Old container empty after setting this child to floating, closing\n"); - tree_close_internal(con->parent, DONT_KILL_WINDOW, false, false); + Con *parent = con->parent; + /* clear the pointer before calling tree_close_internal in which the memory is freed */ + con->parent = NULL; + tree_close_internal(parent, DONT_KILL_WINDOW, false, false); } char *name; @@ -315,6 +318,7 @@ void floating_disable(Con *con, bool automatic) { const bool set_focus = (con == focused); Con *ws = con_get_workspace(con); + Con *parent = con->parent; /* 1: detach from parent container */ TAILQ_REMOVE(&(con->parent->nodes_head), con, nodes); @@ -323,7 +327,9 @@ void floating_disable(Con *con, bool automatic) { /* 2: kill parent container */ TAILQ_REMOVE(&(con->parent->parent->floating_head), con->parent, floating_windows); TAILQ_REMOVE(&(con->parent->parent->focus_head), con->parent, focused); - tree_close_internal(con->parent, DONT_KILL_WINDOW, true, false); + /* clear the pointer before calling tree_close_internal in which the memory is freed */ + con->parent = NULL; + tree_close_internal(parent, DONT_KILL_WINDOW, true, false); /* 3: re-attach to the parent of the currently focused con on the workspace * this floating con was on */ diff --git a/src/randr.c b/src/randr.c index 51255619..e5dcddfc 100644 --- a/src/randr.c +++ b/src/randr.c @@ -846,9 +846,11 @@ void randr_disable_output(Output *output) { } DLOG("destroying disappearing con %p\n", output->con); - tree_close_internal(output->con, DONT_KILL_WINDOW, true, false); - DLOG("Done. Should be fine now\n"); + 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, false); + DLOG("Done. Should be fine now\n"); } output->to_be_disabled = false; From 212a408d4bb1c45068bc6c57fbc0830a5a0339d8 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 8 Nov 2016 19:21:53 +0100 Subject: [PATCH 145/150] debian: install docs to usr/share/doc/i3-wm --- debian/rules | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/debian/rules b/debian/rules index e119f260..e4da3db8 100755 --- a/debian/rules +++ b/debian/rules @@ -13,5 +13,9 @@ override_dh_strip: 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 + %: dh $@ --parallel --builddirectory=build --with=autoreconf From 69ebc0ca1ee986acdbbf6d27b75dc131a6591511 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 8 Nov 2016 19:23:33 +0100 Subject: [PATCH 146/150] debian: remove now-unnecessary lintian overrides --- debian/i3-wm.lintian-overrides | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 debian/i3-wm.lintian-overrides diff --git a/debian/i3-wm.lintian-overrides b/debian/i3-wm.lintian-overrides deleted file mode 100644 index a999fe4c..00000000 --- a/debian/i3-wm.lintian-overrides +++ /dev/null @@ -1,2 +0,0 @@ -# gdm needs the DesktopNames key, even though lintian doesn’t recognize it yet. -desktop-entry-contains-unknown-key usr/share/xsessions/i3.desktop:* DesktopNames From d9530667341d0fb98c9a4396682c1703db429606 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 8 Nov 2016 19:25:24 +0100 Subject: [PATCH 147/150] debian: update standards-version to 3.9.8 (no changes necessary) --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index e128a358..76a84a5a 100644 --- a/debian/control +++ b/debian/control @@ -26,7 +26,7 @@ Build-Depends: debhelper (>= 9), libcairo2-dev (>= 1.14.4), libpango1.0-dev, libpod-simple-perl -Standards-Version: 3.9.7 +Standards-Version: 3.9.8 Homepage: http://i3wm.org/ Package: i3 From 667857f568eb2edc8f4672ed6dffd353afb08974 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 8 Nov 2016 19:53:08 +0100 Subject: [PATCH 148/150] debian: prefix paths debian/tmp/ to avoid confusion Without the prefix, the etc/ directory will be copied from the source directory, as opposed to the debian/tmp directory into which files were installed. --- debian/i3-wm.install | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/i3-wm.install b/debian/i3-wm.install index a75e2371..bff5028c 100644 --- a/debian/i3-wm.install +++ b/debian/i3-wm.install @@ -1,2 +1,2 @@ -etc -usr +debian/tmp/etc +debian/tmp/usr From 9c8dc36895d335f510f59a6d706e840f79c06240 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 8 Nov 2016 19:54:01 +0100 Subject: [PATCH 149/150] release i3 4.13 --- I3_VERSION | 2 +- Makefile.am | 2 +- RELEASE-NOTES-4.12 | 132 --------------------------------------------- RELEASE-NOTES-4.13 | 114 +++++++++++++++++++++++++++++++++++++++ configure.ac | 2 +- 5 files changed, 117 insertions(+), 135 deletions(-) delete mode 100644 RELEASE-NOTES-4.12 create mode 100644 RELEASE-NOTES-4.13 diff --git a/I3_VERSION b/I3_VERSION index f3d68995..341651a9 100644 --- a/I3_VERSION +++ b/I3_VERSION @@ -1 +1 @@ -4.12-non-git +4.13 (2016-11-08) diff --git a/Makefile.am b/Makefile.am index 57d5b019..c90e26c7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -94,7 +94,7 @@ EXTRA_DIST = \ I3_VERSION \ LICENSE \ PACKAGE-MAINTAINER \ - RELEASE-NOTES-4.12 \ + RELEASE-NOTES-4.13 \ generate-command-parser.pl \ parser-specs/commands.spec \ parser-specs/config.spec \ diff --git a/RELEASE-NOTES-4.12 b/RELEASE-NOTES-4.12 deleted file mode 100644 index 57cd9553..00000000 --- a/RELEASE-NOTES-4.12 +++ /dev/null @@ -1,132 +0,0 @@ - - ┌────────────────────────────┐ - │ Release notes for i3 v4.12 │ - └────────────────────────────┘ - -This is i3 v4.12. This version is considered stable. All users of i3 are -strongly encouraged to upgrade. - -If cairo ≥ 1.14.4 is available, i3 and i3bar will use cairo for rendering -(instead of raw X11 drawing primitives). While this is currently optional, -having cairo ≥ 1.14.4 will be a hard requirement in future release. - -This release contains a good number of detail improvements and fixes. - - ┌────────────────────────────┐ - │ Changes in i3 v4.12 │ - └────────────────────────────┘ - - • use https instead of git/http, update contact information, add GPG key - • docs/hacking-howto: fix old cfgparse.y reference to config_parser.c - • docs/ipc: added link to i3ipcpp (C++ library) - • docs/userguide: clarify no_focus documentation - • docs/userguide: add documentation for binding modes - • docs/userguide: fix rendering of __focused__ - • docs/userguide: improve placement of explicit IDs for headings - • docs/userguide: make rendering of key bindings more consistent - • docs/userguide: clarify quoting of “exec” commands - • man/i3-nagbar: fix example invocation - • man/i3: add “floating window” to terminology - • i3-sensible-*: quote variables correctly - • i3-sensible-editor: add neovim - • i3-sensible-terminal: add termit, st - • i3bar: use cairo for all drawing operations - • i3bar: support per-statusblock border and background colors - • i3bar: support different bar background colors depending on whether the bar - is on the focused output or not - • i3bar: multiple tray_output directives on the same bar are now supported - • i3bar: support disabling the modifier by specifying “modifier none” - • use cairo for all drawing operations - • fix a number of memory leaks, thanks to AddressSanitizer - • no_focus is now suppressed for the first window of a workspace - • “workspace next/prev” now looks for numbered workspaces after reaching the - last workspace (it used to incorrectly only look at named workspaces) - • multiple marks can now be set on a single window (but a mark can still only - be present on one window at a time) - • the “unmark” command now supports criteria - • the “con_id” criterion now supports the special value __focused__ - • the “workspace” command now supports the --no-auto-back-and-forth parameter - • the “move window to workspace” command now supports the - --no-auto-back-and-forth parameter - • the “resize grow|shrink width|height” command now works for a nested split - in the same direction - • support _NET_WM_USER_TIME’s special 0 value, indicating that a window - should not be focused - • use 32-bit visual by default if available. This reduces graphical glitches - when using transparency (which is still not officially supported) - • the “move position center” command now supports criteria - • specifying invalid match criteria now results in an error instead of - blindly applying the operation to the currently focused window - • allow mouse bindings to run on the root window - • support matching _NET_WM_WINDOW_TYPE_NOTIFICATION in criteria - • all criteria are now matched, even when con_id or con_mark are given (used - to be a special case) - • allow the “id” criterion to be specified in any base recognized by - strtol(), not only base 10 - • non-true color displays are now supported again (e.g. the Raspberry Pi) - • the “split” command now has a “toggle” option - • the additional color class “decoration_border” was added - • title_format is now stored on containers instead of windows, allowing the - use of title_format on split containers - • On OpenBSD, i3 now uses pledge(2) - • support _NET_WM_DESKTOP (for pager applications like gnome-panel) - • floating workspaces are no longer available (they were not supported for a - while now) - • floating windows now carry the I3_FLOATING_WINDOW atom so that tools like - compositors can be configured to match on floating windows - - ┌────────────────────────────┐ - │ Bugfixes │ - └────────────────────────────┘ - - • i3bar: display short text only on the monitor(s) on which it is necessary - • i3bar: explicitly set cursor using libxcb-cursor if available - • i3bar: fix XEMBED messages - • i3-nagbar: explicitly set cursor using libxcb-cursor if available - • duplicated keybindings are now also detected when one uses bindcode but the - other(s) use(s) bindsym - • keymap fallback for servers without XKB (e.g. TightVNC) has been added - • using pango markup in mode names is now optional, fixing a regression in i3 - v4.11 where modes which contained characters such as “<” would break. - • moving windows to a workspace by specifying a mark now works - • the root output is now used when any RandR request fails (for x2go) - • assignments are now marked as run before executing them, preventing endless - loops/crashes when assignments cause another assignment evaluation - • splitting/floating a dock container no longer crashes i3 - • correctly compare modifier mask when identifying keybindings (fixes - bindings which use --release) - • no longer fail config validation when there is no newline at the end of - the config file - • scrollwheel buttons are now only grabbed when necessary, allowing the use - of “bindsym button*” or scrolling in windows without focusing them (in case - no “bindsym button*” is present) - • parse con_id in base 16 (affected FreeBSD only) - • fix crash when opening a large number of windows - • reject empty swallow definitions to avoid crashes - • don’t remove SubstructureRedirect event mask temporarily (fixes i3bar - stopping after system suspend) - • move urgent flag before killing the parent to avoid a crash - • correctly validate “kill” command to avoid crashing when “kill” is invoked - on workspace containers - • actually accept the documented “workspace” token as an alternative to “→” - in assign statements - • remove _NET_WM_STATE on withdrawn windows to comply with the spec - • the “border” command now uses logical pixels (relevant for hi-dpi displays) - • “tray_output primary” does not properly fall back and hence was removed - from the default config again - • correctly determine focused workspace when moving workspace to output - • revert to default binding mode before reloading the config file - • correctly interpret _MOTIF_WM_HINTS (endianness-dependent) - - ┌────────────────────────────┐ - │ Thanks! │ - └────────────────────────────┘ - -Thanks for testing, bugfixes, discussions and everything I forgot go out to: - - Adaephon, Airblader, Alexis211, bendem, botovq, brianmillar, DavidMikeSimon, - dcoppa, Florian Merkel, fmthoma, frederik, hwangcc23, jolange, Juuso - Lapinlampi, kneitinger, lotheac, nicklan, norrland, pra85, romanblanco, - sur5r, tbu-, tyll, wodny - --- Michael Stapelberg, 2016-03-06 diff --git a/RELEASE-NOTES-4.13 b/RELEASE-NOTES-4.13 new file mode 100644 index 00000000..0e854569 --- /dev/null +++ b/RELEASE-NOTES-4.13 @@ -0,0 +1,114 @@ + + ┌────────────────────────────┐ + │ Release notes for i3 v4.13 │ + └────────────────────────────┘ + +This is i3 v4.13. This version is considered stable. All users of i3 are +strongly encouraged to upgrade. + +For users, there are two changes to be aware of: + +1. The X server DPI is read from the Xft.dpi X resource (if available). + Previously, i3 used to directly look at the X server’s DPI (based on screen + resolution and physical size). Looking at Xft.dpi is more consistent with + other software, more likely to be correct (because it’s user-specified and + not read from possibly broken hardware information) and allows users to + override the value. + +2. It is now possible to set config file variables from X resources using the + “set_from_resource” directive. This allows users to have a single source of + truth for e.g. theming X11 applications (specify “*color0: #121212” and have + it apply to URxvt and your i3 config). + +For packagers, there are three changes that likely require action: + +1. cairo/pango are now required dependencies, as announced in the i3 v4.12 + release notes. + +2. The aforementioned “set_from_resource” feature requires the new dependency + libxcb-util-xrm. + +3. i3 now uses the GNU build system (autotools). Please see + https://github.com/i3/i3/commit/4a52a7e9fb6fb2e1f0256b2e086cfa313f411cd8 for + a lot more details about the rationale and what this means for your package. + Bottomline, things should get simpler for you, though :). + + ┌────────────────────────────┐ + │ Changes in i3 v4.13 │ + └────────────────────────────┘ + + • build: wire up version handling for non-release tarballs (as opposed to git + checkouts) + • build: switch to the GNU build system + • i3bar: disable pango markup for plain-text input + • man/i3-msg: point out default ipc message type + • config: introduce support for specifying variables from X resources + • config: ensure variables match on longest-length, eliminating problems + where one variable was a prefix of another + • config: do not count '\' in comment lines as line continuation + • ipc: introduce a new GET_BINDING_MODES command + • ipc: implement new window::mark event + • ipc: add “output” to IPC events referencing a container + • make fullscreen windows open on the output which is indicated by their + geometry (fixes LibreOffice Impress multi-monitor presentations) + • focus newly managed windows only if they don’t use the globally active + input mode (fixes issues with RubyMine) + • remove title indentation in nested containers (rationale was unclear, + nobody spoke up when we asked about the feature on i3-discuss) + • use the last known timestamp when calling xcb_set_input_focus (might fix + rare race conditions in focus handling) + • introduce the “smart” option for hide_edge_borders, which will hide borders + when there is precisely one window on the workspace + • handle _MOTIF_WM_HINTS changes (_MOTIF_WM_HINTS were previously only + considered when managing a new window) + • don’t change border style if BS_NORMAL is requested in _MOTIF_WM_HINTS + • only add numlock fallback for keybindings where necessary (allows users to + correctly bind keys on the numpad) + • do not match docks in config and command criteria + • get DPI from the Xft.dpi resource instead of directly looking at the screen + resolution/size + • handle _NET_ACTIVE_WINDOW for scratchpad windows (for pagers) + • set _NET_WM_DESKTOP to sticky for scratchpad windows + • add new criteria “tiling” and “floating” + • implement special output name “current” for commands + • handle ResizeRequests for tray clients (fixes VLC tray icon) + + ┌────────────────────────────┐ + │ Bugfixes │ + └────────────────────────────┘ + + • i3bar: fix crash when the I3SOCK environment variable is present + • i3-dmenu-desktop: do not die on failed open + • i3-input: properly position in non-standard cases (fixes an issue where + i3-input would launch off-screen) + • i3-save-tree: rename “mark” to “marks” to reflect our recent change to + allow multiple marks + • mouse bindings: only grab the mouse buttons that need to be grabbed + • no_focus: correctly count the number of windows (makes no_focus work with + tabbed/stacked workspace layouts). + • properly close disabled outputs restored during a restart (this fixes state + handling when RandR changes happen during i3 restarts) + • don’t trigger bindings on window border clicks unless --border was + specified for the binding + • traverse numbered workspaces in correct order + • fix transition from named to numbered workspaces in “workspace next|prev” + • avoid setting urgency hint on content containers and above (fixes crashes) + • don’t trigger unrelated key bindings for --release bindings + • fix colormap handling for containers (fixes taking screenshots using xwd) + • check output crossing on ENTER_NOTIFY to dockarea (fixes pointer jumping) + • fix a use-after-free bug (fixes “floating enable” on single split windows) + + ┌────────────────────────────┐ + │ Thanks! │ + └────────────────────────────┘ + +Thanks for testing, bugfixes, discussions and everything I forgot go out to: + + Benedikt Heine, Cedric Buissart, Chih-Chyuan Hwang, Denton Liu, eplanet, Eric + Engeström, EvilPudding, Ferdinand Bachmann, Hong, Ingo Bürk, Jakob Schnell, + Jakub Wilk, johannes karoff, Johannes Lange, joshrosso, Julien Lequertier, + Kacper Kowalik, Kenneth Lyons, Kyle Kneitinger, madroach, Michael Vetter, + Nathan Schulte, Øsse, Peder Stray, Tony Crisci, Trevor Merrifield, wentasah, + yshui, Zamarin Arthur + +-- Michael Stapelberg, 2016-11-08 diff --git a/configure.ac b/configure.ac index 9e61d997..1a91b3b1 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Run autoreconf -fi to generate a configure script from this file. AC_PREREQ([2.69]) -AC_INIT([i3], [4.12], [https://github.com/i3/i3/issues]) +AC_INIT([i3], [4.13], [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]) From f3fad84fc23bfcb68567810451e3d2566f795f76 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 8 Nov 2016 19:54:14 +0100 Subject: [PATCH 150/150] Set non-git version to 4.13-non-git. --- I3_VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/I3_VERSION b/I3_VERSION index 341651a9..d4cfa42a 100644 --- a/I3_VERSION +++ b/I3_VERSION @@ -1 +1 @@ -4.13 (2016-11-08) +4.13-non-git