├── debian ├── compat ├── i3-wm.wm ├── i3-wm.links ├── watch ├── i3-wm.doc-base ├── i3-wm.manpages ├── i3-wm.install ├── rules └── i3-wm.docs ├── I3_VERSION ├── i3bar ├── .gitignore ├── include │ ├── xcb_atoms.def │ ├── trayclients.h │ ├── mode.h │ ├── ipc.h │ ├── parse_json_header.h │ └── workspaces.h └── LICENSE ├── docs ├── modes.png ├── wsbar.dia ├── wsbar.png ├── i3-sync.dia ├── i3-sync.png ├── logo-30.png ├── snapping.png ├── bigpicture.png ├── bigpicture.xcf ├── tree-shot1.png ├── tree-shot2.png ├── tree-shot3.png ├── tree-shot4.png ├── two_columns.png ├── tree-layout1.png ├── tree-layout2.png ├── two_terminals.png ├── i3-sync-working.dia ├── i3-sync-working.png ├── keyboard-layer1.png ├── keyboard-layer2.png ├── layout-saving-1.png ├── single_terminal.png ├── GPN-2009-06-27 │ ├── xft.jpg │ ├── reparenting.dia │ ├── screenshot.png │ └── xserver_konzept.dia ├── slides-2012-01-25 │ ├── TdilE.jpg │ └── Ubuntu_Linux_Jaunty_screenshot.png ├── slides-2012-03-16 │ ├── TdilE.jpg │ └── Ubuntu_Linux_Jaunty_screenshot.png └── NoName-2009-03-12 │ └── screenshot.png ├── i3-input ├── keysym2ucs.h └── i3-input.h ├── include ├── atoms.xmacro ├── cmdparse.h ├── sync.h ├── sighandler.h ├── main.h ├── atoms_rest.xmacro ├── click.h ├── xinerama.h ├── assignments.h ├── yajl_utils.h ├── fake_outputs.h ├── move.h ├── key_press.h ├── display_version.h ├── manage.h ├── resize.h ├── atoms_NET_SUPPORTED.xmacro ├── regex.h ├── xcursor.h ├── scratchpad.h ├── restore_layout.h ├── output.h ├── config_parser.h ├── load_layout.h └── render.h ├── contrib ├── sticker-7x5cm-stickma.tif.lzma ├── trivial-bar-script.sh └── show-download-count.sh ├── travis ├── prep-bintray.sh ├── check-formatting.sh ├── ha.sh ├── skip-pkg.sh ├── debian-build.sh ├── deploy-github-pages.sh ├── docker-build-and-push.sh ├── check-safe-wrappers.sh ├── run-tests.sh ├── bintray-autobuild-debian.json ├── bintray-autobuild-ubuntu.json ├── docs.sh ├── travis-base-386.Dockerfile ├── travis-base-ubuntu-386.Dockerfile ├── travis-base-ubuntu.Dockerfile └── cleanup-bintray.pl ├── testcases ├── .gitignore ├── t │ ├── 000-load-deps.t │ ├── 134-invalid-command.t │ ├── 002-i3-sync.t │ ├── 151-regress-float-size.t │ ├── 126-regress-close.t │ ├── 152-regress-level-up.t │ ├── 267-regress-mark-restart.t │ ├── 142-regress-move-floating.t │ ├── 260-invalid-criteria.t │ ├── 224-regress-resize-branch.t │ ├── 273-regress-focus-toggle.t │ ├── 168-regress-fullscreen-restart.t │ ├── 292-regress-layout-toggle.t │ ├── 205-ipc-windows.t │ ├── 220-ipc-window-title.t │ ├── 163-wm-state.t │ ├── 001-tile.t │ ├── 184-regress-float-split-resize.t │ ├── 218-regress-floating-split.t │ ├── 197-regression-move-vanish.t │ ├── 182-regress-focus-dock.t │ ├── 281-regress-reload-bindsym.t │ ├── 275-ipc-window-close.t │ ├── 178-regress-workspace-open.t │ ├── 198-regression-scratchpad-crash.t │ ├── 199-ipc-mode-event.t │ ├── 222-regress-dock-resize.t │ ├── 003-ipc.t │ ├── 004-unmanaged.t │ ├── 303-regress-move-floating.t │ ├── 237-regress-assign-focus.t │ ├── 196-randr-output-names.t │ ├── 204-regress-scratchpad-move.t │ ├── 540-sigterm-cleanup.t │ ├── 263-config-reload-reverts-bind-mode.t │ ├── 299-regress-scratchpad-focus.t │ ├── 225-ipc-window-fullscreen.t │ ├── 286-root-window-mouse-binding.t │ ├── 300-restart-non-utf8.t │ ├── 515-create-workspace.t │ ├── 190-scratchpad-diff-ws.t │ ├── 143-regress-floating-restart.t │ ├── 500-multi-monitor.t │ ├── 530-bug-2229.t │ ├── 279-regress-default-floating-border.t │ ├── 282-tabbed-floating-disable-crash.t │ ├── 179-regress-multiple-ws.t │ ├── 148-regress-floatingmovews.t │ ├── 509-workspace_layout.t │ ├── 147-regress-floatingmove.t │ ├── 208-regress-floating-criteria.t │ ├── 276-ipc-window-move.t │ ├── 538-i3bar-primary-output.t │ ├── 514-ipc-workspace-multi-monitor.t │ ├── 104-focus-stack.t │ ├── 191-resize-levels.t │ ├── 262-config-validation.t │ ├── 270-config-no-newline-end.t │ ├── 296-regress-focus-behind-fullscreen-floating.t │ ├── 507-workspace-move-crash.t │ ├── 527-focus-fallback.t │ ├── 137-floating-unmap.t │ ├── 161-regress-borders-restart.t │ ├── 520-regress-focus-direction-floating.t │ ├── 293-sticky-output-crash.t │ ├── 193-ipc-version.t │ ├── 231-ipc-floating-event.t │ ├── 140-focus-lost.t │ ├── 127-regress-floating-parent.t │ ├── 144-regress-floating-resize.t │ ├── 236-floating-focus-raise.t │ ├── 295-net-wm-state-focused.t │ ├── 511-scratchpad-configure-request.t │ ├── 512-move-wraps.t │ ├── 271-for_window_tilingfloating.t │ ├── 277-ipc-window-urgent.t │ ├── 519-mouse-warping.t │ ├── 188-regress-focus-restart.t │ ├── 239-net-close-window-request.t │ ├── 186-regress-assign-focus-parent.t │ ├── 534-dont-warp.t │ ├── 146-floating-reinsert.t │ ├── 173-get-marks.t │ ├── 265-ipc-mark.t │ ├── 115-ipc-workspaces.t │ ├── 128-open-order.t │ ├── 244-new-workspace-floating-enable-center.t │ └── 539-disable_focus_wrapping.t ├── valgrind.supp ├── Makefile.PL └── lib │ └── i3test │ └── Util.pm ├── i3-config-wizard ├── atoms.xmacro └── xcb.h ├── i3-nagbar ├── atoms.xmacro └── i3-nagbar.h ├── .editorconfig ├── AnyEvent-I3 ├── MANIFEST.SKIP ├── t │ ├── 00-load.t │ ├── pod.t │ ├── manifest.t │ ├── pod-coverage.t │ ├── 01-workspaces.t │ ├── 02-sugar.t │ └── boilerplate.t ├── MANIFEST └── README ├── share ├── xsessions │ ├── i3-with-shmlog.desktop │ └── i3.desktop └── applications │ └── i3.desktop ├── .clang-format ├── src ├── version.c ├── sync.c └── key_press.c ├── man ├── asciidoc.conf.in ├── i3-sensible-pager.man ├── i3-sensible-editor.man ├── i3-dump-log.man ├── i3-migrate-config-to-v4.man └── i3-sensible-terminal.man ├── parser-specs └── highlighting.vim ├── i3-sensible-editor ├── libi3 ├── README ├── strndup.c ├── is_debug_build.c ├── get_visualtype.c ├── ipc_send_message.c ├── resolve_tilde.c └── mkdirp.c ├── i3-sensible-pager ├── i3-sensible-terminal ├── RELEASE-NOTES-4.16.1 ├── .github ├── GOVERNANCE.md └── ISSUE_TEMPLATE │ └── feature_request.md ├── m4 └── ax_require_defined.m4 ├── .gitignore └── LICENSE /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /I3_VERSION: -------------------------------------------------------------------------------- 1 | 4.16.1-non-git 2 | -------------------------------------------------------------------------------- /debian/i3-wm.wm: -------------------------------------------------------------------------------- 1 | /usr/bin/i3 2 | -------------------------------------------------------------------------------- /i3bar/.gitignore: -------------------------------------------------------------------------------- 1 | i3bar 2 | *.o 3 | core 4 | doc/i3bar.1 5 | -------------------------------------------------------------------------------- /docs/modes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/modes.png -------------------------------------------------------------------------------- /docs/wsbar.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/wsbar.dia -------------------------------------------------------------------------------- /docs/wsbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/wsbar.png -------------------------------------------------------------------------------- /debian/i3-wm.links: -------------------------------------------------------------------------------- 1 | usr/share/man/man1/i3.1.gz usr/share/man/man1/i3-with-shmlog.1.gz 2 | -------------------------------------------------------------------------------- /docs/i3-sync.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/i3-sync.dia -------------------------------------------------------------------------------- /docs/i3-sync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/i3-sync.png -------------------------------------------------------------------------------- /docs/logo-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/logo-30.png -------------------------------------------------------------------------------- /docs/snapping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/snapping.png -------------------------------------------------------------------------------- /docs/bigpicture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/bigpicture.png -------------------------------------------------------------------------------- /docs/bigpicture.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/bigpicture.xcf -------------------------------------------------------------------------------- /docs/tree-shot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/tree-shot1.png -------------------------------------------------------------------------------- /docs/tree-shot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/tree-shot2.png -------------------------------------------------------------------------------- /docs/tree-shot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/tree-shot3.png -------------------------------------------------------------------------------- /docs/tree-shot4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/tree-shot4.png -------------------------------------------------------------------------------- /docs/two_columns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/two_columns.png -------------------------------------------------------------------------------- /i3-input/keysym2ucs.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | long keysym2ucs(xcb_keysym_t keysym); 4 | -------------------------------------------------------------------------------- /docs/tree-layout1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/tree-layout1.png -------------------------------------------------------------------------------- /docs/tree-layout2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/tree-layout2.png -------------------------------------------------------------------------------- /docs/two_terminals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/two_terminals.png -------------------------------------------------------------------------------- /include/atoms.xmacro: -------------------------------------------------------------------------------- 1 | #include "atoms_NET_SUPPORTED.xmacro" 2 | #include "atoms_rest.xmacro" 3 | -------------------------------------------------------------------------------- /docs/i3-sync-working.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/i3-sync-working.dia -------------------------------------------------------------------------------- /docs/i3-sync-working.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/i3-sync-working.png -------------------------------------------------------------------------------- /docs/keyboard-layer1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/keyboard-layer1.png -------------------------------------------------------------------------------- /docs/keyboard-layer2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/keyboard-layer2.png -------------------------------------------------------------------------------- /docs/layout-saving-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/layout-saving-1.png -------------------------------------------------------------------------------- /docs/single_terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/single_terminal.png -------------------------------------------------------------------------------- /docs/GPN-2009-06-27/xft.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/GPN-2009-06-27/xft.jpg -------------------------------------------------------------------------------- /docs/slides-2012-01-25/TdilE.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/slides-2012-01-25/TdilE.jpg -------------------------------------------------------------------------------- /docs/slides-2012-03-16/TdilE.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/slides-2012-03-16/TdilE.jpg -------------------------------------------------------------------------------- /docs/GPN-2009-06-27/reparenting.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/GPN-2009-06-27/reparenting.dia -------------------------------------------------------------------------------- /docs/GPN-2009-06-27/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/GPN-2009-06-27/screenshot.png -------------------------------------------------------------------------------- /contrib/sticker-7x5cm-stickma.tif.lzma: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/contrib/sticker-7x5cm-stickma.tif.lzma -------------------------------------------------------------------------------- /debian/watch: -------------------------------------------------------------------------------- 1 | version=3 2 | opts=pgpsigurlmangle=s/$/.asc/ \ 3 | https://i3wm.org/downloads/ /downloads/i3-(.*)\.tar\.bz2 4 | -------------------------------------------------------------------------------- /docs/NoName-2009-03-12/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/NoName-2009-03-12/screenshot.png -------------------------------------------------------------------------------- /docs/GPN-2009-06-27/xserver_konzept.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/GPN-2009-06-27/xserver_konzept.dia -------------------------------------------------------------------------------- /travis/prep-bintray.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -x 5 | 6 | sed -i "s,%version%,$(git describe --tags),g" travis/bintray-autobuild-*.json 7 | -------------------------------------------------------------------------------- /docs/slides-2012-01-25/Ubuntu_Linux_Jaunty_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/slides-2012-01-25/Ubuntu_Linux_Jaunty_screenshot.png -------------------------------------------------------------------------------- /docs/slides-2012-03-16/Ubuntu_Linux_Jaunty_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terroo/i3-radius/HEAD/docs/slides-2012-03-16/Ubuntu_Linux_Jaunty_screenshot.png -------------------------------------------------------------------------------- /testcases/.gitignore: -------------------------------------------------------------------------------- 1 | testsuite-* 2 | latest 3 | Makefile 4 | Makefile.old 5 | .last_run_timings.json 6 | _Inline 7 | inc 8 | META.yml 9 | i3-cfg-for-* 10 | - 11 | -------------------------------------------------------------------------------- /i3-config-wizard/atoms.xmacro: -------------------------------------------------------------------------------- 1 | xmacro(_NET_WM_NAME) 2 | xmacro(_NET_WM_WINDOW_TYPE) 3 | xmacro(_NET_WM_WINDOW_TYPE_DIALOG) 4 | xmacro(ATOM) 5 | xmacro(CARDINAL) 6 | xmacro(UTF8_STRING) 7 | -------------------------------------------------------------------------------- /i3-nagbar/atoms.xmacro: -------------------------------------------------------------------------------- 1 | xmacro(_NET_WM_WINDOW_TYPE) 2 | xmacro(_NET_WM_WINDOW_TYPE_DOCK) 3 | xmacro(_NET_WM_STRUT_PARTIAL) 4 | xmacro(I3_SOCKET_PATH) 5 | xmacro(ATOM) 6 | xmacro(CARDINAL) 7 | -------------------------------------------------------------------------------- /i3-config-wizard/xcb.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* from X11/keysymdef.h */ 4 | #define XCB_NUM_LOCK 0xff7f 5 | 6 | #define xmacro(atom) xcb_atom_t A_##atom; 7 | #include "atoms.xmacro" 8 | #undef xmacro 9 | -------------------------------------------------------------------------------- /travis/check-formatting.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -x 5 | 6 | clang-format-6.0 -i $(find . -name "*.[ch]" | tr '\n' ' ') && git diff --exit-code || (echo 'Code was not formatted using clang-format!'; false) 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | charset = utf-8 7 | 8 | [*.{c,h}] 9 | indent_style = space 10 | indent_size = 4 11 | trim_trailing_whitespace = true 12 | -------------------------------------------------------------------------------- /AnyEvent-I3/MANIFEST.SKIP: -------------------------------------------------------------------------------- 1 | ^\.git/ 2 | \.bak$ 3 | blib/ 4 | ^Makefile$ 5 | ^Makefile.old$ 6 | Build 7 | Build.bat 8 | ^pm_to_blib 9 | \.tar\.gz$ 10 | ^pod2htm(.*).tmp$ 11 | ^AnyEvent-I3- 12 | ^MYMETA.* 13 | ^MANIFEST\.bak 14 | -------------------------------------------------------------------------------- /share/xsessions/i3-with-shmlog.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=i3 (with debug log) 3 | Comment=improved dynamic tiling window manager 4 | Exec=i3-with-shmlog 5 | Type=Application 6 | Keywords=tiling;wm;windowmanager;window;manager; 7 | -------------------------------------------------------------------------------- /AnyEvent-I3/t/00-load.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | 3 | use Test::More tests => 1; 4 | 5 | BEGIN { 6 | use_ok( 'AnyEvent::I3' ) || print "Bail out! 7 | "; 8 | } 9 | 10 | diag( "Testing AnyEvent::I3 $AnyEvent::I3::VERSION, Perl $], $^X" ); 11 | -------------------------------------------------------------------------------- /AnyEvent-I3/MANIFEST: -------------------------------------------------------------------------------- 1 | Changes 2 | lib/AnyEvent/I3.pm 3 | Makefile.PL 4 | MANIFEST This list of files 5 | MANIFEST.SKIP 6 | README 7 | t/00-load.t 8 | t/01-workspaces.t 9 | t/02-sugar.t 10 | t/boilerplate.t 11 | t/manifest.t 12 | t/pod-coverage.t 13 | t/pod.t 14 | -------------------------------------------------------------------------------- /share/xsessions/i3.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=i3 3 | Comment=improved dynamic tiling window manager 4 | Exec=i3 5 | TryExec=i3 6 | Type=Application 7 | X-LightDM-DesktopName=i3 8 | DesktopNames=i3 9 | Keywords=tiling;wm;windowmanager;window;manager; 10 | -------------------------------------------------------------------------------- /AnyEvent-I3/t/pod.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | 3 | use strict; 4 | use warnings; 5 | use Test::More; 6 | 7 | # Ensure a recent version of Test::Pod 8 | my $min_tp = 1.22; 9 | eval "use Test::Pod $min_tp"; 10 | plan skip_all => "Test::Pod $min_tp required for testing POD" if $@; 11 | 12 | all_pod_files_ok(); 13 | -------------------------------------------------------------------------------- /debian/i3-wm.doc-base: -------------------------------------------------------------------------------- 1 | Document: i3-wm 2 | Title: i3 documentation 3 | Author: Michael Stapelberg 4 | Abstract: The documentation explains how to use and modify the i3 window 5 | manager. 6 | Section: Window Managers 7 | 8 | Format: HTML 9 | Files: /usr/share/doc/i3-wm/*.html 10 | Index: /usr/share/doc/i3-wm/userguide.html 11 | -------------------------------------------------------------------------------- /debian/i3-wm.manpages: -------------------------------------------------------------------------------- 1 | man/i3.1 2 | man/i3-msg.1 3 | man/i3-input.1 4 | man/i3-nagbar.1 5 | man/i3-config-wizard.1 6 | man/i3-dump-log.1 7 | man/i3-migrate-config-to-v4.1 8 | man/i3-sensible-pager.1 9 | man/i3-sensible-editor.1 10 | man/i3-sensible-terminal.1 11 | man/i3-dmenu-desktop.1 12 | man/i3-save-tree.1 13 | man/i3bar.1 14 | -------------------------------------------------------------------------------- /i3-input/i3-input.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #define die(...) errx(EXIT_FAILURE, __VA_ARGS__); 8 | #define FREE(pointer) \ 9 | do { \ 10 | free(pointer); \ 11 | pointer = NULL; \ 12 | } while (0) 13 | 14 | extern xcb_window_t root; 15 | -------------------------------------------------------------------------------- /debian/i3-wm.install: -------------------------------------------------------------------------------- 1 | debian/tmp/etc 2 | debian/tmp/usr 3 | contrib/dump-asy.pl usr/share/doc/i3-wm/examples/ 4 | contrib/gtk-tree-watch.pl usr/share/doc/i3-wm/examples/ 5 | contrib/i3-wsbar usr/share/doc/i3-wm/examples/ 6 | contrib/per-workspace-layout.pl usr/share/doc/i3-wm/examples/ 7 | contrib/trivial-bar-script.sh usr/share/doc/i3-wm/examples/ 8 | -------------------------------------------------------------------------------- /share/applications/i3.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Name=i3 4 | NoDisplay=true 5 | GenericName=A dynamic tiling window manager 6 | Comment=improved dynamic tiling window manager 7 | Exec=i3 8 | X-GNOME-WMName=i3 9 | X-GNOME-Autostart-Phase=WindowManager 10 | X-GNOME-Provides=windowmanager 11 | X-GNOME-Autostart-Notify=false 12 | -------------------------------------------------------------------------------- /AnyEvent-I3/t/manifest.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | 3 | use strict; 4 | use warnings; 5 | use Test::More; 6 | 7 | unless ( $ENV{RELEASE_TESTING} ) { 8 | plan( skip_all => "Author tests not required for installation" ); 9 | } 10 | 11 | eval "use Test::CheckManifest 0.9"; 12 | plan skip_all => "Test::CheckManifest 0.9 required" if $@; 13 | ok_manifest(); 14 | -------------------------------------------------------------------------------- /travis/ha.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Returns a hash to be used as version number suffix for the i3/travis-base 3 | # docker container. The hash is over all files which influence what gets 4 | # installed in the container, so that any changes in what needs to be installed 5 | # will result in a cache invalidation. 6 | 7 | cat debian/control "$1" | sha256sum | dd bs=1 count=8 status=none 8 | -------------------------------------------------------------------------------- /include/cmdparse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * cmdparse.y: the parser for commands you send to i3 (or bind on keys) 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | char *parse_cmd(const char *new); 15 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: google 2 | AllowShortIfStatementsOnASingleLine: false 3 | AllowShortLoopsOnASingleLine: false 4 | AllowShortFunctionsOnASingleLine: None 5 | AllowShortBlocksOnASingleLine: false 6 | AlwaysBreakBeforeMultilineStrings: false 7 | IndentWidth: 4 8 | PointerBindsToType: false 9 | ColumnLimit: 0 10 | SpaceBeforeParens: ControlStatements 11 | SortIncludes: false 12 | -------------------------------------------------------------------------------- /include/sync.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * sync.c: i3 sync protocol: https://i3wm.org/docs/testsuite.html#i3_sync 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | void sync_respond(xcb_window_t window, uint32_t rnd); 15 | -------------------------------------------------------------------------------- /i3bar/include/xcb_atoms.def: -------------------------------------------------------------------------------- 1 | ATOM_DO(_NET_WM_WINDOW_TYPE) 2 | ATOM_DO(_NET_WM_WINDOW_TYPE_DOCK) 3 | ATOM_DO(_NET_WM_STRUT_PARTIAL) 4 | ATOM_DO(I3_SOCKET_PATH) 5 | ATOM_DO(MANAGER) 6 | ATOM_DO(_NET_SYSTEM_TRAY_ORIENTATION) 7 | ATOM_DO(_NET_SYSTEM_TRAY_VISUAL) 8 | ATOM_DO(_NET_SYSTEM_TRAY_OPCODE) 9 | ATOM_DO(_NET_SYSTEM_TRAY_COLORS) 10 | ATOM_DO(_XEMBED_INFO) 11 | ATOM_DO(_XEMBED) 12 | ATOM_DO(I3_SYNC) 13 | #undef ATOM_DO 14 | -------------------------------------------------------------------------------- /src/version.c: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * Stores the latest Git commit identifier so that it can be linked into i3 8 | * and used dynamically without recompiling every object file. 9 | * 10 | */ 11 | #include 12 | 13 | const char *i3_version = I3_VERSION; 14 | -------------------------------------------------------------------------------- /i3-nagbar/i3-nagbar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #define die(...) errx(EXIT_FAILURE, __VA_ARGS__); 8 | #define FREE(pointer) \ 9 | do { \ 10 | free(pointer); \ 11 | pointer = NULL; \ 12 | } while (0) 13 | 14 | #define xmacro(atom) xcb_atom_t A_##atom; 15 | #include "atoms.xmacro" 16 | #undef xmacro 17 | 18 | extern xcb_window_t root; 19 | -------------------------------------------------------------------------------- /include/sighandler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | */ 8 | #pragma once 9 | 10 | #include 11 | 12 | /** 13 | * Configured a signal handler to gracefully handle crashes and allow the user 14 | * to generate a backtrace and rescue their session. 15 | * 16 | */ 17 | void setup_signal_handler(void); 18 | -------------------------------------------------------------------------------- /travis/skip-pkg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Returns true if Debian/Ubuntu packages should be skipped because this CI run 3 | # was triggered by a pull request. 4 | 5 | # Verify BINTRAY_USER is present (only set on github.com/i3/i3), 6 | # otherwise the CI run was triggered by a pull request. 7 | # Verify CC=gcc so that we only build packages once for each commit, 8 | # not twice (with gcc and clang). 9 | if [ ! -z "$BINTRAY_USER" ] && [ "$CC" = "gcc" ] 10 | then 11 | exit 1 12 | fi 13 | 14 | exit 0 15 | -------------------------------------------------------------------------------- /travis/debian-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -x 5 | 6 | DEST=$1 7 | 8 | mkdir -p build 9 | cd build 10 | ../configure 11 | make echo-version > ../I3_VERSION 12 | make dist-bzip2 13 | # unpack dist tarball 14 | mkdir -p "${DEST}" 15 | tar xf *.tar.bz2 -C "${DEST}" --strip-components=1 16 | cp -r ../debian "${DEST}" 17 | sed -i '/^\s*libxcb-xrm-dev/d' deb/ubuntu-*/DIST/debian/control || true 18 | cd "${DEST}" 19 | debchange -m -l+g$(git describe --tags) 'Automatically built' 20 | dpkg-buildpackage -b 21 | -------------------------------------------------------------------------------- /testcases/t/000-load-deps.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | 4 | use Test::More; 5 | 6 | BEGIN { 7 | my @deps = qw( 8 | X11::XCB::Connection 9 | X11::XCB::Window 10 | AnyEvent 11 | IPC::Run 12 | ExtUtils::PkgConfig 13 | Inline 14 | ); 15 | for my $dep (@deps) { 16 | use_ok($dep) or BAIL_OUT(qq|The Perl module "$dep" could not be loaded. Please see https://build.i3wm.org/docs/testsuite.html#_installing_the_dependencies|); 17 | } 18 | } 19 | 20 | done_testing; 21 | -------------------------------------------------------------------------------- /include/main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * main.c: Initialization, main loop 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | /** 15 | * Enable or disable the main X11 event handling function. 16 | * This is used by drag_pointer() which has its own, modal event handler, which 17 | * takes precedence over the normal event handler. 18 | * 19 | */ 20 | void main_set_x11_cb(bool enable); 21 | -------------------------------------------------------------------------------- /include/atoms_rest.xmacro: -------------------------------------------------------------------------------- 1 | xmacro(_NET_WM_USER_TIME) 2 | xmacro(_NET_STARTUP_ID) 3 | xmacro(_NET_WORKAREA) 4 | xmacro(WM_PROTOCOLS) 5 | xmacro(WM_DELETE_WINDOW) 6 | xmacro(UTF8_STRING) 7 | xmacro(WM_STATE) 8 | xmacro(WM_CLIENT_LEADER) 9 | xmacro(WM_TAKE_FOCUS) 10 | xmacro(WM_WINDOW_ROLE) 11 | xmacro(I3_SOCKET_PATH) 12 | xmacro(I3_CONFIG_PATH) 13 | xmacro(I3_SYNC) 14 | xmacro(I3_SHMLOG_PATH) 15 | xmacro(I3_PID) 16 | xmacro(I3_FLOATING_WINDOW) 17 | xmacro(_NET_REQUEST_FRAME_EXTENTS) 18 | xmacro(_NET_FRAME_EXTENTS) 19 | xmacro(_MOTIF_WM_HINTS) 20 | xmacro(WM_CHANGE_STATE) 21 | -------------------------------------------------------------------------------- /man/asciidoc.conf.in: -------------------------------------------------------------------------------- 1 | ifdef::doctype-manpage[] 2 | ifdef::backend-docbook[] 3 | [header] 4 | template::[header-declarations] 5 | 6 | 7 | {mantitle} 8 | {manvolnum} 9 | i3 10 | @PACKAGE_VERSION@ 11 | i3 Manual 12 | 13 | 14 | {manname} 15 | {manpurpose} 16 | 17 | endif::backend-docbook[] 18 | endif::doctype-manpage[] 19 | -------------------------------------------------------------------------------- /parser-specs/highlighting.vim: -------------------------------------------------------------------------------- 1 | set filetype=i3cmd 2 | syntax case match 3 | syntax clear 4 | 5 | syntax keyword i3specStatement state call 6 | highlight link i3specStatement Statement 7 | 8 | syntax match i3specComment /#.*/ 9 | highlight link i3specComment Comment 10 | 11 | syntax region i3specLiteral start=/'/ end=/'/ 12 | syntax keyword i3specToken string word number end 13 | highlight link i3specLiteral String 14 | highlight link i3specToken String 15 | 16 | syntax match i3specState /[A-Z_]\{3,}/ 17 | highlight link i3specState PreProc 18 | 19 | syntax match i3specSpecial /[->]/ 20 | highlight link i3specSpecial Special 21 | -------------------------------------------------------------------------------- /include/click.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * click.c: Button press (mouse click) events. 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | /** 15 | * The button press X callback. This function determines whether the floating 16 | * modifier is pressed and where the user clicked (decoration, border, inside 17 | * the window). 18 | * 19 | * Then, route_click is called on the appropriate con. 20 | * 21 | */ 22 | int handle_button_press(xcb_button_press_event_t *event); 23 | -------------------------------------------------------------------------------- /AnyEvent-I3/t/pod-coverage.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Test::More; 4 | 5 | # Ensure a recent version of Test::Pod::Coverage 6 | my $min_tpc = 1.08; 7 | eval "use Test::Pod::Coverage $min_tpc"; 8 | plan skip_all => "Test::Pod::Coverage $min_tpc required for testing POD coverage" 9 | if $@; 10 | 11 | # Test::Pod::Coverage doesn't require a minimum Pod::Coverage version, 12 | # but older versions don't recognize some common documentation styles 13 | my $min_pc = 0.18; 14 | eval "use Pod::Coverage $min_pc"; 15 | plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage" 16 | if $@; 17 | 18 | all_pod_coverage_ok(); 19 | -------------------------------------------------------------------------------- /i3-sensible-editor: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # This code is released in public domain by Han Boetes 4 | # 5 | # This script tries to exec an editor by trying some known editors if $EDITOR is 6 | # not set. 7 | # 8 | # Distributions/packagers can enhance this script with a distribution-specific 9 | # mechanism to find the preferred editor 10 | 11 | # Hopefully one of these is installed (no flamewars about preference please!): 12 | for editor in "$VISUAL" "$EDITOR" nano nvim vim vi emacs pico qe mg jed gedit mcedit gvim; do 13 | if command -v "$editor" > /dev/null 2>&1; then 14 | exec "$editor" "$@" 15 | fi 16 | done 17 | -------------------------------------------------------------------------------- /testcases/t/134-invalid-command.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # 5 | # Please read the following documents before working on tests: 6 | # • https://build.i3wm.org/docs/testsuite.html 7 | # (or docs/testsuite) 8 | # 9 | # • https://build.i3wm.org/docs/lib-i3test.html 10 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 11 | # 12 | # • https://build.i3wm.org/docs/ipc.html 13 | # (or docs/ipc) 14 | # 15 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 16 | # (unless you are already familiar with Perl) 17 | # 18 | # 19 | use i3test; 20 | 21 | cmd 'blargh!'; 22 | 23 | does_i3_live; 24 | 25 | done_testing; 26 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # vi: ts=8 sw=8 noet 3 | 4 | export V:=1 5 | export DEB_BUILD_MAINT_OPTIONS = hardening=+all 6 | 7 | override_dh_installchangelogs: 8 | dh_installchangelogs RELEASE-NOTES-* 9 | 10 | override_dh_strip: 11 | dh_strip --dbg-package=i3-wm-dbg 12 | 13 | override_dh_auto_test: 14 | # TODO: enable tests 15 | 16 | override_dh_auto_configure: 17 | # The default is /usr/share/doc/i3 18 | dh_auto_configure -- --docdir=/usr/share/doc/i3-wm 19 | 20 | override_dh_builddeb: 21 | # bintray does not support xz currently. 22 | dh_builddeb -- -Zgzip 23 | 24 | %: 25 | dh $@ --parallel --builddirectory=build --with=autoreconf 26 | -------------------------------------------------------------------------------- /travis/deploy-github-pages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -x 5 | 6 | GITVERSION=$(git describe --tags) 7 | 8 | mkdir build.i3wm.org 9 | cp -r deb/COPY-DOCS build.i3wm.org/docs 10 | cd build.i3wm.org 11 | echo build.i3wm.org > CNAME 12 | git init 13 | 14 | git config user.name "Travis CI" 15 | git config user.email "i3bot@i3wm.org" 16 | git add . 17 | git commit -m "Publish docs/static analysis for github.com/i3/i3 v${GITVERSION}" 18 | 19 | # Hide stdout/stderr because it might contain sensitive info. 20 | set +x 21 | echo "git push" 22 | git push --force --quiet "https://${GH_TOKEN}@github.com/i3/build.i3wm.org.git" master:gh-pages >/dev/null 2>&1 23 | -------------------------------------------------------------------------------- /i3bar/include/trayclients.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3bar - an xcb-based status- and ws-bar for i3 5 | * © 2010 Axel Wagner and contributors (see also: LICENSE) 6 | * 7 | */ 8 | #pragma once 9 | 10 | #include "common.h" 11 | 12 | typedef struct trayclient trayclient; 13 | 14 | TAILQ_HEAD(tc_head, trayclient); 15 | 16 | struct trayclient { 17 | xcb_window_t win; /* The window ID of the tray client */ 18 | bool mapped; /* Whether this window is mapped */ 19 | int xe_version; /* The XEMBED version supported by the client */ 20 | 21 | TAILQ_ENTRY(trayclient) 22 | tailq; /* Pointer for the TAILQ-Macro */ 23 | }; 24 | -------------------------------------------------------------------------------- /libi3/README: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | libi3 is an *INTERNAL* library which contains functions that i3 and related 5 | tools (i3-msg, i3-input, i3-nagbar, i3-config-wizard, i3bar) use. 6 | 7 | It is NOT to be used by other programs. 8 | 9 | Structure 10 | ========= 11 | 12 | Every function gets its own .c file, which in turn gets compiled into an .o 13 | object file. Afterwards, all .o files are archived into one static library 14 | (libi3.a). This library will be linked into all i3 binaries. The linker is able 15 | to eliminate unused .o files when linking, so only the functions which you 16 | actually use will be included in the corresponding binary. 17 | -------------------------------------------------------------------------------- /i3bar/include/mode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3bar - an xcb-based status- and ws-bar for i3 5 | * © 2010 Axel Wagner and contributors (see also: LICENSE) 6 | * 7 | * mode.c: Handle "mode" event and show current binding mode in the bar 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | #include 15 | 16 | #include "common.h" 17 | 18 | /* Name of current binding mode and its render width */ 19 | struct mode { 20 | i3String *name; 21 | int width; 22 | }; 23 | 24 | typedef struct mode mode; 25 | 26 | /* 27 | * Start parsing the received JSON string 28 | * 29 | */ 30 | void parse_mode_json(char *json); 31 | -------------------------------------------------------------------------------- /travis/docker-build-and-push.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | BASENAME=$1 6 | DOCKERFILE=$2 7 | 8 | # .dockerignore is created on demand so that release.sh and other scripts are 9 | # not influenced by our travis setup. 10 | echo .git > .dockerignore 11 | 12 | docker build --pull --no-cache --rm -t=${BASENAME} -f ${DOCKERFILE} . 13 | # For pull requests, travis does not add secure environment variables to the 14 | # environment (because pull requests could then steal their values), so skip 15 | # the login+push step when the variable isn’t set. 16 | if [ -n "${DOCKER_PASS}" ] 17 | then 18 | docker login -u ${DOCKER_USER} -p ${DOCKER_PASS} 19 | docker push ${BASENAME} 20 | fi 21 | -------------------------------------------------------------------------------- /include/xinerama.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * This is LEGACY code (we support RandR, which can do much more than 8 | * Xinerama), but necessary for the poor users of the nVidia binary 9 | * driver which does not support RandR in 2011 *sigh*. 10 | * 11 | */ 12 | #pragma once 13 | 14 | #include 15 | 16 | #include "data.h" 17 | 18 | /** 19 | * We have just established a connection to the X server and need the initial 20 | * Xinerama information to setup workspaces for each screen. 21 | * 22 | */ 23 | void xinerama_init(void); 24 | -------------------------------------------------------------------------------- /testcases/t/002-i3-sync.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # checks if i3 supports I3_SYNC 18 | # 19 | use i3test; 20 | 21 | my $result = sync_with_i3; 22 | ok($result, 'syncing was successful'); 23 | 24 | done_testing; 25 | -------------------------------------------------------------------------------- /travis/check-safe-wrappers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | funcs='malloc|calloc|realloc|strdup|strndup|asprintf|write' 3 | cstring='"([^"\\]|\\.)*"' 4 | cchar="'[^\\\\]'|'\\\\.[^']*'" 5 | regex="^([^'\"]|${cstring}|${cchar})*\<(${funcs})\>" 6 | detected=0 7 | while IFS= read -r file; do 8 | if { cpp -w -fpreprocessed "$file" || exit "$?"; } | grep -E -- "$regex"; then 9 | echo "^ $file calls a function that has a safe counterpart." 10 | detected=1 11 | fi 12 | done << EOF 13 | $(find -name '*.c' -not -name safewrappers.c -not -name strndup.c) 14 | EOF 15 | if [ "$detected" -ne 0 ]; then 16 | echo 17 | echo "Calls of functions that have safe counterparts were detected." 18 | exit 1 19 | fi 20 | -------------------------------------------------------------------------------- /include/assignments.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * assignments.c: Assignments for specific windows (for_window). 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | /** 15 | * Checks the list of assignments for the given window and runs all matching 16 | * ones (unless they have already been run for this specific window). 17 | * 18 | */ 19 | void run_assignments(i3Window *window); 20 | 21 | /** 22 | * Returns the first matching assignment for the given window. 23 | * 24 | */ 25 | Assignment *assignment_for(i3Window *window, int type); 26 | -------------------------------------------------------------------------------- /include/yajl_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * yajl_utils.h 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | /* Shorter names for all those yajl_gen_* functions */ 19 | #define y(x, ...) yajl_gen_##x(gen, ##__VA_ARGS__) 20 | #define ystr(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str)) 21 | 22 | #define ygenalloc() yajl_gen_alloc(NULL) 23 | #define yalloc(callbacks, client) yajl_alloc(callbacks, NULL, client) 24 | typedef size_t ylength; 25 | -------------------------------------------------------------------------------- /include/fake_outputs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * Faking outputs is useful in pathological situations (like network X servers 8 | * which don’t support multi-monitor in a useful way) and for our testsuite. 9 | * 10 | */ 11 | #pragma once 12 | 13 | #include 14 | 15 | /** 16 | * Creates outputs according to the given specification. 17 | * The specification must be in the format wxh+x+y, for example 1024x768+0+0, 18 | * with multiple outputs separated by commas: 19 | * 1900x1200+0+0,1280x1024+1900+0 20 | * 21 | */ 22 | void fake_outputs_init(const char *output_spec); 23 | -------------------------------------------------------------------------------- /i3-sensible-pager: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # This code is released in public domain by Han Boetes 4 | 5 | # This script tries to exec a pager by trying some known pagers if $PAGER is 6 | # not set. 7 | # 8 | # Distributions/packagers can enhance this script with a 9 | # distribution-specific mechanism to find the preferred pager. 10 | 11 | # Hopefully one of these is installed (no flamewars about preference please!): 12 | # We don't use 'more' because it will exit if the file is too short. 13 | # Worst case scenario we'll open the file in your editor. 14 | for pager in "$PAGER" less most w3m pg i3-sensible-editor; do 15 | if command -v "$pager" > /dev/null 2>&1; then 16 | exec "$pager" "$@" 17 | fi 18 | done 19 | -------------------------------------------------------------------------------- /man/i3-sensible-pager.man: -------------------------------------------------------------------------------- 1 | i3-sensible-pager(1) 2 | ==================== 3 | Michael Stapelberg 4 | v4.1, November 2011 5 | 6 | == NAME 7 | 8 | i3-sensible-pager - launches $PAGER with fallbacks 9 | 10 | == SYNOPSIS 11 | 12 | i3-sensible-pager [arguments] 13 | 14 | == DESCRIPTION 15 | 16 | i3-sensible-pager is used by i3-nagbar(1) when you click on the view button. 17 | 18 | It tries to start one of the following (in that order): 19 | 20 | * $PAGER 21 | * less 22 | * most 23 | * w3m 24 | * i3-sensible-editor(1) 25 | 26 | Please don’t complain about the order: If the user has any preference, they will 27 | have $PAGER set. 28 | 29 | == SEE ALSO 30 | 31 | i3(1) 32 | 33 | == AUTHOR 34 | 35 | Michael Stapelberg and contributors 36 | -------------------------------------------------------------------------------- /testcases/valgrind.supp: -------------------------------------------------------------------------------- 1 | # 2 | # Valgrind suppression file for i3 testcases 3 | # 4 | # Format specification: 5 | # http://valgrind.org/docs/manual/manual-core.html#manual-core.suppress 6 | # 7 | 8 | # 9 | # GLib 10 | # 11 | { 12 | Ignore fundamental GType registration 13 | Memcheck:Leak 14 | ... 15 | fun:g_type_register_fundamental 16 | ... 17 | } 18 | 19 | { 20 | Ignore static GType registration 21 | Memcheck:Leak 22 | match-leak-kinds: possible 23 | ... 24 | fun:g_type_register_static 25 | ... 26 | } 27 | 28 | { 29 | Ignore GObject init function 30 | Memcheck:Leak 31 | match-leak-kinds: possible 32 | ... 33 | obj:/usr/lib/libgobject-2.0* 34 | ... 35 | fun:call_init.part.0 36 | ... 37 | } 38 | -------------------------------------------------------------------------------- /include/move.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * move.c: Moving containers into some direction. 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | /** 15 | * Moves the given container in the given direction (TOK_LEFT, TOK_RIGHT, 16 | * TOK_UP, TOK_DOWN from cmdparse.l) 17 | * 18 | */ 19 | void tree_move(Con *con, int direction); 20 | 21 | typedef enum { BEFORE, 22 | AFTER } position_t; 23 | 24 | /** 25 | * This function detaches 'con' from its parent and inserts it either before or 26 | * after 'target'. 27 | * 28 | */ 29 | void insert_con_into(Con *con, Con *target, position_t position); 30 | -------------------------------------------------------------------------------- /libi3/strndup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | */ 8 | #include "libi3.h" 9 | 10 | #include 11 | #include 12 | 13 | #if defined(__APPLE__) 14 | 15 | /* 16 | * Taken from FreeBSD 17 | * Returns a pointer to a new string which is a duplicate of the 18 | * string, but only copies at most n characters. 19 | * 20 | */ 21 | char *strndup(const char *str, size_t n) { 22 | size_t len; 23 | char *copy; 24 | 25 | for (len = 0; len < n && str[len]; len++) 26 | continue; 27 | 28 | copy = smalloc(len + 1); 29 | memcpy(copy, str, len); 30 | copy[len] = '\0'; 31 | return (copy); 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /debian/i3-wm.docs: -------------------------------------------------------------------------------- 1 | docs/debugging.html 2 | docs/hacking-howto.html 3 | docs/i3bar-protocol.html 4 | docs/userguide.html 5 | docs/bigpicture.png 6 | docs/single_terminal.png 7 | docs/snapping.png 8 | docs/two_columns.png 9 | docs/two_terminals.png 10 | docs/modes.png 11 | docs/ipc.html 12 | docs/multi-monitor.html 13 | docs/wsbar.html 14 | docs/wsbar.png 15 | docs/keyboard-layer1.png 16 | docs/keyboard-layer2.png 17 | docs/testsuite.html 18 | docs/i3-sync-working.png 19 | docs/i3-sync.png 20 | docs/tree-layout1.png 21 | docs/tree-layout2.png 22 | docs/tree-shot1.png 23 | docs/tree-shot2.png 24 | docs/tree-shot3.png 25 | docs/tree-shot4.png 26 | docs/refcard.html 27 | docs/refcard_style.css 28 | docs/logo-30.png 29 | docs/lib-i3test.html 30 | docs/lib-i3test-test.html 31 | docs/layout-saving.html 32 | docs/layout-saving-1.png 33 | -------------------------------------------------------------------------------- /testcases/t/151-regress-float-size.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression test for setting a window to floating, tiling and opening a new window 18 | # 19 | use i3test; 20 | 21 | fresh_workspace; 22 | 23 | cmd 'open'; 24 | cmd 'mode toggle'; 25 | cmd 'mode toggle'; 26 | cmd 'open'; 27 | 28 | does_i3_live; 29 | 30 | done_testing; 31 | -------------------------------------------------------------------------------- /testcases/t/126-regress-close.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression: closing of floating clients did crash i3 when closing the 18 | # container which contained this client. 19 | # 20 | use i3test; 21 | 22 | fresh_workspace; 23 | 24 | cmd 'open'; 25 | cmd 'mode toggle'; 26 | cmd 'kill'; 27 | cmd 'kill'; 28 | 29 | does_i3_live; 30 | 31 | done_testing; 32 | -------------------------------------------------------------------------------- /testcases/t/152-regress-level-up.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression test for using level-up to get to the 'content'-container and 18 | # toggle floating 19 | # 20 | use i3test; 21 | 22 | fresh_workspace; 23 | 24 | cmd 'open'; 25 | cmd 'focus parent'; 26 | cmd 'focus parent'; 27 | cmd 'mode toggle'; 28 | 29 | does_i3_live; 30 | 31 | done_testing; 32 | -------------------------------------------------------------------------------- /testcases/t/267-regress-mark-restart.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression test to check if mark and restart commands crash i3 18 | # 19 | use i3test; 20 | 21 | cmd 'open'; 22 | cmd 'mark foo'; 23 | cmd 'open'; 24 | cmd 'mark bar'; 25 | 26 | cmd 'restart'; 27 | 28 | diag('Checking if i3 still lives'); 29 | 30 | does_i3_live; 31 | 32 | done_testing; 33 | -------------------------------------------------------------------------------- /testcases/t/142-regress-move-floating.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression: move a floating window to a different workspace crashes i3 18 | # 19 | use i3test; 20 | 21 | my $tmp = fresh_workspace; 22 | my $otmp = get_unused_workspace(); 23 | 24 | cmd 'open'; 25 | cmd 'mode toggle'; 26 | cmd "move workspace $otmp"; 27 | 28 | does_i3_live; 29 | 30 | done_testing; 31 | -------------------------------------------------------------------------------- /AnyEvent-I3/t/01-workspaces.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | # vim:ts=4:sw=4:expandtab 3 | 4 | use Test::More tests => 3; 5 | use AnyEvent::I3; 6 | use AnyEvent; 7 | 8 | my $i3 = i3(); 9 | my $cv = AnyEvent->condvar; 10 | 11 | # Try to connect to i3 12 | $i3->connect->cb(sub { my ($v) = @_; $cv->send($v->recv) }); 13 | 14 | # But cancel if we are not connected after 0.5 seconds 15 | my $t = AnyEvent->timer(after => 0.5, cb => sub { $cv->send(0) }); 16 | my $connected = $cv->recv; 17 | 18 | SKIP: { 19 | skip 'No connection to i3', 3 unless $connected; 20 | 21 | my $workspaces = $i3->message(1)->recv; 22 | isa_ok($workspaces, 'ARRAY'); 23 | 24 | ok(@{$workspaces} > 0, 'More than zero workspaces found'); 25 | 26 | ok(defined(@{$workspaces}[0]->{num}), 'JSON deserialized'); 27 | } 28 | 29 | diag( "Testing AnyEvent::I3 $AnyEvent::I3::VERSION, Perl $], $^X" ); 30 | -------------------------------------------------------------------------------- /AnyEvent-I3/t/02-sugar.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | # vim:ts=4:sw=4:expandtab 3 | 4 | use Test::More tests => 3; 5 | use AnyEvent::I3; 6 | use AnyEvent; 7 | 8 | my $i3 = i3(); 9 | my $cv = AnyEvent->condvar; 10 | 11 | # Try to connect to i3 12 | $i3->connect->cb(sub { my ($v) = @_; $cv->send($v->recv) }); 13 | 14 | # But cancel if we are not connected after 0.5 seconds 15 | my $t = AnyEvent->timer(after => 0.5, cb => sub { $cv->send(0) }); 16 | my $connected = $cv->recv; 17 | 18 | SKIP: { 19 | skip 'No connection to i3', 3 unless $connected; 20 | 21 | my $workspaces = i3->get_workspaces->recv; 22 | isa_ok($workspaces, 'ARRAY'); 23 | 24 | ok(@{$workspaces} > 0, 'More than zero workspaces found'); 25 | 26 | ok(defined(@{$workspaces}[0]->{num}), 'JSON deserialized'); 27 | } 28 | 29 | diag( "Testing AnyEvent::I3 $AnyEvent::I3::VERSION, Perl $], $^X" ); 30 | -------------------------------------------------------------------------------- /testcases/t/260-invalid-criteria.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Ticket: #2091 18 | use i3test; 19 | 20 | my $ws = fresh_workspace; 21 | open_window; 22 | 23 | my $result = cmd '[con_id=foobar] kill'; 24 | is($result->[0]->{success}, 0, 'command was unsuccessful'); 25 | is($result->[0]->{error}, 'Invalid match: invalid con_id', 'correct error is returned'); 26 | 27 | done_testing; 28 | -------------------------------------------------------------------------------- /man/i3-sensible-editor.man: -------------------------------------------------------------------------------- 1 | i3-sensible-editor(1) 2 | ===================== 3 | Michael Stapelberg 4 | v4.1, November 2011 5 | 6 | == NAME 7 | 8 | i3-sensible-editor - launches $EDITOR with fallbacks 9 | 10 | == SYNOPSIS 11 | 12 | i3-sensible-editor [arguments] 13 | 14 | == DESCRIPTION 15 | 16 | i3-sensible-editor is used by i3-nagbar(1) when you click on the edit button. 17 | 18 | It tries to start one of the following (in that order): 19 | 20 | * $VISUAL 21 | * $EDITOR 22 | * nano 23 | * nvim 24 | * vim 25 | * vi 26 | * emacs 27 | * pico 28 | * qe 29 | * mg 30 | * jed 31 | * gedit 32 | * mcedit 33 | * gvim 34 | 35 | Please don’t complain about the order: If the user has any preference, they will 36 | have $VISUAL or $EDITOR set. 37 | 38 | == SEE ALSO 39 | 40 | i3(1) 41 | 42 | == AUTHOR 43 | 44 | Michael Stapelberg and contributors 45 | -------------------------------------------------------------------------------- /testcases/t/224-regress-resize-branch.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Test that i3 does not crash when resizing a split container 18 | # Ticket: #1220 19 | # Bug still in: 4.7.2-128-g702906d 20 | use i3test; 21 | 22 | open_window; 23 | open_window; 24 | 25 | cmd 'split h'; 26 | 27 | open_window; 28 | 29 | cmd 'focus parent, resize grow left'; 30 | 31 | does_i3_live; 32 | 33 | done_testing; 34 | -------------------------------------------------------------------------------- /man/i3-dump-log.man: -------------------------------------------------------------------------------- 1 | i3-dump-log(1) 2 | ============== 3 | Michael Stapelberg 4 | v4.6, September 2013 5 | 6 | == NAME 7 | 8 | i3-dump-log - dumps the i3 SHM log 9 | 10 | == SYNOPSIS 11 | 12 | i3-dump-log [-s ] [-f] 13 | 14 | == DESCRIPTION 15 | 16 | Debug versions of i3 automatically use 1% of your RAM (but 25 MiB max) to store 17 | full debug log output. This is extremely helpful for bugreports and 18 | figuring out what is going on, without permanently logging to a file. 19 | 20 | With i3-dump-log, you can dump the SHM log to stdout. 21 | 22 | The -f flag works like tail -f, i.e. the process does not terminate after 23 | dumping the log, but prints new lines as they appear. 24 | 25 | == EXAMPLE 26 | 27 | i3-dump-log | gzip -9 > /tmp/i3-log.gz 28 | 29 | == SEE ALSO 30 | 31 | i3(1) 32 | 33 | == AUTHOR 34 | 35 | Michael Stapelberg and contributors 36 | -------------------------------------------------------------------------------- /testcases/t/273-regress-focus-toggle.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression: Checks if i3 still lives after using 'focus mode_toggle' on an 18 | # empty workspace. This regression was fixed in 19 | # 0848844f2d41055f6ffc69af1149d7a873460976. 20 | # 21 | use i3test; 22 | use v5.10; 23 | 24 | my $tmp = fresh_workspace; 25 | 26 | cmd 'focus mode_toggle'; 27 | 28 | does_i3_live; 29 | 30 | done_testing; 31 | -------------------------------------------------------------------------------- /i3-sensible-terminal: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # This code is released in public domain by Han Boetes 4 | # 5 | # This script tries to exec a terminal emulator by trying some known terminal 6 | # emulators. 7 | # 8 | # We welcome patches that add distribution-specific mechanisms to find the 9 | # preferred terminal emulator. On Debian, there is the x-terminal-emulator 10 | # symlink for example. 11 | for terminal in "$TERMINAL" x-terminal-emulator urxvt rxvt termit terminator Eterm aterm uxterm xterm gnome-terminal roxterm xfce4-terminal termite lxterminal mate-terminal terminology st qterminal lilyterm tilix terminix konsole kitty guake tilda alacritty hyper; do 12 | if command -v "$terminal" > /dev/null 2>&1; then 13 | exec "$terminal" "$@" 14 | fi 15 | done 16 | 17 | i3-nagbar -m 'i3-sensible-terminal could not find a terminal emulator. Please install one.' 18 | -------------------------------------------------------------------------------- /testcases/t/168-regress-fullscreen-restart.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Verifies that i3 survives inplace restarts with fullscreen containers 18 | # 19 | use i3test; 20 | 21 | fresh_workspace; 22 | 23 | open_window; 24 | open_window; 25 | 26 | cmd 'layout stacking'; 27 | sync_with_i3; 28 | 29 | cmd 'fullscreen'; 30 | sync_with_i3; 31 | 32 | cmd 'restart'; 33 | 34 | does_i3_live; 35 | 36 | done_testing; 37 | -------------------------------------------------------------------------------- /testcases/t/292-regress-layout-toggle.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression test: verify layout toggle with invalid parameters does not set 18 | # layout to L_DEFAULT, which crashes i3 upon the next IPC message. 19 | # Ticket: #2903 20 | # Bug still in: 4.14-87-g607e97e6 21 | use i3test; 22 | 23 | cmd 'layout toggle 1337 1337'; 24 | 25 | fresh_workspace; 26 | 27 | does_i3_live; 28 | 29 | done_testing; 30 | -------------------------------------------------------------------------------- /libi3/is_debug_build.c: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | */ 8 | #include "libi3.h" 9 | 10 | #include 11 | #include 12 | 13 | /* 14 | * Returns true if this version of i3 is a debug build (anything which is not a 15 | * release version), based on the git version number. 16 | * 17 | */ 18 | bool is_debug_build(void) { 19 | /* i3_version contains either something like this: 20 | * "4.0.2 (2011-11-11, branch "release")". 21 | * or: "4.0.2-123-gCOFFEEBABE (2011-11-11, branch "next")". 22 | * 23 | * So we check for the offset of the first opening round bracket to 24 | * determine whether this is a git version or a release version. */ 25 | return ((strchr(I3_VERSION, '(') - I3_VERSION) > 10); 26 | } 27 | -------------------------------------------------------------------------------- /include/key_press.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * key_press.c: key press handler 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | /** 15 | * There was a key press. We compare this key code with our bindings table and pass 16 | * the bound action to parse_command(). 17 | * 18 | */ 19 | void handle_key_press(xcb_key_press_event_t *event); 20 | 21 | /** 22 | * Kills the commanderror i3-nagbar process, if any. 23 | * 24 | * Called when reloading/restarting, since the user probably fixed their wrong 25 | * keybindings. 26 | * 27 | * If wait_for_it is set (restarting), this function will waitpid(), otherwise, 28 | * ev is assumed to handle it (reloading). 29 | * 30 | */ 31 | void kill_commanderror_nagbar(bool wait_for_it); 32 | -------------------------------------------------------------------------------- /src/sync.c: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * sync.c: i3 sync protocol: https://i3wm.org/docs/testsuite.html#i3_sync 8 | * 9 | */ 10 | #include "all.h" 11 | 12 | void sync_respond(xcb_window_t window, uint32_t rnd) { 13 | DLOG("[i3 sync protocol] Sending random value %d back to X11 window 0x%08x\n", rnd, window); 14 | 15 | void *reply = scalloc(32, 1); 16 | xcb_client_message_event_t *ev = reply; 17 | 18 | ev->response_type = XCB_CLIENT_MESSAGE; 19 | ev->window = window; 20 | ev->type = A_I3_SYNC; 21 | ev->format = 32; 22 | ev->data.data32[0] = window; 23 | ev->data.data32[1] = rnd; 24 | 25 | xcb_send_event(conn, false, window, XCB_EVENT_MASK_NO_EVENT, (char *)ev); 26 | xcb_flush(conn); 27 | free(reply); 28 | } 29 | -------------------------------------------------------------------------------- /i3bar/include/ipc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3bar - an xcb-based status- and ws-bar for i3 5 | * © 2010 Axel Wagner and contributors (see also: LICENSE) 6 | * 7 | * ipc.c: Communicating with i3 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | #include 15 | 16 | /* 17 | * Initiate a connection to i3. 18 | * socket_path must be a valid path to the ipc_socket of i3 19 | * 20 | */ 21 | int init_connection(const char *socket_path); 22 | 23 | /* 24 | * Destroy the connection to i3. 25 | * 26 | */ 27 | void destroy_connection(void); 28 | 29 | /* 30 | * Sends a message to i3. 31 | * type must be a valid I3_IPC_MESSAGE_TYPE (see i3/ipc.h for further information) 32 | * 33 | */ 34 | int i3_send_msg(uint32_t type, const char *payload); 35 | 36 | /* 37 | * Subscribe to all the i3-events, we need 38 | * 39 | */ 40 | void subscribe_events(void); 41 | -------------------------------------------------------------------------------- /i3bar/include/parse_json_header.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3bar - an xcb-based status- and ws-bar for i3 5 | * © 2010 Axel Wagner and contributors (see also: LICENSE) 6 | * 7 | * parse_json_header.c: Parse the JSON protocol header to determine 8 | * protocol version and features. 9 | * 10 | */ 11 | #pragma once 12 | 13 | #include 14 | 15 | #include 16 | 17 | /** 18 | * Parse the JSON protocol header to determine protocol version and features. 19 | * In case the buffer does not contain a valid header (invalid JSON, or no 20 | * version field found), the 'correct' field of the returned header is set to 21 | * false. The amount of bytes consumed by parsing the header is returned in 22 | * *consumed (if non-NULL). 23 | * 24 | */ 25 | void parse_json_header(i3bar_child *child, const unsigned char *buffer, int length, unsigned int *consumed); 26 | -------------------------------------------------------------------------------- /include/display_version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * display_version.c: displays the running i3 version, runs as part of 8 | * i3 --moreversion. 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | /** 15 | * Connects to i3 to find out the currently running version. Useful since it 16 | * might be different from the version compiled into this binary (maybe the 17 | * user didn’t correctly install i3 or forgot te restart it). 18 | * 19 | * The output looks like this: 20 | * Running i3 version: 4.2-202-gb8e782c (2012-08-12, branch "next") (pid 14804) 21 | * 22 | * The i3 binary you just called: /home/michael/i3/i3 23 | * The i3 binary you are running: /home/michael/i3/i3 24 | * 25 | */ 26 | void display_running_version(void); 27 | -------------------------------------------------------------------------------- /libi3/get_visualtype.c: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | */ 8 | #include "libi3.h" 9 | 10 | /* 11 | * Returns the visual type associated with the given screen. 12 | * 13 | */ 14 | xcb_visualtype_t *get_visualtype(xcb_screen_t *screen) { 15 | xcb_depth_iterator_t depth_iter; 16 | for (depth_iter = xcb_screen_allowed_depths_iterator(screen); 17 | depth_iter.rem; 18 | xcb_depth_next(&depth_iter)) { 19 | xcb_visualtype_iterator_t visual_iter; 20 | for (visual_iter = xcb_depth_visuals_iterator(depth_iter.data); 21 | visual_iter.rem; 22 | xcb_visualtype_next(&visual_iter)) { 23 | if (screen->root_visual == visual_iter.data->visual_id) 24 | return visual_iter.data; 25 | } 26 | } 27 | return NULL; 28 | } 29 | -------------------------------------------------------------------------------- /testcases/t/205-ipc-windows.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | 17 | use i3test; 18 | 19 | my $new = AnyEvent->condvar; 20 | my $focus = AnyEvent->condvar; 21 | 22 | my @events = events_for( 23 | sub { open_window }, 24 | 'window'); 25 | 26 | is(scalar @events, 2, 'Received 2 events'); 27 | is($events[0]->{container}->{focused}, 0, 'Window "new" event received'); 28 | is($events[1]->{container}->{focused}, 1, 'Window "focus" event received'); 29 | 30 | done_testing; 31 | -------------------------------------------------------------------------------- /contrib/trivial-bar-script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # vim:ts=4:sw=4:expandtab 3 | # © 2012 Michael Stapelberg, Public Domain 4 | 5 | # This script is a trivial shell script to send your own output to i3bar while 6 | # using the JSON protocol. 7 | # 8 | # It is ugly and that is inherent to using JSON with shell scripts. You 9 | # _really_ should not do that. See i3status or i3status’s contrib/ directory 10 | # for examples of how to handle the output in higher-level languages. 11 | # 12 | # This example is purely for illustration of the protocol. DO NOT USE IT IN THE 13 | # REAL WORLD. 14 | 15 | # Send the header so that i3bar knows we want to use JSON: 16 | echo '{ "version": 1 }' 17 | 18 | # Begin the endless array. 19 | echo '[' 20 | 21 | # We send an empty first array of blocks to make the loop simpler: 22 | echo '[]' 23 | 24 | # Now send blocks with information forever: 25 | while :; 26 | do 27 | echo ",[{\"name\":\"time\",\"full_text\":\"$(date)\"}]" 28 | sleep 1 29 | done 30 | -------------------------------------------------------------------------------- /travis/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -x 5 | 6 | cd build 7 | 8 | # TODO: remove this workaround once https://bugs.debian.org/836723 is fixed 9 | # Found at https://llvm.org/bugs/show_bug.cgi?id=27310#c8: 10 | if [ "$CC" = "clang" ] 11 | then 12 | cat >fixasan.c < 'Window 0'); 20 | 21 | my @events = events_for( 22 | sub { 23 | $window->name('New Window Title'); 24 | sync_with_i3; 25 | }, 26 | 'window'); 27 | 28 | is(scalar @events, 1, 'Received 1 event'); 29 | is($events[0]->{change}, 'title', 'Window title change event received'); 30 | is($events[0]->{container}->{name}, 'New Window Title', 'Window title changed'); 31 | 32 | done_testing; 33 | -------------------------------------------------------------------------------- /travis/bintray-autobuild-debian.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": { 3 | "name": "i3-wm", 4 | "repo": "i3-autobuild", 5 | "subject": "i3" 6 | }, 7 | 8 | "version": { 9 | "name": "%version%", 10 | "desc": "TODO", 11 | "gpgSign": false 12 | }, 13 | 14 | "files": [ 15 | { 16 | "includePattern": "build/deb/debian-amd64/(.*\\.deb)$", 17 | "matrixParams": { 18 | "deb_distribution": "sid", 19 | "deb_component": "main", 20 | "deb_architecture": "amd64" 21 | }, 22 | "uploadPattern": "$1" 23 | }, 24 | { 25 | "includePattern": "build/deb/debian-i386/(.*\\.deb)$", 26 | "matrixParams": { 27 | "deb_distribution": "sid", 28 | "deb_component": "main", 29 | "deb_architecture": "i386" 30 | }, 31 | "uploadPattern": "$1" 32 | } 33 | ], 34 | 35 | "publish": true 36 | } 37 | -------------------------------------------------------------------------------- /testcases/t/163-wm-state.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Tests if WM_STATE is WM_STATE_NORMAL when mapped and WM_STATE_WITHDRAWN when 18 | # unmapped. 19 | # 20 | use i3test; 21 | use X11::XCB qw(ICCCM_WM_STATE_NORMAL ICCCM_WM_STATE_WITHDRAWN); 22 | 23 | my $window = open_window; 24 | 25 | is($window->state, ICCCM_WM_STATE_NORMAL, 'WM_STATE normal'); 26 | 27 | $window->unmap; 28 | 29 | wait_for_unmap $window; 30 | 31 | is($window->state, ICCCM_WM_STATE_WITHDRAWN, 'WM_STATE withdrawn'); 32 | 33 | done_testing; 34 | -------------------------------------------------------------------------------- /travis/bintray-autobuild-ubuntu.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": { 3 | "name": "i3-wm", 4 | "repo": "i3-autobuild-ubuntu", 5 | "subject": "i3" 6 | }, 7 | 8 | "version": { 9 | "name": "%version%", 10 | "desc": "TODO", 11 | "gpgSign": false 12 | }, 13 | 14 | "files": [ 15 | { 16 | "includePattern": "build/deb/ubuntu-amd64/(.*\\.deb)$", 17 | "matrixParams": { 18 | "deb_distribution": "bionic", 19 | "deb_component": "main", 20 | "deb_architecture": "amd64" 21 | }, 22 | "uploadPattern": "$1" 23 | }, 24 | { 25 | "includePattern": "build/deb/ubuntu-i386/(.*\\.deb)$", 26 | "matrixParams": { 27 | "deb_distribution": "bionic", 28 | "deb_component": "main", 29 | "deb_architecture": "i386" 30 | }, 31 | "uploadPattern": "$1" 32 | } 33 | ], 34 | 35 | "publish": true 36 | } 37 | -------------------------------------------------------------------------------- /testcases/t/001-tile.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | 17 | use i3test; 18 | 19 | my $original_rect = X11::XCB::Rect->new(x => 0, y => 0, width => 30, height => 30); 20 | 21 | my $window = open_window(rect => $original_rect, dont_map => 1); 22 | isa_ok($window, 'X11::XCB::Window'); 23 | 24 | is_deeply($window->rect, $original_rect, "rect unmodified before mapping"); 25 | 26 | $window->map; 27 | wait_for_map $window; 28 | 29 | my $new_rect = $window->rect; 30 | ok(!eq_hash($new_rect, $original_rect), "Window got repositioned"); 31 | 32 | done_testing; 33 | -------------------------------------------------------------------------------- /testcases/t/184-regress-float-split-resize.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression: resizing a floating split container leads to a crash. 18 | # (Ticket #588, present until 4412ccbe5a4fad8a4cd594e6f10f937515a4d37c) 19 | # 20 | use i3test; 21 | 22 | my $tmp = fresh_workspace; 23 | 24 | my $first = open_window; 25 | cmd 'split v'; 26 | my $second = open_window; 27 | 28 | cmd 'focus parent'; 29 | cmd 'floating toggle'; 30 | cmd 'layout stacking'; 31 | 32 | cmd 'resize grow up 10 px or 10 ppt'; 33 | 34 | does_i3_live; 35 | 36 | done_testing; 37 | -------------------------------------------------------------------------------- /testcases/t/218-regress-floating-split.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Make sure floating containers really can't be split. 18 | # Ticket: #1177 19 | # Bug still in: 4.7.2-81-g905440d 20 | use i3test; 21 | 22 | my $ws = fresh_workspace; 23 | my $window = open_floating_window; 24 | cmd "layout stacked"; 25 | cmd "splitv"; 26 | 27 | my $floating_con = get_ws($ws)->{floating_nodes}[0]->{nodes}[0]; 28 | 29 | is(@{$floating_con->{nodes}}, 0, 'floating con is still a leaf'); 30 | 31 | cmd 'floating disable'; 32 | 33 | does_i3_live; 34 | 35 | done_testing; 36 | -------------------------------------------------------------------------------- /travis/docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -x 5 | 6 | for f in $(grep '\.html$' debian/i3-wm.docs | grep -v 'docs/refcard.html' | grep -v 'docs/lib-i3test') 7 | do 8 | asciidoc -a linkcss -a stylesdir=https://i3wm.org/css -a scriptsdir=https://i3wm.org/js --backend=xhtml11 -f docs/asciidoc-git.conf $(dirname $f)/$(basename $f .html) 9 | done 10 | ./docs/i3-pod2html i3-dmenu-desktop man/i3-dmenu-desktop.html 11 | ./docs/i3-pod2html i3-save-tree man/i3-save-tree.html 12 | ./docs/i3-pod2html build/testcases/lib/i3test.pm docs/lib-i3test.html 13 | ./docs/i3-pod2html testcases/lib/i3test/Test.pm docs/lib-i3test-test.html 14 | for file in $(sed 's/\.1$/.man/g' debian/i3-wm.manpages) 15 | do 16 | [ -f "$file" ] && asciidoc -a linkcss -a stylesdir=https://i3wm.org/css -a scriptsdir=https://i3wm.org/js --backend=xhtml11 -f docs/asciidoc-git.conf "$file" 17 | done 18 | 19 | mkdir -p deb/COPY-DOCS 20 | 21 | cp $(tr "\n" ' ' < debian/i3-wm.docs) deb/COPY-DOCS/ 22 | cp $(sed 's/\.1$/.html/g' debian/i3-wm.manpages | tr "\n" ' ') deb/COPY-DOCS/ 23 | -------------------------------------------------------------------------------- /testcases/t/197-regression-move-vanish.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression test: moving a window to the right out of a splitv container would 18 | # make it vanish. 19 | # Ticket: #790 20 | # Bug still in: 4.2-277-ga598544 21 | use i3test; 22 | 23 | my $ws = fresh_workspace; 24 | 25 | my $top = open_window; 26 | cmd 'split v'; 27 | my $bottom = open_window; 28 | 29 | is_num_children($ws, 2, 'two windows on workspace level'); 30 | 31 | cmd 'move right'; 32 | 33 | is_num_children($ws, 2, 'still two windows on workspace level'); 34 | 35 | done_testing; 36 | -------------------------------------------------------------------------------- /testcases/t/182-regress-focus-dock.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression test: Focusing a dock window should just do nothing, not crash i3. 18 | # See ticket https://bugs.i3wm.org/575 19 | # Wrong behaviour manifested itself up to (including) commit 20 | # 340592a532b5259c3a3f575de5a9639fad4d1459 21 | # 22 | use i3test; 23 | 24 | fresh_workspace; 25 | 26 | my $window = open_window( 27 | window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), 28 | ); 29 | 30 | cmd '[title="' . $window->name . '"] focus'; 31 | 32 | does_i3_live; 33 | 34 | done_testing; 35 | -------------------------------------------------------------------------------- /testcases/t/281-regress-reload-bindsym.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Test that the binding event works properly 18 | # Ticket: #1210 19 | use i3test i3_config => < /dev/null); 28 | 29 | skip 'xdotool is required to test the binding event. `[apt-get install|pacman -S] xdotool`', 1 if $?; 30 | 31 | qx(xdotool key r); 32 | 33 | does_i3_live; 34 | 35 | } 36 | done_testing; 37 | -------------------------------------------------------------------------------- /contrib/show-download-count.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # © 2012 Han Boetes (see also: LICENSE) 3 | 4 | YEAR=`date "+%Y"` 5 | weblog=$(mktemp) 6 | zcat $(find /var/log/lighttpd/build.i3wm.org -type f -name "access.log.*.gz" | sort | tail -5) > $weblog 7 | # this will match the latest logfile, which is not yet gzipped 8 | find /var/log/lighttpd/build.i3wm.org/log$YEAR -type f \! -name "access.log.*.gz" -exec cat '{}' \; >> $weblog 9 | cat /var/log/lighttpd/build.i3wm.org/access.log >> $weblog 10 | gitlog=$(mktemp) 11 | 12 | # create a git output logfile. Only keep the first 6 chars of the release hash 13 | git log -150 --pretty=' %h %s' next > $gitlog 14 | 15 | awk '/i3-wm_.*\.deb/ {print $7}' $weblog|awk -F'/' '{print $NF}'|awk -F'_' '{print $2 }'|awk -F'-' '{print $NF}' |cut -c 2-8|sort |uniq -c | while read line; do 16 | set -- $line 17 | # $1 is the number of downloads, $2 is the release md5sum 18 | sed -i "/$2/s|^ |$(printf '%3i' $1) d/l |" $gitlog 19 | done 20 | 21 | cat $gitlog 22 | rm $gitlog 23 | rm $weblog 24 | -------------------------------------------------------------------------------- /testcases/t/275-ipc-window-close.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Tests that the ipc close event works properly 18 | # 19 | # Bug still in: 4.8-7-gf4a8253 20 | use i3test; 21 | 22 | my $window = open_window; 23 | 24 | my @events = events_for( 25 | sub { 26 | $window->unmap; 27 | sync_with_i3; 28 | }, 29 | 'window'); 30 | 31 | my @close = grep { $_->{change} eq 'close' } @events; 32 | is(scalar @close, 1, 'Received 1 window::close event'); 33 | is($close[0]->{container}->{window}, $window->{id}, 'the event should contain information about the window'); 34 | 35 | done_testing; 36 | -------------------------------------------------------------------------------- /src/key_press.c: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * key_press.c: key press handler 8 | * 9 | */ 10 | #include "all.h" 11 | 12 | /* 13 | * There was a KeyPress or KeyRelease (both events have the same fields). We 14 | * compare this key code with our bindings table and pass the bound action to 15 | * parse_command(). 16 | * 17 | */ 18 | void handle_key_press(xcb_key_press_event_t *event) { 19 | const bool key_release = (event->response_type == XCB_KEY_RELEASE); 20 | 21 | last_timestamp = event->time; 22 | 23 | DLOG("%s %d, state raw = 0x%x\n", (key_release ? "KeyRelease" : "KeyPress"), event->detail, event->state); 24 | 25 | Binding *bind = get_binding_from_xcb_event((xcb_generic_event_t *)event); 26 | 27 | /* if we couldn't find a binding, we are done */ 28 | if (bind == NULL) 29 | return; 30 | 31 | CommandResult *result = run_binding(bind, NULL); 32 | command_result_free(result); 33 | } 34 | -------------------------------------------------------------------------------- /testcases/t/178-regress-workspace-open.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Tests if empty workspaces are closed when the last child 18 | # exits, as long as they're not empty. 19 | # 20 | use i3test; 21 | 22 | my $i3 = i3(get_socket_path()); 23 | 24 | # Get a workspace and open a container 25 | my $ws = fresh_workspace; 26 | my $con = open_empty_con($i3); 27 | 28 | # Go to a second workspace, kill the container 29 | fresh_workspace; 30 | cmd "[con_id=\"$con\"] kill"; 31 | 32 | # The first workspace should have been closed 33 | ok(!workspace_exists($ws), 'workspace closed'); 34 | 35 | done_testing; 36 | -------------------------------------------------------------------------------- /testcases/t/198-regression-scratchpad-crash.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # When using a command which moves a window to scratchpad from an invisible 18 | # (e.g. unfocused) workspace and immediately shows that window again, i3 19 | # crashed. 20 | # Bug still in: 4.2-305-g22922a9 21 | use i3test; 22 | 23 | my $ws1 = fresh_workspace; 24 | my $invisible_window = open_window; 25 | my $other_focusable_window = open_window; 26 | 27 | my $ws2 = fresh_workspace; 28 | my $id = $invisible_window->id; 29 | cmd qq|[id="$id"] move scratchpad, scratchpad show|; 30 | 31 | does_i3_live; 32 | 33 | done_testing; 34 | -------------------------------------------------------------------------------- /testcases/Makefile.PL: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # vim:ts=4:sw=4:expandtab 3 | use strict; use warnings; 4 | use ExtUtils::MakeMaker; 5 | 6 | WriteMakefile( 7 | NAME => 'i3-testsuite', 8 | MIN_PERL_VERSION => '5.010000', # 5.10.0 9 | PREREQ_PM => { 10 | 'AnyEvent' => 0, 11 | 'X11::XCB' => '0.12', 12 | 'Inline' => 0, 13 | 'Inline::C' => 0, 14 | 'ExtUtils::PkgConfig' => 0, 15 | 'Test::More' => '0.94', 16 | 'IPC::Run' => 0, 17 | }, 18 | PM => {}, # do not install any files from this directory 19 | clean => { 20 | FILES => 'testsuite-* latest i3-cfg-for-*', 21 | }, 22 | # This is a pure-Perl distribution: 23 | linkext => { 24 | LINKTYPE => '', 25 | }, 26 | ); 27 | 28 | package MY; 29 | sub test { } # do not run the tests while installing 30 | 31 | # do not rename the Makefile 32 | sub clean { 33 | my $section = shift->SUPER::clean(@_); 34 | $section =~ s/^\t\Q$_\E\n$//m for 35 | '- $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) $(DEV_NULL)'; 36 | $section; 37 | } 38 | -------------------------------------------------------------------------------- /testcases/t/199-ipc-mode-event.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Verifies that the IPC 'mode' event is sent when modes are changed. 18 | use i3test i3_config => <{change} } @events; 36 | is_deeply(\@changes, [ 'm1' ], 'Mode event received'); 37 | 38 | done_testing; 39 | -------------------------------------------------------------------------------- /testcases/t/222-regress-dock-resize.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Test that i3 does not crash when a command is issued that would resize a dock 18 | # client. 19 | # Ticket: #1201 20 | # Bug still in: 4.7.2-107-g9b03be6 21 | use i3test i3_config => < 'special', 28 | window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), 29 | ); 30 | 31 | cmd('[class="special"] resize grow height 160 px or 16 ppt'); 32 | 33 | does_i3_live; 34 | 35 | done_testing; 36 | -------------------------------------------------------------------------------- /testcases/t/003-ipc.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | 17 | use i3test; 18 | 19 | fresh_workspace; 20 | 21 | ##################################################################### 22 | # Ensure IPC works by switching workspaces 23 | ##################################################################### 24 | 25 | # Create a window so we can get a focus different from NULL 26 | my $window = open_window; 27 | 28 | my $focus = $x->input_focus; 29 | 30 | # Switch to another workspace 31 | fresh_workspace; 32 | 33 | sync_with_i3; 34 | my $new_focus = $x->input_focus; 35 | isnt($focus, $new_focus, "Focus changed"); 36 | 37 | done_testing; 38 | -------------------------------------------------------------------------------- /testcases/t/004-unmanaged.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | 17 | use i3test; 18 | 19 | my $original_rect = X11::XCB::Rect->new(x => 0, y => 0, width => 30, height => 30); 20 | 21 | my $window = open_window( 22 | rect => $original_rect, 23 | override_redirect => 1, 24 | dont_map => 1, 25 | ); 26 | 27 | isa_ok($window, 'X11::XCB::Window'); 28 | 29 | is_deeply($window->rect, $original_rect, "rect unmodified before mapping"); 30 | 31 | $window->map; 32 | 33 | my $new_rect = $window->rect; 34 | isa_ok($new_rect, 'X11::XCB::Rect'); 35 | 36 | is_deeply($new_rect, $original_rect, "window untouched"); 37 | 38 | done_testing; 39 | -------------------------------------------------------------------------------- /testcases/t/303-regress-move-floating.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression: moving a container which is the only child of the only child of a 18 | # floating container crashes i3. 19 | # Ticket: #3556 20 | # Bug still in: 4.16-61-g376833db4 21 | use i3test; 22 | 23 | my $ws = fresh_workspace; 24 | open_window; 25 | open_window; 26 | cmd 'split v, focus parent, floating toggle, focus child, move right'; 27 | does_i3_live; 28 | 29 | $ws = get_ws($ws); 30 | is(scalar @{$ws->{floating_nodes}}, 0, 'No floating nodes in workspace'); 31 | is(scalar @{$ws->{nodes}}, 2, 'Two tiling nodes in workspace'); 32 | 33 | done_testing; 34 | -------------------------------------------------------------------------------- /man/i3-migrate-config-to-v4.man: -------------------------------------------------------------------------------- 1 | i3-migrate-config-to-v4(1) 2 | ========================== 3 | Michael Stapelberg 4 | v4.0, July 2011 5 | 6 | == NAME 7 | 8 | i3-migrate-config-to-v4 - migrates your i3 config file 9 | 10 | == SYNOPSIS 11 | 12 | ------------------------------------------------------- 13 | mv ~/.i3/config ~/.i3/old.config 14 | i3-migrate-config-to-v4 ~/.i3/old.config > ~/.i3/config 15 | ------------------------------------------------------- 16 | 17 | == DESCRIPTION 18 | 19 | i3-migrate-config-to-v4 is a Perl script which migrates your old (< version 4) 20 | configuration files to a version 4 config file. The most significant changes 21 | are the new commands (see the release notes). 22 | 23 | This script will automatically be run by i3 when it detects an old config file. 24 | Please migrate your config file as soon as possible. We plan to include this 25 | script in all i3 release until 2012-08-01. Afterwards, old config files will no 26 | longer be supported. 27 | 28 | == SEE ALSO 29 | 30 | i3(1) 31 | 32 | == AUTHOR 33 | 34 | Michael Stapelberg and contributors 35 | -------------------------------------------------------------------------------- /testcases/t/237-regress-assign-focus.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Verifies that using layout tabbed followed by focus (on a window that is 18 | # assigned to an invisible workspace) will not crash i3. 19 | # Ticket: #1338 20 | # Bug still in: 4.8-91-g294d52e 21 | use i3test i3_config => < 0; 21 | use File::Temp qw(tempfile); 22 | 23 | my ($fh, $filename) = tempfile(UNLINK => 1); 24 | print $fh < 'special'); 28 | 29 | my $tmp2 = fresh_workspace; 30 | 31 | cmd '[class="special"] move scratchpad'; 32 | 33 | does_i3_live; 34 | 35 | done_testing; 36 | -------------------------------------------------------------------------------- /testcases/t/540-sigterm-cleanup.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Tests that the socket file is cleaned up properly after gracefully 18 | # shutting down i3 via SIGTERM. 19 | # Ticket: #3049 20 | use i3test i3_autostart => 0; 21 | 22 | my $config = < 1); 28 | my $socket = get_socket_path(); 29 | ok(-S $socket, "socket $socket exists"); 30 | 31 | exit_forcefully($pid, 'TERM'); 32 | 33 | ok(!-e $socket, "socket $socket no longer exists"); 34 | 35 | done_testing; 36 | -------------------------------------------------------------------------------- /include/manage.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * manage.c: Initially managing new windows (or existing ones on restart). 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | #include "data.h" 15 | 16 | /** 17 | * Go through all existing windows (if the window manager is restarted) and 18 | * manage them 19 | * 20 | */ 21 | void manage_existing_windows(xcb_window_t root); 22 | 23 | /** 24 | * Restores the geometry of each window by reparenting it to the root window 25 | * at the position of its frame. 26 | * 27 | * This is to be called *only* before exiting/restarting i3 because of evil 28 | * side-effects which are to be expected when continuing to run i3. 29 | * 30 | */ 31 | void restore_geometry(void); 32 | 33 | /** 34 | * Do some sanity checks and then reparent the window. 35 | * 36 | */ 37 | void manage_window(xcb_window_t window, 38 | xcb_get_window_attributes_cookie_t cookie, 39 | bool needs_to_be_mapped); 40 | -------------------------------------------------------------------------------- /testcases/t/263-config-reload-reverts-bind-mode.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Verifies that reloading the config reverts to the default 18 | # binding mode. 19 | # Ticket: #2228 20 | # Bug still in: 4.11-262-geb631ce 21 | use i3test i3_config => <{change}, 'default', 'change is "default"'); 37 | 38 | done_testing; 39 | -------------------------------------------------------------------------------- /testcases/t/299-regress-scratchpad-focus.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression test: verify that a scratchpad container that was open in another 18 | # workspace and is moved to the current workspace after a 'scratchpad show' is 19 | # focused. 20 | # Ticket: #3361 21 | # Bug still in: 4.15-190-g4b3ff9cd 22 | use i3test; 23 | 24 | my $expected_focus = open_window; 25 | cmd 'move to scratchpad'; 26 | cmd 'scratchpad show'; 27 | my $ws = fresh_workspace; 28 | open_window; 29 | cmd 'scratchpad show'; 30 | sync_with_i3; 31 | is($x->input_focus, $expected_focus->id, 'scratchpad window brought from other workspace is focused'); 32 | 33 | done_testing; 34 | -------------------------------------------------------------------------------- /testcases/t/225-ipc-window-fullscreen.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Tests that the ipc window::fullscreen_mode event works properly 18 | # 19 | # Bug still in: 4.7.2-135-g7deb23c 20 | use i3test; 21 | 22 | open_window; 23 | 24 | sub fullscreen_subtest { 25 | my ($want) = @_; 26 | my @events = events_for( 27 | sub { cmd 'fullscreen' }, 28 | 'window'); 29 | 30 | is(scalar @events, 1, 'Received 1 event'); 31 | is($events[0]->{container}->{fullscreen_mode}, $want, "fullscreen_mode now $want"); 32 | } 33 | 34 | subtest 'fullscreen on', \&fullscreen_subtest, 1; 35 | subtest 'fullscreen off', \&fullscreen_subtest, 0; 36 | 37 | done_testing; 38 | -------------------------------------------------------------------------------- /testcases/t/286-root-window-mouse-binding.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Verifies that mouse bindings work on the root window if 18 | # --whole-window is set. 19 | # Ticket: #2115 20 | use i3test i3_config => < "\x{AA} <-- invalid"); 25 | 26 | cmd 'restart'; 27 | does_i3_live; 28 | 29 | # Confirm that the invalid character got replaced with U+FFFD - "REPLACEMENT 30 | # CHARACTER" 31 | cmd '[title="^' . "\x{fffd}" . ' <-- invalid$"] fullscreen enable'; 32 | is_num_fullscreen($ws, 1, 'title based criterion works'); 33 | 34 | done_testing; 35 | -------------------------------------------------------------------------------- /include/resize.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * resize.c: Interactive resizing. 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction, bool both_sides); 15 | 16 | void resize_graphical_handler(Con *first, Con *second, orientation_t orientation, const xcb_button_press_event_t *event); 17 | 18 | /** 19 | * Resize the two given containers using the given amount of pixels or 20 | * percentage points. One of the two needs to be 0. A positive amount means 21 | * growing the first container while a negative means shrinking it. 22 | * Returns false when the resize would result in one of the two containers 23 | * having less than 1 pixel of size. 24 | * 25 | */ 26 | bool resize_neighboring_cons(Con *first, Con *second, int px, int ppt); 27 | 28 | /** 29 | * Calculate the minimum percent needed for the given container to be at least 1 30 | * pixel. 31 | * 32 | */ 33 | double percent_for_1px(Con *con); 34 | -------------------------------------------------------------------------------- /testcases/t/515-create-workspace.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Tests that new workspace names are taken from the config, 18 | # then from the first free number starting with 1. 19 | # 20 | use i3test i3_config => <get_workspaces->recv; 31 | 32 | is($ws->[0]->{name}, '1: eggs', 'new workspace uses config name'); 33 | is($ws->[1]->{name}, '2', 'naming continues with next free number'); 34 | 35 | done_testing; 36 | -------------------------------------------------------------------------------- /testcases/t/190-scratchpad-diff-ws.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Test for ticket #676: 'scratchpad show' causes a segfault if the scratchpad 18 | # window is shown on another workspace. 19 | # 20 | use i3test; 21 | 22 | my $i3 = i3(get_socket_path()); 23 | my $tmp = fresh_workspace; 24 | 25 | my $win = open_window; 26 | 27 | my $scratch = open_window(wm_class => 'special'); 28 | cmd '[class="special"] move scratchpad'; 29 | 30 | is_num_children($tmp, 1, 'one window on current ws'); 31 | 32 | my $otmp = fresh_workspace; 33 | cmd 'scratchpad show'; 34 | 35 | cmd "workspace $tmp"; 36 | cmd '[class="special"] scratchpad show'; 37 | 38 | does_i3_live; 39 | 40 | done_testing; 41 | -------------------------------------------------------------------------------- /AnyEvent-I3/README: -------------------------------------------------------------------------------- 1 | AnyEvent-I3 2 | 3 | This module connects to the i3 window manager using the UNIX socket based 4 | IPC interface it provides (if enabled in the configuration file). You can 5 | then subscribe to events or send messages and receive their replies. 6 | 7 | INSTALLATION 8 | 9 | To install this module, run the following commands: 10 | 11 | perl Makefile.PL 12 | make 13 | make test 14 | make install 15 | 16 | SUPPORT AND DOCUMENTATION 17 | 18 | After installing, you can find documentation for this module with the 19 | perldoc command. 20 | 21 | perldoc AnyEvent::I3 22 | 23 | You can also look for information at: 24 | 25 | RT, CPAN's request tracker 26 | https://rt.cpan.org/NoAuth/Bugs.html?Dist=AnyEvent-I3 27 | 28 | The i3 window manager website 29 | https://i3wm.org 30 | 31 | 32 | LICENSE AND COPYRIGHT 33 | 34 | Copyright (C) 2010 Michael Stapelberg 35 | 36 | This program is free software; you can redistribute it and/or modify it 37 | under the terms of either: the GNU General Public License as published 38 | by the Free Software Foundation; or the Artistic License. 39 | 40 | See https://dev.perl.org/licenses/ for more information. 41 | -------------------------------------------------------------------------------- /testcases/t/143-regress-floating-restart.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression: floating windows are tiling after restarting, closing them crashes i3 18 | # 19 | use i3test; 20 | 21 | my $tmp = fresh_workspace; 22 | 23 | cmd 'open'; 24 | cmd 'floating toggle'; 25 | 26 | my $ws = get_ws($tmp); 27 | is(scalar @{$ws->{nodes}}, 0, 'no tiling nodes'); 28 | is(scalar @{$ws->{floating_nodes}}, 1, 'precisely one floating node'); 29 | 30 | cmd 'restart'; 31 | 32 | diag('Checking if i3 still lives'); 33 | 34 | does_i3_live; 35 | 36 | $ws = get_ws($tmp); 37 | is(scalar @{$ws->{nodes}}, 0, 'no tiling nodes'); 38 | is(scalar @{$ws->{floating_nodes}}, 1, 'precisely one floating node'); 39 | 40 | done_testing; 41 | -------------------------------------------------------------------------------- /testcases/t/500-multi-monitor.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Tests that the provided X-Server to the t/5??-*.t tests is actually providing 18 | # multiple monitors. 19 | # 20 | use i3test i3_config => <get_tree->recv; 34 | 35 | my @outputs = map { $_->{name} } @{$tree->{nodes}}; 36 | is_deeply(\@outputs, [ '__i3', 'fake-0', 'fake-1' ], 37 | 'multi-monitor outputs ok'); 38 | 39 | 40 | done_testing; 41 | -------------------------------------------------------------------------------- /RELEASE-NOTES-4.16.1: -------------------------------------------------------------------------------- 1 | 2 | ┌──────────────────────────────┐ 3 | │ Release notes for i3 v4.16.1 │ 4 | └──────────────────────────────┘ 5 | 6 | This is i3 v4.16.1. This version is considered stable. All users of i3 are 7 | strongly encouraged to upgrade. 8 | 9 | This is a bugfix release for v4.16. 10 | 11 | ┌────────────────────────────┐ 12 | │ Bugfixes │ 13 | └────────────────────────────┘ 14 | 15 | • Truncate wm_name utf8 strings to first zero byte 16 | (fixes window title corruption) 17 | • Apply title_align to non-leaf containers 18 | Additionally, marks will now display for non-leaf containers. 19 | • attach_to_workspace: set new parent before tree_render 20 | (fixes a heap-use-after-free) 21 | • Use ipc queue for all messages 22 | (fixes an i3bar crash) 23 | • Fix crash with popups when fullscreen is non-leaf 24 | • Fix: render_con shows floating containers on wrong workspace 25 | 26 | 27 | ┌────────────────────────────┐ 28 | │ Thanks! │ 29 | └────────────────────────────┘ 30 | 31 | Thanks for testing, bugfixes, discussions and everything I forgot go out to: 32 | 33 | Orestis Floros 34 | 35 | -- Michael Stapelberg, 2019-01-27 36 | -------------------------------------------------------------------------------- /testcases/t/530-bug-2229.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Ticket: #2229 18 | # Bug still in: 4.11-262-geb631ce 19 | use i3test i3_config => < <{floating_nodes}}; 34 | 35 | is($floating[0]->{nodes}[0]->{border}, 'normal', 'default floating border is `normal`'); 36 | 37 | done_testing; 38 | -------------------------------------------------------------------------------- /testcases/t/282-tabbed-floating-disable-crash.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Verifies that i3 does not crash when floating and then unfloating an 18 | # unfocused window within a tabbed container. 19 | # Ticket: #1484 20 | # Bug still in: 4.9.1-124-g856e1f9 21 | use i3test i3_config => < <{workspace_layout}, 'tabbed', 'workspace layout is "tabbed"'); 35 | 36 | done_testing; 37 | -------------------------------------------------------------------------------- /include/atoms_NET_SUPPORTED.xmacro: -------------------------------------------------------------------------------- 1 | xmacro(_NET_SUPPORTED) 2 | xmacro(_NET_SUPPORTING_WM_CHECK) 3 | xmacro(_NET_WM_NAME) 4 | xmacro(_NET_WM_VISIBLE_NAME) 5 | xmacro(_NET_WM_MOVERESIZE) 6 | xmacro(_NET_WM_STATE_STICKY) 7 | xmacro(_NET_WM_STATE_FULLSCREEN) 8 | xmacro(_NET_WM_STATE_DEMANDS_ATTENTION) 9 | xmacro(_NET_WM_STATE_MODAL) 10 | xmacro(_NET_WM_STATE_HIDDEN) 11 | xmacro(_NET_WM_STATE_FOCUSED) 12 | xmacro(_NET_WM_STATE) 13 | xmacro(_NET_WM_WINDOW_TYPE) 14 | xmacro(_NET_WM_WINDOW_TYPE_NORMAL) 15 | xmacro(_NET_WM_WINDOW_TYPE_DOCK) 16 | xmacro(_NET_WM_WINDOW_TYPE_DIALOG) 17 | xmacro(_NET_WM_WINDOW_TYPE_UTILITY) 18 | xmacro(_NET_WM_WINDOW_TYPE_TOOLBAR) 19 | xmacro(_NET_WM_WINDOW_TYPE_SPLASH) 20 | xmacro(_NET_WM_WINDOW_TYPE_MENU) 21 | xmacro(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU) 22 | xmacro(_NET_WM_WINDOW_TYPE_POPUP_MENU) 23 | xmacro(_NET_WM_WINDOW_TYPE_TOOLTIP) 24 | xmacro(_NET_WM_WINDOW_TYPE_NOTIFICATION) 25 | xmacro(_NET_WM_DESKTOP) 26 | xmacro(_NET_WM_STRUT_PARTIAL) 27 | xmacro(_NET_CLIENT_LIST) 28 | xmacro(_NET_CLIENT_LIST_STACKING) 29 | xmacro(_NET_CURRENT_DESKTOP) 30 | xmacro(_NET_NUMBER_OF_DESKTOPS) 31 | xmacro(_NET_DESKTOP_NAMES) 32 | xmacro(_NET_DESKTOP_VIEWPORT) 33 | xmacro(_NET_ACTIVE_WINDOW) 34 | xmacro(_NET_CLOSE_WINDOW) 35 | xmacro(_NET_MOVERESIZE_WINDOW) 36 | -------------------------------------------------------------------------------- /testcases/t/147-regress-floatingmove.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression test for moving a con outside of a floating con when there are no 18 | # tiling cons on a workspace 19 | # 20 | use i3test; 21 | 22 | sub sync_cmd { 23 | cmd @_; 24 | sync_with_i3; 25 | } 26 | 27 | my $tmp = fresh_workspace; 28 | 29 | my $left = open_window; 30 | my $mid = open_window; 31 | my $right = open_window; 32 | 33 | # go to workspace level 34 | sync_cmd 'focus parent'; 35 | 36 | # make it floating 37 | sync_cmd 'mode toggle'; 38 | 39 | # move the con outside the floating con 40 | sync_cmd 'move up'; 41 | 42 | does_i3_live; 43 | 44 | # move another con outside 45 | sync_cmd '[id="' . $mid->id . '"] focus'; 46 | sync_cmd 'move up'; 47 | 48 | does_i3_live; 49 | 50 | done_testing; 51 | -------------------------------------------------------------------------------- /.github/GOVERNANCE.md: -------------------------------------------------------------------------------- 1 | # i3 project governance 2 | 3 | ## Overview 4 | 5 | The i3 project uses a governance model commonly described as Benevolent 6 | Dictator For Life (BDFL). This document outlines our understanding of what this 7 | means. 8 | 9 | ## Roles 10 | 11 | * user: anyone who interacts with the i3 project 12 | * core contributor: a handful of people who have contributed significantly to 13 | the project by any means (issue triage, support, documentation, code, etc.). 14 | Core contributors are recognizable via GitHub’s “Member” badge. 15 | * BDFL: a single individual who makes decisions when consensus cannot be 16 | reached. i3’s current BDFL is [@stapelberg](https://github.com/stapelberg). 17 | 18 | ## Decision making process 19 | 20 | In general, we try to reach consensus in discussions. In case consensus cannot 21 | be reached, the BDFL makes a decision. 22 | 23 | For feature requests and code contributions specifically, the values with which 24 | we consider them can be found on the bottom of https://i3wm.org/. These values 25 | are not set in stone and are to be treated as guiding principles, not absolute 26 | rules that must be followed in every case. 27 | 28 | ## Contribution process 29 | 30 | Please see [CONTRIBUTING](CONTRIBUTING.md). 31 | -------------------------------------------------------------------------------- /testcases/t/208-regress-floating-criteria.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression test for focus handling when using floating enable/disable with 18 | # criteria for windows on non-visible workspaces. 19 | # Ticket: #1027 20 | # Bug still in: 4.5.1-90-g6582da9 21 | use i3test i3_config => < 'Borderless window', 31 | wm_class => 'special', 32 | dont_map => 1, 33 | ); 34 | $window->map; 35 | 36 | sync_with_i3; 37 | 38 | cmd '[class="^special$"] focus'; 39 | 40 | does_i3_live; 41 | 42 | done_testing; 43 | -------------------------------------------------------------------------------- /testcases/t/276-ipc-window-move.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Tests that the ipc window::move event works properly 18 | # 19 | # Bug still in: 4.8-7-gf4a8253 20 | use i3test; 21 | 22 | my $dummy_window = open_window; 23 | my $window = open_window; 24 | 25 | sub move_subtest { 26 | my ($cmd) = @_; 27 | my $cv = AnyEvent->condvar; 28 | my @events = events_for( 29 | sub { cmd $cmd }, 30 | 'window'); 31 | 32 | my @move = grep { $_->{change} eq 'move' } @events; 33 | is(scalar @move, 1, 'Received 1 window::move event'); 34 | is($move[0]->{container}->{window}, $window->{id}, 'window id matches'); 35 | } 36 | 37 | subtest 'move left', \&move_subtest, 'move left'; 38 | subtest 'move to workspace', \&move_subtest, 'move to workspace ws_new'; 39 | 40 | done_testing; 41 | -------------------------------------------------------------------------------- /testcases/t/538-i3bar-primary-output.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Tests that i3bars configured to use the primary output do not have 18 | # their output names canonicalized to something other than "primary". 19 | # Ticket: #2948 20 | # Bug still in: 4.14-93-ga3a7d04a 21 | use i3test i3_config => <get_bar_config()->recv; 33 | is(@$bars, 1, 'one bar configured'); 34 | 35 | my $bar_id = shift @$bars; 36 | 37 | my $bar_config = i3->get_bar_config($bar_id)->recv; 38 | is_deeply($bar_config->{outputs}, [ "primary" ], 'bar_config output is primary'); 39 | 40 | done_testing; 41 | -------------------------------------------------------------------------------- /libi3/ipc_send_message.c: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | */ 8 | #include "libi3.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | /* 20 | * Formats a message (payload) of the given size and type and sends it to i3 via 21 | * the given socket file descriptor. 22 | * 23 | * Returns -1 when write() fails, errno will remain. 24 | * Returns 0 on success. 25 | * 26 | */ 27 | int ipc_send_message(int sockfd, const uint32_t message_size, 28 | const uint32_t message_type, const uint8_t *payload) { 29 | const i3_ipc_header_t header = { 30 | /* We don’t use I3_IPC_MAGIC because it’s a 0-terminated C string. */ 31 | .magic = {'i', '3', '-', 'i', 'p', 'c'}, 32 | .size = message_size, 33 | .type = message_type}; 34 | 35 | if (writeall(sockfd, ((void *)&header), sizeof(i3_ipc_header_t)) == -1) 36 | return -1; 37 | 38 | if (writeall(sockfd, payload, message_size) == -1) 39 | return -1; 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /include/regex.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * regex.c: Interface to libPCRE (perl compatible regular expressions). 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | /** 15 | * Creates a new 'regex' struct containing the given pattern and a PCRE 16 | * compiled regular expression. Also, calls pcre_study because this regex will 17 | * most likely be used often (like for every new window and on every relevant 18 | * property change of existing windows). 19 | * 20 | * Returns NULL if the pattern could not be compiled into a regular expression 21 | * (and ELOGs an appropriate error message). 22 | * 23 | */ 24 | struct regex *regex_new(const char *pattern); 25 | 26 | /** 27 | * Frees the given regular expression. It must not be used afterwards! 28 | * 29 | */ 30 | void regex_free(struct regex *regex); 31 | 32 | /** 33 | * Checks if the given regular expression matches the given input and returns 34 | * true if it does. In either case, it logs the outcome using LOG(), so it will 35 | * be visible without debug logging. 36 | * 37 | */ 38 | bool regex_matches(struct regex *regex, const char *input); 39 | -------------------------------------------------------------------------------- /testcases/t/514-ipc-workspace-multi-monitor.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Ticket: #990 18 | # Bug still in: 4.5.1-23-g82b5978 19 | 20 | use i3test i3_config => <condvar; 29 | my @events = events_for( 30 | sub { cmd 'focus output right' }, 31 | 'workspace'); 32 | 33 | my $current_ws = get_ws(focused_ws); 34 | 35 | is(scalar @events, 1, 'Received 1 event'); 36 | is($events[0]->{current}->{id}, $current_ws->{id}, 'Event gave correct current workspace'); 37 | is($events[0]->{old}->{id}, $old_ws->{id}, 'Event gave correct old workspace'); 38 | 39 | done_testing; 40 | -------------------------------------------------------------------------------- /testcases/t/104-focus-stack.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Checks if the focus is correctly restored, when creating a floating client 18 | # over an unfocused tiling client and destroying the floating one again. 19 | 20 | use i3test; 21 | 22 | fresh_workspace; 23 | 24 | cmd 'split h'; 25 | my $tiled_left = open_window; 26 | my $tiled_right = open_window; 27 | 28 | # Get input focus before creating the floating window 29 | my $focus = $x->input_focus; 30 | 31 | # Create a floating window which is smaller than the minimum enforced size of i3 32 | my $window = open_floating_window; 33 | 34 | is($x->input_focus, $window->id, 'floating window focused'); 35 | 36 | $window->unmap; 37 | 38 | wait_for_unmap $window; 39 | 40 | is($x->input_focus, $focus, 'Focus correctly restored'); 41 | 42 | done_testing; 43 | -------------------------------------------------------------------------------- /testcases/t/191-resize-levels.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Verifies that you can resize across different levels of containers even when 18 | # they are all of the same orientation. 19 | # (Ticket #754) 20 | use i3test; 21 | 22 | my $tmp = fresh_workspace; 23 | 24 | open_window; 25 | open_window; 26 | cmd 'split v'; 27 | my $middle = open_window; 28 | open_window; 29 | cmd 'focus parent'; 30 | cmd 'split h'; 31 | open_window; 32 | 33 | cmd '[id="' . $middle->id . '"] focus'; 34 | is($x->input_focus, $middle->id, 'middle window focused'); 35 | 36 | cmd 'resize grow left 10px or 25ppt'; 37 | 38 | my ($nodes, $focus) = get_ws_content($tmp); 39 | 40 | cmp_float($nodes->[0]->{percent}, 0.25, 'left container got only 25%'); 41 | cmp_float($nodes->[1]->{percent}, 0.75, 'right container got 75%'); 42 | 43 | done_testing; 44 | -------------------------------------------------------------------------------- /testcases/t/262-config-validation.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Ensures that calling i3 with the -C switch works (smoke test). 18 | # Ticket: #2144 19 | use i3test i3_autostart => 0; 20 | use POSIX ":sys_wait_h"; 21 | use Time::HiRes qw(sleep); 22 | 23 | my $config = < 1); 31 | isnt($exit_code, 0, 'i3 exited with an error code'); 32 | 33 | my $log = get_i3_log; 34 | 35 | # We don't care so much about the output (there are tests for this), but rather 36 | # that we got correct output at all instead of, e.g., a segfault. 37 | ok($log =~ /Expected one of these tokens/, 'an invalid config token was found'); 38 | 39 | done_testing; 40 | -------------------------------------------------------------------------------- /testcases/t/270-config-no-newline-end.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Make sure that configs that end without a newline don't crash i3. 18 | # Ticket: #2934 19 | use i3test i3_autostart => 0; 20 | 21 | my $first_lines = <<'EOT'; 22 | set $workspace1 workspace number 1 23 | set $workspace0 workspace eggs 24 | 25 | bindsym Mod4+1 $workspace1 26 | EOT 27 | 28 | # Intentionally don't add a trailing newline for the last line since this is 29 | # what triggered the bug. 30 | my $last_line = 'bindsym Mod4+0 $workspace0'; 31 | my $config = "${first_lines}${last_line}"; 32 | 33 | my $pid = launch_with_config($config); 34 | does_i3_live; 35 | 36 | my $i3 = i3(get_socket_path()); 37 | my $ws = $i3->get_workspaces->recv; 38 | is($ws->[0]->{name}, 'eggs', 'last line processed correctly'); 39 | 40 | exit_gracefully($pid); 41 | done_testing; 42 | -------------------------------------------------------------------------------- /testcases/t/296-regress-focus-behind-fullscreen-floating.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Test that directional focus gives focus to floating fullscreen containers when 18 | # switching workspaces. 19 | # Ticket: #3201 20 | # Bug still in: 4.15-59-gb849fe3e 21 | use i3test i3_config => < 0); 29 | my $ws = fresh_workspace(output => 1); 30 | open_window; 31 | open_floating_window; 32 | cmd 'fullscreen enable'; 33 | my $expected_focus = get_focused($ws); 34 | 35 | cmd 'focus left'; 36 | cmd 'focus right'; 37 | 38 | is (get_focused($ws), $expected_focus, 'floating fullscreen window focused after directional focus'); 39 | 40 | done_testing; 41 | -------------------------------------------------------------------------------- /testcases/t/507-workspace-move-crash.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Tests whether i3 crashes on cross-output moves with one workspace per output. 18 | # Ticket: #827 19 | # Bug still in: 4.3-78-g66b389c 20 | # 21 | use List::Util qw(first); 22 | use i3test i3_config => <get_property( 23 | 0, 24 | $x->get_root_window(), 25 | $x->atom(name => '_NET_SUPPORTING_WM_CHECK')->id, 26 | $x->atom(name => 'WINDOW')->id, 27 | 0, 28 | 4096 29 | ); 30 | 31 | my $reply = $x->get_property_reply($cookie->{sequence}); 32 | my $len = $reply->{length}; 33 | return undef if $len == 0; 34 | 35 | return unpack("L", $reply->{value}); 36 | } 37 | 38 | my $window = open_window; 39 | sync_with_i3; 40 | is($x->input_focus, $window->id, 'sanity check: window has input focus'); 41 | cmd 'kill'; 42 | sync_with_i3; 43 | is($x->input_focus, get_ewmh_window(), 'focus falls back to the EWMH window'); 44 | 45 | done_testing; 46 | -------------------------------------------------------------------------------- /m4/ax_require_defined.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_require_defined.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_REQUIRE_DEFINED(MACRO) 8 | # 9 | # DESCRIPTION 10 | # 11 | # AX_REQUIRE_DEFINED is a simple helper for making sure other macros have 12 | # been defined and thus are available for use. This avoids random issues 13 | # where a macro isn't expanded. Instead the configure script emits a 14 | # non-fatal: 15 | # 16 | # ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found 17 | # 18 | # It's like AC_REQUIRE except it doesn't expand the required macro. 19 | # 20 | # Here's an example: 21 | # 22 | # AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) 23 | # 24 | # LICENSE 25 | # 26 | # Copyright (c) 2014 Mike Frysinger 27 | # 28 | # Copying and distribution of this file, with or without modification, are 29 | # permitted in any medium without royalty provided the copyright notice 30 | # and this notice are preserved. This file is offered as-is, without any 31 | # warranty. 32 | 33 | #serial 1 34 | 35 | AC_DEFUN([AX_REQUIRE_DEFINED], [dnl 36 | m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) 37 | ])dnl AX_REQUIRE_DEFINED 38 | -------------------------------------------------------------------------------- /libi3/resolve_tilde.c: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | */ 8 | #include "libi3.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | /* 16 | * This function resolves ~ in pathnames. 17 | * It may resolve wildcards in the first part of the path, but if no match 18 | * or multiple matches are found, it just returns a copy of path as given. 19 | * 20 | */ 21 | char *resolve_tilde(const char *path) { 22 | static glob_t globbuf; 23 | char *head, *tail, *result; 24 | 25 | tail = strchr(path, '/'); 26 | head = sstrndup(path, tail ? (size_t)(tail - path) : strlen(path)); 27 | 28 | int res = glob(head, GLOB_TILDE, NULL, &globbuf); 29 | free(head); 30 | /* no match, or many wildcard matches are bad */ 31 | if (res == GLOB_NOMATCH || globbuf.gl_pathc != 1) 32 | result = sstrdup(path); 33 | else if (res != 0) { 34 | err(EXIT_FAILURE, "glob() failed"); 35 | } else { 36 | head = globbuf.gl_pathv[0]; 37 | result = scalloc(strlen(head) + (tail ? strlen(tail) : 0) + 1, 1); 38 | strcpy(result, head); 39 | if (tail) { 40 | strcat(result, tail); 41 | } 42 | } 43 | globfree(&globbuf); 44 | 45 | return result; 46 | } 47 | -------------------------------------------------------------------------------- /testcases/t/137-floating-unmap.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression test: Floating windows were not correctly unmapped when switching 18 | # to a different workspace. 19 | 20 | use i3test; 21 | 22 | my $i3 = i3(get_socket_path()); 23 | 24 | my $tmp = fresh_workspace; 25 | 26 | ############################################################################# 27 | # 1: open a floating window, get it mapped 28 | ############################################################################# 29 | 30 | # Create a floating window which is smaller than the minimum enforced size of i3 31 | my $window = open_floating_window; 32 | ok($window->mapped, 'Window is mapped'); 33 | 34 | # switch to a different workspace, see if the window is still mapped? 35 | 36 | my $otmp = fresh_workspace; 37 | 38 | sync_with_i3; 39 | 40 | ok(!$window->mapped, 'Window is not mapped after switching ws'); 41 | 42 | cmd "nop testcase done"; 43 | 44 | done_testing; 45 | -------------------------------------------------------------------------------- /testcases/t/161-regress-borders-restart.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression test to check if borders are correctly restored after an inplace 18 | # restart. 19 | # found in eb8ad348b28e243cba1972e802ca8ee636472fc9 20 | # 21 | use List::Util qw(first); 22 | use i3test; 23 | 24 | my $i3 = i3(get_socket_path()); 25 | my $tmp = fresh_workspace; 26 | my $window = open_window; 27 | 28 | sub get_border_style { 29 | my @content = @{get_ws_content($tmp)}; 30 | my $wininfo = first { $_->{window} == $window->id } @content; 31 | 32 | return $wininfo->{border}; 33 | } 34 | 35 | is(get_border_style(), 'normal', 'border style normal'); 36 | 37 | cmd 'border 1pixel'; 38 | 39 | is(get_border_style(), 'pixel', 'border style 1pixel after changing'); 40 | 41 | # perform an inplace-restart 42 | cmd 'restart'; 43 | 44 | does_i3_live; 45 | 46 | is(get_border_style(), 'pixel', 'border style still 1pixel after restart'); 47 | 48 | done_testing; 49 | -------------------------------------------------------------------------------- /testcases/t/520-regress-focus-direction-floating.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Ensure that `focus [direction]` will focus an existing floating con when no 18 | # tiling con exists on the output in [direction] when focusing across outputs 19 | # Bug still in: 4.7.2-204-g893dbae 20 | use i3test i3_config => <input_focus, $win->id, 40 | 'Focusing across outputs with `focus [direction]` should focus an existing floating con when no tiling con exists on the output in [direction].'); 41 | 42 | done_testing; 43 | -------------------------------------------------------------------------------- /i3bar/include/workspaces.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3bar - an xcb-based status- and ws-bar for i3 5 | * © 2010 Axel Wagner and contributors (see also: LICENSE) 6 | * 7 | * workspaces.c: Maintaining the workspace lists 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include "common.h" 13 | 14 | #include 15 | 16 | typedef struct i3_ws i3_ws; 17 | 18 | TAILQ_HEAD(ws_head, i3_ws); 19 | 20 | /* 21 | * Start parsing the received JSON string 22 | * 23 | */ 24 | void parse_workspaces_json(char *json); 25 | 26 | /* 27 | * free() all workspace data structures 28 | * 29 | */ 30 | void free_workspaces(void); 31 | 32 | struct i3_ws { 33 | int num; /* The internal number of the ws */ 34 | char *canonical_name; /* The true name of the ws according to the ipc */ 35 | i3String *name; /* The name of the ws that is displayed on the bar */ 36 | int name_width; /* The rendered width of the name */ 37 | bool visible; /* If the ws is currently visible on an output */ 38 | bool focused; /* If the ws is currently focused */ 39 | bool urgent; /* If the urgent hint of the ws is set */ 40 | rect rect; /* The rect of the ws (not used (yet)) */ 41 | struct i3_output *output; /* The current output of the ws */ 42 | 43 | TAILQ_ENTRY(i3_ws) 44 | tailq; /* Pointer for the TAILQ-Macro */ 45 | }; 46 | -------------------------------------------------------------------------------- /include/xcursor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * xcursor.c: libXcursor support for themed cursors. 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | #include 15 | 16 | enum xcursor_cursor_t { 17 | XCURSOR_CURSOR_POINTER = 0, 18 | XCURSOR_CURSOR_RESIZE_HORIZONTAL, 19 | XCURSOR_CURSOR_RESIZE_VERTICAL, 20 | XCURSOR_CURSOR_TOP_LEFT_CORNER, 21 | XCURSOR_CURSOR_TOP_RIGHT_CORNER, 22 | XCURSOR_CURSOR_BOTTOM_LEFT_CORNER, 23 | XCURSOR_CURSOR_BOTTOM_RIGHT_CORNER, 24 | XCURSOR_CURSOR_WATCH, 25 | XCURSOR_CURSOR_MOVE, 26 | XCURSOR_CURSOR_MAX 27 | }; 28 | 29 | void xcursor_load_cursors(void); 30 | xcb_cursor_t xcursor_get_cursor(enum xcursor_cursor_t c); 31 | int xcursor_get_xcb_cursor(enum xcursor_cursor_t c); 32 | 33 | /** 34 | * Sets the cursor of the root window to the 'pointer' cursor. 35 | * 36 | * This function is called when i3 is initialized, because with some login 37 | * managers, the root window will not have a cursor otherwise. 38 | * 39 | * We have a separate xcursor function to use the same X11 connection as the 40 | * xcursor_load_cursors() function. If we mix the Xlib and the XCB connection, 41 | * races might occur (even though we flush the Xlib connection). 42 | * 43 | */ 44 | void xcursor_set_root_cursor(int cursor_id); 45 | -------------------------------------------------------------------------------- /include/scratchpad.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * scratchpad.c: Scratchpad functions (TODO: more description) 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | /** 15 | * Moves the specified window to the __i3_scratch workspace, making it floating 16 | * and setting the appropriate scratchpad_state. 17 | * 18 | * Gets called upon the command 'move scratchpad'. 19 | * 20 | */ 21 | void scratchpad_move(Con *con); 22 | 23 | /** 24 | * Either shows the top-most scratchpad window (con == NULL) or shows the 25 | * specified con (if it is scratchpad window). 26 | * 27 | * When called with con == NULL and the currently focused window is a 28 | * scratchpad window, this serves as a shortcut to hide it again (so the user 29 | * can press the same key to quickly look something up). 30 | * 31 | */ 32 | bool scratchpad_show(Con *con); 33 | 34 | /** 35 | * When starting i3 initially (and after each change to the connected outputs), 36 | * this function fixes the resolution of the __i3 pseudo-output. When that 37 | * resolution is not set to a function which shares a common divisor with every 38 | * active output’s resolution, floating point calculation errors will lead to 39 | * the scratchpad window moving when shown repeatedly. 40 | * 41 | */ 42 | void scratchpad_fix_resolution(void); 43 | -------------------------------------------------------------------------------- /testcases/t/293-sticky-output-crash.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Verifies that i3 does not crash when opening a floating sticky on one output 18 | # and then switching empty workspaces on the other output. 19 | # Ticket: #3075 20 | # Bug still in: 4.14-191-g9d2d602d 21 | use i3test i3_config => < 0); 29 | open_window; 30 | cmd 'sticky enable, floating enable'; 31 | 32 | # Switch to the right output and open a new workspace. 33 | my $ws = fresh_workspace(output => 1); 34 | does_i3_live; 35 | 36 | # Verify results. 37 | is(@{get_ws($ws)->{floating_nodes}}, 0, 'workspace in right output is empty'); 38 | $ws = fresh_workspace(output => 0); 39 | is(@{get_ws($ws)->{floating_nodes}}, 1, 'new workspace in left output has the sticky container'); 40 | 41 | done_testing; 42 | -------------------------------------------------------------------------------- /testcases/t/193-ipc-version.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Verifies that we can get the version number of i3 via IPC. 18 | use i3test; 19 | 20 | my $i3 = i3(get_socket_path()); 21 | $i3->connect->recv; 22 | # We explicitly send the version message because AnyEvent::I3’s 'version' sugar 23 | # method has a fallback which tries to parse the version number from i3 24 | # --version for older versions, and we want to avoid using that. 25 | my $version = $i3->message(7, "")->recv; 26 | 27 | # We need to change this when the major version changes (but we need to touch a 28 | # lot of changes then anyways). 29 | is($version->{major}, 4, 'major version is 4'); 30 | 31 | cmp_ok($version->{minor}, '>', 0, 'minor version > 0'); 32 | 33 | is(int($version->{minor}), $version->{minor}, 'minor version is an integer'); 34 | is(int($version->{patch}), $version->{patch}, 'patch version is an integer'); 35 | like($version->{human_readable}, qr/branch/, 'human readable version contains branch name'); 36 | 37 | done_testing; 38 | -------------------------------------------------------------------------------- /testcases/t/231-ipc-floating-event.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Test that the window::floating event works correctly. This event should be 18 | # emitted when a window transitions to or from the floating state. 19 | # Bug still in: 4.8-7-gf4a8253 20 | use i3test; 21 | 22 | sub floating_subtest { 23 | my ($win, $cmd, $want) = @_; 24 | 25 | my @events = events_for( 26 | sub { cmd $cmd }, 27 | 'window'); 28 | 29 | my @floating = grep { $_->{change} eq 'floating' } @events; 30 | is(scalar @floating, 1, 'Received 1 floating event'); 31 | is($floating[0]->{container}->{window}, $win->{id}, "window id matches"); 32 | is($floating[0]->{container}->{floating}, $want, "floating is $want"); 33 | } 34 | 35 | my $win = open_window(); 36 | 37 | subtest 'floating enable', \&floating_subtest, $win, '[id="' . $win->{id} . '"] floating enable', 'user_on'; 38 | subtest 'floating disable', \&floating_subtest, $win, '[id="' . $win->{id} . '"] floating disable', 'user_off'; 39 | 40 | done_testing; 41 | -------------------------------------------------------------------------------- /testcases/t/140-focus-lost.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression: Check if the focus stays the same when switching the layout 18 | # bug introduced by 77d0d42ed2d7ac8cafe267c92b35a81c1b9491eb 19 | use i3test; 20 | 21 | my $i3 = i3(get_socket_path()); 22 | 23 | sub check_order { 24 | my ($msg) = @_; 25 | 26 | my @ws = @{$i3->get_workspaces->recv}; 27 | my @nums = map { $_->{num} } grep { defined($_->{num}) } @ws; 28 | my @sorted = sort @nums; 29 | 30 | is_deeply(\@nums, \@sorted, $msg); 31 | } 32 | 33 | my $tmp = fresh_workspace; 34 | 35 | my $left = open_window; 36 | my $mid = open_window; 37 | my $right = open_window; 38 | 39 | diag("left = " . $left->id . ", mid = " . $mid->id . ", right = " . $right->id); 40 | 41 | is($x->input_focus, $right->id, 'Right window focused'); 42 | 43 | cmd 'focus left'; 44 | 45 | is($x->input_focus, $mid->id, 'Mid window focused'); 46 | 47 | cmd 'layout stacked'; 48 | 49 | is($x->input_focus, $mid->id, 'Mid window focused'); 50 | 51 | done_testing; 52 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | --- 5 | 6 | 9 | 10 | ## I'm submitting a… 11 | 12 |
13 | [ ] Bug
14 | [x] Feature Request
15 | [ ] Documentation Request
16 | [ ] Other (Please describe in detail)
17 | 
18 | 19 | ## Current Behavior 20 | 24 | 25 | ## Desired Behavior 26 | 30 | 31 | ## Environment 32 | 36 | Output of `i3 --moreversion 2>&-`: 37 |
38 | i3 version: 
39 | 
40 | 41 | 44 |
45 | - Linux Distribution & Version:
46 | - Are you using a compositor (e.g., xcompmgr or compton):
47 | 
48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | tags 3 | include/GENERATED_*.h 4 | include/all.h.pch 5 | *~ 6 | *.swp 7 | *.gcda 8 | *.gcno 9 | *.dSYM 10 | test.commands_parser 11 | test.config_parser 12 | testcases/MYMETA.json 13 | testcases/MYMETA.yml 14 | testcases/blib/ 15 | testcases/pm_to_blib 16 | AnyEvent-I3/Makefile 17 | AnyEvent-I3/META.yml 18 | AnyEvent-I3/MYMETA.json 19 | AnyEvent-I3/MYMETA.yml 20 | AnyEvent-I3/blib/ 21 | AnyEvent-I3/inc/ 22 | AnyEvent-I3/pm_to_blib 23 | *.output 24 | *.tab.* 25 | *.yy.c 26 | man/*.1 27 | man/*.xml 28 | man/*.html 29 | *.tar.bz2* 30 | i3 31 | i3-input/i3-input 32 | i3-nagbar/i3-nagbar 33 | i3-msg/i3-msg 34 | i3-config-wizard/i3-config-wizard 35 | i3-dump-log/i3-dump-log 36 | libi3.a 37 | docs/*.pdf 38 | docs/*.html 39 | !/docs/refcard.html 40 | i3-command-parser.stamp 41 | i3-config-parser.stamp 42 | .clang_complete 43 | LAST_VERSION 44 | build 45 | 46 | ################################################################################ 47 | # https://raw.githubusercontent.com/github/gitignore/master/Autotools.gitignore 48 | ################################################################################ 49 | 50 | # http://www.gnu.org/software/automake 51 | 52 | Makefile.in 53 | /ar-lib 54 | /test-driver 55 | 56 | # http://www.gnu.org/software/autoconf 57 | 58 | /autom4te.cache 59 | /autoscan.log 60 | /autoscan-*.log 61 | /aclocal.m4 62 | /compile 63 | /config.h.in 64 | /config.guess 65 | /config.sub 66 | /configure 67 | /configure.scan 68 | /depcomp 69 | /install-sh 70 | /missing 71 | /stamp-h1 72 | -------------------------------------------------------------------------------- /include/restore_layout.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * restore_layout.c: Everything for restored containers that is not pure state 8 | * parsing (which can be found in load_layout.c). 9 | * 10 | */ 11 | #pragma once 12 | 13 | #include 14 | 15 | /** 16 | * Opens a separate connection to X11 for placeholder windows when restoring 17 | * layouts. This is done as a safety measure (users can xkill a placeholder 18 | * window without killing their window manager) and for better isolation, both 19 | * on the wire to X11 and thus also in the code. 20 | * 21 | */ 22 | void restore_connect(void); 23 | 24 | /** 25 | * Open placeholder windows for all children of parent. The placeholder window 26 | * will vanish as soon as a real window is swallowed by the container. Until 27 | * then, it exposes the criteria that must be fulfilled for a window to be 28 | * swallowed by this container. 29 | * 30 | */ 31 | void restore_open_placeholder_windows(Con *con); 32 | 33 | /** 34 | * Kill the placeholder window, if placeholder refers to a placeholder window. 35 | * This function is called when manage.c puts a window into an existing 36 | * container. In order not to leak resources, we need to destroy the window and 37 | * all associated X11 objects (pixmap/gc). 38 | * 39 | */ 40 | bool restore_kill_placeholder(xcb_window_t placeholder); 41 | -------------------------------------------------------------------------------- /testcases/t/127-regress-floating-parent.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression: make a container floating, kill its parent, make it tiling again 18 | # 19 | use i3test; 20 | 21 | my $tmp = fresh_workspace; 22 | 23 | cmd 'open'; 24 | my $left = get_focused($tmp); 25 | cmd 'open'; 26 | my $old = get_focused($tmp); 27 | cmd 'split v'; 28 | cmd 'open'; 29 | my $floating = get_focused($tmp); 30 | diag("focused floating: " . get_focused($tmp)); 31 | cmd 'mode toggle'; 32 | sync_with_i3; 33 | 34 | # kill old container 35 | cmd qq|[con_id="$old"] focus|; 36 | is(get_focused($tmp), $old, 'old container focused'); 37 | cmd 'kill'; 38 | 39 | # kill left container 40 | cmd qq|[con_id="$left"] focus|; 41 | is(get_focused($tmp), $left, 'old container focused'); 42 | cmd 'kill'; 43 | 44 | # focus floating window, make it tiling again 45 | cmd qq|[con_id="$floating"] focus|; 46 | is(get_focused($tmp), $floating, 'floating window focused'); 47 | 48 | sync_with_i3; 49 | cmd 'mode toggle'; 50 | 51 | does_i3_live; 52 | 53 | done_testing; 54 | -------------------------------------------------------------------------------- /man/i3-sensible-terminal.man: -------------------------------------------------------------------------------- 1 | i3-sensible-terminal(1) 2 | ======================= 3 | Michael Stapelberg 4 | v4.2, August 2012 5 | 6 | == NAME 7 | 8 | i3-sensible-terminal - launches $TERMINAL with fallbacks 9 | 10 | == SYNOPSIS 11 | 12 | i3-sensible-terminal [arguments] 13 | 14 | == DESCRIPTION 15 | 16 | i3-sensible-terminal is invoked in the i3 default config to start a terminal. 17 | This wrapper script is necessary since there is no distribution-independent 18 | terminal launcher (but for example Debian has x-terminal-emulator). 19 | Distribution packagers are responsible for shipping this script in a way which 20 | is appropriate for the distribution. 21 | 22 | It tries to start one of the following (in that order): 23 | 24 | * $TERMINAL (this is a non-standard variable) 25 | * x-terminal-emulator (only present on Debian and derivatives) 26 | * urxvt 27 | * rxvt 28 | * termit 29 | * terminator 30 | * Eterm 31 | * aterm 32 | * uxterm 33 | * xterm 34 | * gnome-terminal 35 | * roxterm 36 | * xfce4-terminal 37 | * termite 38 | * lxterminal 39 | * mate-terminal 40 | * terminology 41 | * st 42 | * qterminal 43 | * lilyterm 44 | * tilix 45 | * terminix 46 | * konsole 47 | * kitty 48 | * guake 49 | * tilda 50 | * alacritty 51 | * hyper 52 | 53 | Please don’t complain about the order: If the user has any preference, they will 54 | have $TERMINAL set or modified their i3 configuration file. 55 | 56 | == SEE ALSO 57 | 58 | i3(1) 59 | 60 | == AUTHOR 61 | 62 | Michael Stapelberg and contributors 63 | -------------------------------------------------------------------------------- /testcases/t/144-regress-floating-resize.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression: when resizing two containers on a workspace, opening a floating 18 | # client, then closing it again, i3 will re-distribute the space on the 19 | # workspace as if a tiling container was closed, leading to the containers 20 | # taking much more space than they possibly could. 21 | # 22 | use i3test; 23 | use List::Util qw(sum); 24 | 25 | my $tmp = fresh_workspace; 26 | 27 | my $first = open_window; 28 | my $second = open_window; 29 | 30 | my ($nodes, $focus) = get_ws_content($tmp); 31 | my $old_sum = sum map { $_->{rect}->{width} } @{$nodes}; 32 | 33 | cmd 'resize grow left 10 px or 25 ppt'; 34 | cmd 'split v'; 35 | 36 | sync_with_i3; 37 | 38 | my $third = open_window; 39 | 40 | cmd 'mode toggle'; 41 | sync_with_i3; 42 | 43 | cmd 'kill'; 44 | sync_with_i3; 45 | 46 | ($nodes, $focus) = get_ws_content($tmp); 47 | my $new_sum = sum map { $_->{rect}->{width} } @{$nodes}; 48 | 49 | is($old_sum, $new_sum, 'combined container width is still equal'); 50 | 51 | done_testing; 52 | -------------------------------------------------------------------------------- /testcases/t/236-floating-focus-raise.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Test that focusing floating windows with the command `focus [direction]` 18 | # promotes the focused window to the top of the rendering stack. 19 | # Ticket: #1322 20 | # Bug still in: 4.8-88-gcc09348 21 | use i3test; 22 | 23 | my $ws = fresh_workspace; 24 | 25 | my $win1 = open_floating_window; 26 | my $win2 = open_floating_window; 27 | my $win3 = open_floating_window; 28 | 29 | # it's a good idea to do this a few times because of the implementation 30 | for my $i (1 .. 3) { 31 | cmd 'focus left'; 32 | my $ws_con = get_ws($ws); 33 | is($ws_con->{floating_nodes}[-1]->{nodes}[0]->{id}, get_focused($ws), 34 | "focus left put the focused window on top of the floating windows (try $i)"); 35 | } 36 | 37 | for my $i (1 .. 3) { 38 | cmd 'focus right'; 39 | my $ws_con = get_ws($ws); 40 | is($ws_con->{floating_nodes}[-1]->{nodes}[0]->{id}, get_focused($ws), 41 | "focus right put the focused window on top of the floating windows (try $i)"); 42 | } 43 | 44 | done_testing; 45 | -------------------------------------------------------------------------------- /testcases/t/295-net-wm-state-focused.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • http://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • http://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • http://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Tests for setting and removing the _NET_WM_STATE_FOCUSED atom properly. 18 | # Ticket: #2273 19 | use i3test; 20 | use X11::XCB qw(:all); 21 | 22 | my ($windowA, $windowB); 23 | 24 | fresh_workspace; 25 | $windowA = open_window; 26 | ok(is_net_wm_state_focused($windowA), 'a newly opened window that is focused should have _NET_WM_STATE_FOCUSED set'); 27 | 28 | $windowB = open_window; 29 | ok(!is_net_wm_state_focused($windowA), 'when a another window is focused, the old window should not have _NET_WM_STATE_FOCUSED set'); 30 | ok(is_net_wm_state_focused($windowB), 'a newly opened window that is focused should have _NET_WM_STATE_FOCUSED set'); 31 | 32 | # See issue #3495. 33 | cmd 'kill'; 34 | ok(is_net_wm_state_focused($windowA), 'when the second window is closed, the first window should have _NET_WM_STATE_FOCUSED set'); 35 | 36 | fresh_workspace; 37 | ok(!is_net_wm_state_focused($windowA), 'when focus moves to the ewmh support window, no window should have _NET_WM_STATE_FOCUSED set'); 38 | 39 | done_testing; 40 | -------------------------------------------------------------------------------- /travis/travis-base-386.Dockerfile: -------------------------------------------------------------------------------- 1 | # vim:ft=Dockerfile 2 | # Same as travis-base.Dockerfile, but without the test suite dependencies since 3 | # we only build Debian packages on i386, we don’t run the tests. 4 | FROM i386/debian:sid 5 | 6 | RUN echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup 7 | # Paper over occasional network flakiness of some mirrors. 8 | RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry 9 | 10 | # NOTE: I tried exclusively using gce_debian_mirror.storage.googleapis.com 11 | # instead of httpredir.debian.org, but the results (Fetched 123 MB in 36s (3357 12 | # kB/s)) are not any better than httpredir.debian.org (Fetched 123 MB in 34s 13 | # (3608 kB/s)). Hence, let’s stick with httpredir.debian.org (default) for now. 14 | 15 | # Install mk-build-deps (for installing the i3 build dependencies), 16 | # clang and clang-format-6.0 (for checking formatting and building with clang), 17 | # lintian (for checking spelling errors), 18 | RUN linux32 apt-get update && \ 19 | DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ 20 | dpkg-dev devscripts git equivs \ 21 | clang clang-format-6.0 \ 22 | lintian && \ 23 | rm -rf /var/lib/apt/lists/* 24 | 25 | # Install i3 build dependencies. 26 | COPY debian/control /usr/src/i3-debian-packaging/control 27 | RUN linux32 apt-get update && \ 28 | DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ 29 | rm -rf /var/lib/apt/lists/* 30 | -------------------------------------------------------------------------------- /i3bar/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2010 Axel Wagner 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | * Neither the name of Axel Wagner nor the 15 | names of contributors may be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY Axel Wagner ''AS IS'' AND ANY 19 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL Axel Wagner BE LIABLE FOR ANY 22 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /travis/travis-base-ubuntu-386.Dockerfile: -------------------------------------------------------------------------------- 1 | # vim:ft=Dockerfile 2 | # Same as travis-base.Dockerfile, but without the test suite dependencies since 3 | # we only build Debian packages on Ubuntu i386, we don’t run the tests. 4 | FROM i386/ubuntu:bionic 5 | 6 | RUN echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup 7 | # Paper over occasional network flakiness of some mirrors. 8 | RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry 9 | 10 | # NOTE: I tried exclusively using gce_debian_mirror.storage.googleapis.com 11 | # instead of httpredir.debian.org, but the results (Fetched 123 MB in 36s (3357 12 | # kB/s)) are not any better than httpredir.debian.org (Fetched 123 MB in 34s 13 | # (3608 kB/s)). Hence, let’s stick with httpredir.debian.org (default) for now. 14 | 15 | # Install mk-build-deps (for installing the i3 build dependencies), 16 | # clang and clang-format-6.0 (for checking formatting and building with clang), 17 | # lintian (for checking spelling errors), 18 | RUN linux32 apt-get update && \ 19 | DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ 20 | dpkg-dev devscripts git equivs \ 21 | clang clang-format-6.0 \ 22 | lintian && \ 23 | rm -rf /var/lib/apt/lists/* 24 | 25 | # Install i3 build dependencies. 26 | COPY debian/control /usr/src/i3-debian-packaging/control 27 | RUN linux32 apt-get update && \ 28 | DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ 29 | rm -rf /var/lib/apt/lists/* 30 | -------------------------------------------------------------------------------- /AnyEvent-I3/t/boilerplate.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | 3 | use strict; 4 | use warnings; 5 | use Test::More tests => 3; 6 | 7 | sub not_in_file_ok { 8 | my ($filename, %regex) = @_; 9 | open( my $fh, '<', $filename ) 10 | or die "couldn't open $filename for reading: $!"; 11 | 12 | my %violated; 13 | 14 | while (my $line = <$fh>) { 15 | while (my ($desc, $regex) = each %regex) { 16 | if ($line =~ $regex) { 17 | push @{$violated{$desc}||=[]}, $.; 18 | } 19 | } 20 | } 21 | 22 | if (%violated) { 23 | fail("$filename contains boilerplate text"); 24 | diag "$_ appears on lines @{$violated{$_}}" for keys %violated; 25 | } else { 26 | pass("$filename contains no boilerplate text"); 27 | } 28 | } 29 | 30 | sub module_boilerplate_ok { 31 | my ($module) = @_; 32 | not_in_file_ok($module => 33 | 'the great new $MODULENAME' => qr/ - The great new /, 34 | 'boilerplate description' => qr/Quick summary of what the module/, 35 | 'stub function definition' => qr/function[12]/, 36 | ); 37 | } 38 | 39 | TODO: { 40 | local $TODO = "Need to replace the boilerplate text"; 41 | 42 | not_in_file_ok(README => 43 | "The README is used..." => qr/The README is used/, 44 | "'version information here'" => qr/to provide version information/, 45 | ); 46 | 47 | not_in_file_ok(Changes => 48 | "placeholder date/time" => qr(Date/time) 49 | ); 50 | 51 | module_boilerplate_ok('lib/AnyEvent/I3.pm'); 52 | 53 | 54 | } 55 | 56 | -------------------------------------------------------------------------------- /testcases/t/511-scratchpad-configure-request.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Tests that ConfigureRequests don’t make windows fall out of the scratchpad. 18 | # Ticket: #898 19 | # Bug still in: 4.4-15-g770ead6 20 | use i3test i3_config => < 0); 28 | my $right_ws = fresh_workspace(output => 1); 29 | 30 | my $window = open_window; 31 | cmd 'move scratchpad'; 32 | 33 | # Cause a ConfigureRequest by setting the window’s position/size. 34 | my ($a, $t) = $window->rect; 35 | $window->rect(X11::XCB::Rect->new(x => 0, y => 0, width => $a->width, height => $a->height)); 36 | 37 | sync_with_i3; 38 | 39 | my $ws = get_ws($left_ws); 40 | is(scalar @{$ws->{floating_nodes}}, 0, 'scratchpad window still in scratchpad after ConfigureRequest'); 41 | $ws = get_ws($right_ws); 42 | is(scalar @{$ws->{floating_nodes}}, 0, 'scratchpad window still in scratchpad after ConfigureRequest'); 43 | 44 | done_testing; 45 | -------------------------------------------------------------------------------- /testcases/t/512-move-wraps.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Verifies that moving containers wraps across outputs. 18 | # E.g. when you have a container on the right output and you move it to the 19 | # right, it should appear on the left output. 20 | # Bug still in: 4.4-106-g3cd4b8c 21 | use i3test i3_config => < 1); 29 | my $left = fresh_workspace(output => 0); 30 | 31 | my $win = open_window; 32 | 33 | is_num_children($left, 1, 'one container on left workspace'); 34 | 35 | cmd 'move container to output right'; 36 | cmd 'focus output right'; 37 | 38 | is_num_children($left, 0, 'no containers on left workspace'); 39 | is_num_children($right, 1, 'one container on right workspace'); 40 | 41 | cmd 'move container to output right'; 42 | 43 | is_num_children($left, 1, 'one container on left workspace'); 44 | is_num_children($right, 0, 'no containers on right workspace'); 45 | 46 | done_testing; 47 | -------------------------------------------------------------------------------- /travis/travis-base-ubuntu.Dockerfile: -------------------------------------------------------------------------------- 1 | # vim:ft=Dockerfile 2 | # Same as travis-base.Dockerfile, but without the test suite dependencies since 3 | # we only build Debian packages on Ubuntu, we don’t run the tests. 4 | FROM ubuntu:bionic 5 | 6 | RUN echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup 7 | # Paper over occasional network flakiness of some mirrors. 8 | RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry 9 | 10 | # NOTE: I tried exclusively using gce_debian_mirror.storage.googleapis.com 11 | # instead of httpredir.debian.org, but the results (Fetched 123 MB in 36s (3357 12 | # kB/s)) are not any better than httpredir.debian.org (Fetched 123 MB in 34s 13 | # (3608 kB/s)). Hence, let’s stick with httpredir.debian.org (default) for now. 14 | 15 | # Install mk-build-deps (for installing the i3 build dependencies), 16 | # clang and clang-format-6.0 (for checking formatting and building with clang), 17 | # lintian (for checking spelling errors), 18 | # test suite dependencies (for running tests) 19 | RUN apt-get update && \ 20 | DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ 21 | dpkg-dev devscripts git equivs \ 22 | clang clang-format-6.0 \ 23 | lintian && \ 24 | rm -rf /var/lib/apt/lists/* 25 | 26 | # Install i3 build dependencies. 27 | COPY debian/control /usr/src/i3-debian-packaging/control 28 | RUN apt-get update && \ 29 | DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \ 30 | rm -rf /var/lib/apt/lists/* 31 | -------------------------------------------------------------------------------- /include/output.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * output.c: Output (monitor) related functions. 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | /** 15 | * Returns the output container below the given output container. 16 | * 17 | */ 18 | Con *output_get_content(Con *output); 19 | 20 | /** 21 | * Returns an 'output' corresponding to one of left/right/down/up or a specific 22 | * output name. 23 | * 24 | */ 25 | Output *get_output_from_string(Output *current_output, const char *output_str); 26 | 27 | /** 28 | * Retrieves the primary name of an output. 29 | * 30 | */ 31 | char *output_primary_name(Output *output); 32 | 33 | /** 34 | * Returns the output for the given con. 35 | * 36 | */ 37 | Output *get_output_for_con(Con *con); 38 | 39 | /** 40 | * Iterates over all outputs and pushes sticky windows to the currently visible 41 | * workspace on that output. 42 | * 43 | * old_focus is used to determine if a sticky window is going to be focused. 44 | * old_focus might be different than the currently focused container because the 45 | * caller might need to temporarily change the focus and then call 46 | * output_push_sticky_windows. For example, workspace_show needs to set focus to 47 | * one of its descendants first, then call output_push_sticky_windows that 48 | * should focus a sticky window if it was the focused in the previous workspace. 49 | * 50 | */ 51 | void output_push_sticky_windows(Con *old_focus); 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2009, Michael Stapelberg and contributors 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | * Neither the name of Michael Stapelberg nor the 15 | names of contributors may be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY Michael Stapelberg ''AS IS'' AND ANY 19 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL Michael Stapelberg BE LIABLE FOR ANY 22 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /testcases/t/271-for_window_tilingfloating.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | use i3test i3_config => <{nodes}}; 35 | cmp_ok(@nodes, '==', 1, 'one tiling container on this workspace'); 36 | is_deeply($nodes[0]->{marks}, [ 'tiled' ], "mark set for 'tiling' criterion"); 37 | 38 | @nodes = @{get_ws($tmp)->{floating_nodes}}; 39 | cmp_ok(@nodes, '==', 1, 'one floating container on this workspace'); 40 | is_deeply($nodes[0]->{nodes}[0]->{marks}, [ 'floated' ], "mark set for 'floating' criterion"); 41 | 42 | ############################################################## 43 | 44 | done_testing; 45 | -------------------------------------------------------------------------------- /testcases/t/277-ipc-window-urgent.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Test that the window::urgent event works correctly. The window::urgent event 18 | # should be emitted when a window becomes urgent or loses its urgent status. 19 | # 20 | use i3test; 21 | 22 | fresh_workspace; 23 | my $win = open_window; 24 | my $dummy_win = open_window; 25 | 26 | sub urgency_subtest { 27 | my ($subscribecb, $win, $want) = @_; 28 | 29 | my @events = events_for( 30 | $subscribecb, 31 | 'window'); 32 | 33 | my @urgent = grep { $_->{change} eq 'urgent' } @events; 34 | is(scalar @urgent, 1, 'Received 1 window::urgent event'); 35 | is($urgent[0]->{container}->{window}, $win->{id}, "window id matches"); 36 | is($urgent[0]->{container}->{urgent}, $want, "urgent is $want"); 37 | } 38 | 39 | subtest "urgency set", \&urgency_subtest, 40 | sub { 41 | $win->add_hint('urgency'); 42 | sync_with_i3; 43 | }, 44 | $win, 45 | 1; 46 | 47 | subtest "urgency unset", \&urgency_subtest, 48 | sub { 49 | $win->delete_hint('urgency'); 50 | sync_with_i3; 51 | }, 52 | $win, 53 | 0; 54 | 55 | done_testing; 56 | -------------------------------------------------------------------------------- /testcases/t/519-mouse-warping.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 12 | # (unless you are already familiar with Perl) 13 | 14 | use i3test i3_config => <root->warp_pointer(0, 0); 24 | 25 | ###################################################### 26 | # Open one workspace with one window on both outputs # 27 | ###################################################### 28 | 29 | # Open window on workspace 1, left output 30 | is(focused_ws, '1', 'starting with focus on workspace 1'); 31 | open_window; 32 | 33 | # Open window on workspace 2, right output 34 | cmd 'focus output right'; 35 | is(focused_ws, '2', 'moved focus to workspace 2'); 36 | open_window; 37 | 38 | # If mouse_warping is disabled, the pointer has not moved from 39 | # position (0, 0) when focus was switched to workspace 2 40 | $x->root->warp_pointer(0, 0); 41 | 42 | # Ensure focus is still on workspace 2 43 | is(focused_ws, '2', 'warped mouse cursor to (0, 0), focus still in workspace 2'); 44 | 45 | done_testing; 46 | -------------------------------------------------------------------------------- /include/config_parser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * config_parser.h: config parser-related definitions 8 | * 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | #include 15 | 16 | SLIST_HEAD(variables_head, Variable); 17 | extern pid_t config_error_nagbar_pid; 18 | 19 | /** 20 | * An intermediate reprsentation of the result of a parse_config call. 21 | * Currently unused, but the JSON output will be useful in the future when we 22 | * implement a config parsing IPC command. 23 | * 24 | */ 25 | struct ConfigResultIR { 26 | /* The JSON generator to append a reply to. */ 27 | yajl_gen json_gen; 28 | 29 | /* The next state to transition to. Passed to the function so that we can 30 | * determine the next state as a result of a function call, like 31 | * cfg_criteria_pop_state() does. */ 32 | int next_state; 33 | }; 34 | 35 | struct ConfigResultIR *parse_config(const char *input, struct context *context); 36 | 37 | /** 38 | * launch nagbar to indicate errors in the configuration file. 39 | */ 40 | void start_config_error_nagbar(const char *configpath, bool has_errors); 41 | 42 | /** 43 | * Parses the given file by first replacing the variables, then calling 44 | * parse_config and launching i3-nagbar if use_nagbar is true. 45 | * 46 | * The return value is a boolean indicating whether there were errors during 47 | * parsing. 48 | * 49 | */ 50 | bool parse_file(const char *f, bool use_nagbar); 51 | -------------------------------------------------------------------------------- /testcases/t/188-regress-focus-restart.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Verifies that i3 survives inplace restarts with fullscreen containers 18 | # 19 | use i3test; 20 | 21 | my $tmp = fresh_workspace; 22 | 23 | open_window(name => 'first'); 24 | open_window(name => 'second'); 25 | 26 | cmd 'focus left'; 27 | 28 | my ($nodes, $focus) = get_ws_content($tmp); 29 | is(scalar @$nodes, 2, 'two tiling nodes on workspace'); 30 | is($nodes->[0]->{name}, 'first', 'first node name ok'); 31 | is($nodes->[1]->{name}, 'second', 'second node name ok'); 32 | is($focus->[0], $nodes->[0]->{id}, 'first node focused'); 33 | is($focus->[1], $nodes->[1]->{id}, 'second node second in focus stack'); 34 | 35 | cmd 'restart'; 36 | 37 | does_i3_live; 38 | 39 | ($nodes, $focus) = get_ws_content($tmp); 40 | is(scalar @$nodes, 2, 'still two tiling nodes on workspace'); 41 | is($nodes->[0]->{name}, 'first', 'first node name ok'); 42 | is($nodes->[1]->{name}, 'second', 'second node name ok'); 43 | is($focus->[0], $nodes->[0]->{id}, 'first node focused'); 44 | is($focus->[1], $nodes->[1]->{id}, 'second node second in focus stack'); 45 | 46 | done_testing; 47 | -------------------------------------------------------------------------------- /testcases/lib/i3test/Util.pm: -------------------------------------------------------------------------------- 1 | package i3test::Util; 2 | # vim:ts=4:sw=4:expandtab 3 | 4 | use strict; 5 | use warnings; 6 | use v5.10; 7 | 8 | use X11::XCB qw(GET_PROPERTY_TYPE_ANY); 9 | use X11::XCB::Connection; 10 | 11 | use Exporter qw(import); 12 | our @EXPORT = qw( 13 | slurp 14 | get_socket_path 15 | ); 16 | 17 | =encoding utf-8 18 | 19 | =head1 NAME 20 | 21 | i3test::Util - General utility functions 22 | 23 | =cut 24 | 25 | =head1 EXPORT 26 | 27 | =cut 28 | 29 | =head2 slurp($fn) 30 | 31 | Reads the entire file specified in the arguments and returns the content. 32 | 33 | =cut 34 | sub slurp { 35 | my ($file) = @_; 36 | my $content = do { 37 | local $/ = undef; 38 | open my $fh, "<", $file or die "could not open $file: $!"; 39 | <$fh>; 40 | }; 41 | 42 | return $content; 43 | } 44 | 45 | =head2 get_socket_path([X11::XCB::Connection]) 46 | 47 | Gets the socket path from the C atom stored on the X11 root 48 | window. 49 | 50 | =cut 51 | sub get_socket_path { 52 | my ($x) = @_; 53 | $x //= X11::XCB::Connection->new(); 54 | my $atom = $x->atom(name => 'I3_SOCKET_PATH'); 55 | my $cookie = $x->get_property(0, $x->get_root_window(), $atom->id, GET_PROPERTY_TYPE_ANY, 0, 256); 56 | my $reply = $x->get_property_reply($cookie->{sequence}); 57 | my $socketpath = $reply->{value}; 58 | if ($socketpath eq "/tmp/nested-$ENV{DISPLAY}") { 59 | $socketpath .= '-activation'; 60 | } 61 | return $socketpath; 62 | } 63 | 64 | =head1 AUTHOR 65 | 66 | Michael Stapelberg 67 | 68 | =cut 69 | 70 | 1 71 | -------------------------------------------------------------------------------- /testcases/t/239-net-close-window-request.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Test _NET_CLOSE_WINDOW requests to close a window. 18 | # See https://standards.freedesktop.org/wm-spec/wm-spec-latest.html#idm140200472668896 19 | # Ticket: #1396 20 | # Bug still in: 4.8-116-gbb1f857 21 | use i3test; 22 | 23 | sub send_close_window_request { 24 | my ($win) = @_; 25 | 26 | my $msg = pack "CCSLLLLLL", 27 | X11::XCB::CLIENT_MESSAGE, # response_type 28 | 32, # format 29 | 0, # sequence 30 | $win->id, # window 31 | $x->atom(name => '_NET_CLOSE_WINDOW')->id, # message type 32 | 0, # data32[0] 33 | 0, # data32[1] 34 | 0, # data32[2] 35 | 0, # data32[3] 36 | 0; # data32[4] 37 | 38 | $x->send_event(0, $x->get_root_window(), X11::XCB::EVENT_MASK_SUBSTRUCTURE_REDIRECT, $msg); 39 | } 40 | 41 | my $ws = fresh_workspace; 42 | my $win = open_window; 43 | 44 | send_close_window_request($win); 45 | sync_with_i3; 46 | 47 | is(@{get_ws($ws)->{nodes}}, 0, 'When a pager sends a _NET_CLOSE_WINDOW request for a window, the container should be closed'); 48 | 49 | done_testing; 50 | -------------------------------------------------------------------------------- /travis/cleanup-bintray.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # vim:ts=4:sw=4:expandtab 3 | 4 | use strict; 5 | use warnings; 6 | use Data::Dumper; 7 | use HTTP::Tiny; # in core since v5.13.9 8 | use JSON::PP; # in core since v5.13.9 9 | use MIME::Base64; # in core since v5.7 10 | use v5.13; 11 | 12 | my $repo = shift; 13 | 14 | my $auth = $ENV{'BINTRAY_USER'} . ':' . $ENV{'BINTRAY_KEY'}; 15 | die "BINTRAY_USER and/or BINTRAY_KEY environment variables not set" if $auth eq ':'; 16 | # TODO(stapelberg): switch to putting $auth into the URL once perl-modules ≥ 17 | # 5.20 is available on travis (Ubuntu Wily or newer). 18 | my $auth_header = 'Basic ' . MIME::Base64::encode_base64($auth, ""); 19 | my $apiurl = 'https://api.bintray.com/packages/i3/' . $repo . '/i3-wm'; 20 | my $client = HTTP::Tiny->new( 21 | verify_SSL => 1, 22 | default_headers => { 23 | 'authorization' => $auth_header, 24 | }); 25 | my $resp = $client->get($apiurl); 26 | die "Getting versions failed: HTTP status $resp->{status} (content: $resp->{content})" unless $resp->{success}; 27 | my $decoded = decode_json($resp->{content}); 28 | my @versions = reverse sort { 29 | (system("/usr/bin/dpkg", "--compare-versions", "$a", "gt", "$b") == 0) ? 1 : -1 30 | } @{$decoded->{versions}}; 31 | 32 | # Keep the most recent 5 versions. 33 | splice(@versions, 0, 5); 34 | 35 | for my $version (@versions) { 36 | say "Deleting old version $version"; 37 | $resp = $client->request('DELETE', "$apiurl/versions/$version"); 38 | die "Deletion of version $version failed: HTTP status $resp->{status} (content: $resp->{content})" unless $resp->{success}; 39 | } 40 | -------------------------------------------------------------------------------- /testcases/t/186-regress-assign-focus-parent.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Regression test: New windows were not opened in the correct place if they 18 | # matched an assignment. 19 | # Wrong behaviour manifested itself up to (including) commit 20 | # f78caf8c5815ae7a66de9e4b734546fd740cc19d 21 | # 22 | use i3test i3_config => < "testcase"); 34 | is_num_children('targetws', 1, 'precisely one window'); 35 | 36 | open_window(name => "testcase"); 37 | is_num_children('targetws', 2, 'precisely two windows'); 38 | 39 | cmd 'split v'; 40 | 41 | open_window(name => "testcase"); 42 | is_num_children('targetws', 2, 'still two windows'); 43 | 44 | # focus parent. the new window should now be opened right next to the last one. 45 | cmd 'focus parent'; 46 | 47 | open_window(name => "testcase"); 48 | is_num_children('targetws', 3, 'new window opened next to last one'); 49 | 50 | done_testing; 51 | -------------------------------------------------------------------------------- /libi3/mkdirp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | */ 8 | #include "libi3.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | /* 16 | * Emulates mkdir -p (creates any missing folders) 17 | * 18 | */ 19 | 20 | #if !defined(__sun) 21 | int mkdirp(const char *path, mode_t mode) { 22 | if (mkdir(path, mode) == 0) 23 | return 0; 24 | if (errno == EEXIST) { 25 | struct stat st; 26 | /* Check that the named file actually is a directory. */ 27 | if (stat(path, &st)) { 28 | ELOG("stat(%s) failed: %s\n", path, strerror(errno)); 29 | return -1; 30 | } 31 | if (!S_ISDIR(st.st_mode)) { 32 | ELOG("mkdir(%s) failed: %s\n", path, strerror(ENOTDIR)); 33 | return -1; 34 | } 35 | return 0; 36 | } else if (errno != ENOENT) { 37 | ELOG("mkdir(%s) failed: %s\n", path, strerror(errno)); 38 | return -1; 39 | } 40 | char *copy = sstrdup(path); 41 | /* strip trailing slashes, if any */ 42 | while (copy[strlen(copy) - 1] == '/') 43 | copy[strlen(copy) - 1] = '\0'; 44 | 45 | char *sep = strrchr(copy, '/'); 46 | if (sep == NULL) { 47 | free(copy); 48 | return -1; 49 | } 50 | *sep = '\0'; 51 | int result = -1; 52 | if (mkdirp(copy, mode) == 0) 53 | result = mkdirp(path, mode); 54 | free(copy); 55 | 56 | return result; 57 | } 58 | #endif 59 | -------------------------------------------------------------------------------- /testcases/t/534-dont-warp.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Verifies i3 doesn’t warp when a new floating window is opened under the cursor 18 | # over an unfocused workspace. 19 | # Ticket: #2681 20 | # Bug still in: 4.13-210-g80c23afa 21 | use i3test i3_config => <root->warp_pointer(500, 0); 40 | sync_with_i3; 41 | 42 | my $dropdown = open_floating_window; 43 | $dropdown->rect(X11::XCB::Rect->new(x => 1, y => 1, width => 100, height => 100)); 44 | sync_with_i3; 45 | 46 | my $cookie = $x->query_pointer($dropdown->{id}); 47 | my $reply = $x->query_pointer_reply($cookie->{sequence}); 48 | cmp_ok($reply->{root_x}, '<', 1024, 'pointer still on fake-0'); 49 | cmp_ok($reply->{root_y}, '<', 768, 'pointer still on fake-0'); 50 | 51 | done_testing; 52 | -------------------------------------------------------------------------------- /include/load_layout.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * load_layout.c: Restore (parts of) the layout, for example after an inplace 8 | * restart. 9 | * 10 | */ 11 | #pragma once 12 | 13 | #include 14 | 15 | typedef enum { 16 | // We could not determine the content of the JSON file. This typically 17 | // means it’s unreadable or contains garbage. 18 | JSON_CONTENT_UNKNOWN = 0, 19 | 20 | // The JSON file contains a “normal” container, i.e. a container to be 21 | // appended to an existing workspace (or split container!). 22 | JSON_CONTENT_CON = 1, 23 | 24 | // The JSON file contains a workspace container, which needs to be appended 25 | // to the output (next to the other workspaces) with special care to avoid 26 | // naming conflicts and ensuring that the workspace _has_ a name. 27 | JSON_CONTENT_WORKSPACE = 2, 28 | } json_content_t; 29 | 30 | /* Parses the given JSON file until it encounters the first “type” property to 31 | * determine whether the file contains workspaces or regular containers, which 32 | * is important to know when deciding where (and how) to append the contents. 33 | * */ 34 | json_content_t json_determine_content(const char *buf, const size_t len); 35 | 36 | /** 37 | * Returns true if the provided JSON could be parsed by yajl. 38 | * 39 | */ 40 | bool json_validate(const char *buf, const size_t len); 41 | 42 | void tree_append_json(Con *con, const char *buf, const size_t len, char **errormsg); 43 | -------------------------------------------------------------------------------- /testcases/t/146-floating-reinsert.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | use i3test; 18 | 19 | my $tmp = fresh_workspace; 20 | 21 | my $left = open_window; 22 | my $mid = open_window; 23 | 24 | cmd 'split v'; 25 | my $bottom = open_window; 26 | 27 | my ($nodes, $focus) = get_ws_content($tmp); 28 | 29 | ############################################################################# 30 | # 1: open a floating window, get it mapped 31 | ############################################################################# 32 | 33 | # Create a floating window 34 | my $window = open_floating_window; 35 | ok($window->mapped, 'Window is mapped'); 36 | 37 | ($nodes, $focus) = get_ws_content($tmp); 38 | is(@{$nodes->[1]->{nodes}}, 2, 'two windows in split con'); 39 | 40 | ############################################################################# 41 | # 2: make it tiling, see where it ends up 42 | ############################################################################# 43 | 44 | cmd 'floating toggle'; 45 | 46 | ($nodes, $focus) = get_ws_content($tmp); 47 | 48 | is(@{$nodes->[1]->{nodes}}, 3, 'three windows in split con after floating toggle'); 49 | 50 | done_testing; 51 | -------------------------------------------------------------------------------- /testcases/t/173-get-marks.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # checks if the IPC message type get_marks works correctly 18 | # 19 | use i3test; 20 | 21 | sub get_marks { 22 | return i3(get_socket_path())->get_marks->recv; 23 | } 24 | 25 | ############################################################## 26 | # 1: check that get_marks returns no marks yet 27 | ############################################################## 28 | 29 | my $tmp = fresh_workspace; 30 | 31 | my $marks = get_marks(); 32 | is_deeply($marks, [], 'no marks set so far'); 33 | 34 | ############################################################## 35 | # 2: check that setting a mark is reflected in the get_marks reply 36 | ############################################################## 37 | 38 | cmd 'open'; 39 | cmd 'mark foo'; 40 | 41 | is_deeply(get_marks(), [ 'foo' ], 'mark foo set'); 42 | 43 | ############################################################## 44 | # 3: check that the mark is gone after killing the container 45 | ############################################################## 46 | 47 | cmd 'kill'; 48 | 49 | is_deeply(get_marks(), [ ], 'mark gone'); 50 | 51 | done_testing; 52 | -------------------------------------------------------------------------------- /include/render.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | * render.c: Renders (determines position/sizes) the layout tree, updating the 8 | * various rects. Needs to be pushed to X11 (see x.c) to be visible. 9 | * 10 | */ 11 | #pragma once 12 | 13 | #include 14 | 15 | /** 16 | * This is used to keep a state to pass around when rendering a con in render_con(). 17 | * 18 | */ 19 | typedef struct render_params { 20 | /* A copy of the coordinates of the container which is being rendered. */ 21 | int x; 22 | int y; 23 | 24 | /* The computed height for decorations. */ 25 | int deco_height; 26 | /* Container rect, subtract container border. This is the actually usable space 27 | * inside this container for clients. */ 28 | Rect rect; 29 | /* The number of children of the container which is being rendered. */ 30 | int children; 31 | /* A precalculated list of sizes of each child. */ 32 | int *sizes; 33 | } render_params; 34 | 35 | /** 36 | * "Renders" the given container (and its children), meaning that all rects are 37 | * updated correctly. Note that this function does not call any xcb_* 38 | * functions, so the changes are completely done in memory only (and 39 | * side-effect free). As soon as you call x_push_changes(), the changes will be 40 | * updated in X11. 41 | * 42 | */ 43 | void render_con(Con *con, bool already_inset); 44 | 45 | /** 46 | * Returns the height for the decorations 47 | * 48 | */ 49 | int render_deco_height(void); 50 | -------------------------------------------------------------------------------- /testcases/t/265-ipc-mark.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Tests for the window::mark IPC event. 18 | # Ticket: #2501 19 | use i3test; 20 | 21 | sub mark_subtest { 22 | my ($cmd) = @_; 23 | 24 | my @events = events_for( 25 | sub { cmd $cmd }, 26 | 'window'); 27 | 28 | my @mark = grep { $_->{change} eq 'mark' } @events; 29 | is(scalar @mark, 1, 'Received 1 window::mark event'); 30 | } 31 | 32 | ############################################################################### 33 | # Marking a container triggers a 'mark' event. 34 | ############################################################################### 35 | fresh_workspace; 36 | open_window; 37 | 38 | subtest 'mark', \&mark_subtest, 'mark x'; 39 | 40 | ############################################################################### 41 | # Unmarking a container triggers a 'mark' event. 42 | ############################################################################### 43 | fresh_workspace; 44 | open_window; 45 | cmd 'mark x'; 46 | 47 | subtest 'unmark', \&mark_subtest, 'unmark x'; 48 | 49 | ############################################################################### 50 | 51 | done_testing; 52 | -------------------------------------------------------------------------------- /testcases/t/115-ipc-workspaces.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | 17 | use i3test; 18 | 19 | my $old_ws = get_ws(focused_ws()); 20 | 21 | # We are switching to an empty workpspace from an empty workspace, so we expect 22 | # to receive "init", "focus", and "empty". 23 | my @events = events_for( 24 | sub { cmd 'workspace 2' }, 25 | 'workspace'); 26 | 27 | my $current_ws = get_ws(focused_ws()); 28 | 29 | is(scalar @events, 3, 'Received 3 events'); 30 | is($events[0]->{change}, 'init', 'First event has change = init'); 31 | is($events[0]->{current}->{id}, $current_ws->{id}, 'the "current" property contains the initted workspace con'); 32 | 33 | is($events[1]->{change}, 'focus', 'Second event has change = focus'); 34 | is($events[1]->{current}->{id}, $current_ws->{id}, 'the "current" property should contain the focused workspace con'); 35 | is($events[1]->{old}->{id}, $old_ws->{id}, 'the "old" property should contain the workspace con that was focused last'); 36 | 37 | is($events[2]->{change}, 'empty', 'Third event has change = empty'); 38 | is($events[2]->{current}->{id}, $old_ws->{id}, 'the "current" property should contain the emptied workspace con'); 39 | 40 | done_testing; 41 | -------------------------------------------------------------------------------- /testcases/t/128-open-order.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Check if new containers are opened after the currently focused one instead 18 | # of always at the end 19 | use List::Util qw(first); 20 | use i3test; 21 | 22 | my $i3 = i3(get_socket_path()); 23 | 24 | my $tmp = fresh_workspace; 25 | 26 | ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); 27 | 28 | # Open two new container 29 | my $first = open_empty_con($i3); 30 | 31 | ok(@{get_ws_content($tmp)} == 1, 'containers opened'); 32 | 33 | my $second = open_empty_con($i3); 34 | 35 | isnt($first, $second, 'different container focused'); 36 | 37 | ############################################################## 38 | # see if new containers open after the currently focused 39 | ############################################################## 40 | 41 | cmd qq|[con_id="$first"] focus|; 42 | cmd 'open'; 43 | my $content = get_ws_content($tmp); 44 | ok(@{$content} == 3, 'three containers opened'); 45 | 46 | is($content->[0]->{id}, $first, 'first container unmodified'); 47 | isnt($content->[1]->{id}, $second, 'second container replaced'); 48 | is($content->[2]->{id}, $second, 'third container unmodified'); 49 | 50 | done_testing; 51 | -------------------------------------------------------------------------------- /testcases/t/244-new-workspace-floating-enable-center.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • https://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • https://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • https://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Ensures that 'move workspace $new, floating enable' on a marked window 18 | # leaves the window centered on the new workspace. 19 | # Bug still in: 4.10.2-137-ga4f0ed6 20 | use i3test i3_config => <rect; 41 | 42 | is(int($pos->{x} + $pos->{width} / 2), int($x->root->rect->width / 2), 43 | 'x coordinates match'); 44 | is(int($pos->{y} + $pos->{height} / 2), int($x->root->rect->height / 2), 45 | 'y coordinates match'); 46 | 47 | done_testing; 48 | -------------------------------------------------------------------------------- /testcases/t/539-disable_focus_wrapping.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | # vim:ts=4:sw=4:expandtab 3 | # 4 | # Please read the following documents before working on tests: 5 | # • http://build.i3wm.org/docs/testsuite.html 6 | # (or docs/testsuite) 7 | # 8 | # • http://build.i3wm.org/docs/lib-i3test.html 9 | # (alternatively: perldoc ./testcases/lib/i3test.pm) 10 | # 11 | # • http://build.i3wm.org/docs/ipc.html 12 | # (or docs/ipc) 13 | # 14 | # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf 15 | # (unless you are already familiar with Perl) 16 | # 17 | # Tests that focus does not wrap when focus_wrapping is disabled in 18 | # the configuration. 19 | # Ticket: #2352 20 | # Bug still in: 4.14-72-g6411130c 21 | use i3test i3_config => <input_focus, $win2->id, "Second window focused initially"); 38 | cmd "focus $prev"; 39 | is($x->input_focus, $win1->id, "First window focused"); 40 | cmd "focus $prev"; 41 | is($x->input_focus, $win1->id, "First window still focused"); 42 | cmd "focus $next"; 43 | is($x->input_focus, $win2->id, "Second window focused"); 44 | cmd "focus $next"; 45 | is($x->input_focus, $win2->id, "Second window still focused"); 46 | } 47 | 48 | test_orientation('v', 'up', 'down'); 49 | test_orientation('h', 'left', 'right'); 50 | 51 | done_testing; 52 | --------------------------------------------------------------------------------