aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stapelberg <michael@stapelberg.de>2023-10-29 09:58:05 +0100
committerMichael Stapelberg <michael@stapelberg.de>2023-10-29 09:58:05 +0100
commit7e3fa2cbf1aa6520de05b6f77b1ec4c623df5d3b (patch)
treed81eeeb9d369b2d5be52d1102b2a8b2b10b65285
parent1f65396e36a95cf7f6d5f40616f1fa9e3d97e28e (diff)
parent06b3137bd733eebf86d7b892a7c18ed0114bd733 (diff)
downloadi3-7e3fa2cbf1aa6520de05b6f77b1ec4c623df5d3b.tar.gz
i3-7e3fa2cbf1aa6520de05b6f77b1ec4c623df5d3b.zip
Merge branch 'next' into stable
-rw-r--r--.github/workflows/main.yml45
-rw-r--r--RELEASE-NOTES-4.2255
-rw-r--r--RELEASE-NOTES-4.2353
-rw-r--r--debian/changelog2
-rw-r--r--docs/debugging17
-rw-r--r--docs/hacking-howto62
-rw-r--r--docs/i3bar-workspace-protocol184
-rw-r--r--docs/testsuite4
-rw-r--r--docs/userguide45
-rw-r--r--i3-input/main.c39
-rw-r--r--i3bar/include/child.h69
-rw-r--r--i3bar/include/configuration.h11
-rw-r--r--i3bar/include/mode.h4
-rw-r--r--i3bar/include/outputs.h4
-rw-r--r--i3bar/include/workspaces.h5
-rw-r--r--i3bar/include/xcb.h1
-rw-r--r--i3bar/src/child.c508
-rw-r--r--i3bar/src/config.c30
-rw-r--r--i3bar/src/ipc.c93
-rw-r--r--i3bar/src/main.c4
-rw-r--r--i3bar/src/mode.c18
-rw-r--r--i3bar/src/outputs.c21
-rw-r--r--i3bar/src/workspaces.c94
-rw-r--r--i3bar/src/xcb.c87
-rw-r--r--include/commands.h2
-rw-r--r--include/config_directives.h1
-rw-r--r--include/configuration.h4
-rw-r--r--include/libi3.h7
-rw-r--r--include/xcb.h6
-rw-r--r--libi3/draw_util.c90
-rw-r--r--man/i3.man23
-rw-r--r--man/i3bar.man5
-rw-r--r--meson.build12
-rw-r--r--parser-specs/commands.spec5
-rw-r--r--parser-specs/config.spec5
-rw-r--r--release-notes/bugfixes/1-i3bar-nonprimary1
-rw-r--r--release-notes/bugfixes/1-motif1
-rw-r--r--release-notes/bugfixes/1-top-border-resize1
-rw-r--r--release-notes/bugfixes/2-gaps-order1
-rw-r--r--release-notes/bugfixes/2-title-scroll1
-rw-r--r--release-notes/bugfixes/3-bindsym-button-mode1
-rw-r--r--release-notes/bugfixes/3-floating-from-tiling-from1
-rw-r--r--release-notes/bugfixes/4-machine-crash1
-rw-r--r--release-notes/bugfixes/5-for-window-urgent1
-rw-r--r--release-notes/bugfixes/6-motif-append_layout1
-rw-r--r--release-notes/changes/1-bar-padding1
-rw-r--r--release-notes/changes/1-workspace_command1
-rw-r--r--release-notes/changes/2-focus-workspace1
-rw-r--r--release-notes/changes/2-text-alpha-channel1
-rw-r--r--release-notes/changes/3-global-fullscreen1
-rw-r--r--release-notes/changes/3-nonprimary1
-rw-r--r--release-notes/changes/4-mode-in-binding-event1
-rwxr-xr-xrelease.sh4
-rw-r--r--src/bindings.c17
-rw-r--r--src/click.c11
-rw-r--r--src/commands.c54
-rw-r--r--src/config.c1
-rw-r--r--src/config_directives.c5
-rw-r--r--src/config_parser.c4
-rw-r--r--src/handlers.c13
-rw-r--r--src/ipc.c3
-rw-r--r--src/load_layout.c21
-rw-r--r--src/main.c28
-rw-r--r--src/manage.c27
-rw-r--r--src/match.c1
-rw-r--r--src/move.c1
-rw-r--r--src/sd-daemon.c7
-rw-r--r--src/startup.c28
-rw-r--r--src/window.c2
-rw-r--r--src/x.c3
-rw-r--r--src/xcb.c21
-rwxr-xr-xtestcases/complete-run.pl.in2
-rwxr-xr-xtestcases/new-test2
-rw-r--r--testcases/t/001-tile.t2
-rw-r--r--testcases/t/002-i3-sync.t2
-rw-r--r--testcases/t/003-ipc.t2
-rw-r--r--testcases/t/004-unmanaged.t2
-rw-r--r--testcases/t/005-floating.t2
-rw-r--r--testcases/t/100-fullscreen.t14
-rw-r--r--testcases/t/101-focus.t2
-rw-r--r--testcases/t/102-dock.t2
-rw-r--r--testcases/t/104-focus-stack.t2
-rw-r--r--testcases/t/111-goto.t2
-rw-r--r--testcases/t/112-floating-resize.t2
-rw-r--r--testcases/t/113-urgent.t17
-rw-r--r--testcases/t/114-client-leader.t2
-rw-r--r--testcases/t/115-ipc-workspaces.t2
-rw-r--r--testcases/t/116-nestedcons.t2
-rw-r--r--testcases/t/117-workspace.t2
-rw-r--r--testcases/t/118-openkill.t2
-rw-r--r--testcases/t/119-match.t2
-rw-r--r--testcases/t/120-multiple-cmds.t2
-rw-r--r--testcases/t/121-next-prev.t2
-rw-r--r--testcases/t/122-split.t2
-rw-r--r--testcases/t/124-move.t2
-rw-r--r--testcases/t/126-regress-close.t2
-rw-r--r--testcases/t/127-regress-floating-parent.t2
-rw-r--r--testcases/t/128-open-order.t2
-rw-r--r--testcases/t/129-focus-after-close.t2
-rw-r--r--testcases/t/130-close-empty-split.t2
-rw-r--r--testcases/t/131-stacking-order.t2
-rw-r--r--testcases/t/132-move-workspace.t2
-rw-r--r--testcases/t/133-size-hints.t2
-rw-r--r--testcases/t/134-invalid-command.t2
-rw-r--r--testcases/t/135-floating-focus.t2
-rw-r--r--testcases/t/136-floating-ws-empty.t2
-rw-r--r--testcases/t/137-floating-unmap.t2
-rw-r--r--testcases/t/138-floating-attach.t2
-rw-r--r--testcases/t/139-ws-numbers.t2
-rw-r--r--testcases/t/140-focus-lost.t2
-rw-r--r--testcases/t/141-resize.t2
-rw-r--r--testcases/t/142-regress-move-floating.t2
-rw-r--r--testcases/t/143-regress-floating-restart.t2
-rw-r--r--testcases/t/144-regress-floating-resize.t2
-rw-r--r--testcases/t/145-flattening.t2
-rw-r--r--testcases/t/146-floating-reinsert.t2
-rw-r--r--testcases/t/147-regress-floatingmove.t2
-rw-r--r--testcases/t/148-regress-floatingmovews.t2
-rw-r--r--testcases/t/150-regress-dock-restart.t2
-rw-r--r--testcases/t/151-regress-float-size.t2
-rw-r--r--testcases/t/152-regress-level-up.t2
-rw-r--r--testcases/t/153-floating-originalsize.t2
-rw-r--r--testcases/t/154-regress-multiple-dock.t2
-rw-r--r--testcases/t/155-floating-split-size.t2
-rw-r--r--testcases/t/156-fullscreen-focus.t2
-rw-r--r--testcases/t/158-wm_take_focus.t2
-rw-r--r--testcases/t/159-socketpaths.t2
-rw-r--r--testcases/t/161-regress-borders-restart.t2
-rw-r--r--testcases/t/162-regress-dock-urgent.t2
-rw-r--r--testcases/t/163-wm-state.t2
-rw-r--r--testcases/t/164-kill-win-vs-client.t2
-rw-r--r--testcases/t/165-for_window.t2
-rw-r--r--testcases/t/166-assign.t2
-rw-r--r--testcases/t/167-workspace_layout.t2
-rw-r--r--testcases/t/168-regress-fullscreen-restart.t2
-rw-r--r--testcases/t/169-border-toggle.t2
-rw-r--r--testcases/t/170-force_focus_wrapping.t2
-rw-r--r--testcases/t/171-config-migrate.t2
-rw-r--r--testcases/t/172-start-on-named-ws.t2
-rw-r--r--testcases/t/173-get-marks.t2
-rw-r--r--testcases/t/174-border-config.t2
-rw-r--r--testcases/t/175-startup-notification.t2
-rw-r--r--testcases/t/176-workspace-baf.t2
-rw-r--r--testcases/t/177-bar-config.t2
-rw-r--r--testcases/t/178-regress-workspace-open.t2
-rw-r--r--testcases/t/179-regress-multiple-ws.t2
-rw-r--r--testcases/t/180-fd-leaks.t2
-rw-r--r--testcases/t/181-regress-float-border.t2
-rw-r--r--testcases/t/182-regress-focus-dock.t2
-rw-r--r--testcases/t/183-config-variables.t2
-rw-r--r--testcases/t/184-regress-float-split-resize.t2
-rw-r--r--testcases/t/185-scratchpad.t2
-rw-r--r--testcases/t/186-regress-assign-focus-parent.t2
-rw-r--r--testcases/t/187-commands-parser.t17
-rw-r--r--testcases/t/188-regress-focus-restart.t2
-rw-r--r--testcases/t/189-floating-constraints.t2
-rw-r--r--testcases/t/190-scratchpad-diff-ws.t2
-rw-r--r--testcases/t/191-resize-levels.t2
-rw-r--r--testcases/t/192-layout.t2
-rw-r--r--testcases/t/193-ipc-version.t2
-rw-r--r--testcases/t/194-regress-floating-size.t2
-rw-r--r--testcases/t/195-net-active-window.t2
-rw-r--r--testcases/t/196-randr-output-names.t2
-rw-r--r--testcases/t/197-regression-move-vanish.t2
-rw-r--r--testcases/t/198-regression-scratchpad-crash.t2
-rw-r--r--testcases/t/199-ipc-mode-event.t2
-rw-r--r--testcases/t/200-urgency-timer.t2
-rw-r--r--testcases/t/201-config-parser.t4
-rw-r--r--testcases/t/202-scratchpad-criteria.t2
-rw-r--r--testcases/t/203-regress-assign-and-move.t2
-rw-r--r--testcases/t/204-regress-scratchpad-move.t2
-rw-r--r--testcases/t/205-ipc-windows.t2
-rw-r--r--testcases/t/206-fullscreen-scratchpad.t2
-rw-r--r--testcases/t/207-shmlog.t2
-rw-r--r--testcases/t/208-regress-floating-criteria.t2
-rw-r--r--testcases/t/209-ewmh-net-workarea.t2
-rw-r--r--testcases/t/210-mark-unmark.t2
-rw-r--r--testcases/t/211-regress-urgency-assign.t2
-rw-r--r--testcases/t/212-assign-urgency.t2
-rw-r--r--testcases/t/213-layout-restore-simple.t2
-rw-r--r--testcases/t/214-layout-restore-criteria.t2
-rw-r--r--testcases/t/215-layout-restore-crash.t2
-rw-r--r--testcases/t/216-layout-restore-split-swallows.t2
-rw-r--r--testcases/t/217-NET_CURRENT_DESKTOP.t2
-rw-r--r--testcases/t/218-regress-floating-split.t2
-rw-r--r--testcases/t/219-ipc-window-focus.t2
-rw-r--r--testcases/t/220-ipc-window-title.t2
-rw-r--r--testcases/t/221-floating-type-hints.t2
-rw-r--r--testcases/t/222-regress-dock-resize.t2
-rw-r--r--testcases/t/223-net-client-list.t2
-rw-r--r--testcases/t/224-regress-resize-branch.t2
-rw-r--r--testcases/t/225-ipc-window-fullscreen.t2
-rw-r--r--testcases/t/226-internal-workspaces.t2
-rw-r--r--testcases/t/227-ipc-workspace-empty.t2
-rw-r--r--testcases/t/228-border-widths.t2
-rw-r--r--testcases/t/229-cleanup-tmpdir.t2
-rw-r--r--testcases/t/230-floating-fullscreen-restart.t2
-rw-r--r--testcases/t/231-ipc-floating-event.t2
-rw-r--r--testcases/t/232-cmd-move-criteria.t2
-rw-r--r--testcases/t/233-regress-manage-focus-unmapped.t2
-rw-r--r--testcases/t/234-ewmh-desktop-names.t2
-rw-r--r--testcases/t/235-check-config-no-x.t2
-rw-r--r--testcases/t/236-floating-focus-raise.t2
-rw-r--r--testcases/t/237-regress-assign-focus.t2
-rw-r--r--testcases/t/238-ipc-binding-event.t2
-rw-r--r--testcases/t/239-net-close-window-request.t2
-rw-r--r--testcases/t/240-focus-on-window-activation.t2
-rw-r--r--testcases/t/241-consistent-center.t2
-rw-r--r--testcases/t/242-no-focus.t2
-rw-r--r--testcases/t/243-move-to-mark.t2
-rw-r--r--testcases/t/244-new-workspace-floating-enable-center.t2
-rw-r--r--testcases/t/245-move-position-mouse.t2
-rw-r--r--testcases/t/246-window-decoration-focus.t2
-rw-r--r--testcases/t/247-config-line-continuation.t2
-rw-r--r--testcases/t/248-regress-urgency-clear.t2
-rw-r--r--testcases/t/249-layout-restore-floating.t2
-rw-r--r--testcases/t/250-layout-restore-multiple-criteria.t2
-rw-r--r--testcases/t/251-command-criteria-focused.t2
-rw-r--r--testcases/t/252-floating-size.t2
-rw-r--r--testcases/t/253-multiple-net-wm-state-atoms.t2
-rw-r--r--testcases/t/254-move-to-output-with-criteria.t2
-rw-r--r--testcases/t/255-multiple-marks.t2
-rw-r--r--testcases/t/256-no-auto-back-and-forth.t2
-rw-r--r--testcases/t/257-keypress-group1-fallback.t2
-rw-r--r--testcases/t/258-keypress-release.t2
-rw-r--r--testcases/t/259-net-wm-user-time.t2
-rw-r--r--testcases/t/260-invalid-criteria.t2
-rw-r--r--testcases/t/261-match-con_id-con_mark-combinations.t2
-rw-r--r--testcases/t/262-config-validation.t2
-rw-r--r--testcases/t/263-config-reload-reverts-bind-mode.t2
-rw-r--r--testcases/t/264-dock-criteria.t2
-rw-r--r--testcases/t/265-ipc-mark.t2
-rw-r--r--testcases/t/266-net-moveresize-window.t2
-rw-r--r--testcases/t/267-regress-mark-restart.t2
-rw-r--r--testcases/t/268-ipc-config.t2
-rw-r--r--testcases/t/269-focus-stack-above.t2
-rw-r--r--testcases/t/270-config-no-newline-end.t2
-rw-r--r--testcases/t/271-for_window_tilingfloating.t2
-rw-r--r--testcases/t/272-regress-focus-assign.t2
-rw-r--r--testcases/t/273-regress-focus-toggle.t2
-rw-r--r--testcases/t/274-move-branch-position.t2
-rw-r--r--testcases/t/275-ipc-window-close.t2
-rw-r--r--testcases/t/276-ipc-window-move.t2
-rw-r--r--testcases/t/277-ipc-window-urgent.t2
-rw-r--r--testcases/t/278-layout-restore-output.t2
-rw-r--r--testcases/t/279-regress-default-floating-border.t2
-rw-r--r--testcases/t/280-wm-class-change-handler.t2
-rw-r--r--testcases/t/281-regress-reload-bindsym.t2
-rw-r--r--testcases/t/282-tabbed-floating-disable-crash.t2
-rw-r--r--testcases/t/283-net-wm-state-hidden.t2
-rw-r--r--testcases/t/284-ewmh-visible-name.t2
-rw-r--r--testcases/t/285-sticky.t2
-rw-r--r--testcases/t/286-root-window-mouse-binding.t2
-rw-r--r--testcases/t/287-edge-borders.t2
-rw-r--r--testcases/t/288-i3-floating-window-atom.t2
-rw-r--r--testcases/t/289-ipc-shutdown-event.t2
-rw-r--r--testcases/t/290-keypress-numlock.t2
-rw-r--r--testcases/t/291-swap.t2
-rw-r--r--testcases/t/292-regress-layout-toggle.t2
-rw-r--r--testcases/t/293-focus-follows-mouse.t2
-rw-r--r--testcases/t/293-sticky-output-crash.t2
-rw-r--r--testcases/t/294-focus-order.t2
-rw-r--r--testcases/t/294-update-ewmh-atoms.t2
-rw-r--r--testcases/t/295-net-wm-state-focused.t2
-rw-r--r--testcases/t/296-regress-focus-behind-fullscreen-floating.t2
-rw-r--r--testcases/t/297-assign-workspace-to-output.t2
-rw-r--r--testcases/t/297-scroll-tabbed.t41
-rw-r--r--testcases/t/298-ipc-misbehaving-connection.t2
-rw-r--r--testcases/t/299-regress-scratchpad-focus.t2
-rw-r--r--testcases/t/300-restart-non-utf8.t2
-rw-r--r--testcases/t/301-shape.t2
-rw-r--r--testcases/t/302-tree.t2
-rw-r--r--testcases/t/303-regress-move-floating.t2
-rw-r--r--testcases/t/304-ipc-workspace-init.t2
-rw-r--r--testcases/t/305-restart-reply.t2
-rw-r--r--testcases/t/306-move-to-parent.t2
-rw-r--r--testcases/t/307-focus-next-prev.t2
-rw-r--r--testcases/t/308-focus_wrapping.t2
-rw-r--r--testcases/t/309-crash-move-parent.t2
-rw-r--r--testcases/t/310-client-message-sticky.t2
-rw-r--r--testcases/t/311-get-binding-modes.t2
-rw-r--r--testcases/t/312-regress-layout-default.t2
-rw-r--r--testcases/t/313-include.t2
-rwxr-xr-xtestcases/t/314-window-icon-padding.t2
-rw-r--r--testcases/t/315-all-criterion.t2
-rw-r--r--testcases/t/315-long-commands.t2
-rw-r--r--testcases/t/316-drag-container.t2
-rw-r--r--testcases/t/316-transient-for-loop.t2
-rw-r--r--testcases/t/317-bar-config-font-fallback.t42
-rw-r--r--testcases/t/317-bar-config-font-order.t10
-rw-r--r--testcases/t/317-bar-output-trailing-space.t2
-rw-r--r--testcases/t/318-i3-dmenu-desktop.t2
-rw-r--r--testcases/t/319-gaps.t2
-rw-r--r--testcases/t/320-mouse-bindings.t89
-rw-r--r--testcases/t/500-multi-monitor.t2
-rw-r--r--testcases/t/501-scratchpad.t2
-rw-r--r--testcases/t/502-focus-output.t2
-rw-r--r--testcases/t/503-workspace.t2
-rw-r--r--testcases/t/504-move-workspace-to-output.t2
-rw-r--r--testcases/t/505-scratchpad-resolution.t2
-rw-r--r--testcases/t/506-focus-right.t2
-rw-r--r--testcases/t/507-workspace-move-crash.t2
-rw-r--r--testcases/t/509-workspace_layout.t2
-rw-r--r--testcases/t/510-focus-across-outputs.t2
-rw-r--r--testcases/t/511-scratchpad-configure-request.t2
-rw-r--r--testcases/t/512-move-wraps.t2
-rw-r--r--testcases/t/513-move-workspace.t2
-rw-r--r--testcases/t/514-ipc-workspace-multi-monitor.t2
-rw-r--r--testcases/t/515-create-workspace.t2
-rw-r--r--testcases/t/516-move.t2
-rw-r--r--testcases/t/517-regress-move-direction-ipc.t2
-rw-r--r--testcases/t/518-interpret-workspace-numbers.t2
-rw-r--r--testcases/t/519-mouse-warping.t2
-rw-r--r--testcases/t/520-regress-focus-direction-floating.t2
-rw-r--r--testcases/t/521-ewmh-desktop-viewport.t2
-rw-r--r--testcases/t/522-rename-assigned-workspace.t2
-rw-r--r--testcases/t/523-move-position-center.t2
-rw-r--r--testcases/t/524-move.t2
-rw-r--r--testcases/t/525-i3bar-mouse-bindings.t2
-rw-r--r--testcases/t/526-reconfigure-dock.t2
-rw-r--r--testcases/t/527-focus-fallback.t2
-rw-r--r--testcases/t/528-workspace-next-prev-reversed.t2
-rw-r--r--testcases/t/529-net-wm-desktop.t2
-rw-r--r--testcases/t/530-bug-2229.t2
-rw-r--r--testcases/t/531-fullscreen-on-given-output.t2
-rw-r--r--testcases/t/532-xresources.t2
-rw-r--r--testcases/t/533-randr15.t2
-rw-r--r--testcases/t/534-dont-warp.t2
-rw-r--r--testcases/t/535-workspace-next-prev.t2
-rw-r--r--testcases/t/536-net-wm-desktop_mm.t2
-rw-r--r--testcases/t/537-move-single-to-output.t2
-rw-r--r--testcases/t/538-i3bar-primary-output.t31
-rw-r--r--testcases/t/539-disable_focus_wrapping.t2
-rw-r--r--testcases/t/540-sigterm-cleanup.t2
-rw-r--r--testcases/t/541-resize-set-tiling.t2
-rw-r--r--testcases/t/542-layout-restore-remanage.t2
-rw-r--r--testcases/t/543-move-workspace-to-multiple-outputs.t2
-rw-r--r--testcases/t/544-focus-multiple-outputs.t2
-rw-r--r--testcases/t/546-empty-bindcommand.t2
-rw-r--r--testcases/t/547-explicit-mode-default.t2
-rw-r--r--testcases/t/547-nested-variables.t2
-rw-r--r--testcases/t/548-motif-hints.t55
-rw-r--r--testcases/t/549-focus-wrapping-gaps.t2
-rwxr-xr-xtravis/push-balto.sh4
-rwxr-xr-xtravis/skip-pkg.sh14
-rw-r--r--travis/travis-base-386.Dockerfile33
-rw-r--r--travis/travis-base-ubuntu-386.Dockerfile33
-rw-r--r--travis/travis-base-ubuntu.Dockerfile2
-rw-r--r--travis/travis-base.Dockerfile2
349 files changed, 1836 insertions, 979 deletions
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 5e460a63..8578678d 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -23,31 +23,22 @@ jobs:
BALTO_TOKEN: ${{ secrets.BALTO_TOKEN }}
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- run: git fetch --prune --unshallow
- name: construct container name
run: |
echo "BASENAME=i3wm/travis-base:$(date +'%Y-%m')-$(./travis/ha.sh travis/travis-base.Dockerfile)" >> $GITHUB_ENV
- echo "BASENAME_386=i3wm/travis-base-386:$(date +'%Y-%m')-$(./travis/ha.sh travis/travis-base-386.Dockerfile)" >> $GITHUB_ENV
echo "BASENAME_UBUNTU=i3wm/travis-base-ubuntu:$(date +'%Y-%m')-$(./travis/ha.sh travis/travis-base-ubuntu.Dockerfile)" >> $GITHUB_ENV
- echo "BASENAME_UBUNTU_386=i3wm/travis-base-ubuntu-386:$(date +'%Y-%m')-$(./travis/ha.sh travis/travis-base-ubuntu-386.Dockerfile)" >> $GITHUB_ENV
- name: fetch or build Docker container
run: |
docker pull ${{ env.BASENAME }} || ./travis/docker-build-and-push.sh ${{ env.BASENAME }} travis/travis-base.Dockerfile
- name: fetch or build extra Docker containers
+ if: github.ref == 'refs/heads/next' && matrix.compiler == 'gcc'
run: |
- echo "::group::Ubuntu amd64"
- ./travis/skip-pkg.sh || docker pull ${{ env.BASENAME_UBUNTU }} || ./travis/docker-build-and-push.sh ${{ env.BASENAME_UBUNTU }} travis/travis-base-ubuntu.Dockerfile
- echo "::endgroup::"
- echo "::group::Debian i386"
- ./travis/skip-pkg.sh || docker pull ${{ env.BASENAME_386 }} || ./travis/docker-build-and-push.sh ${{ env.BASENAME_386 }} travis/travis-base-386.Dockerfile
- echo "::endgroup::"
- echo "::group::Ubuntu i386"
- ./travis/skip-pkg.sh || docker pull ${{ env.BASENAME_UBUNTU_386 }} || ./travis/docker-build-and-push.sh ${{ env.BASENAME_UBUNTU_386 }} travis/travis-base-ubuntu-386.Dockerfile
- echo "::endgroup::"
+ docker pull ${{ env.BASENAME_UBUNTU }} || ./travis/docker-build-and-push.sh ${{ env.BASENAME_UBUNTU }} travis/travis-base-ubuntu.Dockerfile
- name: build i3
run: |
- docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 -e CC ${{ env.BASENAME }} /bin/sh -c 'rm -rf build; mkdir -p build && cd build && CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Wstrict-prototypes -Wmissing-prototypes -Werror -fno-common" meson .. -Ddocs=true -Dmans=true -Db_sanitize=address && ninja -v'
+ docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 -e CC ${{ env.BASENAME }} /bin/sh -c 'rm -rf build; mkdir -p build && cd build && CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Wstrict-prototypes -Wmissing-prototypes -Werror -fno-common -D_FORTIFY_SOURCE=3" meson setup .. -Ddocs=true -Dmans=true -Db_sanitize=address --buildtype=debugoptimized && ninja -v'
- name: check spelling
run: |
docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${{ env.BASENAME }} ./travis/check-spelling.pl
@@ -62,41 +53,39 @@ jobs:
if: ${{ failure() }}
- name: build dist tarball
run: |
- docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 -e CC ${{ env.BASENAME }} /bin/sh -c 'rm -rf distbuild; mkdir distbuild && cd distbuild && meson .. -Ddocs=true -Dmans=true && meson dist --no-tests'
+ docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 -e CC ${{ env.BASENAME }} /bin/sh -c 'rm -rf distbuild; mkdir distbuild && cd distbuild && meson setup .. -Ddocs=true -Dmans=true && meson dist --no-tests'
- name: build Debian packages
+ if: github.ref == 'refs/heads/next' && matrix.compiler == 'gcc'
run: |
echo "::group::Debian amd64"
- ./travis/skip-pkg.sh || docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${{ env.BASENAME }} ./travis/debian-build.sh deb/debian-amd64/DIST
+ docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${{ env.BASENAME }} ./travis/debian-build.sh deb/debian-amd64/DIST
echo "::endgroup::"
echo "::group::Ubuntu amd64"
- ./travis/skip-pkg.sh || docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${{ env.BASENAME_UBUNTU }} ./travis/debian-build.sh deb/ubuntu-amd64/DIST
- echo "::endgroup::"
- echo "::group::Debian i386"
- ./travis/skip-pkg.sh || docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${{ env.BASENAME_386 }} linux32 ./travis/debian-build.sh deb/debian-i386/DIST
- echo "::endgroup::"
- echo "::group::Ubuntu i386"
- ./travis/skip-pkg.sh || docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${{ env.BASENAME_UBUNTU_386 }} linux32 ./travis/debian-build.sh deb/ubuntu-i386/DIST
+ docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${{ env.BASENAME_UBUNTU }} ./travis/debian-build.sh deb/ubuntu-amd64/DIST
echo "::endgroup::"
- name: push Debian packages to balto
+ if: github.ref == 'refs/heads/next' && matrix.compiler == 'gcc'
run: |
- ./travis/skip-pkg.sh || travis/push-balto.sh
+ travis/push-balto.sh
- name: build docs
+ if: github.ref == 'refs/heads/next' && matrix.compiler == 'gcc'
run: |
- ./travis/skip-pkg.sh || docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${{ env.BASENAME }} ./travis/docs.sh
+ docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${{ env.BASENAME }} ./travis/docs.sh
- name: push docs to GitHub pages
+ if: github.ref == 'refs/heads/next' && matrix.compiler == 'gcc'
run: |
- ./travis/skip-pkg.sh || travis/deploy-github-pages.sh
+ travis/deploy-github-pages.sh
formatting:
name: Check formatting
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: check & print release notes
run: ./release-notes/generator.pl
- name: Install dependencies
run: |
- sudo apt-get install -y clang-format-12
+ sudo apt-get install -y clang-format-15
- name: Check formatting
- run: clang-format-12 --dry-run --Werror $(git ls-files '*.c' '*.h')
+ run: clang-format-15 --dry-run --Werror $(git ls-files '*.c' '*.h')
- name: Verify safe wrapper functions are used
run: ./travis/check-safe-wrappers.sh
diff --git a/RELEASE-NOTES-4.22 b/RELEASE-NOTES-4.22
deleted file mode 100644
index 36db5456..00000000
--- a/RELEASE-NOTES-4.22
+++ /dev/null
@@ -1,55 +0,0 @@
-
- ┌──────────────────────────────┐
- │ Release notes for i3 v4.22 │
- └──────────────────────────────┘
-
-This is i3 v4.22. This version is considered stable. All users of i3 are
-strongly encouraged to upgrade.
-
-The biggest change in this release is the merge of the i3-gaps fork.
-The i3-gaps fork was the most popular fork of i3, adding the option to
-show gaps between tiled windows and/or the screen edges.
-
-See https://i3wm.org/docs/userguide.html#gaps for more details.
-
-Instead of maintaining two versions of i3 (both upstream and downstream,
-meaning in Linux distributions and other package collections),
-we concluded it would be better for everyone to merge this feature.
-
-For users of i3: gaps are off by default, so there is no change in behavior.
-For users of i3-gaps: the configuration is compatible, so you can switch
-to i3 v4.22 or newer, without any changes in behavior.
-
-Thanks to Ingo Bürk for maintaining i3-gaps for many years,
-for becoming a core i3 maintainer and for helping make this merge possible!
-
- ┌────────────────────────────┐
- │ Changes in i3 v4.22 │
- └────────────────────────────┘
-
- • i3bar: bar { padding } config directive now implemented (supports bar { height } from i3-gaps)
- • i3-dmenu-desktop: allow more than one --entry-type with the --show-duplicates flag
- • You can now enable gaps using the gaps config directive and/or command
- • colors now support an optional alpha value at the end (#rrggbbaa)
- • the hide_edge_borders option now supports the smart_no_gaps keyword
- • Support nonprimary keyword for outputs
- • add "mode" field in binding event
-
- ┌────────────────────────────┐
- │ Bugfixes │
- └────────────────────────────┘
-
- • gaps: workspace gaps assignments are no longer order-dependent
- • Fix compliance to _MOTIF_WM_HINTS spec when all decorations are set
- • The floating_from and tiling_from criteria now also work in commands
-
- ┌────────────────────────────┐
- │ Thanks! │
- └────────────────────────────┘
-
-Thanks for testing, bugfixes, discussions and everything I forgot go out to:
-
- bodea, Demian, Erich Heine, Ingo Bürk, Matias Goldfeld, Orestis Floros,
- Tudor Brindus
-
--- Michael Stapelberg, 2023-01-02
diff --git a/RELEASE-NOTES-4.23 b/RELEASE-NOTES-4.23
new file mode 100644
index 00000000..52a9b18a
--- /dev/null
+++ b/RELEASE-NOTES-4.23
@@ -0,0 +1,53 @@
+
+ ┌──────────────────────────────┐
+ │ Release notes for i3 v4.23 │
+ └──────────────────────────────┘
+
+This is i3 v4.23. This version is considered stable. All users of i3 are
+strongly encouraged to upgrade.
+
+The biggest feature of this release is i3bar’s workspace button protocol,
+which allows the workspace_command program or script to filter, re-arrange,
+or otherwise customize the displayed workspaces:
+https://i3wm.org/docs/i3bar-workspace-protocol.html
+
+ ┌────────────────────────────┐
+ │ Changes in i3 v4.23 │
+ └────────────────────────────┘
+
+ • docs/userguide: add an example for negative lookaheads
+ • docs/userguide: fix default binding mistake
+ • docs/userguide: add link to tiling drag
+ • docs/hacking-howto: update build instructions, startup
+ • docs/debugging: add note about ptrace
+ • man/i3: remove outdated I3SOCK description
+ • all: build with -D_FORTIFY_SOURCE=3
+ • i3bar: fix configuring bars on “output nonprimary”
+ • i3bar: implement workspace button protocol
+ • add “focus workspace” command
+ • allow switching workspaces when in global fullscreen mode
+ • exec: single-fork instead of double-forking
+ • share X11 graphics context (GC) globally
+
+ ┌────────────────────────────┐
+ │ Bugfixes │
+ └────────────────────────────┘
+
+ • fix regression with i3bar's output nonprimary
+ • fix top border resizing on tiling windows
+ • fix workspace not being focused on title bar scroll
+ • fix mouse bindings in modes
+ • fix crashes when using machine criterion
+ • fix for_window not working with urgency flags
+ • motif hints: respect maximum border style in append_layout
+
+ ┌────────────────────────────┐
+ │ Thanks! │
+ └────────────────────────────┘
+
+Thanks for testing, bugfixes, discussions and everything I forgot go out to:
+
+ Harm te Hennepe, Nikita Bobko, Nikolay Nechaev, Orestis Floros, Sergey
+ Zhmylove, slyshot, Uli Schlachter, Wesley Schwengle
+
+-- Michael Stapelberg, 2023-10-29
diff --git a/debian/changelog b/debian/changelog
index 980224d0..927b1352 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ i3-wm (4.22-1) unstable; urgency=medium
* New upstream release.
- -- Michael Stapelberg <stapelberg@debian.org> Mon, 02 Jan 2023 09:34:02 +0100
+ -- Michael Stapelberg <stapelberg@debian.org> Mon, 02 Jan 2023 09:46:22 +0100
i3-wm (4.21.2-1) unstable; urgency=medium
diff --git a/docs/debugging b/docs/debugging
index 562a11f2..cfc260cc 100644
--- a/docs/debugging
+++ b/docs/debugging
@@ -147,16 +147,17 @@ After pressing "b" in the crash dialog, you will get a file called
id (PID) and the second one is incremented each time you generate a backtrace,
starting at 0.
-== Sending bug reports/debugging on IRC
+In Linux, if the backtrace just says +No stack.+, that's because gdb does not
+have necessary permissions to attach to a running process. You can fix that by
+running from a terminal (you can open a new tty, e.g. with ctrl-alt-F2):
-When sending bug reports, please attach the *whole* log file. Even if you think
-you found the section which clearly highlights the problem, additional
-information might be necessary to completely diagnose the problem.
+---------------------------------------------------------------------
+echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
+---------------------------------------------------------------------
-When debugging with us in IRC, be prepared to use a so-called nopaste service
-such as https://pastebin.com because pasting large amounts of text in IRC
-sometimes leads to incomplete lines (servers have line length limitations) or
-flood kicks.
+Afterwards, try re-generating the stack trace. Note that this setting re-sets
+after reboot, see more info at
+https://www.kernel.org/doc/Documentation/security/Yama.txt.
== Debugging i3bar
diff --git a/docs/hacking-howto b/docs/hacking-howto
index c6dd6fa4..ae48c448 100644
--- a/docs/hacking-howto
+++ b/docs/hacking-howto
@@ -14,7 +14,7 @@ you find necessary, please do not hesitate to contact me.
<p>
++++
This document is not 100% up to date. Specifically, everything up to and
-including <<data_structures>> has been updated recently. The rest might contain
+including <<startup>> has been updated recently. The rest might contain
outdated information.
++++
</p>
@@ -34,30 +34,18 @@ Guide → Compiling a Meson project]. In case you’re unfamiliar:
=== Build system features
-* We use the +AX_ENABLE_BUILDDIR+ macro to enforce builds happening in a separate
- directory. This is a prerequisite for the +AX_EXTEND_SRCDIR+ macro and building
- in a separate directory is common practice anyway. In case this causes any
- trouble when packaging i3 for your distribution, please open an issue.
+* +ninja test+ runs the i3 testsuite. See docs/testsuite for details.
-* +make check+ runs the i3 testsuite. See docs/testsuite for details.
+* +meson dist+ builds a release tarball and runs tests on the result.
-* +make distcheck+ (runs testsuite on +make dist+ result, tiny bit quicker
- feedback cycle than waiting for the travis build to catch the issue).
+* +meson -Ddocs=true -Dmans=true+ will enable the options to build docs and
+ manpages. These options require additional dependencies that are normally not
+ required for users who just want to build i3.
-* +make uninstall+ (occasionally requested by users who compile from source)
-
-* +make+ will build manpages/docs by default if the tools are installed.
- Conversely, manpages/docs are not tried to be built for users who don’t want
- to install all these dependencies to get started hacking on i3. Manpages and
- docs can be disabled with the +--disable-mans++ and ++--disable-docs++
- configure options respectively.
-
-* non-release builds will enable address sanitizer by default. Use the
- +--disable-sanitizers+ configure option to turn off all sanitizers, and see
- +--help+ for available sanitizers.
-
-* Coverage reports are now generated using +make check-code-coverage+, which
- requires specifying +--enable-code-coverage+ when calling configure.
+* +meson -Db_sanitize=address+ will enable the address sanitizer which is
+ disabled by default. A summary of memory leaks will be printed on program
+ exit. This can include false-positives. For other options of the +b_sanitize+
+ flag see https://mesonbuild.com/Builtin-options.html.
== Pull requests
@@ -341,30 +329,26 @@ ensure that the operating system on which i3 is compiled has all the expected
features, i3 comes with +include/queue.h+. On BSD systems, you can use +man
queue(3)+. On Linux, you have to use google (or read the source).
-The lists used are +SLIST+ (single linked lists), +CIRCLEQ+ (circular
-queues) and +TAILQ+ (tail queues). Usually, only forward traversal is necessary,
-so an +SLIST+ works fine. If inserting elements at arbitrary positions or at
-the end of a list is necessary, a +TAILQ+ is used instead. However, for the
-windows inside a container, a +CIRCLEQ+ is necessary to go from the currently
-selected window to the window above/below.
-
-== Naming conventions
-
-There is a row of standard variables used in many events. The following names
-should be chosen for those:
+The lists used are +SLIST+ (single linked lists), +CIRCLEQ+ (circular queues)
+and +TAILQ+ (tail queues). Usually, +TAILQ+ is used which allows inserting
+elements at arbitrary positions or at the end of the list. If only forward
+traversal is necessary, an +SLIST+ can be used. +CIRCLEQ+ is used just to
+manage the X11 state of each window.
- * +conn+ is the xcb_connection_t
- * +event+ is the event of the particular type
- * +con+ names a container
- * +current+ is a loop variable when using +TAILQ_FOREACH+ etc.
+[[startup]]
+== Startup (src/main.c, main())
-== Startup (src/mainx.c, main())
+Among other things, the main() function does the following:
* Establish the xcb connection
+ * Load the i3 config
* Check for XKB extension on the separate X connection, load Xcursor
- * Check for RandR screens (with a fall-back to Xinerama)
+ * Set up EWMH hints
* Grab the keycodes for which bindings exist
+ * Check for XRandR screens
* Manage all existing windows
+ * Exec configured startup processes
+ * Start i3bar if configured
* Enter the event loop
== Keybindings
diff --git a/docs/i3bar-workspace-protocol b/docs/i3bar-workspace-protocol
new file mode 100644
index 00000000..016fc965
--- /dev/null
+++ b/docs/i3bar-workspace-protocol
@@ -0,0 +1,184 @@
+i3bar workspace buttons protocol
+================================
+
+This document explains the protocol in which i3bar expects input for
+configuring workspace buttons. This feature is available since i3 version 4.23.
+
+The program defined by the +workspace_command+ configuration option for i3bar can
+modify the workspace buttons displayed by i3bar. The command should constantly
+print in its standard output a stream of messages following the protocol
+defined in this page.
+
+If you are looking for the status line protocol instead, see https://i3wm.org/docs/i3bar-protocol.html.
+
+== The protocol
+
+Each message should be a newline-delimited JSON array. The array is in the same
+format as the +GET_WORKSPACES+ ipc event, see
+https://i3wm.org/docs/ipc.html#_workspaces_reply.
+
+As an example, this is the output of the +i3-msg -t get_workspaces+ command:
+------------------------------
+[
+ {
+ "id": 94131549984064,
+ "num": 1,
+ "name": "1",
+ "visible": false,
+ "focused": false,
+ "output": "HDMI-A-0",
+ "urgent": false
+ },
+ {
+ "id": 94131550477584,
+ "num": 2,
+ "name": "2",
+ "visible": true,
+ "focused": true,
+ "output": "HDMI-A-0",
+ "urgent": false
+ },
+ {
+ "id": 94131550452704,
+ "num": 3,
+ "name": "3:some workspace",
+ "visible": false,
+ "focused": false,
+ "output": "HDMI-A-0",
+ "urgent": false
+ }
+]
+------------------------------
+
+Please note that this example was pretty printed for human consumption, with
+the +"rect"+ field removed. Workspace button commands should output each array
+in one line.
+
+Each element in the array represents a workspace. i3bar creates one workspace
+button for each element in the array. The order of these buttons is the same as
+the order of the elements in the array.
+
+In general, we recommend subscribing to the +workspace+ and +output+
+https://i3wm.org/docs/ipc.html#_workspace_event[events],
+fetching the current workspace information with +GET_WORKSPACES+, modifying the
+JSON array in the response according to your needs and then printing it to the
+standard output. However, you are free to build a new message from the ground
+up.
+
+=== Workspace objects in detail
+
+The documentation of +GET_WORKSPACES+ should be sufficient to understand the
+meaning of each property but here we provide extra notes for each property and
+its meaning with respect to i3bar.
+
+All properties but +name+ are optional.
+
+id (integer)::
+ If it is included it will be used to switch to that workspace when you
+ click the corresponding button. If it's not provided, the +name+ will be
+ used. You can use the +id+ field to present workspaces under a modified
+ name.
+num (integer)::
+ The only use of a workspace's number is if the +strip_workspace_numbers+
+ setting is enabled.
+name (string)::
+ The only required property. If an +id+ is provided you can freely change
+ the +name+ as you wish, effectively renaming the buttons of i3bar.
+visible (boolean)::
+ Defaults to +false+ if not included. +focused+ takes precedence over it,
+ however +visible+ is important for more than one monitors.
+focused (boolean)::
+ Defaults to +false+ if not included. Generally, exactly one of the
+ workspaces should be +focused+. If not, no button will have the
+ +focused_workspace+ color.
+urgent (boolean)::
+ Defaults to +false+ if not included.
+rect (map)::
+ Not used by i3bar but will be ignored.
+output (string)::
+ Defaults to the primary output if not included.
+
+== Examples
+
+These example scripts require the https://stedolan.github.io/jq/[jq] utility to
+be installed but otherwise just use the standard +i3-msg+ utility included with
+i3. However, you can write your own scripts in your preferred language, with
+the help of one of the
+https://i3wm.org/docs/ipc.html#_see_also_existing_libraries[pre-existing i3
+libraries]
+
+=== Base configuration
+
+------------------------------
+bar {
+ …
+ workspace_command /path/to/your/script.sh
+ …
+}
+------------------------------
+
+=== Re-create the default behaviour of i3bar
+
+Not very useful by itself but this will be the basic building block of all the
+following scripts. This one does not require +jq+.
+
+------------------------------
+#!/bin/sh
+i3-msg -t subscribe -m '["workspace", "output"]' | {
+ # Initially print the current workspaces before we receive any events. This
+ # avoids having an empty bar when starting up.
+ i3-msg -t get_workspaces;
+ # Then, while we receive events, update the workspace information.
+ while read; do i3-msg -t get_workspaces; done;
+}
+------------------------------
+
+=== Hide workspace named +foo+ unless if it is focused.
+
+------------------------------
+#!/bin/sh
+i3-msg -t subscribe -m '["workspace", "output"]' | {
+ i3-msg -t get_workspaces;
+ while read; do i3-msg -t get_workspaces; done;
+} | jq --unbuffered -c '[ .[] | select(.name != "foo" or .focused) ]'
+------------------------------
+
+Important! Make sure you use the +--unbuffered+ flag with +jq+, otherwise you
+might not get the changes in real-time but whenever they are flushed, which
+might mean that you are getting an empty bar until enough events are written.
+
+=== Show empty workspaces +foo+ and +bar+ on LVDS1 even if they do not exist at the moment.
+
+------------------------------
+#!/bin/sh
+i3-msg -t subscribe -m '["workspace", "output"]' | {
+ i3-msg -t get_workspaces;
+ while read; do i3-msg -t get_workspaces; done;
+} | jq --unbuffered -c '
+ def fake_ws(name): {
+ name: name,
+ output: "LVDS1",
+ };
+ . + [ fake_ws("foo"), fake_ws("bar") ] | unique_by(.name)
+'
+------------------------------
+
+=== Sort workspaces in reverse alphanumeric order
+
+------------------------------
+#!/bin/sh
+i3-msg -t subscribe -m '["workspace", "output"]' | {
+ i3-msg -t get_workspaces;
+ while read; do i3-msg -t get_workspaces; done;
+} | jq --unbuffered -c 'sort_by(.name) | reverse'
+------------------------------
+
+=== Append "foo" to the name of each workspace
+
+------------------------------
+#!/bin/sh
+i3-msg -t subscribe -m '["workspace", "output"]' | {
+ i3-msg -t get_workspaces;
+ while read; do i3-msg -t get_workspaces; done;
+} | jq --unbuffered -c '[ .[] | .name |= . + " foo" ]'
+------------------------------
diff --git a/docs/testsuite b/docs/testsuite
index ec87429c..ea706649 100644
--- a/docs/testsuite
+++ b/docs/testsuite
@@ -36,8 +36,8 @@ that, but it will also be useful for every future change.
Apart from this document, you should also have a look at:
-1. The "Modern Perl" book, which can be found at
- http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+1. The "Modern Perl" book:
+ https://i3wm.org/downloads/modern_perl_a4.pdf
2. The latest Perl documentation of the "i3test" (general testcase setup) and
"i3test::Test" (additional test instructions) modules:
https://build.i3wm.org/docs/lib-i3test.html respectively
diff --git a/docs/userguide b/docs/userguide
index 120e4b90..d211c1d5 100644
--- a/docs/userguide
+++ b/docs/userguide
@@ -202,7 +202,8 @@ Floating windows are always on top of tiling windows.
Since i3 4.21, it's possible to drag tiling containers using the mouse. The
drag can be initiated either by dragging the window's titlebar or by pressing
the <<floating_modifier>> and dragging the container while holding the
-left-click button.
+left-click button. See the <<config_tiling_drag>> option for configuring which
+action triggers the tiling drag.
Once the drag is initiated and the cursor has left the original container, drop
indicators are created according to the position of the cursor relatively to
@@ -317,7 +318,7 @@ single workspace on which you open three terminal windows. All these terminal
windows are directly attached to one node inside i3’s layout tree, the
workspace node. By default, the workspace node’s orientation is +horizontal+.
-Now you move one of these terminals down (+$mod+Shift+j+ by default). The
+Now you move one of these terminals down (+$mod+Shift+k+ by default). The
workspace node’s orientation will be changed to +vertical+. The terminal window
you moved down is directly attached to the workspace and appears on the bottom
of the screen. A new (horizontal) container was created to accommodate the
@@ -1438,6 +1439,8 @@ bindsym Mod1+F fullscreen toggle
You can configure how to initiate the tiling drag feature (see <<tiling_drag>>).
+The default is +modifier+.
+
*Syntax*:
--------------------------------
tiling_drag off
@@ -1611,6 +1614,30 @@ bar {
}
-------------------------------------------------
+[[workspace_command]]
+=== Workspace buttons command
+
+Since i3 4.23, i3bar can run a program and use its +stdout+ output to define
+the workspace buttons displayed on the left hand side of the bar. With this
+feature, you can, for example, rename the buttons of workspaces, hide specific
+workspaces, always show a workspace button even if the workspace does not exist
+or change the order of the buttons.
+
+Also see <<status_command>> for the statusline option and
+https://i3wm.org/docs/i3bar-workspace-protocol.html for the detailed protocol.
+
+*Syntax*:
+------------------------
+workspace_command <command>
+------------------------
+
+*Example*:
+-------------------------------------------------
+bar {
+ workspace_command /path/to/script.sh
+}
+-------------------------------------------------
+
=== Display mode
You can either have i3bar be visible permanently at one edge of the screen
@@ -2174,6 +2201,10 @@ bindsym $mod+x [class="(?i)firefox"] kill
# kill only the About dialog from Firefox
bindsym $mod+x [class="Firefox" window_role="About"] kill
+# kill all windows except for Firefox and Gnome Terminal.
+# case-insensitive and uses negative lookaheads, supported by PCRE
+bindsym $mod+x [class="^(?i)(?!firefox)(?!gnome-terminal).*"] kill
+
# enable floating mode and move container to workspace 4
for_window [class="^evil-app$"] floating enable, move container to workspace 4
@@ -2397,6 +2428,9 @@ available:
<criteria>::
Sets focus to the container that matches the specified criteria.
See <<command_criteria>>.
+workspace::
+ Sets focus to the workspace that contains the container that matches the
+ specified criteria.
left|right|up|down::
Sets focus to the nearest container in the given direction.
parent::
@@ -2423,6 +2457,7 @@ output::
*Syntax*:
----------------------------------------------
<criteria> focus
+<criteria> focus workspace
focus left|right|down|up
focus parent|child|floating|tiling|mode_toggle
focus next|prev [sibling]
@@ -2434,6 +2469,10 @@ focus output left|right|down|up|current|primary|nonprimary|next|<output1> [outpu
# Focus firefox
bindsym $mod+F1 [class="Firefox"] focus
+# Focus the workspace where firefox is, without necessarily focusing firefox
+# itself.
+bindsym $mod+x [class="Firefox"] focus workspace
+
# Focus container on the left, bottom, top, right
bindsym $mod+j focus left
bindsym $mod+k focus down
@@ -2462,7 +2501,7 @@ bindsym $mod+x focus output primary
bindsym $mod+x focus output nonprimary
# Cycle focus between outputs VGA1 and LVDS1 but not DVI0
-bindsym $mod+x move workspace to output VGA1 LVDS1
+bindsym $mod+x focus output VGA1 LVDS1
-------------------------------------------------
Note that you might not have a primary output configured yet. To do so, run:
diff --git a/i3-input/main.c b/i3-input/main.c
index ef9e0701..afe16ccc 100644
--- a/i3-input/main.c
+++ b/i3-input/main.c
@@ -163,29 +163,32 @@ static void finish_input(void) {
char *command = (char *)concat_strings(glyphs_utf8, input_position);
/* count the occurrences of %s in the string */
- int c;
- int len = strlen(format);
- int cnt = 0;
- for (c = 0; c < (len - 1); c++)
- if (format[c] == '%' && format[c + 1] == 's')
+ const size_t len = strlen(format);
+ size_t cnt = 0;
+ for (size_t c = 0; c < (len - 1); c++) {
+ if (format[c] == '%' && format[c + 1] == 's') {
cnt++;
- printf("occurrences = %d\n", cnt);
+ }
+ }
+ printf("occurrences = %ld\n", cnt);
/* allocate space for the output */
- int inputlen = strlen(command);
- char *full = scalloc(strlen(format) - (2 * cnt) /* format without all %s */
- + (inputlen * cnt) /* replaced %s */
- + 1, /* trailing NUL */
- 1);
+ const size_t input_len = strlen(command);
+ const size_t full_len = MAX(input_len, /* avoid compiler warning */
+ strlen(format) - (2 * cnt) /* format without all %s */
+ + (input_len * cnt) /* replaced %s */
+ + 1 /* trailing NUL */
+ );
+ char *full = scalloc(full_len, 1);
char *dest = full;
- for (c = 0; c < len; c++) {
- /* if this is not % or it is % but without a following 's',
- * just copy the character */
- if (format[c] != '%' || (c == (len - 1)) || format[c + 1] != 's')
+ for (size_t c = 0; c < len; c++) {
+ /* if this is not % or it is % but without a following 's', just copy
+ * the character */
+ if (format[c] != '%' || (c == (len - 1)) || format[c + 1] != 's') {
*(dest++) = format[c];
- else {
- strncat(dest, command, inputlen);
- dest += inputlen;
+ } else {
+ strncat(dest, command, input_len);
+ dest += input_len;
/* skip the following 's' of '%s' */
c++;
}
diff --git a/i3bar/include/child.h b/i3bar/include/child.h
index ae523bc0..e77b51e3 100644
--- a/i3bar/include/child.h
+++ b/i3bar/include/child.h
@@ -11,7 +11,7 @@
#include <config.h>
-#include <stdbool.h>
+#include <ev.h>
#define STDIN_CHUNK_SIZE 1024
@@ -40,6 +40,18 @@ typedef struct {
*/
bool click_events;
bool click_events_init;
+
+ /**
+ * stdin- and SIGCHLD-watchers
+ */
+ ev_io *stdin_io;
+ ev_child *child_sig;
+ int stdin_fd;
+
+ /**
+ * Line read from child that did not include a newline character.
+ */
+ char *pending_line;
} i3bar_child;
/*
@@ -50,36 +62,66 @@ void clear_statusline(struct statusline_head *head, bool free_resources);
/*
* Start a child process with the specified command and reroute stdin.
- * We actually start a $SHELL to execute the command so we don't have to care
- * about arguments and such
+ * We actually start a shell to execute the command so we don't have to care
+ * about arguments and such.
+ *
+ * If `command' is NULL, such as in the case when no `status_command' is given
+ * in the bar config, no child will be started.
*
*/
void start_child(char *command);
/*
+ * Same as start_child but starts the configured client that manages workspace
+ * buttons.
+ *
+ */
+void start_ws_child(char *command);
+
+/*
+ * Returns true if the status child process is alive.
+ *
+ */
+bool status_child_is_alive(void);
+
+/*
+ * Returns true if the workspace child process is alive.
+ *
+ */
+bool ws_child_is_alive(void);
+
+/*
* kill()s the child process (if any). Called when exit()ing.
*
*/
-void kill_child_at_exit(void);
+void kill_children_at_exit(void);
/*
- * kill()s the child process (if any) and closes and
- * free()s the stdin- and SIGCHLD-watchers
+ * kill()s the child process (if any) and closes and free()s the stdin- and
+ * SIGCHLD-watchers
*
*/
void kill_child(void);
/*
+ * kill()s the workspace child process (if any) and closes and free()s the
+ * stdin- and SIGCHLD-watchers.
+ * Similar to kill_child.
+ *
+ */
+void kill_ws_child(void);
+
+/*
* Sends a SIGSTOP to the child process (if existent)
*
*/
-void stop_child(void);
+void stop_children(void);
/*
* Sends a SIGCONT to the child process (if existent)
*
*/
-void cont_child(void);
+void cont_children(void);
/*
* Whether or not the child want click events
@@ -92,3 +134,14 @@ bool child_want_click_events(void);
*
*/
void send_block_clicked(int button, const char *name, const char *instance, int x, int y, int x_rel, int y_rel, int out_x, int out_y, int width, int height, int mods);
+
+/*
+ * When workspace_command is enabled this function is used to re-parse the
+ * latest received JSON from the client.
+ */
+void repeat_last_ws_json(void);
+
+/*
+ * Replaces the workspace buttons with an error message.
+ */
+void set_workspace_button_error(const char *message);
diff --git a/i3bar/include/configuration.h b/i3bar/include/configuration.h
index 24079c5d..c9bae7c3 100644
--- a/i3bar/include/configuration.h
+++ b/i3bar/include/configuration.h
@@ -62,6 +62,7 @@ typedef struct config_t {
bool strip_ws_name;
char *bar_id;
char *command;
+ char *workspace_command;
char *fontname;
i3String *separator_symbol;
TAILQ_HEAD(tray_outputs_head, tray_output_t) tray_outputs;
@@ -79,17 +80,17 @@ typedef struct config_t {
extern config_t config;
/**
- * Start parsing the received bar configuration JSON string
+ * Parse the received bar configuration JSON string
*
*/
-void parse_config_json(char *json);
+void parse_config_json(const unsigned char *json, size_t size);
/**
- * Start parsing the received bar configuration list. The only usecase right
- * now is to automatically get the first bar id.
+ * Parse the received bar configuration list. The only usecase right now is to
+ * automatically get the first bar id.
*
*/
-void parse_get_first_i3bar_config(char *json);
+void parse_get_first_i3bar_config(const unsigned char *json, size_t size);
/**
* free()s the color strings as soon as they are not needed anymore.
diff --git a/i3bar/include/mode.h b/i3bar/include/mode.h
index e8e4296d..4646b9f4 100644
--- a/i3bar/include/mode.h
+++ b/i3bar/include/mode.h
@@ -24,7 +24,7 @@ struct mode {
typedef struct mode mode;
/*
- * Start parsing the received JSON string
+ * Parse the received JSON string
*
*/
-void parse_mode_json(char *json);
+void parse_mode_json(const unsigned char *json, size_t size);
diff --git a/i3bar/include/outputs.h b/i3bar/include/outputs.h
index 4685e51e..560abe53 100644
--- a/i3bar/include/outputs.h
+++ b/i3bar/include/outputs.h
@@ -22,10 +22,10 @@ SLIST_HEAD(outputs_head, i3_output);
extern struct outputs_head* outputs;
/*
- * Start parsing the received JSON string
+ * Parse the received JSON string
*
*/
-void parse_outputs_json(char* json);
+void parse_outputs_json(const unsigned char* json, size_t size);
/*
* Initiate the outputs list
diff --git a/i3bar/include/workspaces.h b/i3bar/include/workspaces.h
index ff61450c..6c8e7145 100644
--- a/i3bar/include/workspaces.h
+++ b/i3bar/include/workspaces.h
@@ -18,10 +18,10 @@ typedef struct i3_ws i3_ws;
TAILQ_HEAD(ws_head, i3_ws);
/*
- * Start parsing the received JSON string
+ * Parse the received JSON string
*
*/
-void parse_workspaces_json(char *json);
+void parse_workspaces_json(const unsigned char *json, size_t size);
/*
* free() all workspace data structures
@@ -38,7 +38,6 @@ struct i3_ws {
bool visible; /* If the ws is currently visible on an output */
bool focused; /* If the ws is currently focused */
bool urgent; /* If the urgent hint of the ws is set */
- rect rect; /* The rect of the ws (not used (yet)) */
struct i3_output *output; /* The current output of the ws */
TAILQ_ENTRY(i3_ws) tailq; /* Pointer for the TAILQ-Macro */
diff --git a/i3bar/include/xcb.h b/i3bar/include/xcb.h
index 0e3ca22d..fa274d01 100644
--- a/i3bar/include/xcb.h
+++ b/i3bar/include/xcb.h
@@ -12,7 +12,6 @@
#include <config.h>
#include <stdint.h>
-//#include "outputs.h"
#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
#define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1
diff --git a/i3bar/src/child.c b/i3bar/src/child.c
index df4c6601..20858f68 100644
--- a/i3bar/src/child.c
+++ b/i3bar/src/child.c
@@ -10,6 +10,7 @@
#include "common.h"
#include "yajl_utils.h"
+#include <ctype.h> /* isspace */
#include <err.h>
#include <errno.h>
#include <ev.h>
@@ -27,14 +28,30 @@
#include <yajl/yajl_parse.h>
/* Global variables for child_*() */
-i3bar_child child = {0};
-#define DLOG_CHILD DLOG("%s: pid=%ld stopped=%d stop_signal=%d cont_signal=%d click_events=%d click_events_init=%d\n", \
- __func__, (long)child.pid, child.stopped, child.stop_signal, child.cont_signal, child.click_events, child.click_events_init)
-
-/* stdin- and SIGCHLD-watchers */
-ev_io *stdin_io;
-int stdin_fd;
-ev_child *child_sig;
+i3bar_child status_child = {0};
+i3bar_child ws_child = {0};
+
+#define DLOG_CHILD(c) \
+ do { \
+ if ((c).pid == 0) { \
+ DLOG("%s: child pid = 0\n", __func__); \
+ } else if ((c).pid == status_child.pid) { \
+ DLOG("%s: status_command: pid=%ld stopped=%d stop_signal=%d cont_signal=%d click_events=%d click_events_init=%d\n", \
+ __func__, (long)(c).pid, (c).stopped, (c).stop_signal, (c).cont_signal, (c).click_events, (c).click_events_init); \
+ } else if ((c).pid == ws_child.pid) { \
+ DLOG("%s: workspace_command: pid=%ld stopped=%d stop_signal=%d cont_signal=%d click_events=%d click_events_init=%d\n", \
+ __func__, (long)(c).pid, (c).stopped, (c).stop_signal, (c).cont_signal, (c).click_events, (c).click_events_init); \
+ } else { \
+ ELOG("%s: unknown child, this should never happen " \
+ "pid=%ld stopped=%d stop_signal=%d cont_signal=%d click_events=%d click_events_init=%d\n", \
+ __func__, (long)(c).pid, (c).stopped, (c).stop_signal, (c).cont_signal, (c).click_events, (c).click_events_init); \
+ } \
+ } while (0)
+#define DLOG_CHILDREN \
+ do { \
+ DLOG_CHILD(status_child); \
+ DLOG_CHILD(ws_child); \
+ } while (0)
/* JSON parser for stdin */
yajl_handle parser;
@@ -127,7 +144,7 @@ __attribute__((format(printf, 1, 2))) static void set_statusline_error(const cha
TAILQ_INSERT_TAIL(&statusline_head, message_block, blocks);
finish:
- FREE(message);
+ free(message);
va_end(args);
}
@@ -135,22 +152,27 @@ finish:
* Stop and free() the stdin- and SIGCHLD-watchers
*
*/
-static void cleanup(void) {
- if (stdin_io != NULL) {
- ev_io_stop(main_loop, stdin_io);
- FREE(stdin_io);
- close(stdin_fd);
- stdin_fd = 0;
- close(child_stdin);
- child_stdin = 0;
+static void cleanup(i3bar_child *c) {
+ DLOG_CHILD(*c);
+
+ if (c->stdin_io != NULL) {
+ ev_io_stop(main_loop, c->stdin_io);
+ FREE(c->stdin_io);
+
+ if (c->pid == status_child.pid) {
+ close(child_stdin);
+ child_stdin = 0;
+ }
+ close(c->stdin_fd);
}
- if (child_sig != NULL) {
- ev_child_stop(main_loop, child_sig);
- FREE(child_sig);
+ if (c->child_sig != NULL) {
+ ev_child_stop(main_loop, c->child_sig);
+ FREE(c->child_sig);
}
- memset(&child, 0, sizeof(i3bar_child));
+ FREE(c->pending_line);
+ memset(c, 0, sizeof(i3bar_child));
}
/*
@@ -362,15 +384,13 @@ static int stdin_end_array(void *context) {
* Returns NULL on EOF.
*
*/
-static unsigned char *get_buffer(ev_io *watcher, int *ret_buffer_len) {
- int fd = watcher->fd;
- int n = 0;
+static unsigned char *get_buffer(int fd, int *ret_buffer_len) {
int rec = 0;
int buffer_len = STDIN_CHUNK_SIZE;
unsigned char *buffer = smalloc(buffer_len + 1);
buffer[0] = '\0';
while (1) {
- n = read(fd, buffer + rec, buffer_len - rec);
+ const ssize_t n = read(fd, buffer + rec, buffer_len - rec);
if (n == -1) {
if (errno == EAGAIN) {
/* finish up */
@@ -390,10 +410,11 @@ static unsigned char *get_buffer(ev_io *watcher, int *ret_buffer_len) {
if (rec == buffer_len) {
buffer_len += STDIN_CHUNK_SIZE;
- buffer = srealloc(buffer, buffer_len);
+ buffer = srealloc(buffer, buffer_len + 1);
}
}
- if (*buffer == '\0') {
+ buffer[rec] = '\0';
+ if (buffer[0] == '\0') {
FREE(buffer);
rec = -1;
}
@@ -443,13 +464,14 @@ static bool read_json_input(unsigned char *input, int length) {
* in statusline
*
*/
-static void stdin_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
+static void stdin_io_cb(int fd) {
int rec;
- unsigned char *buffer = get_buffer(watcher, &rec);
- if (buffer == NULL)
+ unsigned char *buffer = get_buffer(fd, &rec);
+ if (buffer == NULL) {
return;
+ }
bool has_urgent = false;
- if (child.version > 0) {
+ if (status_child.version > 0) {
has_urgent = read_json_input(buffer, rec);
} else {
read_flat_input((char *)buffer, rec);
@@ -463,22 +485,23 @@ static void stdin_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
* whether this is JSON or plain text
*
*/
-static void stdin_io_first_line_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
+static void stdin_io_first_line_cb(int fd) {
int rec;
- unsigned char *buffer = get_buffer(watcher, &rec);
- if (buffer == NULL)
+ unsigned char *buffer = get_buffer(fd, &rec);
+ if (buffer == NULL) {
return;
+ }
DLOG("Detecting input type based on buffer *%.*s*\n", rec, buffer);
/* Detect whether this is JSON or plain text. */
unsigned int consumed = 0;
/* At the moment, we don’t care for the version. This might change
* in the future, but for now, we just discard it. */
- parse_json_header(&child, buffer, rec, &consumed);
- if (child.version > 0) {
- /* If hide-on-modifier is set, we start of by sending the
- * child a SIGSTOP, because the bars aren't mapped at start */
+ parse_json_header(&status_child, buffer, rec, &consumed);
+ if (status_child.version > 0) {
+ /* If hide-on-modifier is set, we start of by sending the status_child
+ * a SIGSTOP, because the bars aren't mapped at start */
if (config.hide_on_modifier) {
- stop_child();
+ stop_children();
}
draw_bars(read_json_input(buffer + consumed, rec - consumed));
} else {
@@ -489,9 +512,133 @@ static void stdin_io_first_line_cb(struct ev_loop *loop, ev_io *watcher, int rev
read_flat_input((char *)buffer, rec);
}
free(buffer);
- ev_io_stop(main_loop, stdin_io);
- ev_io_init(stdin_io, &stdin_io_cb, stdin_fd, EV_READ);
- ev_io_start(main_loop, stdin_io);
+}
+
+static bool isempty(char *s) {
+ while (*s != '\0') {
+ if (!isspace(*s)) {
+ return false;
+ }
+ s++;
+ }
+ return true;
+}
+
+static char *append_string(const char *previous, const char *str) {
+ if (previous != NULL) {
+ char *result;
+ sasprintf(&result, "%s%s", previous, str);
+ return result;
+ }
+ return sstrdup(str);
+}
+
+static char *ws_last_json;
+
+static void ws_stdin_io_cb(int fd) {
+ int rec;
+ unsigned char *buffer = get_buffer(fd, &rec);
+ if (buffer == NULL) {
+ return;
+ }
+
+ gchar **strings = g_strsplit((const char *)buffer, "\n", 0);
+ for (int idx = 0; strings[idx] != NULL; idx++) {
+ if (ws_child.pending_line == NULL && isempty(strings[idx])) {
+ /* In the normal case where the buffer ends with '\n', the last
+ * string should be empty */
+ continue;
+ }
+
+ if (strings[idx + 1] == NULL) {
+ /* This is the last string but it is not empty, meaning that we have
+ * read data that is incomplete, save it for later. */
+ char *new = append_string(ws_child.pending_line, strings[idx]);
+ free(ws_child.pending_line);
+ ws_child.pending_line = new;
+ continue;
+ }
+
+ free(ws_last_json);
+ ws_last_json = append_string(ws_child.pending_line, strings[idx]);
+ FREE(ws_child.pending_line);
+
+ parse_workspaces_json((const unsigned char *)ws_last_json, strlen(ws_last_json));
+ }
+
+ g_strfreev(strings);
+ free(buffer);
+
+ draw_bars(false);
+}
+
+static void common_stdin_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
+ if (watcher == status_child.stdin_io) {
+ if (status_child.version == (uint32_t)-1) {
+ stdin_io_first_line_cb(watcher->fd);
+ } else {
+ stdin_io_cb(watcher->fd);
+ }
+ } else if (watcher == ws_child.stdin_io) {
+ ws_stdin_io_cb(watcher->fd);
+ } else {
+ ELOG("Got callback for unknown watcher fd=%d\n", watcher->fd);
+ }
+}
+
+/*
+ * When workspace_command is enabled this function is used to re-parse the
+ * latest received JSON from the client.
+ */
+void repeat_last_ws_json(void) {
+ if (ws_last_json) {
+ DLOG("Repeating last workspace JSON\n");
+ parse_workspaces_json((const unsigned char *)ws_last_json, strlen(ws_last_json));
+ }
+}
+
+/*
+ * Wrapper around set_workspace_button_error to mimic the call of
+ * set_statusline_error.
+ */
+__attribute__((format(printf, 1, 2))) static void set_workspace_button_error_f(const char *format, ...) {
+ char *message;
+ va_list args;
+ va_start(args, format);
+ if (vasprintf(&message, format, args) == -1) {
+ goto finish;
+ }
+
+ set_workspace_button_error(message);
+
+finish:
+ free(message);
+ va_end(args);
+}
+
+/*
+ * Replaces the workspace buttons with an error message.
+ */
+void set_workspace_button_error(const char *message) {
+ free_workspaces();
+
+ char *name = NULL;
+ sasprintf(&name, "Error: %s", message);
+
+ i3_output *output;
+ SLIST_FOREACH (output, outputs, slist) {
+ i3_ws *fake_ws = scalloc(1, sizeof(i3_ws));
+ /* Don't set the canonical_name field to make this workspace unfocusable. */
+ fake_ws->name = i3string_from_utf8(name);
+ fake_ws->name_width = predict_text_width(fake_ws->name);
+ fake_ws->num = -1;
+ fake_ws->urgent = fake_ws->visible = true;
+ fake_ws->output = output;
+
+ TAILQ_INSERT_TAIL(output->workspaces, fake_ws, tailq);
+ }
+
+ free(name);
}
/*
@@ -501,27 +648,45 @@ static void stdin_io_first_line_cb(struct ev_loop *loop, ev_io *watcher, int rev
*
*/
static void child_sig_cb(struct ev_loop *loop, ev_child *watcher, int revents) {
- int exit_status = WEXITSTATUS(watcher->rstatus);
+ const int exit_status = WEXITSTATUS(watcher->rstatus);
ELOG("Child (pid: %d) unexpectedly exited with status %d\n",
- child.pid,
+ watcher->pid,
exit_status);
+ void (*error_function_pointer)(const char *, ...) = NULL;
+ const char *command_type = "";
+ i3bar_child *c = NULL;
+ if (watcher->pid == status_child.pid) {
+ command_type = "status_command";
+ error_function_pointer = set_statusline_error;
+ c = &status_child;
+ } else if (watcher->pid == ws_child.pid) {
+ command_type = "workspace_command";
+ error_function_pointer = set_workspace_button_error_f;
+ c = &ws_child;
+ } else {
+ ELOG("Unknown child pid, this should never happen\n");
+ return;
+ }
+ DLOG_CHILD(*c);
+
/* this error is most likely caused by a user giving a nonexecutable or
* nonexistent file, so we will handle those cases separately. */
- if (exit_status == 126)
- set_statusline_error("status_command is not executable (exit %d)", exit_status);
- else if (exit_status == 127)
- set_statusline_error("status_command not found or is missing a library dependency (exit %d)", exit_status);
- else
- set_statusline_error("status_command process exited unexpectedly (exit %d)", exit_status);
+ if (exit_status == 126) {
+ error_function_pointer("%s is not executable (exit %d)", command_type, exit_status);
+ } else if (exit_status == 127) {
+ error_function_pointer("%s not found or is missing a library dependency (exit %d)", command_type, exit_status);
+ } else {
+ error_function_pointer("%s process exited unexpectedly (exit %d)", command_type, exit_status);
+ }
- cleanup();
+ cleanup(c);
draw_bars(false);
}
static void child_write_output(void) {
- if (child.click_events) {
+ if (status_child.click_events) {
const unsigned char *output;
size_t size;
ssize_t n;
@@ -535,7 +700,7 @@ static void child_write_output(void) {
yajl_gen_clear(gen);
if (n == -1) {
- child.click_events = false;
+ status_child.click_events = false;
kill_child();
set_statusline_error("child_write_output failed");
draw_bars(false);
@@ -543,6 +708,41 @@ static void child_write_output(void) {
}
}
+static pid_t sfork(void) {
+ const pid_t pid = fork();
+ if (pid == -1) {
+ ELOG("Couldn't fork(): %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ return pid;
+}
+
+static void spipe(int pipedes[2]) {
+ if (pipe(pipedes) == -1) {
+ err(EXIT_FAILURE, "pipe(pipe_in)");
+ }
+}
+
+static void exec_shell(char *command) {
+ execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, (char *)NULL);
+}
+
+static void setup_child_cb(i3bar_child *child) {
+ /* We set O_NONBLOCK because blocking is evil in event-driven software */
+ fcntl(child->stdin_fd, F_SETFL, O_NONBLOCK);
+
+ child->stdin_io = smalloc(sizeof(ev_io));
+ ev_io_init(child->stdin_io, &common_stdin_cb, child->stdin_fd, EV_READ);
+ ev_io_start(main_loop, child->stdin_io);
+
+ /* We must cleanup, if the child unexpectedly terminates */
+ child->child_sig = smalloc(sizeof(ev_child));
+ ev_child_init(child->child_sig, &child_sig_cb, child->pid, 0);
+ ev_child_start(main_loop, child->child_sig);
+
+ DLOG_CHILD(*child);
+}
+
/*
* Start a child process with the specified command and reroute stdin.
* We actually start a shell to execute the command so we don't have to care
@@ -553,8 +753,9 @@ static void child_write_output(void) {
*
*/
void start_child(char *command) {
- if (command == NULL)
+ if (command == NULL) {
return;
+ }
/* Allocate a yajl parser which will be used to parse stdin. */
static yajl_callbacks callbacks = {
@@ -568,69 +769,77 @@ void start_child(char *command) {
.yajl_end_array = stdin_end_array,
};
parser = yajl_alloc(&callbacks, NULL, &parser_context);
-
gen = yajl_gen_alloc(NULL);
int pipe_in[2]; /* pipe we read from */
int pipe_out[2]; /* pipe we write to */
+ spipe(pipe_in);
+ spipe(pipe_out);
- if (pipe(pipe_in) == -1)
- err(EXIT_FAILURE, "pipe(pipe_in)");
- if (pipe(pipe_out) == -1)
- err(EXIT_FAILURE, "pipe(pipe_out)");
-
- child.pid = fork();
- switch (child.pid) {
- case -1:
- ELOG("Couldn't fork(): %s\n", strerror(errno));
- exit(EXIT_FAILURE);
- case 0:
- /* Child-process. Reroute streams and start shell */
-
- close(pipe_in[0]);
- close(pipe_out[1]);
+ status_child.pid = sfork();
+ if (status_child.pid == 0) {
+ /* Child-process. Reroute streams and start shell */
+ close(pipe_in[0]);
+ close(pipe_out[1]);
- dup2(pipe_in[1], STDOUT_FILENO);
- dup2(pipe_out[0], STDIN_FILENO);
+ dup2(pipe_in[1], STDOUT_FILENO);
+ dup2(pipe_out[0], STDIN_FILENO);
- setpgid(child.pid, 0);
- execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, (char *)NULL);
- return;
- default:
- /* Parent-process. Reroute streams */
+ setpgid(status_child.pid, 0);
+ exec_shell(command);
+ return;
+ }
+ /* Parent-process. Reroute streams */
+ close(pipe_in[1]);
+ close(pipe_out[0]);
- close(pipe_in[1]);
- close(pipe_out[0]);
+ status_child.stdin_fd = pipe_in[0];
+ child_stdin = pipe_out[1];
+ status_child.version = -1;
- stdin_fd = pipe_in[0];
- child_stdin = pipe_out[1];
+ setup_child_cb(&status_child);
+}
- break;
+/*
+ * Same as start_child but starts the configured client that manages workspace
+ * buttons.
+ *
+ */
+void start_ws_child(char *command) {
+ if (command == NULL) {
+ return;
}
- /* We set O_NONBLOCK because blocking is evil in event-driven software */
- fcntl(stdin_fd, F_SETFL, O_NONBLOCK);
+ ws_child.stop_signal = SIGSTOP;
+ ws_child.cont_signal = SIGCONT;
- stdin_io = smalloc(sizeof(ev_io));
- ev_io_init(stdin_io, &stdin_io_first_line_cb, stdin_fd, EV_READ);
- ev_io_start(main_loop, stdin_io);
+ int pipe_in[2]; /* pipe we read from */
+ spipe(pipe_in);
- /* We must cleanup, if the child unexpectedly terminates */
- child_sig = smalloc(sizeof(ev_child));
- ev_child_init(child_sig, &child_sig_cb, child.pid, 0);
- ev_child_start(main_loop, child_sig);
+ ws_child.pid = sfork();
+ if (ws_child.pid == 0) {
+ /* Child-process. Reroute streams and start shell */
+ close(pipe_in[0]);
+ dup2(pipe_in[1], STDOUT_FILENO);
- atexit(kill_child_at_exit);
- DLOG_CHILD;
+ setpgid(ws_child.pid, 0);
+ exec_shell(command);
+ return;
+ }
+ /* Parent-process. Reroute streams */
+ close(pipe_in[1]);
+ ws_child.stdin_fd = pipe_in[0];
+
+ setup_child_cb(&ws_child);
}
static void child_click_events_initialize(void) {
- DLOG_CHILD;
+ DLOG_CHILD(status_child);
- if (!child.click_events_init) {
+ if (!status_child.click_events_init) {
yajl_gen_array_open(gen);
child_write_output();
- child.click_events_init = true;
+ status_child.click_events_init = true;
}
}
@@ -639,7 +848,7 @@ static void child_click_events_initialize(void) {
*
*/
void send_block_clicked(int button, const char *name, const char *instance, int x, int y, int x_rel, int y_rel, int out_x, int out_y, int width, int height, int mods) {
- if (!child.click_events) {
+ if (!status_child.click_events) {
return;
}
@@ -706,35 +915,85 @@ void send_block_clicked(int button, const char *name, const char *instance, int
child_write_output();
}
+static bool is_alive(i3bar_child *c) {
+ return c->pid > 0;
+}
+
+/*
+ * Returns true if the status child process is alive.
+ *
+ */
+bool status_child_is_alive(void) {
+ return is_alive(&status_child);
+}
+
+/*
+ * Returns true if the workspace child process is alive.
+ *
+ */
+bool ws_child_is_alive(void) {
+ return is_alive(&ws_child);
+}
+
/*
* kill()s the child process (if any). Called when exit()ing.
*
*/
-void kill_child_at_exit(void) {
- DLOG_CHILD;
+void kill_children_at_exit(void) {
+ DLOG_CHILDREN;
+ cont_children();
- if (child.pid > 0) {
- if (child.cont_signal > 0 && child.stopped)
- killpg(child.pid, child.cont_signal);
- killpg(child.pid, SIGTERM);
+ if (is_alive(&status_child)) {
+ killpg(status_child.pid, SIGTERM);
+ }
+ if (is_alive(&ws_child)) {
+ killpg(ws_child.pid, SIGTERM);
}
}
+static void cont_child(i3bar_child *c) {
+ if (is_alive(c) && c->cont_signal > 0 && c->stopped) {
+ c->stopped = false;
+ killpg(c->pid, c->cont_signal);
+ }
+}
+
+static void kill_and_wait(i3bar_child *c) {
+ DLOG_CHILD(*c);
+ if (!is_alive(c)) {
+ return;
+ }
+
+ cont_child(c);
+ killpg(c->pid, SIGTERM);
+ int status;
+ waitpid(c->pid, &status, 0);
+ cleanup(c);
+}
+
/*
- * kill()s the child process (if existent) and closes and
- * free()s the stdin- and SIGCHLD-watchers
+ * kill()s the child process (if any) and closes and free()s the stdin- and
+ * SIGCHLD-watchers
*
*/
void kill_child(void) {
- DLOG_CHILD;
+ kill_and_wait(&status_child);
+}
- if (child.pid > 0) {
- if (child.cont_signal > 0 && child.stopped)
- killpg(child.pid, child.cont_signal);
- killpg(child.pid, SIGTERM);
- int status;
- waitpid(child.pid, &status, 0);
- cleanup();
+/*
+ * kill()s the workspace child process (if any) and closes and free()s the
+ * stdin- and SIGCHLD-watchers.
+ * Similar to kill_child.
+ *
+ */
+void kill_ws_child(void) {
+ kill_and_wait(&ws_child);
+}
+
+static void stop_child(i3bar_child *c) {
+ if (c->stop_signal > 0 && !c->stopped) {
+ c->stopped = true;
+ killpg(c->pid, c->stop_signal);
}
}
@@ -742,26 +1001,21 @@ void kill_child(void) {
* Sends a SIGSTOP to the child process (if existent)
*
*/
-void stop_child(void) {
- DLOG_CHILD;
-
- if (child.stop_signal > 0 && !child.stopped) {
- child.stopped = true;
- killpg(child.pid, child.stop_signal);
- }
+void stop_children(void) {
+ DLOG_CHILDREN;
+ stop_child(&status_child);
+ stop_child(&ws_child);
}
/*
* Sends a SIGCONT to the child process (if existent)
*
*/
-void cont_child(void) {
- DLOG_CHILD;
+void cont_children(void) {
+ DLOG_CHILDREN;
- if (child.cont_signal > 0 && child.stopped) {
- child.stopped = false;
- killpg(child.pid, child.cont_signal);
- }
+ cont_child(&status_child);
+ cont_child(&ws_child);
}
/*
@@ -769,5 +1023,5 @@ void cont_child(void) {
*
*/
bool child_want_click_events(void) {
- return child.click_events;
+ return status_child.click_events;
}
diff --git a/i3bar/src/config.c b/i3bar/src/config.c
index ccea937d..cebd5d5d 100644
--- a/i3bar/src/config.c
+++ b/i3bar/src/config.c
@@ -188,11 +188,17 @@ static int config_string_cb(void *params_, const unsigned char *val, size_t _len
}
if (!strcmp(cur_key, "status_command")) {
- DLOG("command = %.*s\n", len, val);
+ DLOG("status_command = %.*s\n", len, val);
sasprintf(&config.command, "%.*s", len, val);
return 1;
}
+ if (!strcmp(cur_key, "workspace_command")) {
+ DLOG("workspace_command = %.*s\n", len, val);
+ sasprintf(&config.workspace_command, "%.*s", len, val);
+ return 1;
+ }
+
if (!strcmp(cur_key, "font")) {
DLOG("font = %.*s\n", len, val);
FREE(config.fontname);
@@ -396,16 +402,15 @@ static yajl_callbacks outputs_callbacks = {
};
/*
- * Start parsing the received bar configuration JSON string
+ * Parse the received bar configuration JSON string
*
*/
-void parse_config_json(char *json) {
- yajl_handle handle = yajl_alloc(&outputs_callbacks, NULL, NULL);
-
+void parse_config_json(const unsigned char *json, size_t size) {
TAILQ_INIT(&(config.bindings));
TAILQ_INIT(&(config.tray_outputs));
- yajl_status state = yajl_parse(handle, (const unsigned char *)json, strlen(json));
+ yajl_handle handle = yajl_alloc(&outputs_callbacks, NULL, NULL);
+ yajl_status state = yajl_parse(handle, json, size);
/* FIXME: Proper error handling for JSON parsing */
switch (state) {
@@ -418,6 +423,11 @@ void parse_config_json(char *json) {
break;
}
+ if (config.disable_ws && config.workspace_command) {
+ ELOG("You have specified 'workspace_buttons no'. Your 'workspace_command %s' will be ignored.\n", config.workspace_command);
+ FREE(config.workspace_command);
+ }
+
yajl_free(handle);
}
@@ -427,16 +437,16 @@ static int i3bar_config_string_cb(void *params_, const unsigned char *val, size_
}
/*
- * Start parsing the received bar configuration list. The only usecase right
- * now is to automatically get the first bar id.
+ * Parse the received bar configuration list. The only usecase right now is to
+ * automatically get the first bar id.
*
*/
-void parse_get_first_i3bar_config(char *json) {
+void parse_get_first_i3bar_config(const unsigned char *json, size_t size) {
yajl_callbacks configs_callbacks = {
.yajl_string = i3bar_config_string_cb,
};
yajl_handle handle = yajl_alloc(&configs_callbacks, NULL, NULL);
- yajl_parse(handle, (const unsigned char *)json, strlen(json));
+ yajl_parse(handle, json, size);
yajl_free(handle);
}
diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c
index 06ddf9b5..95130209 100644
--- a/i3bar/src/ipc.c
+++ b/i3bar/src/ipc.c
@@ -24,14 +24,24 @@ ev_io *i3_connection;
const char *sock_path;
-typedef void (*handler_t)(char *);
+typedef void (*handler_t)(const unsigned char *, size_t);
+
+/*
+ * Returns true when i3bar is configured to read workspace information from i3
+ * via JSON over the i3 IPC interface, as opposed to reading workspace
+ * information from the workspace_command via JSON over stdout.
+ *
+ */
+static bool i3_provides_workspaces(void) {
+ return !config.disable_ws && config.workspace_command == NULL;
+}
/*
* Called, when we get a reply to a command from i3.
* Since i3 does not give us much feedback on commands, we do not much
*
*/
-static void got_command_reply(char *reply) {
+static void got_command_reply(const unsigned char *reply, size_t size) {
/* TODO: Error handling for command replies */
}
@@ -39,9 +49,9 @@ static void got_command_reply(char *reply) {
* Called, when we get a reply with workspaces data
*
*/
-static void got_workspace_reply(char *reply) {
+static void got_workspace_reply(const unsigned char *reply, size_t size) {
DLOG("Got workspace data!\n");
- parse_workspaces_json(reply);
+ parse_workspaces_json(reply, size);
draw_bars(false);
}
@@ -50,7 +60,7 @@ static void got_workspace_reply(char *reply) {
* Since i3 does not give us much feedback on commands, we do not much
*
*/
-static void got_subscribe_reply(char *reply) {
+static void got_subscribe_reply(const unsigned char *reply, size_t size) {
DLOG("Got subscribe reply: %s\n", reply);
/* TODO: Error handling for subscribe commands */
}
@@ -59,12 +69,12 @@ static void got_subscribe_reply(char *reply) {
* Called, when we get a reply with outputs data
*
*/
-static void got_output_reply(char *reply) {
+static void got_output_reply(const unsigned char *reply, size_t size) {
DLOG("Clearing old output configuration...\n");
free_outputs();
DLOG("Parsing outputs JSON...\n");
- parse_outputs_json(reply);
+ parse_outputs_json(reply, size);
DLOG("Reconfiguring windows...\n");
reconfig_windows(false);
@@ -73,8 +83,19 @@ static void got_output_reply(char *reply) {
kick_tray_clients(o_walk);
}
- if (!config.disable_ws) {
+ if (i3_provides_workspaces()) {
i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL);
+ } else if (config.workspace_command) {
+ /* Communication with the workspace child is one-way. Since we called
+ * free_outputs() and free_workspaces() we have lost our workspace
+ * information which will result in no workspace buttons. A
+ * well-behaving client should be subscribed to output events as well
+ * and re-send the output information to i3bar. Even in that case
+ * though there is a race condition where the child can send the new
+ * workspace information after the output change before i3bar receives
+ * the output event from i3. For this reason, we re-parse the latest
+ * received JSON. */
+ repeat_last_ws_json();
}
draw_bars(false);
@@ -84,10 +105,10 @@ static void got_output_reply(char *reply) {
* Called when we get the configuration for our bar instance
*
*/
-static void got_bar_config(char *reply) {
+static void got_bar_config(const unsigned char *reply, size_t size) {
if (!config.bar_id) {
DLOG("Received bar list \"%s\"\n", reply);
- parse_get_first_i3bar_config(reply);
+ parse_get_first_i3bar_config(reply, size);
if (!config.bar_id) {
ELOG("No bar configuration found, please configure a bar block in your i3 config file.\n");
@@ -106,13 +127,14 @@ static void got_bar_config(char *reply) {
i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_OUTPUTS, NULL);
free_colors(&(config.colors));
- parse_config_json(reply);
+ parse_config_json(reply, size);
/* Now we can actually use 'config', so let's subscribe to the appropriate
* events and request the workspaces if necessary. */
subscribe_events();
- if (!config.disable_ws)
+ if (i3_provides_workspaces()) {
i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL);
+ }
/* Initialize the rest of XCB */
init_xcb_late(config.fontname);
@@ -121,6 +143,7 @@ static void got_bar_config(char *reply) {
init_colors(&(config.colors));
start_child(config.command);
+ start_ws_child(config.workspace_command);
}
/* Data structure to easily call the reply handlers later */
@@ -143,7 +166,7 @@ handler_t reply_handlers[] = {
* Called, when a workspace event arrives (i.e. the user changed the workspace)
*
*/
-static void got_workspace_event(char *event) {
+static void got_workspace_event(const unsigned char *event, size_t size) {
DLOG("Got workspace event!\n");
i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL);
}
@@ -152,7 +175,7 @@ static void got_workspace_event(char *event) {
* Called, when an output event arrives (i.e. the screen configuration changed)
*
*/
-static void got_output_event(char *event) {
+static void got_output_event(const unsigned char *event, size_t size) {
DLOG("Got output event!\n");
i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_OUTPUTS, NULL);
}
@@ -161,9 +184,9 @@ static void got_output_event(char *event) {
* Called, when a mode event arrives (i3 changed binding mode).
*
*/
-static void got_mode_event(char *event) {
+static void got_mode_event(const unsigned char *event, size_t size) {
DLOG("Got mode event!\n");
- parse_mode_json(event);
+ parse_mode_json(event, size);
draw_bars(false);
}
@@ -183,11 +206,11 @@ static bool strings_differ(char *a, char *b) {
* Called, when a barconfig_update event arrives (i.e. i3 changed the bar hidden_state or mode)
*
*/
-static void got_bar_config_update(char *event) {
+static void got_bar_config_update(const unsigned char *event, size_t size) {
/* check whether this affect this bar instance by checking the bar_id */
char *expected_id;
sasprintf(&expected_id, "\"id\":\"%s\"", config.bar_id);
- char *found_id = strstr(event, expected_id);
+ char *found_id = strstr((const char *)event, expected_id);
FREE(expected_id);
if (found_id == NULL)
return;
@@ -201,10 +224,12 @@ static void got_bar_config_update(char *event) {
DLOG("Received bar config update \"%s\"\n", event);
char *old_command = config.command;
+ char *old_workspace_command = config.workspace_command;
config.command = NULL;
+ config.workspace_command = NULL;
bar_display_mode_t old_mode = config.hide_on_modifier;
- parse_config_json(event);
+ parse_config_json(event, size);
if (old_mode != config.hide_on_modifier) {
reconfig_windows(true);
}
@@ -214,13 +239,21 @@ static void got_bar_config_update(char *event) {
init_colors(&(config.colors));
/* restart status command process */
- if (strings_differ(old_command, config.command)) {
+ if (!status_child_is_alive() || strings_differ(old_command, config.command)) {
kill_child();
clear_statusline(&statusline_head, true);
start_child(config.command);
}
free(old_command);
+ /* restart workspace command process */
+ if (!ws_child_is_alive() || strings_differ(old_workspace_command, config.workspace_command)) {
+ free_workspaces();
+ kill_ws_child();
+ start_ws_child(config.workspace_command);
+ }
+ free(old_workspace_command);
+
draw_bars(false);
}
@@ -284,7 +317,7 @@ static void got_data(struct ev_loop *loop, ev_io *watcher, int events) {
/* Now that we know, what to expect, we can start read()ing the rest
* of the message */
- char *buffer = smalloc(size + 1);
+ unsigned char *buffer = smalloc(size + 1);
rec = 0;
while (rec < size) {
@@ -304,10 +337,11 @@ static void got_data(struct ev_loop *loop, ev_io *watcher, int events) {
/* And call the callback (indexed by the type) */
if (type & (1UL << 31)) {
type ^= 1UL << 31;
- event_handlers[type](buffer);
+ event_handlers[type](buffer, size);
} else {
- if (reply_handlers[type])
- reply_handlers[type](buffer);
+ if (reply_handlers[type]) {
+ reply_handlers[type](buffer, size);
+ }
}
FREE(header);
@@ -340,8 +374,9 @@ int i3_send_msg(uint32_t type, const char *payload) {
memcpy(walk, &type, sizeof(uint32_t));
walk += sizeof(uint32_t);
- if (payload != NULL)
- strncpy(walk, payload, len);
+ if (payload != NULL) {
+ memcpy(walk, payload, len);
+ }
swrite(i3_connection->fd, buffer, to_write);
@@ -376,9 +411,9 @@ void destroy_connection(void) {
*
*/
void subscribe_events(void) {
- if (config.disable_ws) {
- i3_send_msg(I3_IPC_MESSAGE_TYPE_SUBSCRIBE, "[ \"output\", \"mode\", \"barconfig_update\" ]");
- } else {
+ if (i3_provides_workspaces()) {
i3_send_msg(I3_IPC_MESSAGE_TYPE_SUBSCRIBE, "[ \"workspace\", \"output\", \"mode\", \"barconfig_update\" ]");
+ } else {
+ i3_send_msg(I3_IPC_MESSAGE_TYPE_SUBSCRIBE, "[ \"output\", \"mode\", \"barconfig_update\" ]");
}
}
diff --git a/i3bar/src/main.c b/i3bar/src/main.c
index 4e93bb02..ce5257bf 100644
--- a/i3bar/src/main.c
+++ b/i3bar/src/main.c
@@ -185,12 +185,12 @@ int main(int argc, char **argv) {
ev_signal_start(main_loop, sig_int);
ev_signal_start(main_loop, sig_hup);
+ atexit(kill_children_at_exit);
+
/* From here on everything should run smooth for itself, just start listening for
* events. We stop simply stop the event loop, when we are finished */
ev_loop(main_loop, 0);
- kill_child();
-
clean_xcb();
ev_default_destroy();
diff --git a/i3bar/src/mode.c b/i3bar/src/mode.c
index 13d02110..aea43ab4 100644
--- a/i3bar/src/mode.c
+++ b/i3bar/src/mode.c
@@ -16,7 +16,6 @@
/* A datatype to pass through the callbacks to save the state */
struct mode_json_params {
- char *json;
char *cur_key;
char *name;
bool pango_markup;
@@ -96,26 +95,17 @@ static yajl_callbacks mode_callbacks = {
};
/*
- * Start parsing the received JSON string
+ * Parse the received JSON string
*
*/
-void parse_mode_json(char *json) {
- /* FIXME: Fasciliate stream processing, i.e. allow starting to interpret
- * JSON in chunks */
+void parse_mode_json(const unsigned char *json, size_t size) {
struct mode_json_params params;
-
mode binding;
-
params.cur_key = NULL;
- params.json = json;
params.mode = &binding;
- yajl_handle handle;
- yajl_status state;
-
- handle = yajl_alloc(&mode_callbacks, NULL, (void *)&params);
-
- state = yajl_parse(handle, (const unsigned char *)json, strlen(json));
+ yajl_handle handle = yajl_alloc(&mode_callbacks, NULL, (void *)&params);
+ yajl_status state = yajl_parse(handle, json, size);
/* FIXME: Proper error handling for JSON parsing */
switch (state) {
diff --git a/i3bar/src/outputs.c b/i3bar/src/outputs.c
index 168f3eef..5aca53cd 100644
--- a/i3bar/src/outputs.c
+++ b/i3bar/src/outputs.c
@@ -18,10 +18,8 @@
/* A datatype to pass through the callbacks to save the state */
struct outputs_json_params {
- struct outputs_head *outputs;
i3_output *outputs_walk;
char *cur_key;
- char *json;
bool in_rect;
};
@@ -263,21 +261,17 @@ void init_outputs(void) {
}
/*
- * Start parsing the received JSON string
+ * Parse the received JSON string
*
*/
-void parse_outputs_json(char *json) {
+void parse_outputs_json(const unsigned char *json, size_t size) {
struct outputs_json_params params;
params.outputs_walk = NULL;
params.cur_key = NULL;
- params.json = json;
params.in_rect = false;
- yajl_handle handle;
- yajl_status state;
- handle = yajl_alloc(&outputs_callbacks, NULL, (void *)&params);
-
- state = yajl_parse(handle, (const unsigned char *)json, strlen(json));
+ yajl_handle handle = yajl_alloc(&outputs_callbacks, NULL, (void *)&params);
+ yajl_status state = yajl_parse(handle, json, size);
/* FIXME: Proper errorhandling for JSON-parsing */
switch (state) {
@@ -291,6 +285,7 @@ void parse_outputs_json(char *json) {
}
yajl_free(handle);
+ free(params.cur_key);
}
/*
@@ -319,12 +314,14 @@ void free_outputs(void) {
*
*/
i3_output *get_output_by_name(char *name) {
- i3_output *walk;
if (name == NULL) {
return NULL;
}
+ const bool is_primary = !strcasecmp(name, "primary");
+
+ i3_output *walk;
SLIST_FOREACH (walk, outputs, slist) {
- if (!strcmp(walk->name, name)) {
+ if ((is_primary && walk->primary) || !strcmp(walk->name, name)) {
break;
}
}
diff --git a/i3bar/src/workspaces.c b/i3bar/src/workspaces.c
index bd56f5d0..10c9fcf0 100644
--- a/i3bar/src/workspaces.c
+++ b/i3bar/src/workspaces.c
@@ -19,7 +19,8 @@ struct workspaces_json_params {
struct ws_head *workspaces;
i3_ws *workspaces_walk;
char *cur_key;
- char *json;
+ bool need_output;
+ bool parsing_rect;
};
/*
@@ -71,26 +72,23 @@ static int workspaces_integer_cb(void *params_, long long val) {
return 1;
}
+ /* rect is unused, so we don't bother to save it */
if (!strcmp(params->cur_key, "x")) {
- params->workspaces_walk->rect.x = (int)val;
FREE(params->cur_key);
return 1;
}
if (!strcmp(params->cur_key, "y")) {
- params->workspaces_walk->rect.y = (int)val;
FREE(params->cur_key);
return 1;
}
if (!strcmp(params->cur_key, "width")) {
- params->workspaces_walk->rect.w = (int)val;
FREE(params->cur_key);
return 1;
}
if (!strcmp(params->cur_key, "height")) {
- params->workspaces_walk->rect.h = (int)val;
FREE(params->cur_key);
return 1;
}
@@ -156,15 +154,16 @@ static int workspaces_string_cb(void *params_, const unsigned char *val, size_t
sasprintf(&output_name, "%.*s", len, val);
i3_output *target = get_output_by_name(output_name);
+ i3_ws *ws = params->workspaces_walk;
if (target != NULL) {
- params->workspaces_walk->output = target;
-
- TAILQ_INSERT_TAIL(params->workspaces_walk->output->workspaces,
- params->workspaces_walk,
- tailq);
+ ws->output = target;
+ TAILQ_INSERT_TAIL(ws->output->workspaces, ws, tailq);
}
+ params->need_output = false;
FREE(output_name);
+ FREE(params->cur_key);
+
return 1;
}
@@ -172,28 +171,42 @@ static int workspaces_string_cb(void *params_, const unsigned char *val, size_t
}
/*
- * We hit the start of a JSON map (rect or a new output)
+ * We hit the start of a JSON map (rect or a new workspace)
*
*/
static int workspaces_start_map_cb(void *params_) {
struct workspaces_json_params *params = (struct workspaces_json_params *)params_;
- i3_ws *new_workspace = NULL;
-
if (params->cur_key == NULL) {
- new_workspace = smalloc(sizeof(i3_ws));
+ i3_ws *new_workspace = scalloc(1, sizeof(i3_ws));
new_workspace->num = -1;
- new_workspace->name = NULL;
- new_workspace->visible = 0;
- new_workspace->focused = 0;
- new_workspace->urgent = 0;
- memset(&new_workspace->rect, 0, sizeof(rect));
- new_workspace->output = NULL;
params->workspaces_walk = new_workspace;
+ params->need_output = true;
+ params->parsing_rect = false;
+ } else {
+ params->parsing_rect = true;
+ }
+
+ return 1;
+}
+
+static int workspaces_end_map_cb(void *params_) {
+ struct workspaces_json_params *params = (struct workspaces_json_params *)params_;
+ i3_ws *ws = params->workspaces_walk;
+ const bool parsing_rect = params->parsing_rect;
+ params->parsing_rect = false;
+
+ if (parsing_rect || !ws || !ws->name || !params->need_output) {
return 1;
}
+ ws->output = get_output_by_name("primary");
+ if (ws->output == NULL) {
+ ws->output = SLIST_FIRST(outputs);
+ }
+ TAILQ_INSERT_TAIL(ws->output->workspaces, ws, tailq);
+
return 1;
}
@@ -216,43 +229,42 @@ static yajl_callbacks workspaces_callbacks = {
.yajl_integer = workspaces_integer_cb,
.yajl_string = workspaces_string_cb,
.yajl_start_map = workspaces_start_map_cb,
+ .yajl_end_map = workspaces_end_map_cb,
.yajl_map_key = workspaces_map_key_cb,
};
/*
- * Start parsing the received JSON string
+ * Parse the received JSON string
*
*/
-void parse_workspaces_json(char *json) {
- /* FIXME: Fasciliate stream processing, i.e. allow starting to interpret
- * JSON in chunks */
- struct workspaces_json_params params;
-
+void parse_workspaces_json(const unsigned char *json, size_t size) {
free_workspaces();
- params.workspaces_walk = NULL;
- params.cur_key = NULL;
- params.json = json;
-
- yajl_handle handle;
- yajl_status state;
- handle = yajl_alloc(&workspaces_callbacks, NULL, (void *)&params);
-
- state = yajl_parse(handle, (const unsigned char *)json, strlen(json));
+ struct workspaces_json_params params = {0};
+ yajl_handle handle = yajl_alloc(&workspaces_callbacks, NULL, (void *)&params);
+ yajl_status state = yajl_parse(handle, json, size);
/* FIXME: Proper error handling for JSON parsing */
switch (state) {
case yajl_status_ok:
break;
case yajl_status_client_canceled:
- case yajl_status_error:
- ELOG("Could not parse workspaces reply!\n");
- exit(EXIT_FAILURE);
+ case yajl_status_error: {
+ unsigned char *err = yajl_get_error(handle, 1, json, size);
+ ELOG("Could not parse workspaces reply, error:\n%s\njson:---%s---\n", err, json);
+ yajl_free_error(handle, err);
+
+ if (config.workspace_command) {
+ kill_ws_child();
+ set_workspace_button_error("Could not parse workspace_command's JSON");
+ } else {
+ exit(EXIT_FAILURE);
+ }
break;
+ }
}
yajl_free(handle);
-
FREE(params.cur_key);
}
@@ -261,14 +273,14 @@ void parse_workspaces_json(char *json) {
*
*/
void free_workspaces(void) {
- i3_output *outputs_walk;
if (outputs == NULL) {
return;
}
- i3_ws *ws_walk;
+ i3_output *outputs_walk;
SLIST_FOREACH (outputs_walk, outputs, slist) {
if (outputs_walk->workspaces != NULL && !TAILQ_EMPTY(outputs_walk->workspaces)) {
+ i3_ws *ws_walk;
TAILQ_FOREACH (ws_walk, outputs_walk->workspaces, tailq) {
I3STRING_FREE(ws_walk->name);
FREE(ws_walk->canonical_name);
diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c
index 0cda125c..4ff44d27 100644
--- a/i3bar/src/xcb.c
+++ b/i3bar/src/xcb.c
@@ -334,7 +334,7 @@ static void hide_bars(void) {
}
xcb_unmap_window(xcb_connection, walk->bar.id);
}
- stop_child();
+ stop_children();
}
/*
@@ -351,7 +351,7 @@ static void unhide_bars(void) {
uint32_t mask;
uint32_t values[5];
- cont_child();
+ cont_children();
SLIST_FOREACH (walk, outputs, slist) {
if (walk->bar.id == XCB_NONE) {
@@ -500,6 +500,49 @@ static int predict_button_width(int name_width) {
logical_px(config.ws_min_width));
}
+static char *quote_workspace_name(const char *in) {
+ /* To properly handle workspace names with double quotes in them, we need
+ * to escape the double quotes. We allocate a large enough buffer (twice
+ * the unescaped size is always enough), then we copy character by
+ * character. */
+ const size_t namelen = strlen(in);
+ const size_t len = namelen + strlen("workspace \"\"") + 1;
+ char *out = scalloc(2 * len, 1);
+ memcpy(out, "workspace \"", strlen("workspace \""));
+ size_t inpos, outpos;
+ for (inpos = 0, outpos = strlen("workspace \"");
+ inpos < namelen;
+ inpos++, outpos++) {
+ if (in[inpos] == '"' || in[inpos] == '\\') {
+ out[outpos] = '\\';
+ outpos++;
+ }
+ out[outpos] = in[inpos];
+ }
+ out[outpos] = '"';
+ return out;
+}
+
+static void focus_workspace(i3_ws *ws) {
+ char *buffer = NULL;
+ if (ws->id != 0) {
+ /* Workspace ID has higher precedence since the workspace_command is
+ * allowed to change workspace names as long as it provides a valid ID. */
+ sasprintf(&buffer, "[con_id=%lld] focus workspace", ws->id);
+ goto done;
+ }
+
+ if (ws->canonical_name == NULL) {
+ return;
+ }
+
+ buffer = quote_workspace_name(ws->canonical_name);
+
+done:
+ i3_send_msg(I3_IPC_MESSAGE_TYPE_RUN_COMMAND, buffer);
+ free(buffer);
+}
+
/*
* Handle a button press event (i.e. a mouse click on one of our bars).
* We determine, whether the click occurred on a workspace button or if the scroll-
@@ -620,37 +663,7 @@ static void handle_button(xcb_button_press_event_t *event) {
return;
}
- /* To properly handle workspace names with double quotes in them, we need
- * to escape the double quotes. Unfortunately, that’s rather ugly in C: We
- * first count the number of double quotes, then we allocate a large enough
- * buffer, then we copy character by character. */
- int num_quotes = 0;
- size_t namelen = 0;
- const char *utf8_name = cur_ws->canonical_name;
- for (const char *walk = utf8_name; *walk != '\0'; walk++) {
- if (*walk == '"' || *walk == '\\')
- num_quotes++;
- /* While we’re looping through the name anyway, we can save one
- * strlen(). */
- namelen++;
- }
-
- const size_t len = namelen + strlen("workspace \"\"") + 1;
- char *buffer = scalloc(len + num_quotes, 1);
- memcpy(buffer, "workspace \"", strlen("workspace \""));
- size_t inpos, outpos;
- for (inpos = 0, outpos = strlen("workspace \"");
- inpos < namelen;
- inpos++, outpos++) {
- if (utf8_name[inpos] == '"' || utf8_name[inpos] == '\\') {
- buffer[outpos] = '\\';
- outpos++;
- }
- buffer[outpos] = utf8_name[inpos];
- }
- buffer[outpos] = '"';
- i3_send_msg(I3_IPC_MESSAGE_TYPE_RUN_COMMAND, buffer);
- free(buffer);
+ focus_workspace(cur_ws);
}
/*
@@ -674,9 +687,9 @@ static void handle_visibility_notify(xcb_visibility_notify_event_t *event) {
}
if (num_visible == 0) {
- stop_child();
+ stop_children();
} else {
- cont_child();
+ cont_children();
}
}
@@ -1945,10 +1958,10 @@ void reconfig_windows(bool redraw_bars) {
/* Unmap the window, and draw it again when in dock mode */
umap_cookie = xcb_unmap_window_checked(xcb_connection, walk->bar.id);
if (config.hide_on_modifier == M_DOCK) {
- cont_child();
+ cont_children();
map_cookie = xcb_map_window_checked(xcb_connection, walk->bar.id);
} else {
- stop_child();
+ stop_children();
}
if (config.hide_on_modifier == M_HIDE) {
diff --git a/include/commands.h b/include/commands.h
index 2ae2643c..17d06681 100644
--- a/include/commands.h
+++ b/include/commands.h
@@ -198,7 +198,7 @@ void cmd_focus_level(I3_CMD, const char *level);
* Implementation of 'focus'.
*
*/
-void cmd_focus(I3_CMD);
+void cmd_focus(I3_CMD, bool focus_workspace);
/**
* Implementation of 'fullscreen [enable|disable|toggle] [global]'.
diff --git a/include/config_directives.h b/include/config_directives.h
index 600226e9..f910d591 100644
--- a/include/config_directives.h
+++ b/include/config_directives.h
@@ -105,6 +105,7 @@ CFGFUN(bar_tray_output, const char *output);
CFGFUN(bar_tray_padding, const long spacing_px);
CFGFUN(bar_color_single, const char *colorclass, const char *color);
CFGFUN(bar_status_command, const char *command);
+CFGFUN(bar_workspace_command, const char *command);
CFGFUN(bar_binding_mode_indicator, const char *value);
CFGFUN(bar_workspace_buttons, const char *value);
CFGFUN(bar_workspace_min_width, const long width);
diff --git a/include/configuration.h b/include/configuration.h
index 99f4b64e..19d2f714 100644
--- a/include/configuration.h
+++ b/include/configuration.h
@@ -335,6 +335,10 @@ struct Barconfig {
* Will be passed to the shell. */
char *status_command;
+ /** Command that should be run to get the workspace buttons. Will be passed
+ * to the shell. */
+ char *workspace_command;
+
/** Font specification for all text rendered on the bar. */
char *font;
diff --git a/include/libi3.h b/include/libi3.h
index 005167c7..549c8e56 100644
--- a/include/libi3.h
+++ b/include/libi3.h
@@ -572,6 +572,7 @@ typedef struct surface_t {
/* A classic XCB graphics context. */
xcb_gcontext_t gc;
+ bool owns_gc;
int width;
int height;
@@ -686,3 +687,9 @@ bool is_background_set(xcb_connection_t *conn, xcb_screen_t *screen);
*
*/
bool boolstr(const char *str);
+
+/**
+ * Get depth of visual specified by visualid
+ *
+ */
+uint16_t get_visual_depth(xcb_visualid_t visual_id);
diff --git a/include/xcb.h b/include/xcb.h
index ba4ff2f3..93998d26 100644
--- a/include/xcb.h
+++ b/include/xcb.h
@@ -99,12 +99,6 @@ xcb_atom_t xcb_get_preferred_window_type(xcb_get_property_reply_t *reply);
bool xcb_reply_contains_atom(xcb_get_property_reply_t *prop, xcb_atom_t atom);
/**
- * Get depth of visual specified by visualid
- *
- */
-uint16_t get_visual_depth(xcb_visualid_t visual_id);
-
-/**
* Get visual type specified by visualid
*
*/
diff --git a/libi3/draw_util.c b/libi3/draw_util.c
index 903e3536..4cc27a36 100644
--- a/libi3/draw_util.c
+++ b/libi3/draw_util.c
@@ -29,6 +29,78 @@ static bool surface_initialized(surface_t *surface) {
}
/*
+ * Get a GC for the given depth. The given drawable must have this depth.
+ *
+ * Per the X11 protocol manual for "CreateGC":
+ * > The gcontext can be used with any destination drawable having the same root
+ * > and depth as the specified drawable;
+ */
+static xcb_gcontext_t get_gc(xcb_connection_t *conn, uint8_t depth, xcb_drawable_t drawable, bool *should_free) {
+ static struct {
+ uint8_t depth;
+ xcb_gcontext_t gc;
+ } gc_cache[2] = {
+ 0,
+ };
+
+ size_t index = 0;
+ bool cache = false;
+
+ *should_free = false;
+ for (; index < sizeof(gc_cache) / sizeof(gc_cache[0]); index++) {
+ if (gc_cache[index].depth == depth) {
+ return gc_cache[index].gc;
+ }
+ if (gc_cache[index].depth == 0) {
+ cache = true;
+ break;
+ }
+ }
+
+ xcb_gcontext_t gc = xcb_generate_id(conn);
+ /* The drawable is only used to get the root and depth, thus the GC is not
+ * tied to the drawable and it can be re-used with different drawables. */
+ xcb_void_cookie_t gc_cookie = xcb_create_gc_checked(conn, gc, drawable, 0, NULL);
+
+ xcb_generic_error_t *error = xcb_request_check(conn, gc_cookie);
+ if (error != NULL) {
+ ELOG("Could not create graphical context. Error code: %d. Please report this bug.\n", error->error_code);
+ free(error);
+ return gc;
+ }
+
+ if (cache) {
+ gc_cache[index].depth = depth;
+ gc_cache[index].gc = gc;
+ } else {
+ *should_free = true;
+ }
+
+ return gc;
+}
+
+/*
+ * Get depth of visual specified by visualid
+ *
+ */
+uint16_t get_visual_depth(xcb_visualid_t visual_id) {
+ xcb_depth_iterator_t depth_iter;
+
+ depth_iter = xcb_screen_allowed_depths_iterator(root_screen);
+ for (; depth_iter.rem; xcb_depth_next(&depth_iter)) {
+ xcb_visualtype_iterator_t visual_iter;
+
+ visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
+ for (; visual_iter.rem; xcb_visualtype_next(&visual_iter)) {
+ if (visual_id == visual_iter.data->visual_id) {
+ return depth_iter.data->depth;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
* Initialize the surface to represent the given drawable.
*
*/
@@ -41,15 +113,7 @@ void draw_util_surface_init(xcb_connection_t *conn, surface_t *surface, xcb_draw
if (visual == NULL)
visual = visual_type;
- surface->gc = xcb_generate_id(conn);
- xcb_void_cookie_t gc_cookie = xcb_create_gc_checked(conn, surface->gc, surface->id, 0, NULL);
-
- xcb_generic_error_t *error = xcb_request_check(conn, gc_cookie);
- if (error != NULL) {
- ELOG("Could not create graphical context. Error code: %d. Please report this bug.\n", error->error_code);
- free(error);
- }
-
+ surface->gc = get_gc(conn, get_visual_depth(visual->visual_id), drawable, &surface->owns_gc);
surface->surface = cairo_xcb_surface_create(conn, surface->id, visual, width, height);
surface->cr = cairo_create(surface->surface);
}
@@ -68,11 +132,9 @@ void draw_util_surface_free(xcb_connection_t *conn, surface_t *surface) {
status, cairo_status_to_string(status));
}
- /* NOTE: This function is also called on uninitialised surface_t instances.
- * The x11 error from xcb_free_gc(conn, XCB_NONE) is silently ignored
- * elsewhere.
- */
- xcb_free_gc(conn, surface->gc);
+ if (surface->owns_gc) {
+ xcb_free_gc(conn, surface->gc);
+ }
cairo_surface_destroy(surface->surface);
cairo_destroy(surface->cr);
diff --git a/man/i3.man b/man/i3.man
index 1974f0b9..b2433108 100644
--- a/man/i3.man
+++ b/man/i3.man
@@ -317,32 +317,25 @@ xsetroot -solid "#333333"
# Enable core dumps in case something goes wrong
ulimit -c unlimited
-# Start i3 and log to ~/.i3/logfile
-echo "Starting at $(date)" >> ~/.i3/logfile
-exec /usr/bin/i3 -V -d all >> ~/.i3/logfile
+# Start i3 and log to ~/.local/share/i3/log
+mkdir -p ~/.local/share/i3
+echo "Starting at $(date)" >> ~/.local/share/i3/log
+exec /usr/bin/i3 -V -d all >> ~/.local/share/i3/log
-------------------------------------------------------------
== ENVIRONMENT
=== I3SOCK
-This variable overwrites the IPC socket path (placed in
-/tmp/i3-%u.XXXXXX/ipc-socket.%p by default, where %u is replaced with your UNIX
-username, %p is replaced with i3’s PID and XXXXXX is a string of random
-characters from the portable filename character set (see mkdtemp(3))). The IPC
-socket is used by external programs like i3-msg(1) or i3bar(1).
-
-== TODO
-
-There is still lot of work to do. Please check our bugtracker for up-to-date
-information about tasks which are still not finished.
+This variable overwrites the IPC socket path (see userguide for default
+location). The IPC socket is used by external programs like i3-msg(1), i3bar(1)
+or user-made scripts.
== SEE ALSO
You should have a copy of the userguide (featuring nice screenshots/graphics
which is why this is not integrated into this manpage), the debugging guide,
-and the "how to hack" guide. If you are building from source, run:
- +make -C docs+
+and the "how to hack" guide.
You can also access these documents online at https://i3wm.org/
diff --git a/man/i3bar.man b/man/i3bar.man
index 479e10fc..761748f3 100644
--- a/man/i3bar.man
+++ b/man/i3bar.man
@@ -46,9 +46,12 @@ Be verbose.
workspace switching buttons and a statusline generated by i3status(1) or
similar. It is automatically invoked (and configured through) i3.
-i3bar supports colors via a JSON protocol starting from v4.2, see
+i3bar supports using a JSON protocol for setting the status line, see
https://i3wm.org/docs/i3bar-protocol.html
+Since i3 4.23, i3bar supports another JSON protocol for setting workspace
+buttons. See https://i3wm.org/docs/i3bar-workspace-protocol.html.
+
== ENVIRONMENT
=== I3SOCK
diff --git a/meson.build b/meson.build
index b272c271..79f9a738 100644
--- a/meson.build
+++ b/meson.build
@@ -6,17 +6,17 @@
project(
'i3',
'c',
- version: '4.22',
+ version: '4.23',
default_options: [
'c_std=c11',
'warning_level=1', # enable all warnings (-Wall)
# TODO(https://github.com/i3/i3/issues/4087): switch to
# 'buildtype=debugoptimized',
],
- # Ubuntu 18.04 (supported until 2023) has meson 0.45.
+ # Ubuntu 20.04 (supported until 2025) has meson 0.53.
# We can revisit our minimum supported meson version
# if it turns out to be too hard to maintain.
- meson_version: '>=0.45.0',
+ meson_version: '>=0.47.0',
)
cc = meson.get_compiler('c')
@@ -86,6 +86,7 @@ if get_option('docs')
'docs/wsbar',
'docs/testsuite',
'docs/i3bar-protocol',
+ 'docs/i3bar-workspace-protocol',
'docs/layout-saving',
]
foreach m : doc_toc_inputs
@@ -125,7 +126,7 @@ if get_option('docs')
endforeach
else
- if run_command('[', '-f', 'docs/hacking-howto.html', ']').returncode() == 0
+ if run_command('[', '-f', 'docs/hacking-howto.html', ']', check: false).returncode() == 0
install_data(
[
'docs/hacking-howto.html',
@@ -135,6 +136,7 @@ else
'docs/wsbar.html',
'docs/testsuite.html',
'docs/i3bar-protocol.html',
+ 'docs/i3bar-workspace-protocol.html',
'docs/layout-saving.html',
'docs/debugging.html',
],
@@ -269,7 +271,7 @@ if get_option('mans')
endforeach
else
- if run_command('[', '-f', 'man/i3.1', ']').returncode() == 0
+ if run_command('[', '-f', 'man/i3.1', ']', check: false).returncode() == 0
install_data(
[
'man/i3.1',
diff --git a/parser-specs/commands.spec b/parser-specs/commands.spec
index 336a8d42..c0dcca7c 100644
--- a/parser-specs/commands.spec
+++ b/parser-specs/commands.spec
@@ -186,6 +186,7 @@ state WORKSPACE_NUMBER:
# focus output <output>
# focus tiling|floating|mode_toggle
# focus parent|child
+# focus workspace
# focus
state FOCUS:
direction = 'left', 'right', 'up', 'down'
@@ -198,8 +199,10 @@ state FOCUS:
-> call cmd_focus_window_mode($window_mode)
level = 'parent', 'child'
-> call cmd_focus_level($level)
+ workspace = 'workspace'
+ -> call cmd_focus(1)
end
- -> call cmd_focus()
+ -> call cmd_focus(0)
state FOCUS_AUTO:
'sibling'
diff --git a/parser-specs/config.spec b/parser-specs/config.spec
index 52bd3212..33708b52 100644
--- a/parser-specs/config.spec
+++ b/parser-specs/config.spec
@@ -528,6 +528,7 @@ state BAR:
'set' -> BAR_IGNORE_LINE
'i3bar_command' -> BAR_BAR_COMMAND
'status_command' -> BAR_STATUS_COMMAND
+ 'workspace_command' -> BAR_WORKSPACE_COMMAND
'socket_path' -> BAR_SOCKET_PATH
'mode' -> BAR_MODE
'hidden_state' -> BAR_HIDDEN_STATE
@@ -567,6 +568,10 @@ state BAR_STATUS_COMMAND:
command = string
-> call cfg_bar_status_command($command); BAR
+state BAR_WORKSPACE_COMMAND:
+ command = string
+ -> call cfg_bar_workspace_command($command); BAR
+
state BAR_SOCKET_PATH:
path = string
-> call cfg_bar_socket_path($path); BAR
diff --git a/release-notes/bugfixes/1-i3bar-nonprimary b/release-notes/bugfixes/1-i3bar-nonprimary
new file mode 100644
index 00000000..b787a5a6
--- /dev/null
+++ b/release-notes/bugfixes/1-i3bar-nonprimary
@@ -0,0 +1 @@
+fix regression with i3bar's output nonprimary
diff --git a/release-notes/bugfixes/1-motif b/release-notes/bugfixes/1-motif
deleted file mode 100644
index 793d8f36..00000000
--- a/release-notes/bugfixes/1-motif
+++ /dev/null
@@ -1 +0,0 @@
-Fix compliance to _MOTIF_WM_HINTS spec when all decorations are set
diff --git a/release-notes/bugfixes/1-top-border-resize b/release-notes/bugfixes/1-top-border-resize
new file mode 100644
index 00000000..bdc21041
--- /dev/null
+++ b/release-notes/bugfixes/1-top-border-resize
@@ -0,0 +1 @@
+fix top border resizing on tiling windows
diff --git a/release-notes/bugfixes/2-gaps-order b/release-notes/bugfixes/2-gaps-order
deleted file mode 100644
index 8c3c78df..00000000
--- a/release-notes/bugfixes/2-gaps-order
+++ /dev/null
@@ -1 +0,0 @@
-gaps: workspace gaps assignments are no longer order-dependent
diff --git a/release-notes/bugfixes/2-title-scroll b/release-notes/bugfixes/2-title-scroll
new file mode 100644
index 00000000..af43ccd7
--- /dev/null
+++ b/release-notes/bugfixes/2-title-scroll
@@ -0,0 +1 @@
+fix workspace not being focused on title bar scroll
diff --git a/release-notes/bugfixes/3-bindsym-button-mode b/release-notes/bugfixes/3-bindsym-button-mode
new file mode 100644
index 00000000..8d929d3b
--- /dev/null
+++ b/release-notes/bugfixes/3-bindsym-button-mode
@@ -0,0 +1 @@
+fix mouse bindings in modes
diff --git a/release-notes/bugfixes/3-floating-from-tiling-from b/release-notes/bugfixes/3-floating-from-tiling-from
deleted file mode 100644
index a29b5102..00000000
--- a/release-notes/bugfixes/3-floating-from-tiling-from
+++ /dev/null
@@ -1 +0,0 @@
-The floating_from and tiling_from criteria now also work in commands
diff --git a/release-notes/bugfixes/4-machine-crash b/release-notes/bugfixes/4-machine-crash
new file mode 100644
index 00000000..24dc04ee
--- /dev/null
+++ b/release-notes/bugfixes/4-machine-crash
@@ -0,0 +1 @@
+fix crashes when using machine criterion
diff --git a/release-notes/bugfixes/5-for-window-urgent b/release-notes/bugfixes/5-for-window-urgent
new file mode 100644
index 00000000..344b3fb2
--- /dev/null
+++ b/release-notes/bugfixes/5-for-window-urgent
@@ -0,0 +1 @@
+fix for_window not working with urgency flags
diff --git a/release-notes/bugfixes/6-motif-append_layout b/release-notes/bugfixes/6-motif-append_layout
new file mode 100644
index 00000000..4437ab5a
--- /dev/null
+++ b/release-notes/bugfixes/6-motif-append_layout
@@ -0,0 +1 @@
+motif hints: respect maximum border style in append_layout
diff --git a/release-notes/changes/1-bar-padding b/release-notes/changes/1-bar-padding
deleted file mode 100644
index 212e9d1a..00000000
--- a/release-notes/changes/1-bar-padding
+++ /dev/null
@@ -1 +0,0 @@
-i3bar: bar { padding } config directive now implemented (supports bar { height } from i3-gaps)
diff --git a/release-notes/changes/1-workspace_command b/release-notes/changes/1-workspace_command
new file mode 100644
index 00000000..7a6bba7b
--- /dev/null
+++ b/release-notes/changes/1-workspace_command
@@ -0,0 +1 @@
+add workspace_command option in i3bar
diff --git a/release-notes/changes/2-focus-workspace b/release-notes/changes/2-focus-workspace
new file mode 100644
index 00000000..638266f2
--- /dev/null
+++ b/release-notes/changes/2-focus-workspace
@@ -0,0 +1 @@
+add "focus workspace" command
diff --git a/release-notes/changes/2-text-alpha-channel b/release-notes/changes/2-text-alpha-channel
deleted file mode 100644
index 2ac7cb46..00000000
--- a/release-notes/changes/2-text-alpha-channel
+++ /dev/null
@@ -1 +0,0 @@
-colors now support an optional alpha value at the end (#rrggbbaa)
diff --git a/release-notes/changes/3-global-fullscreen b/release-notes/changes/3-global-fullscreen
new file mode 100644
index 00000000..e09aaf44
--- /dev/null
+++ b/release-notes/changes/3-global-fullscreen
@@ -0,0 +1 @@
+Allow switching workspaces when in global fullscreen mode
diff --git a/release-notes/changes/3-nonprimary b/release-notes/changes/3-nonprimary
deleted file mode 100644
index f27bba76..00000000
--- a/release-notes/changes/3-nonprimary
+++ /dev/null
@@ -1 +0,0 @@
-Support nonprimary keyword for outputs
diff --git a/release-notes/changes/4-mode-in-binding-event b/release-notes/changes/4-mode-in-binding-event
deleted file mode 100644
index e06014d3..00000000
--- a/release-notes/changes/4-mode-in-binding-event
+++ /dev/null
@@ -1 +0,0 @@
-add "mode" field in binding event
diff --git a/release.sh b/release.sh
index 587b99ee..a1b615f4 100755
--- a/release.sh
+++ b/release.sh
@@ -3,8 +3,8 @@
set -eu
-export RELEASE_VERSION="4.21"
-export PREVIOUS_VERSION="4.20.1"
+export RELEASE_VERSION="4.22"
+export PREVIOUS_VERSION="4.21.1"
export RELEASE_BRANCH="next"
if [ ! -e "../i3.github.io" ]
diff --git a/src/bindings.c b/src/bindings.c
index 4cb916fa..e5804919 100644
--- a/src/bindings.c
+++ b/src/bindings.c
@@ -631,6 +631,7 @@ void switch_mode(const char *new_mode) {
current_binding_mode = mode->name;
translate_keysyms();
grab_all_keys(conn);
+ regrab_all_buttons(conn);
/* Reset all B_UPON_KEYRELEASE_IGNORE_MODS bindings to avoid possibly
* activating one of them. */
@@ -845,7 +846,7 @@ CommandResult *run_binding(Binding *bind, Con *con) {
Binding *bind_cp = binding_copy(bind);
/* The "mode" command might change the current mode, so back it up to
* correctly produce an event later. */
- const char *modename = current_binding_mode;
+ char *modename = sstrdup(current_binding_mode);
CommandResult *result = parse_command(command, NULL, NULL);
free(command);
@@ -873,6 +874,7 @@ CommandResult *run_binding(Binding *bind, Con *con) {
}
ipc_send_binding_event("run", bind_cp, modename);
+ FREE(modename);
binding_free(bind_cp);
return result;
@@ -1007,7 +1009,7 @@ bool load_keymap(void) {
int *bindings_get_buttons_to_grab(void) {
/* Let's make the reasonable assumption that there's no more than 25
* buttons. */
- int num_max = 25;
+ const int num_max = 25;
int buffer[num_max];
int num = 0;
@@ -1033,12 +1035,17 @@ int *bindings_get_buttons_to_grab(void) {
}
/* Avoid duplicates. */
+ bool exists = false;
for (int i = 0; i < num; i++) {
- if (buffer[i] == button)
- continue;
+ if (buffer[i] == button) {
+ exists = true;
+ break;
+ }
}
- buffer[num++] = button;
+ if (!exists) {
+ buffer[num++] = button;
+ }
}
buffer[num++] = 0;
diff --git a/src/click.c b/src/click.c
index a5e50632..27dd7109 100644
--- a/src/click.c
+++ b/src/click.c
@@ -39,6 +39,9 @@ static bool tiling_resize_for_border(Con *con, border_t border, xcb_button_press
case BORDER_BOTTOM:
search_direction = D_DOWN;
break;
+ default:
+ ELOG("BUG: invalid border value %d\n", border);
+ return false;
}
bool res = resize_find_tiling_participants(&first, &second, search_direction, false);
@@ -125,8 +128,11 @@ static bool tiling_resize(Con *con, xcb_button_press_event_t *event, const click
DLOG("checks for right >= %d\n", con->window_rect.x + con->window_rect.width);
if (dest == CLICK_DECORATION) {
return tiling_resize_for_border(con, BORDER_TOP, event, use_threshold);
+ } else if (dest == CLICK_BORDER) {
+ if (event->event_y >= 0 && event->event_y <= (int32_t)bsr.y &&
+ event->event_x >= (int32_t)bsr.x && event->event_x <= (int32_t)(con->rect.width + bsr.width))
+ return tiling_resize_for_border(con, BORDER_TOP, event, false);
}
-
if (event->event_x >= 0 && event->event_x <= (int32_t)bsr.x &&
event->event_y >= (int32_t)bsr.y && event->event_y <= (int32_t)(con->rect.height + bsr.height))
return tiling_resize_for_border(con, BORDER_LEFT, event, false);
@@ -215,6 +221,9 @@ static void route_click(Con *con, xcb_button_press_event_t *event, const bool mo
/* 1: see if the user scrolled on the decoration of a stacked/tabbed con */
if (in_stacked && dest == CLICK_DECORATION && is_scroll) {
DLOG("Scrolling on a window decoration\n");
+ /* Correctly move workspace focus first, see: #5472 */
+ workspace_show(ws);
+
/* Use the focused child of the tabbed / stacked container, not the
* container the user scrolled on. */
Con *current = TAILQ_FIRST(&(con->parent->focus_head));
diff --git a/src/commands.c b/src/commands.c
index 8a87877c..009e98bf 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -844,6 +844,13 @@ out:
free(buf);
}
+static void disable_global_fullscreen(void) {
+ Con *fs = con_get_fullscreen_con(croot, CF_GLOBAL);
+ if (fs) {
+ con_disable_fullscreen(fs);
+ }
+}
+
/*
* Implementation of 'workspace next|prev|next_on_output|prev_on_output'.
*
@@ -853,10 +860,7 @@ void cmd_workspace(I3_CMD, const char *which) {
DLOG("which=%s\n", which);
- if (con_get_fullscreen_con(croot, CF_GLOBAL)) {
- yerror("Cannot switch workspace while in global fullscreen");
- return;
- }
+ disable_global_fullscreen();
if (strcmp(which, "next") == 0)
ws = workspace_next();
@@ -885,10 +889,7 @@ void cmd_workspace(I3_CMD, const char *which) {
void cmd_workspace_number(I3_CMD, const char *which, const char *_no_auto_back_and_forth) {
const bool no_auto_back_and_forth = (_no_auto_back_and_forth != NULL);
- if (con_get_fullscreen_con(croot, CF_GLOBAL)) {
- yerror("Cannot switch workspace while in global fullscreen");
- return;
- }
+ disable_global_fullscreen();
long parsed_num = ws_name_to_number(which);
if (parsed_num == -1) {
@@ -920,10 +921,7 @@ void cmd_workspace_number(I3_CMD, const char *which, const char *_no_auto_back_a
*
*/
void cmd_workspace_back_and_forth(I3_CMD) {
- if (con_get_fullscreen_con(croot, CF_GLOBAL)) {
- yerror("Cannot switch workspace while in global fullscreen");
- return;
- }
+ disable_global_fullscreen();
workspace_back_and_forth();
@@ -944,10 +942,7 @@ void cmd_workspace_name(I3_CMD, const char *name, const char *_no_auto_back_and_
return;
}
- if (con_get_fullscreen_con(croot, CF_GLOBAL)) {
- yerror("Cannot switch workspace while in global fullscreen");
- return;
- }
+ disable_global_fullscreen();
DLOG("should switch to workspace %s\n", name);
if (!no_auto_back_and_forth && maybe_back_and_forth(cmd_output, name)) {
@@ -1325,7 +1320,7 @@ void cmd_focus_direction(I3_CMD, const char *direction_str) {
HANDLE_EMPTY_MATCH;
CMD_FOCUS_WARN_CHILDREN;
- direction_t direction;
+ direction_t direction = D_LEFT;
position_t position;
bool auto_direction = true;
if (strcmp(direction_str, "prev") == 0) {
@@ -1459,7 +1454,7 @@ void cmd_focus_level(I3_CMD, const char *level) {
* Implementation of 'focus'.
*
*/
-void cmd_focus(I3_CMD) {
+void cmd_focus(I3_CMD, bool focus_workspace) {
DLOG("current_match = %p\n", current_match);
if (match_is_empty(current_match)) {
@@ -1481,11 +1476,12 @@ void cmd_focus(I3_CMD) {
Con *ws = con_get_workspace(current->con);
/* If no workspace could be found, this was a dock window.
* Just skip it, you cannot focus dock windows. */
- if (!ws)
+ if (!ws) {
continue;
+ }
/* In case this is a scratchpad window, call scratchpad_show(). */
- if (ws == __i3_scratch) {
+ if (ws == __i3_scratch && !focus_workspace) {
scratchpad_show(current->con);
/* While for the normal focus case we can change focus multiple
* times and only a single window ends up focused, we could show
@@ -1493,8 +1489,15 @@ void cmd_focus(I3_CMD) {
break;
}
- LOG("focusing %p / %s\n", current->con, current->con->name);
- con_activate_unblock(current->con);
+ if (focus_workspace) {
+ /* Show the workspace of the matched container, without necessarily
+ * focusing it. */
+ LOG("focusing workspace %p / %s - %p / %s\n", current->con, current->con->name, ws, ws->name);
+ workspace_show(ws);
+ } else {
+ LOG("focusing %p / %s\n", current->con, current->con->name);
+ con_activate_unblock(current->con);
+ }
}
cmd_output->needs_tree_render = true;
@@ -1575,7 +1578,6 @@ void cmd_move_direction(I3_CMD, const char *direction_str, long amount, const ch
owindow *current;
HANDLE_EMPTY_MATCH;
- Con *initially_focused = focused;
direction_t direction = parse_direction(direction_str);
const bool is_ppt = mode && strcmp(mode, "ppt") == 0;
@@ -1609,12 +1611,6 @@ void cmd_move_direction(I3_CMD, const char *direction_str, long amount, const ch
}
}
- /* The move command should not disturb focus. con_exists is called because
- * tree_move calls tree_flatten. */
- if (focused != initially_focused && con_exists(initially_focused)) {
- con_activate(initially_focused);
- }
-
// XXX: default reply for now, make this a better reply
ysuccess(true);
}
diff --git a/src/config.c b/src/config.c
index f06a3f8d..bf3ec6dc 100644
--- a/src/config.c
+++ b/src/config.c
@@ -105,6 +105,7 @@ static void free_configuration(void) {
FREE(barconfig->outputs);
FREE(barconfig->socket_path);
FREE(barconfig->status_command);
+ FREE(barconfig->workspace_command);
FREE(barconfig->i3bar_command);
FREE(barconfig->font);
FREE(barconfig->colors.background);
diff --git a/src/config_directives.c b/src/config_directives.c
index 9077fe98..81adf351 100644
--- a/src/config_directives.c
+++ b/src/config_directives.c
@@ -873,6 +873,11 @@ CFGFUN(bar_status_command, const char *command) {
current_bar->status_command = sstrdup(command);
}
+CFGFUN(bar_workspace_command, const char *command) {
+ FREE(current_bar->workspace_command);
+ current_bar->workspace_command = sstrdup(command);
+}
+
CFGFUN(bar_binding_mode_indicator, const char *value) {
current_bar->hide_binding_mode_indicator = !boolstr(value);
}
diff --git a/src/config_parser.c b/src/config_parser.c
index baf5848a..d3eace8b 100644
--- a/src/config_parser.c
+++ b/src/config_parser.c
@@ -919,7 +919,7 @@ parse_file_result_t parse_file(struct parser_ctx *ctx, const char *f, IncludedFi
continuation = NULL;
}
- strncpy(buf + strlen(buf), buffer, strlen(buffer) + 1);
+ strcpy(buf + strlen(buf), buffer);
/* Skip comments and empty lines. */
if (skip_line || comment) {
@@ -1043,7 +1043,7 @@ parse_file_result_t parse_file(struct parser_ctx *ctx, const char *f, IncludedFi
} else {
/* Copy until the next variable, then copy its value */
strncpy(destwalk, walk, distance);
- strncpy(destwalk + distance, nearest->value, strlen(nearest->value));
+ strcpy(destwalk + distance, nearest->value);
walk += distance + strlen(nearest->key);
destwalk += distance + strlen(nearest->value);
}
diff --git a/src/handlers.c b/src/handlers.c
index 17968a43..6ba11708 100644
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -422,6 +422,7 @@ static void handle_configure_request(xcb_configure_request_event_t *event) {
} else if (config.focus_on_window_activation == FOWA_URGENT || (config.focus_on_window_activation == FOWA_SMART && !workspace_is_visible(workspace))) {
DLOG("Marking con = %p urgent\n", con);
con_set_urgency(con, true);
+ con = remanage_window(con);
tree_render();
} else {
DLOG("Ignoring request for con = %p.\n", con);
@@ -691,12 +692,16 @@ static void handle_client_message(xcb_client_message_event_t *event) {
}
} else if (event->data.data32[1] == A__NET_WM_STATE_DEMANDS_ATTENTION) {
/* Check if the urgent flag must be set or not */
- if (event->data.data32[0] == _NET_WM_STATE_ADD)
+ if (event->data.data32[0] == _NET_WM_STATE_ADD) {
con_set_urgency(con, true);
- else if (event->data.data32[0] == _NET_WM_STATE_REMOVE)
+ con = remanage_window(con);
+ } else if (event->data.data32[0] == _NET_WM_STATE_REMOVE) {
con_set_urgency(con, false);
- else if (event->data.data32[0] == _NET_WM_STATE_TOGGLE)
+ con = remanage_window(con);
+ } else if (event->data.data32[0] == _NET_WM_STATE_TOGGLE) {
con_set_urgency(con, !con->urgent);
+ con = remanage_window(con);
+ }
} else if (event->data.data32[1] == A__NET_WM_STATE_STICKY) {
DLOG("Received a client message to modify _NET_WM_STATE_STICKY.\n");
if (event->data.data32[0] == _NET_WM_STATE_ADD)
@@ -763,6 +768,7 @@ static void handle_client_message(xcb_client_message_event_t *event) {
} else if (config.focus_on_window_activation == FOWA_URGENT || (config.focus_on_window_activation == FOWA_SMART && !workspace_is_visible(ws))) {
DLOG("Marking con = %p urgent\n", con);
con_set_urgency(con, true);
+ con = remanage_window(con);
} else
DLOG("Ignoring request for con = %p.\n", con);
}
@@ -982,6 +988,7 @@ static bool handle_hints(Con *con, xcb_get_property_reply_t *reply) {
bool urgency_hint;
window_update_hints(con->window, reply, &urgency_hint);
con_set_urgency(con, urgency_hint);
+ remanage_window(con);
tree_render();
return true;
}
diff --git a/src/ipc.c b/src/ipc.c
index f69ba2ae..d20090c6 100644
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -739,7 +739,7 @@ static void dump_bar_bindings(yajl_gen gen, Barconfig *config) {
static char *canonicalize_output_name(char *name) {
/* Do not canonicalize special output names. */
- if (strcasecmp(name, "primary") == 0) {
+ if (strcasecmp(name, "primary") == 0 || strcasecmp(name, "nonprimary") == 0) {
return name;
}
Output *output = get_output_by_name(name, false);
@@ -827,6 +827,7 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
ystr("top");
YSTR_IF_SET(status_command);
+ YSTR_IF_SET(workspace_command);
YSTR_IF_SET(font);
if (config->bar_height) {
diff --git a/src/load_layout.c b/src/load_layout.c
index 053649d0..603b029d 100644
--- a/src/load_layout.c
+++ b/src/load_layout.c
@@ -40,7 +40,7 @@ static int num_marks;
struct pending_marks {
char *mark;
Con *con_to_be_marked;
-} * marks;
+} *marks;
/* This list is used for reordering the focus stack after parsing the 'focus'
* array. */
@@ -351,17 +351,18 @@ static int json_string(void *ctx, const unsigned char *val, size_t len) {
} else if (strcasecmp(last_key, "border") == 0) {
char *buf = NULL;
sasprintf(&buf, "%.*s", (int)len, val);
- if (strcasecmp(buf, "none") == 0)
- json_node->border_style = BS_NONE;
- else if (strcasecmp(buf, "1pixel") == 0) {
- json_node->border_style = BS_PIXEL;
+ if (strcasecmp(buf, "none") == 0) {
+ json_node->max_user_border_style = json_node->border_style = BS_NONE;
+ } else if (strcasecmp(buf, "1pixel") == 0) {
+ json_node->max_user_border_style = json_node->border_style = BS_PIXEL;
json_node->current_border_width = 1;
- } else if (strcasecmp(buf, "pixel") == 0)
- json_node->border_style = BS_PIXEL;
- else if (strcasecmp(buf, "normal") == 0)
- json_node->border_style = BS_NORMAL;
- else
+ } else if (strcasecmp(buf, "pixel") == 0) {
+ json_node->max_user_border_style = json_node->border_style = BS_PIXEL;
+ } else if (strcasecmp(buf, "normal") == 0) {
+ json_node->max_user_border_style = json_node->border_style = BS_NORMAL;
+ } else {
LOG("Unhandled \"border\": %s\n", buf);
+ }
free(buf);
} else if (strcasecmp(last_key, "type") == 0) {
char *buf = NULL;
diff --git a/src/main.c b/src/main.c
index 6d6b9c9c..6fae7e41 100644
--- a/src/main.c
+++ b/src/main.c
@@ -579,7 +579,11 @@ int main(int argc, char *argv[]) {
/* Initialize the libev event loop. This needs to be done before loading
* the config file because the parser will install an ev_child watcher
- * for the nagbar when config errors are found. */
+ * for the nagbar when config errors are found.
+ *
+ * Main loop must be ev's default loop because (at the moment of writing)
+ * only the default loop can handle ev_child events and reap zombies
+ * (the start_application routine relies on that too). */
main_loop = EV_DEFAULT;
if (main_loop == NULL)
die("Could not initialize libev. Bad LIBEV_FLAGS?\n");
@@ -1002,10 +1006,11 @@ int main(int argc, char *argv[]) {
char *log_stream_socket_path = get_process_filename("log-stream-socket");
int log_socket = create_socket(log_stream_socket_path, &current_log_stream_socket_path);
free(log_stream_socket_path);
+ struct ev_io *log_io = NULL;
if (log_socket == -1) {
ELOG("Could not create the log socket, i3-dump-log -f will not work\n");
} else {
- struct ev_io *log_io = scalloc(1, sizeof(struct ev_io));
+ log_io = scalloc(1, sizeof(struct ev_io));
ev_io_init(log_io, log_new_client, log_socket, EV_READ);
ev_io_start(main_loop, log_io);
}
@@ -1013,12 +1018,13 @@ int main(int argc, char *argv[]) {
/* Also handle the UNIX domain sockets passed via socket
* activation. The parameter 0 means "do not remove the
* environment variables", we need to be able to reexec. */
+ struct ev_io *socket_ipc_io = NULL;
listen_fds = sd_listen_fds(0);
- if (listen_fds < 0)
+ if (listen_fds < 0) {
ELOG("socket activation: Error in sd_listen_fds\n");
- else if (listen_fds == 0)
+ } else if (listen_fds == 0) {
DLOG("socket activation: no sockets passed\n");
- else {
+ } else {
int flags;
for (int fd = SD_LISTEN_FDS_START;
fd < (SD_LISTEN_FDS_START + listen_fds);
@@ -1033,9 +1039,9 @@ int main(int argc, char *argv[]) {
ELOG("Could not disable FD_CLOEXEC on fd %d\n", fd);
}
- struct ev_io *ipc_io = scalloc(1, sizeof(struct ev_io));
- ev_io_init(ipc_io, ipc_new_client, fd, EV_READ);
- ev_io_start(main_loop, ipc_io);
+ socket_ipc_io = scalloc(1, sizeof(struct ev_io));
+ ev_io_init(socket_ipc_io, ipc_new_client, fd, EV_READ);
+ ev_io_start(main_loop, socket_ipc_io);
}
}
@@ -1198,4 +1204,10 @@ int main(int argc, char *argv[]) {
sd_notify(1, "READY=1");
ev_loop(main_loop, 0);
+
+ /* Free these heap allocations just to satisfy LeakSanitizer. */
+ FREE(ipc_io);
+ FREE(socket_ipc_io);
+ FREE(log_io);
+ FREE(xcb_watcher);
}
diff --git a/src/manage.c b/src/manage.c
index a7de243e..aeef703f 100644
--- a/src/manage.c
+++ b/src/manage.c
@@ -678,27 +678,34 @@ out:
free(attr);
}
-/*
- * Remanages a window: performs a swallow check and runs assignments.
- * Returns con for the window regardless if it updated.
- *
- */
-Con *remanage_window(Con *con) {
+static Con *placeholder_for_con(Con *con) {
/* Make sure this windows hasn't already been swallowed. */
if (con->window->swallowed) {
- run_assignments(con->window);
- return con;
+ return NULL;
}
Match *match;
Con *nc = con_for_window(croot, con->window, &match);
if (nc == NULL || nc->window == NULL || nc->window == con->window) {
- run_assignments(con->window);
- return con;
+ return NULL;
}
/* Make sure the placeholder that wants to swallow this window didn't spawn
* after the window to follow current behavior: adding a placeholder won't
* swallow windows currently managed. */
if (nc->window->managed_since > con->window->managed_since) {
+ return NULL;
+ }
+ return nc;
+}
+
+/*
+ * Remanages a window: performs a swallow check and runs assignments.
+ * Returns con for the window regardless if it updated.
+ *
+ */
+Con *remanage_window(Con *con) {
+ Con *nc = placeholder_for_con(con);
+ if (!nc) {
+ /* The con is not updated, just run assignments */
run_assignments(con->window);
return con;
}
diff --git a/src/match.c b/src/match.c
index 34314e25..cfd7d324 100644
--- a/src/match.c
+++ b/src/match.c
@@ -80,6 +80,7 @@ void match_copy(Match *dest, Match *src) {
DUPLICATE_REGEX(instance);
DUPLICATE_REGEX(window_role);
DUPLICATE_REGEX(workspace);
+ DUPLICATE_REGEX(machine);
}
/*
diff --git a/src/move.c b/src/move.c
index 1a161647..d368a4d3 100644
--- a/src/move.c
+++ b/src/move.c
@@ -241,6 +241,7 @@ static void move_to_output_directed(Con *con, direction_t direction) {
con_focus(con);
focused = old_ws;
workspace_show(ws);
+ con_focus(con);
}
/* force re-painting the indicators */
diff --git a/src/sd-daemon.c b/src/sd-daemon.c
index 84761025..9d698e5f 100644
--- a/src/sd-daemon.c
+++ b/src/sd-daemon.c
@@ -340,6 +340,11 @@ int sd_notify(int unset_environment, const char *state) {
goto finish;
}
+ if (strlen(e) > sizeof(sockaddr.un.sun_path)) {
+ r = -EINVAL;
+ goto finish;
+ }
+
if ((fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0) {
r = -errno;
goto finish;
@@ -347,7 +352,7 @@ int sd_notify(int unset_environment, const char *state) {
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sa.sa_family = AF_UNIX;
- strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
+ strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path) - 1);
if (sockaddr.un.sun_path[0] == '@')
sockaddr.un.sun_path[0] = 0;
diff --git a/src/startup.c b/src/startup.c
index 9b0576e8..a34bd663 100644
--- a/src/startup.c
+++ b/src/startup.c
@@ -118,10 +118,9 @@ void startup_sequence_delete(struct Startup_Sequence *sequence) {
}
/*
- * Starts the given application by passing it through a shell. We use double
- * fork to avoid zombie processes. As the started application’s parent exits
- * (immediately), the application is reparented to init (process-id 1), which
- * correctly handles children, so we don’t have to do it :-).
+ * Starts the given application by passing it through a shell. Zombie processes
+ * will be collected by ev in the default loop, we don't have to manually
+ * deal with it.
*
* The shell used to start applications is the system's bourne shell (i.e.,
* /bin/sh).
@@ -173,7 +172,8 @@ void start_application(const char *command, bool no_startup_id) {
LOG("executing: %s\n", command);
if (fork() == 0) {
- /* Child process */
+ /* Child process.
+ * It will be reaped by ev, even though there is no corresponding ev_child */
setsid();
setrlimit(RLIMIT_CORE, &original_rlimit_core);
/* Close all socket activation file descriptors explicitly, we disabled
@@ -186,18 +186,14 @@ void start_application(const char *command, bool no_startup_id) {
unsetenv("LISTEN_PID");
unsetenv("LISTEN_FDS");
signal(SIGPIPE, SIG_DFL);
- if (fork() == 0) {
- /* Setup the environment variable(s) */
- if (!no_startup_id)
- sn_launcher_context_setup_child_process(context);
- setenv("I3SOCK", current_socketpath, 1);
-
- execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, NULL);
- /* not reached */
- }
- _exit(EXIT_SUCCESS);
+ /* Setup the environment variable(s) */
+ if (!no_startup_id)
+ sn_launcher_context_setup_child_process(context);
+ setenv("I3SOCK", current_socketpath, 1);
+
+ execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, NULL);
+ /* not reached */
}
- wait(0);
if (!no_startup_id) {
/* Change the pointer of the root window to indicate progress */
diff --git a/src/window.c b/src/window.c
index eeff0741..7abe995a 100644
--- a/src/window.c
+++ b/src/window.c
@@ -516,7 +516,7 @@ void window_update_machine(i3Window *win, xcb_get_property_reply_t *prop) {
void window_update_icon(i3Window *win, xcb_get_property_reply_t *prop) {
uint32_t *data = NULL;
- uint32_t width, height;
+ uint32_t width = 0, height = 0;
uint64_t len = 0;
const uint32_t pref_size = (uint32_t)(render_deco_height() - logical_px(2));
diff --git a/src/x.c b/src/x.c
index 9720e833..48105b03 100644
--- a/src/x.c
+++ b/src/x.c
@@ -731,6 +731,9 @@ void x_draw_decoration(Con *con) {
/* Make sure the icon does not escape title boundaries */
icon_offset_x = min(deco_width - icon_size - icon_padding - title_padding, title_offset_x + predict_text_width(title) + icon_padding);
break;
+ default:
+ ELOG("BUG: invalid config.title_align value %d\n", config.title_align);
+ return;
}
draw_util_text(title, dest_surface,
diff --git a/src/xcb.c b/src/xcb.c
index 5258dcc2..866fc009 100644
--- a/src/xcb.c
+++ b/src/xcb.c
@@ -164,27 +164,6 @@ bool xcb_reply_contains_atom(xcb_get_property_reply_t *prop, xcb_atom_t atom) {
}
/*
- * Get depth of visual specified by visualid
- *
- */
-uint16_t get_visual_depth(xcb_visualid_t visual_id) {
- xcb_depth_iterator_t depth_iter;
-
- depth_iter = xcb_screen_allowed_depths_iterator(root_screen);
- for (; depth_iter.rem; xcb_depth_next(&depth_iter)) {
- xcb_visualtype_iterator_t visual_iter;
-
- visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
- for (; visual_iter.rem; xcb_visualtype_next(&visual_iter)) {
- if (visual_id == visual_iter.data->visual_id) {
- return depth_iter.data->depth;
- }
- }
- }
- return 0;
-}
-
-/*
* Get visual type specified by visualid
*
*/
diff --git a/testcases/complete-run.pl.in b/testcases/complete-run.pl.in
index 00f8e609..0a1e11c6 100755
--- a/testcases/complete-run.pl.in
+++ b/testcases/complete-run.pl.in
@@ -203,7 +203,7 @@ for my $display (@displays) {
# Read previous timing information, if available. We will be able to roughly
# predict the test duration and schedule a good order for the tests.
my $timingsjson = slurp('.last_run_timings.json') if -e '.last_run_timings.json';
-%timings = %{decode_json($timingsjson)} if length($timingsjson) > 0;
+%timings = %{decode_json($timingsjson)} if length($timingsjson // '') > 0;
# Re-order the files so that those which took the longest time in the previous
# run will be started at the beginning to not delay the whole run longer than
diff --git a/testcases/new-test b/testcases/new-test
index e0b2e13f..57e50341 100755
--- a/testcases/new-test
+++ b/testcases/new-test
@@ -53,7 +53,7 @@ my $header = <<'EOF';
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# TODO: Description of this file.
diff --git a/testcases/t/001-tile.t b/testcases/t/001-tile.t
index 356b7b3a..c6bf7b24 100644
--- a/testcases/t/001-tile.t
+++ b/testcases/t/001-tile.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test;
diff --git a/testcases/t/002-i3-sync.t b/testcases/t/002-i3-sync.t
index 9466f860..4b108405 100644
--- a/testcases/t/002-i3-sync.t
+++ b/testcases/t/002-i3-sync.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# checks if i3 supports I3_SYNC
diff --git a/testcases/t/003-ipc.t b/testcases/t/003-ipc.t
index 89c60f1c..94c2c56e 100644
--- a/testcases/t/003-ipc.t
+++ b/testcases/t/003-ipc.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test;
diff --git a/testcases/t/004-unmanaged.t b/testcases/t/004-unmanaged.t
index 1f3c6ccd..88cdc522 100644
--- a/testcases/t/004-unmanaged.t
+++ b/testcases/t/004-unmanaged.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test;
diff --git a/testcases/t/005-floating.t b/testcases/t/005-floating.t
index d85826b3..61c26cba 100644
--- a/testcases/t/005-floating.t
+++ b/testcases/t/005-floating.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test;
diff --git a/testcases/t/100-fullscreen.t b/testcases/t/100-fullscreen.t
index d817bee0..26ec9fe6 100644
--- a/testcases/t/100-fullscreen.t
+++ b/testcases/t/100-fullscreen.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test;
@@ -185,7 +185,9 @@ cmd 'focus left';
is($x->input_focus, $window->id, 'fullscreen window still focused');
################################################################################
-# Verify that changing workspace while in global fullscreen does not work.
+# Verify that changing workspace while in global fullscreen disables fullscreen
+# first.
+# See #2974
################################################################################
$tmp = fresh_workspace;
@@ -197,11 +199,11 @@ is(focused_ws(), $tmp, 'workspace selected');
$other = get_unused_workspace;
cmd "workspace $other";
-is($x->input_focus, $window->id, 'window still focused');
-is(focused_ws(), $tmp, 'workspace still selected');
+isnt($x->input_focus, $window->id, 'window not focused anymore');
+is(focused_ws(), $other, 'workspace switched');
+is_num_fullscreen($other, 0, 'no fullscreen windows');
+is_num_fullscreen($tmp, 0, 'no fullscreen windows');
-# leave global fullscreen so that is does not interfere with the other tests
-$window->fullscreen(0);
sync_with_i3;
################################################################################
diff --git a/testcases/t/101-focus.t b/testcases/t/101-focus.t
index 1e87a544..0784979b 100644
--- a/testcases/t/101-focus.t
+++ b/testcases/t/101-focus.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test;
diff --git a/testcases/t/102-dock.t b/testcases/t/102-dock.t
index 60352d6d..1b513cb4 100644
--- a/testcases/t/102-dock.t
+++ b/testcases/t/102-dock.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test;
diff --git a/testcases/t/104-focus-stack.t b/testcases/t/104-focus-stack.t
index d2193368..7624a13e 100644
--- a/testcases/t/104-focus-stack.t
+++ b/testcases/t/104-focus-stack.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Checks if the focus is correctly restored, when creating a floating client
diff --git a/testcases/t/111-goto.t b/testcases/t/111-goto.t
index ade653d1..8617be47 100644
--- a/testcases/t/111-goto.t
+++ b/testcases/t/111-goto.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test;
diff --git a/testcases/t/112-floating-resize.t b/testcases/t/112-floating-resize.t
index 947ca3b6..d393cac1 100644
--- a/testcases/t/112-floating-resize.t
+++ b/testcases/t/112-floating-resize.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test;
diff --git a/testcases/t/113-urgent.t b/testcases/t/113-urgent.t
index 0de90193..f99b1942 100644
--- a/testcases/t/113-urgent.t
+++ b/testcases/t/113-urgent.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test i3_autostart => 0;
@@ -50,6 +50,8 @@ my $config = <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [urgent=latest class=special] focus
+
force_display_urgency_hint 0ms
EOT
@@ -361,6 +363,19 @@ for ($type = 1; $type <= 2; $type++) {
ok(!$win1_info->{urgent}, 'win1 window is not marked urgent after focusing');
##############################################################################
+#
+##############################################################################
+ $tmp = fresh_workspace;
+ $win1 = open_window(wm_class => 'special');
+ $win2 = open_window;
+ is($x->input_focus, $win2->id, 'second window has focus');
+
+ cmd 'nop hello';
+ set_urgency($win1, 1, $type);
+ sync_with_i3;
+ is($x->input_focus, $win1->id, 'first window got focus');
+
+##############################################################################
exit_gracefully($pid);
}
diff --git a/testcases/t/114-client-leader.t b/testcases/t/114-client-leader.t
index 3ecc644d..7826f028 100644
--- a/testcases/t/114-client-leader.t
+++ b/testcases/t/114-client-leader.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test;
diff --git a/testcases/t/115-ipc-workspaces.t b/testcases/t/115-ipc-workspaces.t
index b0c4354e..d47e525c 100644
--- a/testcases/t/115-ipc-workspaces.t
+++ b/testcases/t/115-ipc-workspaces.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test;
diff --git a/testcases/t/116-nestedcons.t b/testcases/t/116-nestedcons.t
index 7b15c5f0..a945b034 100644
--- a/testcases/t/116-nestedcons.t
+++ b/testcases/t/116-nestedcons.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test;
diff --git a/testcases/t/117-workspace.t b/testcases/t/117-workspace.t
index 6345ae68..f9283a6f 100644
--- a/testcases/t/117-workspace.t
+++ b/testcases/t/117-workspace.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests whether we can switch to a non-existent workspace
diff --git a/testcases/t/118-openkill.t b/testcases/t/118-openkill.t
index 08b5cda9..ad82c18b 100644
--- a/testcases/t/118-openkill.t
+++ b/testcases/t/118-openkill.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests whether opening an empty container and killing it again works
diff --git a/testcases/t/119-match.t b/testcases/t/119-match.t
index 65c41f1f..33a8d580 100644
--- a/testcases/t/119-match.t
+++ b/testcases/t/119-match.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests all kinds of matching methods
diff --git a/testcases/t/120-multiple-cmds.t b/testcases/t/120-multiple-cmds.t
index 114d7129..7d3a5fb6 100644
--- a/testcases/t/120-multiple-cmds.t
+++ b/testcases/t/120-multiple-cmds.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests multiple commands (using ';') and multiple operations (using ',')
diff --git a/testcases/t/121-next-prev.t b/testcases/t/121-next-prev.t
index 72c52c9a..758ab10a 100644
--- a/testcases/t/121-next-prev.t
+++ b/testcases/t/121-next-prev.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests focus switching (next/prev)
diff --git a/testcases/t/122-split.t b/testcases/t/122-split.t
index fe93880c..66f26ce6 100644
--- a/testcases/t/122-split.t
+++ b/testcases/t/122-split.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests splitting
diff --git a/testcases/t/124-move.t b/testcases/t/124-move.t
index b4a8ca3e..27d56ef4 100644
--- a/testcases/t/124-move.t
+++ b/testcases/t/124-move.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests moving. Basically, there are four different code-paths:
diff --git a/testcases/t/126-regress-close.t b/testcases/t/126-regress-close.t
index bdb31df2..3e02602c 100644
--- a/testcases/t/126-regress-close.t
+++ b/testcases/t/126-regress-close.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression: closing of floating clients did crash i3 when closing the
diff --git a/testcases/t/127-regress-floating-parent.t b/testcases/t/127-regress-floating-parent.t
index ebacd3e5..3571fb85 100644
--- a/testcases/t/127-regress-floating-parent.t
+++ b/testcases/t/127-regress-floating-parent.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression: make a container floating, kill its parent, make it tiling again
diff --git a/testcases/t/128-open-order.t b/testcases/t/128-open-order.t
index b0ab321f..1e52d77b 100644
--- a/testcases/t/128-open-order.t
+++ b/testcases/t/128-open-order.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Check if new containers are opened after the currently focused one instead
diff --git a/testcases/t/129-focus-after-close.t b/testcases/t/129-focus-after-close.t
index 8bfa0140..fe498b9c 100644
--- a/testcases/t/129-focus-after-close.t
+++ b/testcases/t/129-focus-after-close.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Check if the focus is correctly restored after closing windows.
diff --git a/testcases/t/130-close-empty-split.t b/testcases/t/130-close-empty-split.t
index 2e3cb794..62b49ed5 100644
--- a/testcases/t/130-close-empty-split.t
+++ b/testcases/t/130-close-empty-split.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Check if empty split containers are automatically closed.
diff --git a/testcases/t/131-stacking-order.t b/testcases/t/131-stacking-order.t
index 3d89e0f3..7e0c7768 100644
--- a/testcases/t/131-stacking-order.t
+++ b/testcases/t/131-stacking-order.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Check if stacking containers can be used independently of
diff --git a/testcases/t/132-move-workspace.t b/testcases/t/132-move-workspace.t
index c7721c3d..bcfdaa7e 100644
--- a/testcases/t/132-move-workspace.t
+++ b/testcases/t/132-move-workspace.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Checks if the 'move [window/container] to workspace' command works correctly
diff --git a/testcases/t/133-size-hints.t b/testcases/t/133-size-hints.t
index a16c5399..c7e8e889 100644
--- a/testcases/t/133-size-hints.t
+++ b/testcases/t/133-size-hints.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Checks if size hints are interpreted correctly.
diff --git a/testcases/t/134-invalid-command.t b/testcases/t/134-invalid-command.t
index c10771c8..ed4cad00 100644
--- a/testcases/t/134-invalid-command.t
+++ b/testcases/t/134-invalid-command.t
@@ -12,7 +12,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
#
diff --git a/testcases/t/135-floating-focus.t b/testcases/t/135-floating-focus.t
index 168151f4..3666add9 100644
--- a/testcases/t/135-floating-focus.t
+++ b/testcases/t/135-floating-focus.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test;
diff --git a/testcases/t/136-floating-ws-empty.t b/testcases/t/136-floating-ws-empty.t
index 6b2a028e..7bc739e5 100644
--- a/testcases/t/136-floating-ws-empty.t
+++ b/testcases/t/136-floating-ws-empty.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test: when only having a floating window on a workspace, it should
diff --git a/testcases/t/137-floating-unmap.t b/testcases/t/137-floating-unmap.t
index 97aa02e0..261b4a09 100644
--- a/testcases/t/137-floating-unmap.t
+++ b/testcases/t/137-floating-unmap.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test: Floating windows were not correctly unmapped when switching
diff --git a/testcases/t/138-floating-attach.t b/testcases/t/138-floating-attach.t
index fecb3cb3..f24026fa 100644
--- a/testcases/t/138-floating-attach.t
+++ b/testcases/t/138-floating-attach.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test: New windows were attached to the container of a floating window
diff --git a/testcases/t/139-ws-numbers.t b/testcases/t/139-ws-numbers.t
index 5d808c0b..4817b396 100644
--- a/testcases/t/139-ws-numbers.t
+++ b/testcases/t/139-ws-numbers.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Check if numbered workspaces and named workspaces are sorted in the right way
diff --git a/testcases/t/140-focus-lost.t b/testcases/t/140-focus-lost.t
index c13cfdc4..dca67d54 100644
--- a/testcases/t/140-focus-lost.t
+++ b/testcases/t/140-focus-lost.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression: Check if the focus stays the same when switching the layout
diff --git a/testcases/t/141-resize.t b/testcases/t/141-resize.t
index 5a264169..78e25956 100644
--- a/testcases/t/141-resize.t
+++ b/testcases/t/141-resize.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests resizing tiling containers
diff --git a/testcases/t/142-regress-move-floating.t b/testcases/t/142-regress-move-floating.t
index f1ff051e..2aa8c6c0 100644
--- a/testcases/t/142-regress-move-floating.t
+++ b/testcases/t/142-regress-move-floating.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression: move a floating window to a different workspace crashes i3
diff --git a/testcases/t/143-regress-floating-restart.t b/testcases/t/143-regress-floating-restart.t
index 816793c6..8f6ab6f0 100644
--- a/testcases/t/143-regress-floating-restart.t
+++ b/testcases/t/143-regress-floating-restart.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression: floating windows are tiling after restarting, closing them crashes i3
diff --git a/testcases/t/144-regress-floating-resize.t b/testcases/t/144-regress-floating-resize.t
index d21e8289..50683165 100644
--- a/testcases/t/144-regress-floating-resize.t
+++ b/testcases/t/144-regress-floating-resize.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression: when resizing two containers on a workspace, opening a floating
diff --git a/testcases/t/145-flattening.t b/testcases/t/145-flattening.t
index 3f84cdc1..b5f6b62d 100644
--- a/testcases/t/145-flattening.t
+++ b/testcases/t/145-flattening.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# by moving the window in the opposite orientation that its parent has, we
diff --git a/testcases/t/146-floating-reinsert.t b/testcases/t/146-floating-reinsert.t
index 0742a037..49f39551 100644
--- a/testcases/t/146-floating-reinsert.t
+++ b/testcases/t/146-floating-reinsert.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
use i3test;
diff --git a/testcases/t/147-regress-floatingmove.t b/testcases/t/147-regress-floatingmove.t
index a03b87d7..60205ea4 100644
--- a/testcases/t/147-regress-floatingmove.t
+++ b/testcases/t/147-regress-floatingmove.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test for moving a con outside of a floating con when there are no
diff --git a/testcases/t/148-regress-floatingmovews.t b/testcases/t/148-regress-floatingmovews.t
index 2bee4249..329d2559 100644
--- a/testcases/t/148-regress-floatingmovews.t
+++ b/testcases/t/148-regress-floatingmovews.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test for correct focus behaviour when moving a floating con to
diff --git a/testcases/t/150-regress-dock-restart.t b/testcases/t/150-regress-dock-restart.t
index 0fb15a56..d849d195 100644
--- a/testcases/t/150-regress-dock-restart.t
+++ b/testcases/t/150-regress-dock-restart.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test for inplace restarting with dock clients
diff --git a/testcases/t/151-regress-float-size.t b/testcases/t/151-regress-float-size.t
index c6069d81..1aae00cd 100644
--- a/testcases/t/151-regress-float-size.t
+++ b/testcases/t/151-regress-float-size.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test for setting a window to floating, tiling and opening a new window
diff --git a/testcases/t/152-regress-level-up.t b/testcases/t/152-regress-level-up.t
index ba6820a3..b06ab46d 100644
--- a/testcases/t/152-regress-level-up.t
+++ b/testcases/t/152-regress-level-up.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test for using level-up to get to the 'content'-container and
diff --git a/testcases/t/153-floating-originalsize.t b/testcases/t/153-floating-originalsize.t
index 87e7e531..dafa853f 100644
--- a/testcases/t/153-floating-originalsize.t
+++ b/testcases/t/153-floating-originalsize.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test if the requested width/height is set after making the window floating.
diff --git a/testcases/t/154-regress-multiple-dock.t b/testcases/t/154-regress-multiple-dock.t
index 5ae84f06..bf841ef1 100644
--- a/testcases/t/154-regress-multiple-dock.t
+++ b/testcases/t/154-regress-multiple-dock.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test for closing one of multiple dock clients
diff --git a/testcases/t/155-floating-split-size.t b/testcases/t/155-floating-split-size.t
index 4f9b12f3..5221f585 100644
--- a/testcases/t/155-floating-split-size.t
+++ b/testcases/t/155-floating-split-size.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test to see if i3 combines the geometry of all children in a split container
diff --git a/testcases/t/156-fullscreen-focus.t b/testcases/t/156-fullscreen-focus.t
index 62711915..3af158aa 100644
--- a/testcases/t/156-fullscreen-focus.t
+++ b/testcases/t/156-fullscreen-focus.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test if new containers get focused when there is a fullscreen container at
diff --git a/testcases/t/158-wm_take_focus.t b/testcases/t/158-wm_take_focus.t
index c4b42964..e9a32cd0 100644
--- a/testcases/t/158-wm_take_focus.t
+++ b/testcases/t/158-wm_take_focus.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests if the WM_TAKE_FOCUS protocol is correctly handled by i3
diff --git a/testcases/t/159-socketpaths.t b/testcases/t/159-socketpaths.t
index e73239ad..072d6940 100644
--- a/testcases/t/159-socketpaths.t
+++ b/testcases/t/159-socketpaths.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests if the various ipc_socket_path options are correctly handled
diff --git a/testcases/t/161-regress-borders-restart.t b/testcases/t/161-regress-borders-restart.t
index 0b45df06..31cf9398 100644
--- a/testcases/t/161-regress-borders-restart.t
+++ b/testcases/t/161-regress-borders-restart.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test to check if borders are correctly restored after an inplace
diff --git a/testcases/t/162-regress-dock-urgent.t b/testcases/t/162-regress-dock-urgent.t
index d558b0d9..36a5625a 100644
--- a/testcases/t/162-regress-dock-urgent.t
+++ b/testcases/t/162-regress-dock-urgent.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test for setting the urgent hint on dock clients.
diff --git a/testcases/t/163-wm-state.t b/testcases/t/163-wm-state.t
index 8b679386..7e165558 100644
--- a/testcases/t/163-wm-state.t
+++ b/testcases/t/163-wm-state.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests if WM_STATE is WM_STATE_NORMAL when mapped and WM_STATE_WITHDRAWN when
diff --git a/testcases/t/164-kill-win-vs-client.t b/testcases/t/164-kill-win-vs-client.t
index fe3fd011..d48301d8 100644
--- a/testcases/t/164-kill-win-vs-client.t
+++ b/testcases/t/164-kill-win-vs-client.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests if WM_STATE is WM_STATE_NORMAL when mapped and WM_STATE_WITHDRAWN when
diff --git a/testcases/t/165-for_window.t b/testcases/t/165-for_window.t
index 5ea5183c..77fbf848 100644
--- a/testcases/t/165-for_window.t
+++ b/testcases/t/165-for_window.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
use i3test i3_autostart => 0;
diff --git a/testcases/t/166-assign.t b/testcases/t/166-assign.t
index 249bbf87..bb817b6c 100644
--- a/testcases/t/166-assign.t
+++ b/testcases/t/166-assign.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests if assignments work
diff --git a/testcases/t/167-workspace_layout.t b/testcases/t/167-workspace_layout.t
index 597d545e..22f6d7ca 100644
--- a/testcases/t/167-workspace_layout.t
+++ b/testcases/t/167-workspace_layout.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests the workspace_layout config option.
diff --git a/testcases/t/168-regress-fullscreen-restart.t b/testcases/t/168-regress-fullscreen-restart.t
index 421c1abc..2f012cb6 100644
--- a/testcases/t/168-regress-fullscreen-restart.t
+++ b/testcases/t/168-regress-fullscreen-restart.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that i3 survives inplace restarts with fullscreen containers
diff --git a/testcases/t/169-border-toggle.t b/testcases/t/169-border-toggle.t
index 4146fd79..cc94bf2a 100644
--- a/testcases/t/169-border-toggle.t
+++ b/testcases/t/169-border-toggle.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests if the 'border toggle' command works correctly
diff --git a/testcases/t/170-force_focus_wrapping.t b/testcases/t/170-force_focus_wrapping.t
index 20641b0a..718b5d98 100644
--- a/testcases/t/170-force_focus_wrapping.t
+++ b/testcases/t/170-force_focus_wrapping.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests if the 'force_focus_wrapping' config directive works correctly.
diff --git a/testcases/t/171-config-migrate.t b/testcases/t/171-config-migrate.t
index 99158eab..eb66a853 100644
--- a/testcases/t/171-config-migrate.t
+++ b/testcases/t/171-config-migrate.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests if i3-migrate-config-to-v4 correctly migrates all config file
diff --git a/testcases/t/172-start-on-named-ws.t b/testcases/t/172-start-on-named-ws.t
index d1af6c07..a5b64fd9 100644
--- a/testcases/t/172-start-on-named-ws.t
+++ b/testcases/t/172-start-on-named-ws.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# checks if i3 starts up on workspace '1' or the first configured named workspace
diff --git a/testcases/t/173-get-marks.t b/testcases/t/173-get-marks.t
index 556014a1..01169704 100644
--- a/testcases/t/173-get-marks.t
+++ b/testcases/t/173-get-marks.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# checks if the IPC message type get_marks works correctly
diff --git a/testcases/t/174-border-config.t b/testcases/t/174-border-config.t
index 66e2cb65..94c06fe6 100644
--- a/testcases/t/174-border-config.t
+++ b/testcases/t/174-border-config.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests the new_window and new_float config option.
diff --git a/testcases/t/175-startup-notification.t b/testcases/t/175-startup-notification.t
index cd6f3950..a5f3ba5b 100644
--- a/testcases/t/175-startup-notification.t
+++ b/testcases/t/175-startup-notification.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test for the startup notification protocol.
diff --git a/testcases/t/176-workspace-baf.t b/testcases/t/176-workspace-baf.t
index 16738429..fa329f19 100644
--- a/testcases/t/176-workspace-baf.t
+++ b/testcases/t/176-workspace-baf.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Checks if the 'workspace back_and_forth' command and the
diff --git a/testcases/t/177-bar-config.t b/testcases/t/177-bar-config.t
index 278fd596..1ced3ce0 100644
--- a/testcases/t/177-bar-config.t
+++ b/testcases/t/177-bar-config.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Checks that the bar config is parsed correctly.
diff --git a/testcases/t/178-regress-workspace-open.t b/testcases/t/178-regress-workspace-open.t
index 17bce095..f11e3734 100644
--- a/testcases/t/178-regress-workspace-open.t
+++ b/testcases/t/178-regress-workspace-open.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests if empty workspaces are closed when the last child
diff --git a/testcases/t/179-regress-multiple-ws.t b/testcases/t/179-regress-multiple-ws.t
index 7ed2b75d..21abafce 100644
--- a/testcases/t/179-regress-multiple-ws.t
+++ b/testcases/t/179-regress-multiple-ws.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# The command "move workspace prev; workspace prev" will lead to an error.
diff --git a/testcases/t/180-fd-leaks.t b/testcases/t/180-fd-leaks.t
index 6ca0dc6f..8413e571 100644
--- a/testcases/t/180-fd-leaks.t
+++ b/testcases/t/180-fd-leaks.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that i3 does not leak any file descriptors in 'exec'.
diff --git a/testcases/t/181-regress-float-border.t b/testcases/t/181-regress-float-border.t
index b6352e1c..fb019d22 100644
--- a/testcases/t/181-regress-float-border.t
+++ b/testcases/t/181-regress-float-border.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test: Changing border style should not have an impact on the size
diff --git a/testcases/t/182-regress-focus-dock.t b/testcases/t/182-regress-focus-dock.t
index 198bd2d7..a47b0ecd 100644
--- a/testcases/t/182-regress-focus-dock.t
+++ b/testcases/t/182-regress-focus-dock.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test: Focusing a dock window should just do nothing, not crash i3.
diff --git a/testcases/t/183-config-variables.t b/testcases/t/183-config-variables.t
index d135ed59..515d763d 100644
--- a/testcases/t/183-config-variables.t
+++ b/testcases/t/183-config-variables.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Checks that variables are parsed correctly by using for_window rules with
diff --git a/testcases/t/184-regress-float-split-resize.t b/testcases/t/184-regress-float-split-resize.t
index f785eb84..92b4bd5a 100644
--- a/testcases/t/184-regress-float-split-resize.t
+++ b/testcases/t/184-regress-float-split-resize.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression: resizing a floating split container leads to a crash.
diff --git a/testcases/t/185-scratchpad.t b/testcases/t/185-scratchpad.t
index 0cd9ac3b..00563785 100644
--- a/testcases/t/185-scratchpad.t
+++ b/testcases/t/185-scratchpad.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests for the scratchpad functionality.
diff --git a/testcases/t/186-regress-assign-focus-parent.t b/testcases/t/186-regress-assign-focus-parent.t
index 49d8ea75..50665f6d 100644
--- a/testcases/t/186-regress-assign-focus-parent.t
+++ b/testcases/t/186-regress-assign-focus-parent.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test: New windows were not opened in the correct place if they
diff --git a/testcases/t/187-commands-parser.t b/testcases/t/187-commands-parser.t
index 3404df1f..5eaadd35 100644
--- a/testcases/t/187-commands-parser.t
+++ b/testcases/t/187-commands-parser.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests the standalone parser binary to see if it calls the right code when
@@ -106,30 +106,35 @@ is(parser_calls('resize shrink left 25 px or 33 ppt;'),
is(parser_calls('[con_mark=yay] focus'),
"cmd_criteria_add(con_mark, yay)\n" .
- "cmd_focus()",
+ "cmd_focus(0)",
'criteria focus ok');
+is(parser_calls('[con_mark=yay] focus workspace'),
+ "cmd_criteria_add(con_mark, yay)\n" .
+ "cmd_focus(1)",
+ 'criteria focus workspace ok');
+
is(parser_calls("[con_mark=yay con_mark=bar] focus"),
"cmd_criteria_add(con_mark, yay)\n" .
"cmd_criteria_add(con_mark, bar)\n" .
- "cmd_focus()",
+ "cmd_focus(0)",
'criteria focus ok');
is(parser_calls("[con_mark=yay\tcon_mark=bar] focus"),
"cmd_criteria_add(con_mark, yay)\n" .
"cmd_criteria_add(con_mark, bar)\n" .
- "cmd_focus()",
+ "cmd_focus(0)",
'criteria focus ok');
is(parser_calls("[con_mark=yay\tcon_mark=bar]\tfocus"),
"cmd_criteria_add(con_mark, yay)\n" .
"cmd_criteria_add(con_mark, bar)\n" .
- "cmd_focus()",
+ "cmd_focus(0)",
'criteria focus ok');
is(parser_calls('[con_mark="yay"] focus'),
"cmd_criteria_add(con_mark, yay)\n" .
- "cmd_focus()",
+ "cmd_focus(0)",
'quoted criteria focus ok');
# Make sure trailing whitespace is stripped off: While this is not an issue for
diff --git a/testcases/t/188-regress-focus-restart.t b/testcases/t/188-regress-focus-restart.t
index 51d3a8a7..0f73feea 100644
--- a/testcases/t/188-regress-focus-restart.t
+++ b/testcases/t/188-regress-focus-restart.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that i3 survives inplace restarts with fullscreen containers
diff --git a/testcases/t/189-floating-constraints.t b/testcases/t/189-floating-constraints.t
index ba5f76aa..87e1f223 100644
--- a/testcases/t/189-floating-constraints.t
+++ b/testcases/t/189-floating-constraints.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests the floating_{minimum,maximum}_size config options.
diff --git a/testcases/t/190-scratchpad-diff-ws.t b/testcases/t/190-scratchpad-diff-ws.t
index 23327110..acbfa972 100644
--- a/testcases/t/190-scratchpad-diff-ws.t
+++ b/testcases/t/190-scratchpad-diff-ws.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test for ticket #676: 'scratchpad show' causes a segfault if the scratchpad
diff --git a/testcases/t/191-resize-levels.t b/testcases/t/191-resize-levels.t
index 9e483230..fe3561d4 100644
--- a/testcases/t/191-resize-levels.t
+++ b/testcases/t/191-resize-levels.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that you can resize across different levels of containers even when
diff --git a/testcases/t/192-layout.t b/testcases/t/192-layout.t
index c86b3656..db3dff76 100644
--- a/testcases/t/192-layout.t
+++ b/testcases/t/192-layout.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that switching between the different layouts works as expected.
diff --git a/testcases/t/193-ipc-version.t b/testcases/t/193-ipc-version.t
index 82449de7..475bf85d 100644
--- a/testcases/t/193-ipc-version.t
+++ b/testcases/t/193-ipc-version.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that we can get the version number of i3 via IPC.
diff --git a/testcases/t/194-regress-floating-size.t b/testcases/t/194-regress-floating-size.t
index 4f4217c0..61c18e7f 100644
--- a/testcases/t/194-regress-floating-size.t
+++ b/testcases/t/194-regress-floating-size.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that the size requested by floating windows is set by i3, no matter
diff --git a/testcases/t/195-net-active-window.t b/testcases/t/195-net-active-window.t
index 4ce12089..a6f0d94f 100644
--- a/testcases/t/195-net-active-window.t
+++ b/testcases/t/195-net-active-window.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that the _NET_ACTIVE_WINDOW message only changes focus when the
diff --git a/testcases/t/196-randr-output-names.t b/testcases/t/196-randr-output-names.t
index a822cdc2..caf0e67f 100644
--- a/testcases/t/196-randr-output-names.t
+++ b/testcases/t/196-randr-output-names.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verify that i3 allows strange RandR output names such as DVI-I_1/digital.
diff --git a/testcases/t/197-regression-move-vanish.t b/testcases/t/197-regression-move-vanish.t
index 7f8f9621..0c85b557 100644
--- a/testcases/t/197-regression-move-vanish.t
+++ b/testcases/t/197-regression-move-vanish.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test: moving a window to the right out of a splitv container would
diff --git a/testcases/t/198-regression-scratchpad-crash.t b/testcases/t/198-regression-scratchpad-crash.t
index c295ce3d..02229751 100644
--- a/testcases/t/198-regression-scratchpad-crash.t
+++ b/testcases/t/198-regression-scratchpad-crash.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# When using a command which moves a window to scratchpad from an invisible
diff --git a/testcases/t/199-ipc-mode-event.t b/testcases/t/199-ipc-mode-event.t
index 0e4f8960..4548fe3b 100644
--- a/testcases/t/199-ipc-mode-event.t
+++ b/testcases/t/199-ipc-mode-event.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that the IPC 'mode' event is sent when modes are changed.
diff --git a/testcases/t/200-urgency-timer.t b/testcases/t/200-urgency-timer.t
index 6d2f2bd8..4192f5b4 100644
--- a/testcases/t/200-urgency-timer.t
+++ b/testcases/t/200-urgency-timer.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
#
diff --git a/testcases/t/201-config-parser.t b/testcases/t/201-config-parser.t
index af50d81d..c7f79093 100644
--- a/testcases/t/201-config-parser.t
+++ b/testcases/t/201-config-parser.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests the standalone parser binary to see if it calls the right code when
@@ -776,7 +776,7 @@ EOT
$expected = <<'EOT';
cfg_bar_start()
cfg_bar_output(LVDS-1)
-ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'hidden_state', 'id', 'modifier', 'wheel_up_cmd', 'wheel_down_cmd', 'bindsym', 'position', 'output', 'tray_output', 'tray_padding', 'font', 'separator_symbol', 'binding_mode_indicator', 'workspace_buttons', 'workspace_min_width', 'strip_workspace_numbers', 'strip_workspace_name', 'verbose', 'height', 'padding', 'colors', '}'
+ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'i3bar_command', 'status_command', 'workspace_command', 'socket_path', 'mode', 'hidden_state', 'id', 'modifier', 'wheel_up_cmd', 'wheel_down_cmd', 'bindsym', 'position', 'output', 'tray_output', 'tray_padding', 'font', 'separator_symbol', 'binding_mode_indicator', 'workspace_buttons', 'workspace_min_width', 'strip_workspace_numbers', 'strip_workspace_name', 'verbose', 'height', 'padding', 'colors', '}'
ERROR: CONFIG: (in file <stdin>)
ERROR: CONFIG: Line 1: bar {
ERROR: CONFIG: Line 2: output LVDS-1
diff --git a/testcases/t/202-scratchpad-criteria.t b/testcases/t/202-scratchpad-criteria.t
index 9d86be94..3489d5e9 100644
--- a/testcases/t/202-scratchpad-criteria.t
+++ b/testcases/t/202-scratchpad-criteria.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that using criteria to address scratchpad windows works.
diff --git a/testcases/t/203-regress-assign-and-move.t b/testcases/t/203-regress-assign-and-move.t
index c70ce4ce..80675112 100644
--- a/testcases/t/203-regress-assign-and-move.t
+++ b/testcases/t/203-regress-assign-and-move.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that you can assign a window _and_ use for_window with a move
diff --git a/testcases/t/204-regress-scratchpad-move.t b/testcases/t/204-regress-scratchpad-move.t
index c6fd7ae5..85e57ec0 100644
--- a/testcases/t/204-regress-scratchpad-move.t
+++ b/testcases/t/204-regress-scratchpad-move.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Moves the last window of a workspace to the scratchpad. The workspace will be
diff --git a/testcases/t/205-ipc-windows.t b/testcases/t/205-ipc-windows.t
index bafd155f..798e0031 100644
--- a/testcases/t/205-ipc-windows.t
+++ b/testcases/t/205-ipc-windows.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test;
diff --git a/testcases/t/206-fullscreen-scratchpad.t b/testcases/t/206-fullscreen-scratchpad.t
index cd7c4919..1515a394 100644
--- a/testcases/t/206-fullscreen-scratchpad.t
+++ b/testcases/t/206-fullscreen-scratchpad.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Assure that no window is in fullscreen mode after showing a scratchpad window
diff --git a/testcases/t/207-shmlog.t b/testcases/t/207-shmlog.t
index 94f4bdea..43f1a852 100644
--- a/testcases/t/207-shmlog.t
+++ b/testcases/t/207-shmlog.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
use i3test;
diff --git a/testcases/t/208-regress-floating-criteria.t b/testcases/t/208-regress-floating-criteria.t
index a1f264d9..3e01a215 100644
--- a/testcases/t/208-regress-floating-criteria.t
+++ b/testcases/t/208-regress-floating-criteria.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test for focus handling when using floating enable/disable with
diff --git a/testcases/t/209-ewmh-net-workarea.t b/testcases/t/209-ewmh-net-workarea.t
index 7fade619..c1583744 100644
--- a/testcases/t/209-ewmh-net-workarea.t
+++ b/testcases/t/209-ewmh-net-workarea.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies the _NET_WORKAREA hint is deleted in case it is already set on the
diff --git a/testcases/t/210-mark-unmark.t b/testcases/t/210-mark-unmark.t
index 166ca23f..3880a344 100644
--- a/testcases/t/210-mark-unmark.t
+++ b/testcases/t/210-mark-unmark.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# checks if mark and unmark work correctly
diff --git a/testcases/t/211-regress-urgency-assign.t b/testcases/t/211-regress-urgency-assign.t
index 5bcc7460..0c866bf6 100644
--- a/testcases/t/211-regress-urgency-assign.t
+++ b/testcases/t/211-regress-urgency-assign.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that windows are properly recognized as urgent when they start up
diff --git a/testcases/t/212-assign-urgency.t b/testcases/t/212-assign-urgency.t
index 2fb235d3..9536c5e2 100644
--- a/testcases/t/212-assign-urgency.t
+++ b/testcases/t/212-assign-urgency.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests if the urgency hint will be set appropriately when opening a window
diff --git a/testcases/t/213-layout-restore-simple.t b/testcases/t/213-layout-restore-simple.t
index c2c533ff..82568089 100644
--- a/testcases/t/213-layout-restore-simple.t
+++ b/testcases/t/213-layout-restore-simple.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Restores a simple layout from a JSON file.
diff --git a/testcases/t/214-layout-restore-criteria.t b/testcases/t/214-layout-restore-criteria.t
index d21ba2b2..a6d73a20 100644
--- a/testcases/t/214-layout-restore-criteria.t
+++ b/testcases/t/214-layout-restore-criteria.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests all supported criteria for the "swallows" key.
diff --git a/testcases/t/215-layout-restore-crash.t b/testcases/t/215-layout-restore-crash.t
index d9fcd54a..978c08c1 100644
--- a/testcases/t/215-layout-restore-crash.t
+++ b/testcases/t/215-layout-restore-crash.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that i3 does not crash when a layout is partially loadable.
diff --git a/testcases/t/216-layout-restore-split-swallows.t b/testcases/t/216-layout-restore-split-swallows.t
index 6baf141c..01a0e286 100644
--- a/testcases/t/216-layout-restore-split-swallows.t
+++ b/testcases/t/216-layout-restore-split-swallows.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that i3 removes swallows specifications for split containers.
diff --git a/testcases/t/217-NET_CURRENT_DESKTOP.t b/testcases/t/217-NET_CURRENT_DESKTOP.t
index 5928ec32..22b13d8c 100644
--- a/testcases/t/217-NET_CURRENT_DESKTOP.t
+++ b/testcases/t/217-NET_CURRENT_DESKTOP.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies the _NET_CURRENT_DESKTOP property correctly tracks the currently
diff --git a/testcases/t/218-regress-floating-split.t b/testcases/t/218-regress-floating-split.t
index 1c65848b..f57d1535 100644
--- a/testcases/t/218-regress-floating-split.t
+++ b/testcases/t/218-regress-floating-split.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Make sure floating containers really can't be split.
diff --git a/testcases/t/219-ipc-window-focus.t b/testcases/t/219-ipc-window-focus.t
index 770536f3..08ed7fc5 100644
--- a/testcases/t/219-ipc-window-focus.t
+++ b/testcases/t/219-ipc-window-focus.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test i3_config => <<EOT;
diff --git a/testcases/t/220-ipc-window-title.t b/testcases/t/220-ipc-window-title.t
index b5d14e23..ad5405b8 100644
--- a/testcases/t/220-ipc-window-title.t
+++ b/testcases/t/220-ipc-window-title.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test;
diff --git a/testcases/t/221-floating-type-hints.t b/testcases/t/221-floating-type-hints.t
index 0c049d8b..75c69f0e 100644
--- a/testcases/t/221-floating-type-hints.t
+++ b/testcases/t/221-floating-type-hints.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that windows with properties that indicate they should be floating
diff --git a/testcases/t/222-regress-dock-resize.t b/testcases/t/222-regress-dock-resize.t
index 272beb95..f0f606b0 100644
--- a/testcases/t/222-regress-dock-resize.t
+++ b/testcases/t/222-regress-dock-resize.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that i3 does not crash when a command is issued that would resize a dock
diff --git a/testcases/t/223-net-client-list.t b/testcases/t/223-net-client-list.t
index 83ce2989..2a755f14 100644
--- a/testcases/t/223-net-client-list.t
+++ b/testcases/t/223-net-client-list.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that _NET_CLIENT_LIST is properly updated on the root window as windows
diff --git a/testcases/t/224-regress-resize-branch.t b/testcases/t/224-regress-resize-branch.t
index aeddd877..4cf6aef2 100644
--- a/testcases/t/224-regress-resize-branch.t
+++ b/testcases/t/224-regress-resize-branch.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that i3 does not crash when resizing a split container
diff --git a/testcases/t/225-ipc-window-fullscreen.t b/testcases/t/225-ipc-window-fullscreen.t
index bc150546..a4a7ca72 100644
--- a/testcases/t/225-ipc-window-fullscreen.t
+++ b/testcases/t/225-ipc-window-fullscreen.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that the ipc window::fullscreen_mode event works properly
diff --git a/testcases/t/226-internal-workspaces.t b/testcases/t/226-internal-workspaces.t
index 054b4f40..f62624f6 100644
--- a/testcases/t/226-internal-workspaces.t
+++ b/testcases/t/226-internal-workspaces.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that internal workspaces (those whose name starts with __) cannot be
diff --git a/testcases/t/227-ipc-workspace-empty.t b/testcases/t/227-ipc-workspace-empty.t
index b1f517ef..90e04ec3 100644
--- a/testcases/t/227-ipc-workspace-empty.t
+++ b/testcases/t/227-ipc-workspace-empty.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Checks the workspace "empty" event semantics.
diff --git a/testcases/t/228-border-widths.t b/testcases/t/228-border-widths.t
index e2dc9b85..1ad9e229 100644
--- a/testcases/t/228-border-widths.t
+++ b/testcases/t/228-border-widths.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that the border widths can be set separately for floating and
diff --git a/testcases/t/229-cleanup-tmpdir.t b/testcases/t/229-cleanup-tmpdir.t
index b63de986..d611ab70 100644
--- a/testcases/t/229-cleanup-tmpdir.t
+++ b/testcases/t/229-cleanup-tmpdir.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Makes sure i3 deletes its temporary directory when exiting.
diff --git a/testcases/t/230-floating-fullscreen-restart.t b/testcases/t/230-floating-fullscreen-restart.t
index 69bc5ddb..d77eb256 100644
--- a/testcases/t/230-floating-fullscreen-restart.t
+++ b/testcases/t/230-floating-fullscreen-restart.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Ensures floating windows don’t drop out of fullscreen mode when restarting
diff --git a/testcases/t/231-ipc-floating-event.t b/testcases/t/231-ipc-floating-event.t
index 96c94a49..f054d7e3 100644
--- a/testcases/t/231-ipc-floating-event.t
+++ b/testcases/t/231-ipc-floating-event.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that the window::floating event works correctly. This event should be
diff --git a/testcases/t/232-cmd-move-criteria.t b/testcases/t/232-cmd-move-criteria.t
index 312c9660..8281ef9e 100644
--- a/testcases/t/232-cmd-move-criteria.t
+++ b/testcases/t/232-cmd-move-criteria.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that the `move [direction]` command works with criteria
diff --git a/testcases/t/233-regress-manage-focus-unmapped.t b/testcases/t/233-regress-manage-focus-unmapped.t
index 64db0bd7..6193b8fd 100644
--- a/testcases/t/233-regress-manage-focus-unmapped.t
+++ b/testcases/t/233-regress-manage-focus-unmapped.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that an assignment that unmaps a window does not disturb input focus.
diff --git a/testcases/t/234-ewmh-desktop-names.t b/testcases/t/234-ewmh-desktop-names.t
index 246a0a46..bd792902 100644
--- a/testcases/t/234-ewmh-desktop-names.t
+++ b/testcases/t/234-ewmh-desktop-names.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that the EWMH specified property _NET_DESKTOP_NAMES is updated properly
diff --git a/testcases/t/235-check-config-no-x.t b/testcases/t/235-check-config-no-x.t
index dce70894..7b7bde2d 100644
--- a/testcases/t/235-check-config-no-x.t
+++ b/testcases/t/235-check-config-no-x.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Check whether the -C option works without a display and doesn't
diff --git a/testcases/t/236-floating-focus-raise.t b/testcases/t/236-floating-focus-raise.t
index 53e5b08e..bb175bdc 100644
--- a/testcases/t/236-floating-focus-raise.t
+++ b/testcases/t/236-floating-focus-raise.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that focusing floating windows with the command `focus [direction]`
diff --git a/testcases/t/237-regress-assign-focus.t b/testcases/t/237-regress-assign-focus.t
index fa8608b8..f697558f 100644
--- a/testcases/t/237-regress-assign-focus.t
+++ b/testcases/t/237-regress-assign-focus.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that using layout tabbed followed by focus (on a window that is
diff --git a/testcases/t/238-ipc-binding-event.t b/testcases/t/238-ipc-binding-event.t
index 6916593d..403afbad 100644
--- a/testcases/t/238-ipc-binding-event.t
+++ b/testcases/t/238-ipc-binding-event.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that the binding event works properly
diff --git a/testcases/t/239-net-close-window-request.t b/testcases/t/239-net-close-window-request.t
index 763da681..73063e6f 100644
--- a/testcases/t/239-net-close-window-request.t
+++ b/testcases/t/239-net-close-window-request.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test _NET_CLOSE_WINDOW requests to close a window.
diff --git a/testcases/t/240-focus-on-window-activation.t b/testcases/t/240-focus-on-window-activation.t
index efcd5ca4..50828ff0 100644
--- a/testcases/t/240-focus-on-window-activation.t
+++ b/testcases/t/240-focus-on-window-activation.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests for the focus_on_window_activation directive
diff --git a/testcases/t/241-consistent-center.t b/testcases/t/241-consistent-center.t
index a3758554..2ea95bf4 100644
--- a/testcases/t/241-consistent-center.t
+++ b/testcases/t/241-consistent-center.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that most of i3's centering methods produce consistent results.
diff --git a/testcases/t/242-no-focus.t b/testcases/t/242-no-focus.t
index 6fd27fe0..7656d496 100644
--- a/testcases/t/242-no-focus.t
+++ b/testcases/t/242-no-focus.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test the 'no_focus' directive.
diff --git a/testcases/t/243-move-to-mark.t b/testcases/t/243-move-to-mark.t
index 390da04d..68b55135 100644
--- a/testcases/t/243-move-to-mark.t
+++ b/testcases/t/243-move-to-mark.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests for the 'move [window|container] to mark' command
diff --git a/testcases/t/244-new-workspace-floating-enable-center.t b/testcases/t/244-new-workspace-floating-enable-center.t
index 314187bd..5197fc69 100644
--- a/testcases/t/244-new-workspace-floating-enable-center.t
+++ b/testcases/t/244-new-workspace-floating-enable-center.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Ensures that 'move workspace $new, floating enable' on a marked window
diff --git a/testcases/t/245-move-position-mouse.t b/testcases/t/245-move-position-mouse.t
index 01e2c30e..2dd94938 100644
--- a/testcases/t/245-move-position-mouse.t
+++ b/testcases/t/245-move-position-mouse.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests the 'move [window|container] [to] position mouse|cursor|pointer command.
diff --git a/testcases/t/246-window-decoration-focus.t b/testcases/t/246-window-decoration-focus.t
index 265cb87a..197a66c5 100644
--- a/testcases/t/246-window-decoration-focus.t
+++ b/testcases/t/246-window-decoration-focus.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Ensure that hovering over the window decoration of a window causes it to focus
diff --git a/testcases/t/247-config-line-continuation.t b/testcases/t/247-config-line-continuation.t
index c54f1ac4..1c32bedb 100644
--- a/testcases/t/247-config-line-continuation.t
+++ b/testcases/t/247-config-line-continuation.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Checks that the line continuation are parsed correctly
diff --git a/testcases/t/248-regress-urgency-clear.t b/testcases/t/248-regress-urgency-clear.t
index cb700c0e..99932170 100644
--- a/testcases/t/248-regress-urgency-clear.t
+++ b/testcases/t/248-regress-urgency-clear.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Ensures the urgency hint is cleared properly in the case where i3 set it (due
diff --git a/testcases/t/249-layout-restore-floating.t b/testcases/t/249-layout-restore-floating.t
index 61cfda5c..8b6576a2 100644
--- a/testcases/t/249-layout-restore-floating.t
+++ b/testcases/t/249-layout-restore-floating.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies floating containers are restored in the correct place in the
diff --git a/testcases/t/250-layout-restore-multiple-criteria.t b/testcases/t/250-layout-restore-multiple-criteria.t
index 10a6d771..51d28d81 100644
--- a/testcases/t/250-layout-restore-multiple-criteria.t
+++ b/testcases/t/250-layout-restore-multiple-criteria.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# TODO: Description of this file.
diff --git a/testcases/t/251-command-criteria-focused.t b/testcases/t/251-command-criteria-focused.t
index a880f591..80bcfb65 100644
--- a/testcases/t/251-command-criteria-focused.t
+++ b/testcases/t/251-command-criteria-focused.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests for the special value "__focused__" in command criteria.
diff --git a/testcases/t/252-floating-size.t b/testcases/t/252-floating-size.t
index 5c746de9..51c36b29 100644
--- a/testcases/t/252-floating-size.t
+++ b/testcases/t/252-floating-size.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test behavior of "resize <width> <height>" command.
diff --git a/testcases/t/253-multiple-net-wm-state-atoms.t b/testcases/t/253-multiple-net-wm-state-atoms.t
index 3a3e7c6e..3e67e6b0 100644
--- a/testcases/t/253-multiple-net-wm-state-atoms.t
+++ b/testcases/t/253-multiple-net-wm-state-atoms.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Ticket: #1873
diff --git a/testcases/t/254-move-to-output-with-criteria.t b/testcases/t/254-move-to-output-with-criteria.t
index c129aa71..775965cd 100644
--- a/testcases/t/254-move-to-output-with-criteria.t
+++ b/testcases/t/254-move-to-output-with-criteria.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that "move container to output" works correctly when
diff --git a/testcases/t/255-multiple-marks.t b/testcases/t/255-multiple-marks.t
index 61fac006..e680c0c7 100644
--- a/testcases/t/255-multiple-marks.t
+++ b/testcases/t/255-multiple-marks.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests for mark/unmark with multiple marks on a single window.
diff --git a/testcases/t/256-no-auto-back-and-forth.t b/testcases/t/256-no-auto-back-and-forth.t
index 4242b430..9736a81a 100644
--- a/testcases/t/256-no-auto-back-and-forth.t
+++ b/testcases/t/256-no-auto-back-and-forth.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test for the --no-auto-back-and-forth flag.
diff --git a/testcases/t/257-keypress-group1-fallback.t b/testcases/t/257-keypress-group1-fallback.t
index bc08aa2f..6a1bc73a 100644
--- a/testcases/t/257-keypress-group1-fallback.t
+++ b/testcases/t/257-keypress-group1-fallback.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that when using multiple keyboard layouts at the same time, bindings
diff --git a/testcases/t/258-keypress-release.t b/testcases/t/258-keypress-release.t
index 614164ab..78b1e905 100644
--- a/testcases/t/258-keypress-release.t
+++ b/testcases/t/258-keypress-release.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that --release key bindings are not shadowed by non-release key
diff --git a/testcases/t/259-net-wm-user-time.t b/testcases/t/259-net-wm-user-time.t
index c1182616..fab55e06 100644
--- a/testcases/t/259-net-wm-user-time.t
+++ b/testcases/t/259-net-wm-user-time.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test for _NET_WM_USER_TIME.
diff --git a/testcases/t/260-invalid-criteria.t b/testcases/t/260-invalid-criteria.t
index b8cc2f1f..3d2cb108 100644
--- a/testcases/t/260-invalid-criteria.t
+++ b/testcases/t/260-invalid-criteria.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Ticket: #2091
diff --git a/testcases/t/261-match-con_id-con_mark-combinations.t b/testcases/t/261-match-con_id-con_mark-combinations.t
index efc62ba0..a34dbfa5 100644
--- a/testcases/t/261-match-con_id-con_mark-combinations.t
+++ b/testcases/t/261-match-con_id-con_mark-combinations.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Ticket: #2111
diff --git a/testcases/t/262-config-validation.t b/testcases/t/262-config-validation.t
index d4df70c7..4cbc69fd 100644
--- a/testcases/t/262-config-validation.t
+++ b/testcases/t/262-config-validation.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Ensures that calling i3 with the -C switch works (smoke test).
diff --git a/testcases/t/263-config-reload-reverts-bind-mode.t b/testcases/t/263-config-reload-reverts-bind-mode.t
index 1416b6b9..cce4f959 100644
--- a/testcases/t/263-config-reload-reverts-bind-mode.t
+++ b/testcases/t/263-config-reload-reverts-bind-mode.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that reloading the config reverts to the default
diff --git a/testcases/t/264-dock-criteria.t b/testcases/t/264-dock-criteria.t
index fe482409..a12d7bbe 100644
--- a/testcases/t/264-dock-criteria.t
+++ b/testcases/t/264-dock-criteria.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that command or config criteria does not match dock clients
diff --git a/testcases/t/265-ipc-mark.t b/testcases/t/265-ipc-mark.t
index a101944e..1930559f 100644
--- a/testcases/t/265-ipc-mark.t
+++ b/testcases/t/265-ipc-mark.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests for the window::mark IPC event.
diff --git a/testcases/t/266-net-moveresize-window.t b/testcases/t/266-net-moveresize-window.t
index b31aeed6..2c437614 100644
--- a/testcases/t/266-net-moveresize-window.t
+++ b/testcases/t/266-net-moveresize-window.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests for _NET_MOVERESIZE_WINDOW.
diff --git a/testcases/t/267-regress-mark-restart.t b/testcases/t/267-regress-mark-restart.t
index fe22e70c..d2a016bb 100644
--- a/testcases/t/267-regress-mark-restart.t
+++ b/testcases/t/267-regress-mark-restart.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test to check if mark and restart commands crash i3
diff --git a/testcases/t/268-ipc-config.t b/testcases/t/268-ipc-config.t
index 9ac749b6..c3f36b1c 100644
--- a/testcases/t/268-ipc-config.t
+++ b/testcases/t/268-ipc-config.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that the config file is returned raw via the IPC interface.
diff --git a/testcases/t/269-focus-stack-above.t b/testcases/t/269-focus-stack-above.t
index 66034211..2497432a 100644
--- a/testcases/t/269-focus-stack-above.t
+++ b/testcases/t/269-focus-stack-above.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies a ConfigureWindow request with stack-mode=Above is translated into
diff --git a/testcases/t/270-config-no-newline-end.t b/testcases/t/270-config-no-newline-end.t
index 24c017f2..8cd99ce8 100644
--- a/testcases/t/270-config-no-newline-end.t
+++ b/testcases/t/270-config-no-newline-end.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Make sure that configs that end without a newline don't crash i3.
diff --git a/testcases/t/271-for_window_tilingfloating.t b/testcases/t/271-for_window_tilingfloating.t
index f11908ab..94684452 100644
--- a/testcases/t/271-for_window_tilingfloating.t
+++ b/testcases/t/271-for_window_tilingfloating.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
use i3test i3_autostart => 0;
diff --git a/testcases/t/272-regress-focus-assign.t b/testcases/t/272-regress-focus-assign.t
index 44b188af..fb1ffa17 100644
--- a/testcases/t/272-regress-focus-assign.t
+++ b/testcases/t/272-regress-focus-assign.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression: Checks if focus is stolen when a window is managed which is
diff --git a/testcases/t/273-regress-focus-toggle.t b/testcases/t/273-regress-focus-toggle.t
index b51d74b6..50a7bbec 100644
--- a/testcases/t/273-regress-focus-toggle.t
+++ b/testcases/t/273-regress-focus-toggle.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression: Checks if i3 still lives after using 'focus mode_toggle' on an
diff --git a/testcases/t/274-move-branch-position.t b/testcases/t/274-move-branch-position.t
index e4d97819..50a39388 100644
--- a/testcases/t/274-move-branch-position.t
+++ b/testcases/t/274-move-branch-position.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that movement of a con into a branch will place the moving con at the
diff --git a/testcases/t/275-ipc-window-close.t b/testcases/t/275-ipc-window-close.t
index ccaf4440..ab258256 100644
--- a/testcases/t/275-ipc-window-close.t
+++ b/testcases/t/275-ipc-window-close.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that the ipc close event works properly
diff --git a/testcases/t/276-ipc-window-move.t b/testcases/t/276-ipc-window-move.t
index 708963df..561633ab 100644
--- a/testcases/t/276-ipc-window-move.t
+++ b/testcases/t/276-ipc-window-move.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that the ipc window::move event works properly
diff --git a/testcases/t/277-ipc-window-urgent.t b/testcases/t/277-ipc-window-urgent.t
index 4eea2cdc..2789c07f 100644
--- a/testcases/t/277-ipc-window-urgent.t
+++ b/testcases/t/277-ipc-window-urgent.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that the window::urgent event works correctly. The window::urgent event
diff --git a/testcases/t/278-layout-restore-output.t b/testcases/t/278-layout-restore-output.t
index e87cfa8b..06a31fbd 100644
--- a/testcases/t/278-layout-restore-output.t
+++ b/testcases/t/278-layout-restore-output.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that entire outputs can be saved and restored properly by i3.
diff --git a/testcases/t/279-regress-default-floating-border.t b/testcases/t/279-regress-default-floating-border.t
index ba905b9c..03e8298b 100644
--- a/testcases/t/279-regress-default-floating-border.t
+++ b/testcases/t/279-regress-default-floating-border.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# This is a regression test for a bug where a normal floating default border is
diff --git a/testcases/t/280-wm-class-change-handler.t b/testcases/t/280-wm-class-change-handler.t
index 90268bd3..10a7ef85 100644
--- a/testcases/t/280-wm-class-change-handler.t
+++ b/testcases/t/280-wm-class-change-handler.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that changes to WM_CLASS are internally processed by i3 by updating the
diff --git a/testcases/t/281-regress-reload-bindsym.t b/testcases/t/281-regress-reload-bindsym.t
index 27b00245..2bc7d2c1 100644
--- a/testcases/t/281-regress-reload-bindsym.t
+++ b/testcases/t/281-regress-reload-bindsym.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that the binding event works properly
diff --git a/testcases/t/282-tabbed-floating-disable-crash.t b/testcases/t/282-tabbed-floating-disable-crash.t
index c7eebd7e..5734037d 100644
--- a/testcases/t/282-tabbed-floating-disable-crash.t
+++ b/testcases/t/282-tabbed-floating-disable-crash.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that i3 does not crash when floating and then unfloating an
diff --git a/testcases/t/283-net-wm-state-hidden.t b/testcases/t/283-net-wm-state-hidden.t
index 102a3ffc..d6c7b2f8 100644
--- a/testcases/t/283-net-wm-state-hidden.t
+++ b/testcases/t/283-net-wm-state-hidden.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests for setting and removing the _NET_WM_STATE_HIDDEN atom properly.
diff --git a/testcases/t/284-ewmh-visible-name.t b/testcases/t/284-ewmh-visible-name.t
index c83b019a..f2072b5b 100644
--- a/testcases/t/284-ewmh-visible-name.t
+++ b/testcases/t/284-ewmh-visible-name.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that _NET_WM_VISIBLE_NAME is set correctly.
diff --git a/testcases/t/285-sticky.t b/testcases/t/285-sticky.t
index 8dfe9aea..62fe7544 100644
--- a/testcases/t/285-sticky.t
+++ b/testcases/t/285-sticky.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests sticky windows.
diff --git a/testcases/t/286-root-window-mouse-binding.t b/testcases/t/286-root-window-mouse-binding.t
index 0da373b7..9b5cce07 100644
--- a/testcases/t/286-root-window-mouse-binding.t
+++ b/testcases/t/286-root-window-mouse-binding.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that mouse bindings work on the root window if
diff --git a/testcases/t/287-edge-borders.t b/testcases/t/287-edge-borders.t
index 3dfc3407..eb4c18c8 100644
--- a/testcases/t/287-edge-borders.t
+++ b/testcases/t/287-edge-borders.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that the hide_edge_borders smart option works
diff --git a/testcases/t/288-i3-floating-window-atom.t b/testcases/t/288-i3-floating-window-atom.t
index 4b90dc82..e66bf22c 100644
--- a/testcases/t/288-i3-floating-window-atom.t
+++ b/testcases/t/288-i3-floating-window-atom.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests for our proprietary atom I3_FLOATING_WINDOW to allow
diff --git a/testcases/t/289-ipc-shutdown-event.t b/testcases/t/289-ipc-shutdown-event.t
index a56c4ac7..68fc1fb8 100644
--- a/testcases/t/289-ipc-shutdown-event.t
+++ b/testcases/t/289-ipc-shutdown-event.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test the ipc shutdown event. This event is triggered when the connection to
diff --git a/testcases/t/290-keypress-numlock.t b/testcases/t/290-keypress-numlock.t
index 94a5747d..ab703713 100644
--- a/testcases/t/290-keypress-numlock.t
+++ b/testcases/t/290-keypress-numlock.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that one can bind on numpad keys in different numlock states.
diff --git a/testcases/t/291-swap.t b/testcases/t/291-swap.t
index 781315e5..6ca98216 100644
--- a/testcases/t/291-swap.t
+++ b/testcases/t/291-swap.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests the swap command.
diff --git a/testcases/t/292-regress-layout-toggle.t b/testcases/t/292-regress-layout-toggle.t
index e34faddd..aae911f5 100644
--- a/testcases/t/292-regress-layout-toggle.t
+++ b/testcases/t/292-regress-layout-toggle.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test: verify layout toggle with invalid parameters does not set
diff --git a/testcases/t/293-focus-follows-mouse.t b/testcases/t/293-focus-follows-mouse.t
index 55958c3e..2fb62513 100644
--- a/testcases/t/293-focus-follows-mouse.t
+++ b/testcases/t/293-focus-follows-mouse.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests the focus_follows_mouse setting.
diff --git a/testcases/t/293-sticky-output-crash.t b/testcases/t/293-sticky-output-crash.t
index 93ebaee9..628d74db 100644
--- a/testcases/t/293-sticky-output-crash.t
+++ b/testcases/t/293-sticky-output-crash.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that i3 does not crash when opening a floating sticky on one output
diff --git a/testcases/t/294-focus-order.t b/testcases/t/294-focus-order.t
index dfadd0af..23427230 100644
--- a/testcases/t/294-focus-order.t
+++ b/testcases/t/294-focus-order.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verify that the current focus stack order is preserved after various
diff --git a/testcases/t/294-update-ewmh-atoms.t b/testcases/t/294-update-ewmh-atoms.t
index f13b1764..1a67c0ce 100644
--- a/testcases/t/294-update-ewmh-atoms.t
+++ b/testcases/t/294-update-ewmh-atoms.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies _NET_DESKTOP_NAMES, _NET_CURRENT_DESKTOP and _NET_CURRENT_DESKTOP
diff --git a/testcases/t/295-net-wm-state-focused.t b/testcases/t/295-net-wm-state-focused.t
index fd7c2513..68283e9c 100644
--- a/testcases/t/295-net-wm-state-focused.t
+++ b/testcases/t/295-net-wm-state-focused.t
@@ -11,7 +11,7 @@
# • http://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests for setting and removing the _NET_WM_STATE_FOCUSED atom properly.
diff --git a/testcases/t/296-regress-focus-behind-fullscreen-floating.t b/testcases/t/296-regress-focus-behind-fullscreen-floating.t
index 0867f082..4f942355 100644
--- a/testcases/t/296-regress-focus-behind-fullscreen-floating.t
+++ b/testcases/t/296-regress-focus-behind-fullscreen-floating.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that directional focus gives focus to floating fullscreen containers when
diff --git a/testcases/t/297-assign-workspace-to-output.t b/testcases/t/297-assign-workspace-to-output.t
index 68aa1f89..06caf96a 100644
--- a/testcases/t/297-assign-workspace-to-output.t
+++ b/testcases/t/297-assign-workspace-to-output.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test assignments of workspaces to outputs.
diff --git a/testcases/t/297-scroll-tabbed.t b/testcases/t/297-scroll-tabbed.t
index b535d0cd..0d5066d5 100644
--- a/testcases/t/297-scroll-tabbed.t
+++ b/testcases/t/297-scroll-tabbed.t
@@ -11,16 +11,18 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests if scrolling the tab bar on a tabbed container works and verifies that
# only one window is focused as a result.
# Ticket: #3215 (PR)
# Bug still in: 4.15-92-g666aa9e0
-use i3test;
+use i3test i3_autostart => 0;
use i3test::XTEST;
+my $pid = launch_with_config('-default');
+
sub scroll_down {
# button5 = scroll down
xtest_button_press(5, 3, 3);
@@ -81,4 +83,39 @@ cmd '[id=' . $outside->id . '] focus';
scroll_up;
is($x->input_focus, $first->id, 'Scrolling from outside the tabbed container works');
+exit_gracefully($pid);
+
+###############################################################################
+# Test that focus changes workspace correctly with 'focus_follows_mouse no'
+# See issue #5472.
+###############################################################################
+$pid = launch_with_config(<<EOT
+# i3 config file (v4)
+font font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+focus_follows_mouse no
+fake-outputs 1024x768+0+0,1024x768+1024+0
+EOT
+);
+
+my $ws1 = fresh_workspace(output => 0);
+$first = open_window;
+cmd 'layout tabbed';
+is($x->input_focus, $first->id, 'sanity check: window focused');
+open_window;
+
+my $ws2 = fresh_workspace(output => 1);
+ok(get_ws($ws2)->{focused}, 'sanity check: second workspace focused');
+
+# Decoration of top left window.
+$x->root->warp_pointer(3, 3);
+
+my @events = events_for( sub { scroll_up }, 'workspace');
+is($x->input_focus, $first->id, 'window focused');
+is(scalar @events, 1, 'Received 1 workspace event');
+is($events[0]->{change}, 'focus', 'Event has change = focus');
+is($events[0]->{current}->{name}, $ws1, 'new == ws1');
+is($events[0]->{old}->{name}, $ws2, 'old == ws2');
+
+exit_gracefully($pid);
+
done_testing;
diff --git a/testcases/t/298-ipc-misbehaving-connection.t b/testcases/t/298-ipc-misbehaving-connection.t
index d53ee92d..fe4fe523 100644
--- a/testcases/t/298-ipc-misbehaving-connection.t
+++ b/testcases/t/298-ipc-misbehaving-connection.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that i3 will not hang if a connected client stops reading from its
diff --git a/testcases/t/299-regress-scratchpad-focus.t b/testcases/t/299-regress-scratchpad-focus.t
index 504ecd32..2eb14972 100644
--- a/testcases/t/299-regress-scratchpad-focus.t
+++ b/testcases/t/299-regress-scratchpad-focus.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression test: verify that a scratchpad container that was open in another
diff --git a/testcases/t/300-restart-non-utf8.t b/testcases/t/300-restart-non-utf8.t
index 81b56583..50dbad59 100644
--- a/testcases/t/300-restart-non-utf8.t
+++ b/testcases/t/300-restart-non-utf8.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verify that i3 does not crash when restart is issued while a window with a
diff --git a/testcases/t/301-shape.t b/testcases/t/301-shape.t
index b18ac0ca..c9bf1681 100644
--- a/testcases/t/301-shape.t
+++ b/testcases/t/301-shape.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test shape support.
diff --git a/testcases/t/302-tree.t b/testcases/t/302-tree.t
index a2551a3e..8003bc67 100644
--- a/testcases/t/302-tree.t
+++ b/testcases/t/302-tree.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Contains various tests that use the cmp_tree subroutine.
diff --git a/testcases/t/303-regress-move-floating.t b/testcases/t/303-regress-move-floating.t
index 396e586f..f742bc16 100644
--- a/testcases/t/303-regress-move-floating.t
+++ b/testcases/t/303-regress-move-floating.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Regression: moving a container which is the only child of the only child of a
diff --git a/testcases/t/304-ipc-workspace-init.t b/testcases/t/304-ipc-workspace-init.t
index 4c181f7c..4b6136ea 100644
--- a/testcases/t/304-ipc-workspace-init.t
+++ b/testcases/t/304-ipc-workspace-init.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that the workspace init event is correctly sent.
diff --git a/testcases/t/305-restart-reply.t b/testcases/t/305-restart-reply.t
index 0493d4ff..03db3c3b 100644
--- a/testcases/t/305-restart-reply.t
+++ b/testcases/t/305-restart-reply.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verify that restart produces a reply.
diff --git a/testcases/t/306-move-to-parent.t b/testcases/t/306-move-to-parent.t
index 8610cff9..ae1257d7 100644
--- a/testcases/t/306-move-to-parent.t
+++ b/testcases/t/306-move-to-parent.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Make sure the trick used to move the container to its parent works.
diff --git a/testcases/t/307-focus-next-prev.t b/testcases/t/307-focus-next-prev.t
index 4f8a8ecd..618c170a 100644
--- a/testcases/t/307-focus-next-prev.t
+++ b/testcases/t/307-focus-next-prev.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test focus next|prev
diff --git a/testcases/t/308-focus_wrapping.t b/testcases/t/308-focus_wrapping.t
index 9fa5858c..18d426bb 100644
--- a/testcases/t/308-focus_wrapping.t
+++ b/testcases/t/308-focus_wrapping.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests focus_wrapping yes|no|force|workspace with cmp_tree
diff --git a/testcases/t/309-crash-move-parent.t b/testcases/t/309-crash-move-parent.t
index eb58251b..423af0f2 100644
--- a/testcases/t/309-crash-move-parent.t
+++ b/testcases/t/309-crash-move-parent.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that moving a container that is to be flattened does not crash i3
diff --git a/testcases/t/310-client-message-sticky.t b/testcases/t/310-client-message-sticky.t
index 0e7d8b7c..f815d6b1 100644
--- a/testcases/t/310-client-message-sticky.t
+++ b/testcases/t/310-client-message-sticky.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verify that _NET_WM_DESKTOP sticky requests do not conflict with dock
diff --git a/testcases/t/311-get-binding-modes.t b/testcases/t/311-get-binding-modes.t
index 3a00f695..1d77d43d 100644
--- a/testcases/t/311-get-binding-modes.t
+++ b/testcases/t/311-get-binding-modes.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies the GET_BINDING_MODE IPC command
diff --git a/testcases/t/312-regress-layout-default.t b/testcases/t/312-regress-layout-default.t
index b23cf50b..ade1bc4b 100644
--- a/testcases/t/312-regress-layout-default.t
+++ b/testcases/t/312-regress-layout-default.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies i3 does not crash when using layout default.
diff --git a/testcases/t/313-include.t b/testcases/t/313-include.t
index 9b8b0fab..dc89eb5c 100644
--- a/testcases/t/313-include.t
+++ b/testcases/t/313-include.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies the include directive.
diff --git a/testcases/t/314-window-icon-padding.t b/testcases/t/314-window-icon-padding.t
index 71cf5bd5..a1a9c07e 100755
--- a/testcases/t/314-window-icon-padding.t
+++ b/testcases/t/314-window-icon-padding.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies title_window_icon behavior.
diff --git a/testcases/t/315-all-criterion.t b/testcases/t/315-all-criterion.t
index f11410fd..11744cd9 100644
--- a/testcases/t/315-all-criterion.t
+++ b/testcases/t/315-all-criterion.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests all kinds of matching methods
diff --git a/testcases/t/315-long-commands.t b/testcases/t/315-long-commands.t
index 3db37dab..4b51d791 100644
--- a/testcases/t/315-long-commands.t
+++ b/testcases/t/315-long-commands.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that commands with more than 10 non-identified words doesn't works
diff --git a/testcases/t/316-drag-container.t b/testcases/t/316-drag-container.t
index 7e2b8494..4a217d46 100644
--- a/testcases/t/316-drag-container.t
+++ b/testcases/t/316-drag-container.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test dragging containers.
diff --git a/testcases/t/316-transient-for-loop.t b/testcases/t/316-transient-for-loop.t
index 336a8d8d..ceb2713d 100644
--- a/testcases/t/316-transient-for-loop.t
+++ b/testcases/t/316-transient-for-loop.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that i3 does not get stuck in an endless loop between two windows that
diff --git a/testcases/t/317-bar-config-font-fallback.t b/testcases/t/317-bar-config-font-fallback.t
new file mode 100644
index 00000000..020fd3ee
--- /dev/null
+++ b/testcases/t/317-bar-config-font-fallback.t
@@ -0,0 +1,42 @@
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • https://build.i3wm.org/docs/testsuite.html
+# (or docs/testsuite)
+#
+# • https://build.i3wm.org/docs/lib-i3test.html
+# (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • https://build.i3wm.org/docs/ipc.html
+# (or docs/ipc)
+#
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
+# (unless you are already familiar with Perl)
+#
+# Verifies that bar config blocks get the i3-wide font configured,
+# regardless of where the font is configured in the config file
+# (before or after the bar config blocks).
+# Ticket: #5031
+# Bug still in: 4.20-105-g4db383e4
+use i3test i3_config => <<'EOT';
+# i3 config file (v4)
+
+bar {
+ # no font directive here, no i3-wide font configured (yet)
+}
+
+# NOTE: iso99887 is invalid font specification, so it should always fallback
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso99887-9
+EOT
+
+my $i3 = i3(get_socket_path(0));
+my $bars = $i3->get_bar_config()->recv;
+
+my $bar_id = shift @$bars;
+my $bar_config = $i3->get_bar_config($bar_id)->recv;
+
+# This should fallback to 'fixed' due to nonexistent font set in config
+is($bar_config->{font}, 'fixed', 'font fallback ok');
+
+done_testing;
diff --git a/testcases/t/317-bar-config-font-order.t b/testcases/t/317-bar-config-font-order.t
index 3c1fdcdd..31bda2f5 100644
--- a/testcases/t/317-bar-config-font-order.t
+++ b/testcases/t/317-bar-config-font-order.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that bar config blocks get the i3-wide font configured,
@@ -34,6 +34,12 @@ my $bars = $i3->get_bar_config()->recv;
my $bar_id = shift @$bars;
my $bar_config = $i3->get_bar_config($bar_id)->recv;
-is($bar_config->{font}, 'fixed', 'font ok');
+
+# This should either load the font specified, or fallback to 'fixed'
+my %valid_fonts = map {; $_ => 1 } qw(
+ -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+ fixed
+);
+is($valid_fonts{ $bar_config->{font} }, 1, 'font ok');
done_testing;
diff --git a/testcases/t/317-bar-output-trailing-space.t b/testcases/t/317-bar-output-trailing-space.t
index 540d30c9..5f266230 100644
--- a/testcases/t/317-bar-output-trailing-space.t
+++ b/testcases/t/317-bar-output-trailing-space.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that any trailing whitespace in strings (including in
diff --git a/testcases/t/318-i3-dmenu-desktop.t b/testcases/t/318-i3-dmenu-desktop.t
index 2ad7f41b..9ccef925 100644
--- a/testcases/t/318-i3-dmenu-desktop.t
+++ b/testcases/t/318-i3-dmenu-desktop.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that i3-dmenu-desktop correctly parses Exec= lines in .desktop files
diff --git a/testcases/t/319-gaps.t b/testcases/t/319-gaps.t
index fa723dfc..fff01fb0 100644
--- a/testcases/t/319-gaps.t
+++ b/testcases/t/319-gaps.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Basic gaps functionality test
diff --git a/testcases/t/320-mouse-bindings.t b/testcases/t/320-mouse-bindings.t
new file mode 100644
index 00000000..b1e81228
--- /dev/null
+++ b/testcases/t/320-mouse-bindings.t
@@ -0,0 +1,89 @@
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • https://build.i3wm.org/docs/testsuite.html
+# (or docs/testsuite)
+#
+# • https://build.i3wm.org/docs/lib-i3test.html
+# (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • https://build.i3wm.org/docs/ipc.html
+# (or docs/ipc)
+#
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
+# (unless you are already familiar with Perl)
+#
+# Test button bindsyms
+use i3test i3_config => <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+focus_follows_mouse no
+
+for_window[class="mark_A"] mark A
+for_window[class="mark_B"] mark B
+for_window[class="mark_C"] mark C
+for_window[class="mark_D"] mark D
+
+bindsym button1 --whole-window [con_mark=A] focus
+bindsym button2 --whole-window [con_mark=B] focus
+
+bindsym button4 --whole-window [con_mark=B] focus
+mode "testmode" {
+ bindsym button4 --whole-window [con_mark=C] focus
+ bindsym button5 --whole-window [con_mark=D] focus
+}
+
+default_border pixel 0
+
+EOT
+use i3test::XTEST;
+
+sub button {
+ my ($button, $window, $msg) = @_;
+ xtest_button_press($button, 5, 5);
+ xtest_button_release($button, 5, 5);
+ xtest_sync_with_i3;
+
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+ is_focus($window, $msg);
+}
+
+sub is_focus {
+ my ($window, $msg) = @_;
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+ is($x->input_focus, $window->id, $msg);
+}
+
+# Leftmost window is focused on button presses that have no binding
+my $L = open_window;
+my $A = open_window(wm_class => 'mark_A');
+my $B = open_window(wm_class => 'mark_B');
+is_focus($B, 'sanity check');
+is_focus(open_window, 'sanity check, other window');
+
+button(1, $A, 'button 1 binding');
+button(1, $A, 'button 1 binding, again');
+button(2, $B, 'button 2 binding');
+button(1, $A, 'button 1 binding');
+button(3, $L, 'button 3, no binding');
+
+# Test modes, see #4539
+# Unfortunately, grabbing / ungrabbing doesn't seem to work correctly in xvfb
+# so we can't really test this.
+
+my $C = open_window(wm_class => 'mark_C');
+my $D = open_window(wm_class => 'mark_D');
+
+button(4, $B, 'button 4 binding outside mode');
+button(5, $L, 'button 5 no binding outside mode');
+
+cmd 'mode testmode';
+button(4, $C, 'button 4 binding inside mode');
+button(5, $D, 'button 5 binding inside mode');
+
+cmd 'mode default';
+button(4, $B, 'button 4 binding outside mode');
+button(5, $L, 'button 5 no binding outside mode');
+
+done_testing;
diff --git a/testcases/t/500-multi-monitor.t b/testcases/t/500-multi-monitor.t
index 8d2c6496..2f647247 100644
--- a/testcases/t/500-multi-monitor.t
+++ b/testcases/t/500-multi-monitor.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that the provided X-Server to the t/5??-*.t tests is actually providing
diff --git a/testcases/t/501-scratchpad.t b/testcases/t/501-scratchpad.t
index 3b7fa90c..52858718 100644
--- a/testcases/t/501-scratchpad.t
+++ b/testcases/t/501-scratchpad.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that scratchpad windows show up on the proper output.
diff --git a/testcases/t/502-focus-output.t b/testcases/t/502-focus-output.t
index 5b051de4..c13e7e14 100644
--- a/testcases/t/502-focus-output.t
+++ b/testcases/t/502-focus-output.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies the 'focus output' command works properly.
diff --git a/testcases/t/503-workspace.t b/testcases/t/503-workspace.t
index cb0ad92f..04ac8a59 100644
--- a/testcases/t/503-workspace.t
+++ b/testcases/t/503-workspace.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests whether 'workspace next_on_output' and the like work correctly.
diff --git a/testcases/t/504-move-workspace-to-output.t b/testcases/t/504-move-workspace-to-output.t
index 4ec33f66..f6b5e9f8 100644
--- a/testcases/t/504-move-workspace-to-output.t
+++ b/testcases/t/504-move-workspace-to-output.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests whether the 'move workspace <ws> to [output] <output>' command works
diff --git a/testcases/t/505-scratchpad-resolution.t b/testcases/t/505-scratchpad-resolution.t
index e72b4dfb..fc4758fa 100644
--- a/testcases/t/505-scratchpad-resolution.t
+++ b/testcases/t/505-scratchpad-resolution.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that scratchpad windows don’t move due to floating point caulcation
diff --git a/testcases/t/506-focus-right.t b/testcases/t/506-focus-right.t
index 2d8ed205..aa436b23 100644
--- a/testcases/t/506-focus-right.t
+++ b/testcases/t/506-focus-right.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that focus output right works with monitor setups that don’t line up
diff --git a/testcases/t/507-workspace-move-crash.t b/testcases/t/507-workspace-move-crash.t
index 7adbb6e2..a3141300 100644
--- a/testcases/t/507-workspace-move-crash.t
+++ b/testcases/t/507-workspace-move-crash.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests whether i3 crashes on cross-output moves with one workspace per output.
diff --git a/testcases/t/509-workspace_layout.t b/testcases/t/509-workspace_layout.t
index 40e7e881..2a4131d4 100644
--- a/testcases/t/509-workspace_layout.t
+++ b/testcases/t/509-workspace_layout.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests whether workspace_layout is properly set after startup.
diff --git a/testcases/t/510-focus-across-outputs.t b/testcases/t/510-focus-across-outputs.t
index 065437f0..621119bb 100644
--- a/testcases/t/510-focus-across-outputs.t
+++ b/testcases/t/510-focus-across-outputs.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that switching workspaces via 'focus $dir' never leaves a floating
diff --git a/testcases/t/511-scratchpad-configure-request.t b/testcases/t/511-scratchpad-configure-request.t
index 0a06c070..7dd76108 100644
--- a/testcases/t/511-scratchpad-configure-request.t
+++ b/testcases/t/511-scratchpad-configure-request.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that ConfigureRequests don’t make windows fall out of the scratchpad.
diff --git a/testcases/t/512-move-wraps.t b/testcases/t/512-move-wraps.t
index d346a176..8f2324b9 100644
--- a/testcases/t/512-move-wraps.t
+++ b/testcases/t/512-move-wraps.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that moving containers wraps across outputs.
diff --git a/testcases/t/513-move-workspace.t b/testcases/t/513-move-workspace.t
index db8890a9..f2ffbdf6 100644
--- a/testcases/t/513-move-workspace.t
+++ b/testcases/t/513-move-workspace.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests whether moving workspaces between outputs works correctly.
diff --git a/testcases/t/514-ipc-workspace-multi-monitor.t b/testcases/t/514-ipc-workspace-multi-monitor.t
index ac918fe3..c12e3046 100644
--- a/testcases/t/514-ipc-workspace-multi-monitor.t
+++ b/testcases/t/514-ipc-workspace-multi-monitor.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Ticket: #990
diff --git a/testcases/t/515-create-workspace.t b/testcases/t/515-create-workspace.t
index e90cf66a..2d10a4eb 100644
--- a/testcases/t/515-create-workspace.t
+++ b/testcases/t/515-create-workspace.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that new workspace names are taken from the config,
diff --git a/testcases/t/516-move.t b/testcases/t/516-move.t
index 3db8c4f0..29606c9e 100644
--- a/testcases/t/516-move.t
+++ b/testcases/t/516-move.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests if a simple 'move <direction>' command will move containers across outputs.
diff --git a/testcases/t/517-regress-move-direction-ipc.t b/testcases/t/517-regress-move-direction-ipc.t
index 2f7f2b27..5a1010e1 100644
--- a/testcases/t/517-regress-move-direction-ipc.t
+++ b/testcases/t/517-regress-move-direction-ipc.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Make sure the command `move <direction>` properly sends the workspace focus
diff --git a/testcases/t/518-interpret-workspace-numbers.t b/testcases/t/518-interpret-workspace-numbers.t
index c7ab8367..d51b708c 100644
--- a/testcases/t/518-interpret-workspace-numbers.t
+++ b/testcases/t/518-interpret-workspace-numbers.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that workspace assignment config directives for plain numbers will
diff --git a/testcases/t/519-mouse-warping.t b/testcases/t/519-mouse-warping.t
index 3cfb1ec2..193982fd 100644
--- a/testcases/t/519-mouse-warping.t
+++ b/testcases/t/519-mouse-warping.t
@@ -8,7 +8,7 @@
# • https://build.i3wm.org/docs/lib-i3test.html
# (alternatively: perldoc ./testcases/lib/i3test.pm)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
use i3test i3_config => <<EOT;
diff --git a/testcases/t/520-regress-focus-direction-floating.t b/testcases/t/520-regress-focus-direction-floating.t
index 74da7489..cec9c866 100644
--- a/testcases/t/520-regress-focus-direction-floating.t
+++ b/testcases/t/520-regress-focus-direction-floating.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Ensure that `focus [direction]` will focus an existing floating con when no
diff --git a/testcases/t/521-ewmh-desktop-viewport.t b/testcases/t/521-ewmh-desktop-viewport.t
index a4119367..fb050aac 100644
--- a/testcases/t/521-ewmh-desktop-viewport.t
+++ b/testcases/t/521-ewmh-desktop-viewport.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that the EWMH specified property _NET_DESKTOP_VIEWPORT is updated
diff --git a/testcases/t/522-rename-assigned-workspace.t b/testcases/t/522-rename-assigned-workspace.t
index 9897e4ee..a9e0d04c 100644
--- a/testcases/t/522-rename-assigned-workspace.t
+++ b/testcases/t/522-rename-assigned-workspace.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
#
diff --git a/testcases/t/523-move-position-center.t b/testcases/t/523-move-position-center.t
index cf4e5070..eda7c9cf 100644
--- a/testcases/t/523-move-position-center.t
+++ b/testcases/t/523-move-position-center.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies that 'move position center' moves floating cons to the center of
diff --git a/testcases/t/524-move.t b/testcases/t/524-move.t
index e880b18e..b9ae6098 100644
--- a/testcases/t/524-move.t
+++ b/testcases/t/524-move.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests the behaviour of 'move <direction>' when moving containers across
diff --git a/testcases/t/525-i3bar-mouse-bindings.t b/testcases/t/525-i3bar-mouse-bindings.t
index 3593ea0b..b8055746 100644
--- a/testcases/t/525-i3bar-mouse-bindings.t
+++ b/testcases/t/525-i3bar-mouse-bindings.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Ensures that mouse bindings on the i3bar work correctly.
diff --git a/testcases/t/526-reconfigure-dock.t b/testcases/t/526-reconfigure-dock.t
index 97e98a60..ad64e77f 100644
--- a/testcases/t/526-reconfigure-dock.t
+++ b/testcases/t/526-reconfigure-dock.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test reconfiguration of dock clients.
diff --git a/testcases/t/527-focus-fallback.t b/testcases/t/527-focus-fallback.t
index 531e1854..ca22fcab 100644
--- a/testcases/t/527-focus-fallback.t
+++ b/testcases/t/527-focus-fallback.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Ticket: #1378
diff --git a/testcases/t/528-workspace-next-prev-reversed.t b/testcases/t/528-workspace-next-prev-reversed.t
index 4f63e7fe..b58457b8 100644
--- a/testcases/t/528-workspace-next-prev-reversed.t
+++ b/testcases/t/528-workspace-next-prev-reversed.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests whether 'workspace next' works correctly.
diff --git a/testcases/t/529-net-wm-desktop.t b/testcases/t/529-net-wm-desktop.t
index f1da2980..d9827326 100644
--- a/testcases/t/529-net-wm-desktop.t
+++ b/testcases/t/529-net-wm-desktop.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests for _NET_WM_DESKTOP.
diff --git a/testcases/t/530-bug-2229.t b/testcases/t/530-bug-2229.t
index a177ee3c..15a405a3 100644
--- a/testcases/t/530-bug-2229.t
+++ b/testcases/t/530-bug-2229.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Ticket: #2229
diff --git a/testcases/t/531-fullscreen-on-given-output.t b/testcases/t/531-fullscreen-on-given-output.t
index 2459f06c..fec9952e 100644
--- a/testcases/t/531-fullscreen-on-given-output.t
+++ b/testcases/t/531-fullscreen-on-given-output.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that fullscreen windows appear on the output indicated by
diff --git a/testcases/t/532-xresources.t b/testcases/t/532-xresources.t
index 1ff48e51..7acd99e7 100644
--- a/testcases/t/532-xresources.t
+++ b/testcases/t/532-xresources.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests for using X resources in the config.
diff --git a/testcases/t/533-randr15.t b/testcases/t/533-randr15.t
index 51d1c9f6..9e8f2e8a 100644
--- a/testcases/t/533-randr15.t
+++ b/testcases/t/533-randr15.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# TODO: Description of this file.
diff --git a/testcases/t/534-dont-warp.t b/testcases/t/534-dont-warp.t
index 8c943208..02cc8f75 100644
--- a/testcases/t/534-dont-warp.t
+++ b/testcases/t/534-dont-warp.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Verifies i3 doesn’t warp when a new floating window is opened under the cursor
diff --git a/testcases/t/535-workspace-next-prev.t b/testcases/t/535-workspace-next-prev.t
index dc881b35..0020586e 100644
--- a/testcases/t/535-workspace-next-prev.t
+++ b/testcases/t/535-workspace-next-prev.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests whether 'workspace next' works correctly.
diff --git a/testcases/t/536-net-wm-desktop_mm.t b/testcases/t/536-net-wm-desktop_mm.t
index 3e4c9747..cc037c37 100644
--- a/testcases/t/536-net-wm-desktop_mm.t
+++ b/testcases/t/536-net-wm-desktop_mm.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests for _NET_WM_DESKTOP.
diff --git a/testcases/t/537-move-single-to-output.t b/testcases/t/537-move-single-to-output.t
index ab144897..8693043e 100644
--- a/testcases/t/537-move-single-to-output.t
+++ b/testcases/t/537-move-single-to-output.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that windows inside containers with a single child do not jump
diff --git a/testcases/t/538-i3bar-primary-output.t b/testcases/t/538-i3bar-primary-output.t
index 249d5777..fbb8d464 100644
--- a/testcases/t/538-i3bar-primary-output.t
+++ b/testcases/t/538-i3bar-primary-output.t
@@ -11,14 +11,16 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that i3bars configured to use the primary output do not have
# their output names canonicalized to something other than "primary".
# Ticket: #2948
+# Ticket: #5346
# Bug still in: 4.14-93-ga3a7d04a
-use i3test i3_config => <<EOT;
+use i3test i3_autostart => 0;
+my $config = <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
@@ -28,6 +30,7 @@ bar {
output primary
}
EOT
+my $pid = launch_with_config($config);
my $bars = i3->get_bar_config()->recv;
is(@$bars, 1, 'one bar configured');
@@ -36,5 +39,29 @@ my $bar_id = shift @$bars;
my $bar_config = i3->get_bar_config($bar_id)->recv;
is_deeply($bar_config->{outputs}, [ "primary" ], 'bar_config output is primary');
+exit_gracefully($pid);
+
+# Same but for "nonprimary"
+
+$config = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+fake-outputs 1024x768+0+0P,1024x768+0+0
+
+bar {
+ output nonprimary
+}
+EOT
+$pid = launch_with_config($config);
+
+$bars = i3->get_bar_config()->recv;
+is(@$bars, 1, 'one bar configured');
+
+$bar_id = shift @$bars;
+
+$bar_config = i3->get_bar_config($bar_id)->recv;
+is_deeply($bar_config->{outputs}, [ "nonprimary" ], 'bar_config output is nonprimary');
+exit_gracefully($pid);
done_testing;
diff --git a/testcases/t/539-disable_focus_wrapping.t b/testcases/t/539-disable_focus_wrapping.t
index 8d2e8472..9c08e5f1 100644
--- a/testcases/t/539-disable_focus_wrapping.t
+++ b/testcases/t/539-disable_focus_wrapping.t
@@ -11,7 +11,7 @@
# • http://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that focus does not wrap when focus_wrapping is disabled in
diff --git a/testcases/t/540-sigterm-cleanup.t b/testcases/t/540-sigterm-cleanup.t
index 5e5b9bf3..11e3cea7 100644
--- a/testcases/t/540-sigterm-cleanup.t
+++ b/testcases/t/540-sigterm-cleanup.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that the socket file is cleaned up properly after gracefully
diff --git a/testcases/t/541-resize-set-tiling.t b/testcases/t/541-resize-set-tiling.t
index 0298fecd..e5b9e99e 100644
--- a/testcases/t/541-resize-set-tiling.t
+++ b/testcases/t/541-resize-set-tiling.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests resizing tiling containers
diff --git a/testcases/t/542-layout-restore-remanage.t b/testcases/t/542-layout-restore-remanage.t
index 82ec84d0..10015065 100644
--- a/testcases/t/542-layout-restore-remanage.t
+++ b/testcases/t/542-layout-restore-remanage.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests that swallowing still works after a window gets managed and its property
diff --git a/testcases/t/543-move-workspace-to-multiple-outputs.t b/testcases/t/543-move-workspace-to-multiple-outputs.t
index 7b0f8c2b..46b90e22 100644
--- a/testcases/t/543-move-workspace-to-multiple-outputs.t
+++ b/testcases/t/543-move-workspace-to-multiple-outputs.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test using multiple outputs for 'move workspace to output …'
diff --git a/testcases/t/544-focus-multiple-outputs.t b/testcases/t/544-focus-multiple-outputs.t
index 2d09dfba..e91226b6 100644
--- a/testcases/t/544-focus-multiple-outputs.t
+++ b/testcases/t/544-focus-multiple-outputs.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test using multiple output for 'focus output …'
diff --git a/testcases/t/546-empty-bindcommand.t b/testcases/t/546-empty-bindcommand.t
index dae26293..27296e76 100644
--- a/testcases/t/546-empty-bindcommand.t
+++ b/testcases/t/546-empty-bindcommand.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that i3 doesn't crash if the binding command is empty.
diff --git a/testcases/t/547-explicit-mode-default.t b/testcases/t/547-explicit-mode-default.t
index a966c7f6..7f055ec3 100644
--- a/testcases/t/547-explicit-mode-default.t
+++ b/testcases/t/547-explicit-mode-default.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that explicitly defined default mode doesn't cause segfault.
diff --git a/testcases/t/547-nested-variables.t b/testcases/t/547-nested-variables.t
index 990a42e9..ee2428a0 100644
--- a/testcases/t/547-nested-variables.t
+++ b/testcases/t/547-nested-variables.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that i3 doesn't crash if the config contains nested variables.
diff --git a/testcases/t/548-motif-hints.t b/testcases/t/548-motif-hints.t
index 9fe890cf..7174af82 100644
--- a/testcases/t/548-motif-hints.t
+++ b/testcases/t/548-motif-hints.t
@@ -11,17 +11,19 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test that setting and unsetting motif hints updates window decorations
# accordingly, respecting user configuration.
# Ticket: #3678
# Ticket: #5149
+# Ticket: #5438
# Bug still in: 4.21
+use File::Temp qw(tempfile);
use List::Util qw(first);
-use i3test i3_autostart => 0;
use X11::XCB qw(:all);
+use i3test i3_autostart => 0;
my $use_floating;
sub subtest_with_config {
@@ -71,10 +73,12 @@ sub _change_motif_property {
}
sub open_window_with_motifs {
- my $value = shift;
+ my ($value, %args) = @_;
+
+ $args{kill_all} //= 1;
# we don't need other windows anymore, simplifies get_border_style
- kill_all_windows;
+ kill_all_windows if $args{kill_all};
my $open = \&open_window;
if ($use_floating) {
@@ -82,6 +86,7 @@ sub open_window_with_motifs {
}
my $window = $open->(
+ %args,
before_map => sub {
my ($window) = @_;
_change_motif_property($window, $value);
@@ -117,7 +122,7 @@ sub is_border_style {
}
local $Test::Builder::Level = $Test::Builder::Level + 1;
- is(get_border_style($window), $expected, $msg);
+ is(get_border_style, $expected, $msg);
}
###############################################################################
@@ -202,4 +207,44 @@ change_motif_property(1);
is_border_style('pixel', 'because of user maximum=pixel');
};
+###############################################################################
+# Test with append_layout
+# See #5438
+###############################################################################
+
+$use_floating = 0;
+
+my $config = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+EOT
+my $pid = launch_with_config($config);
+
+my ($fh, $filename) = tempfile(UNLINK => 1);
+print $fh <<'EOT';
+{
+ "nodes": [
+ {
+ "border": "none",
+ "swallows": [
+ {
+ "class": "^Special$"
+ }
+ ],
+ "type": "con"
+ }
+ ],
+ "type": "con"
+}
+EOT
+$fh->flush;
+cmd "append_layout $filename";
+
+# can't use get_border_style because append_layout creates a parent container
+is(@{get_ws(focused_ws)->{nodes}}[0]->{nodes}[0]->{border}, 'none', 'placeholder has border style none');
+
+$window = open_window_with_motifs(1, wm_class => 'Special', instance => 'Special', kill_all => 0);
+is(@{get_ws(focused_ws)->{nodes}}[0]->{nodes}[0]->{border}, 'none', 'window has border style none');
+
done_testing;
diff --git a/testcases/t/549-focus-wrapping-gaps.t b/testcases/t/549-focus-wrapping-gaps.t
index 135bea8c..f84e7326 100644
--- a/testcases/t/549-focus-wrapping-gaps.t
+++ b/testcases/t/549-focus-wrapping-gaps.t
@@ -11,7 +11,7 @@
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# • https://i3wm.org/downloads/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Ensure focus wrapping works with negative gaps
diff --git a/travis/push-balto.sh b/travis/push-balto.sh
index ffa5ee15..4cd8bb1a 100755
--- a/travis/push-balto.sh
+++ b/travis/push-balto.sh
@@ -2,7 +2,7 @@
set -e
-for fn in distbuild/deb/debian-amd64/*.deb distbuild/deb/debian-i386/*.deb
+for fn in distbuild/deb/debian-amd64/*.deb
do
echo "pushing $fn to balto"
curl \
@@ -12,7 +12,7 @@ do
https://i3.baltorepo.com/i3/i3-autobuild/upload/
done
-for fn in distbuild/deb/ubuntu-amd64/*.deb distbuild/deb/ubuntu-i386/*.deb
+for fn in distbuild/deb/ubuntu-amd64/*.deb
do
echo "pushing $fn to balto"
curl \
diff --git a/travis/skip-pkg.sh b/travis/skip-pkg.sh
deleted file mode 100755
index 0ca1d749..00000000
--- a/travis/skip-pkg.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-# Returns true if Debian/Ubuntu packages should be skipped because this CI run
-# was triggered by a pull request.
-
-# Verify BALTO_TOKEN is present (only set on github.com/i3/i3),
-# otherwise the CI run was triggered by a pull request.
-# Verify CC=gcc so that we only build packages once for each commit,
-# not twice (with gcc and clang).
-if [ ! -z "$BALTO_TOKEN" ] && [ "$CC" = "gcc" ]
-then
- exit 1
-fi
-
-exit 0
diff --git a/travis/travis-base-386.Dockerfile b/travis/travis-base-386.Dockerfile
deleted file mode 100644
index 8996e029..00000000
--- a/travis/travis-base-386.Dockerfile
+++ /dev/null
@@ -1,33 +0,0 @@
-# vim:ft=Dockerfile
-# Same as travis-base.Dockerfile, but without the test suite dependencies since
-# we only build Debian packages on i386, we don’t run the tests.
-FROM i386/debian:sid
-
-RUN echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup
-# Paper over occasional network flakiness of some mirrors.
-RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry
-
-# NOTE: I tried exclusively using gce_debian_mirror.storage.googleapis.com
-# instead of httpredir.debian.org, but the results (Fetched 123 MB in 36s (3357
-# kB/s)) are not any better than httpredir.debian.org (Fetched 123 MB in 34s
-# (3608 kB/s)). Hence, let’s stick with httpredir.debian.org (default) for now.
-
-# Install mk-build-deps (for installing the i3 build dependencies),
-# lintian (for checking spelling errors),
-RUN linux32 apt-get update && \
- DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
- dpkg-dev devscripts git equivs \
- build-essential clang \
- lintian && \
- rm -rf /var/lib/apt/lists/*
-
-# Install i3 build dependencies.
-COPY debian/control /usr/src/i3-debian-packaging/control
-RUN linux32 apt-get update && \
- DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \
- rm -rf /var/lib/apt/lists/*
-
-# The user outside of Docker (GitHub Actions CI runner) and inside of Docker
-# (root) are different, and newer versions of git error out in that scenario.
-# To fix this, explicitly configure /usr/src/i3 as a safe directory:
-RUN git config --global --add safe.directory /usr/src/i3
diff --git a/travis/travis-base-ubuntu-386.Dockerfile b/travis/travis-base-ubuntu-386.Dockerfile
deleted file mode 100644
index 4a41fe3e..00000000
--- a/travis/travis-base-ubuntu-386.Dockerfile
+++ /dev/null
@@ -1,33 +0,0 @@
-# vim:ft=Dockerfile
-# Same as travis-base.Dockerfile, but without the test suite dependencies since
-# we only build Debian packages on Ubuntu i386, we don’t run the tests.
-FROM i386/ubuntu:bionic
-
-RUN echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup
-# Paper over occasional network flakiness of some mirrors.
-RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry
-
-# NOTE: I tried exclusively using gce_debian_mirror.storage.googleapis.com
-# instead of httpredir.debian.org, but the results (Fetched 123 MB in 36s (3357
-# kB/s)) are not any better than httpredir.debian.org (Fetched 123 MB in 34s
-# (3608 kB/s)). Hence, let’s stick with httpredir.debian.org (default) for now.
-
-# Install mk-build-deps (for installing the i3 build dependencies),
-# lintian (for checking spelling errors),
-RUN linux32 apt-get update && \
- DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
- dpkg-dev devscripts git equivs \
- build-essential clang \
- lintian && \
- rm -rf /var/lib/apt/lists/*
-
-# Install i3 build dependencies.
-COPY debian/control /usr/src/i3-debian-packaging/control
-RUN linux32 apt-get update && \
- DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \
- rm -rf /var/lib/apt/lists/*
-
-# The user outside of Docker (GitHub Actions CI runner) and inside of Docker
-# (root) are different, and newer versions of git error out in that scenario.
-# To fix this, explicitly configure /usr/src/i3 as a safe directory:
-RUN git config --global --add safe.directory /usr/src/i3
diff --git a/travis/travis-base-ubuntu.Dockerfile b/travis/travis-base-ubuntu.Dockerfile
index 8523b92c..253e6382 100644
--- a/travis/travis-base-ubuntu.Dockerfile
+++ b/travis/travis-base-ubuntu.Dockerfile
@@ -1,7 +1,7 @@
# vim:ft=Dockerfile
# Same as travis-base.Dockerfile, but without the test suite dependencies since
# we only build Debian packages on Ubuntu, we don’t run the tests.
-FROM ubuntu:bionic
+FROM ubuntu:jammy
RUN echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup
# Paper over occasional network flakiness of some mirrors.
diff --git a/travis/travis-base.Dockerfile b/travis/travis-base.Dockerfile
index 52ae0656..3733a9b8 100644
--- a/travis/travis-base.Dockerfile
+++ b/travis/travis-base.Dockerfile
@@ -16,7 +16,7 @@ RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
dpkg-dev devscripts git equivs \
- build-essential clang \
+ build-essential clang libclang-rt-dev \
lintian \
libmodule-install-perl libanyevent-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-perl libinline-c-perl libxml-simple-perl libmouse-perl libmousex-nativetraits-perl libextutils-depends-perl perl libtest-deep-perl libtest-exception-perl libxml-parser-perl libtest-simple-perl libtest-fatal-perl libdata-dump-perl libtest-differences-perl libxml-tokeparser-perl libipc-run-perl libxcb-xtest0-dev libx11-xcb-perl libjson-xs-perl x11-xserver-utils && \
rm -rf /var/lib/apt/lists/*