I was naively passing the workspace to runLayout without filtering out
floating windows from its stack, like XMonad.Operations.windows does.
The fact that 'windows' does this filtering explains how layouts like
those in LimitWindows continue to behave correctly in the presence of
floating windows.
This fixes some incorrect behavior where the presence of a floating
windows caused visible windows (other than the focused one) to be
included in the surfaceRing.
Verify that rotateSome behaves as expected and never fails to pattern
match.
In order to run these tests, I ran a custom script:
scripts/run-tests.sh tests/RotateSome.hs
where the script contained the following:
set -eu
toplevel=$(git rev-parse --show-toplevel)
XMONAD="${XMONAD:-$toplevel/../xmonad}"
main=$(realpath -e "$1")
instances_target="$XMONAD/tests/Instances.hs"
instances_symlink="$toplevel/tests/Instances.hs"
properties_target="$XMONAD/tests/Properties"
properties_symlink="$toplevel/tests/Properties"
utils_target="$XMONAD/tests/Utils.hs"
utils_symlink="$toplevel/tests/Utils.hs"
trap "
rm '$instances_symlink' '$utils_symlink' '$properties_symlink' || true
" EXIT INT QUIT TERM
ln -s "$instances_target" "$instances_symlink"
ln -s "$properties_target" "$properties_symlink"
ln -s "$utils_target" "$utils_symlink"
runghc -DTESTING \
-i"$toplevel" \
-i"$toplevel/tests" \
"$main"
This module provides a pure function, 'rotateSome', as well as a pair of
X actions that use it to rotate unshown windows through the focused
stack position while leaving other windows in place. I find this useful
in combination with layouts such as LimitWindows, which determine window
visibility based on stack position.
Provide boring-aware versions of the 'siftUp' and 'siftDown' functions.
Since these actions never affect the position of boring windows, they
work well with layouts that decide which windows are visible/hidden
based on stack position, such as LimitWindows.
Provide swap-like functions that handle the wrapping case by exchanging
the windows at either end of the stack rather than rotating the stack.
https://github.com/xmonad/xmonad/issues/234
The effect is the same, but this seems to express the intent more
clearly, and it will make it easier to factor out the shared behavior
with skipBoringSwapUp.
Provide boring-aware versions of 'swapUp' and 'swapDown'.
Note that 'iterate f x' produces a list whose zeroth element is
'x' prior to any application of 'f'. The 'focusUp' and 'focusDown'
operations reject this iteration by checking in the filter predicate
that the focus actually changed:
filter ((`notElem` W.focus st:bs) . W.focus)
We can't do that for swaps, since our focus never changes, so we drop
the zeroth iteration prior to any predicate-based filtering.
The filter predicate checks whether the window immediately below the
our focus is boring. If so, we've performed an uninteresting upwards
swap and should continue swapping until we either swap past a window
that is not boring or wrap around the top of the stack.
It's particularly important that we accept the wrapping case regardless
of any boring neighbor, otherwise we risk missing a legitimate
non-boring swap. Consider, for example, the following stack:
focus: A
up: []
down: [B, boringC]
A swapUp yields:
focus: A
up: [boringC, B]
down: []
This should be considered non-boring, since the non-boring windows
swapped order: A B -> B A. If we were to reject it, we'd swap A up past
boringC and up again past B, putting us back where we started.
Put another way, if our focus was at the top of the stack, then all
other windows were necessarily below it. We want a swapUp to place our
focus below the lowest non-boring window. A wrap around to the bottom of
the stack guarantees that is the case.
Some users like to include type signatures in their configuration. The
Minimize type constructor was not exported, making it impossible to
write a type signature when using minimize.
With this change, a user can write an xmonad.hs like:
import XMonad
import XMonad.Layout.Minimize (Minimize, minimize)
import XMonad.Layout.LayoutModifier
myLayout :: ModifiedLayout
Minimize
(Choose Tall (Choose (Mirror Tall) Full))
Window
myLayout = minimize $ layoutHook def
main :: IO ()
main = xmonad def { layoutHook = myLayout }