Entirely unnecessary for the current version of `cycleWindowSets`, but
if anyone ever wants to use `greedyView`, this shows that it's not at
all complicated to adapt `unView` to that.
To make this more "obviously correct", make it resemble the `view`
implementation, just do the exact reverse. Now the only complex bit is
the "undelete" operation.
This also fixes another issue: state was only preserved in the focused
workspace, but it may have changed in another visible workspace as well.
The property test is updated to test this.
The way that workspace cycling is implemented right now—by generating
new windowsets where the things we want happen to be true and then
replacing the old windowsets—is not safe, as workspaces and layouts may
carry state with them. That state will get lost in translation when
windowsets are simply replaced.
As an example, a conflict occurs when using `X.L.ShowWName.showWName` in
one's layoutHook. When cycling through workspaces via, e.g.,
`cycleRecentWS` the flashed workspace tag will not disappear, as the
necessary state to control this isn't present in the new windowset.
Instead, what we want to do is to keep the "current" windowset alive and
actually switch to the requested workspaces. This mostly works without
much trouble, the only hard part is maintaining the invariant that
previewed workspaces don't count towards the history of recently-viewed
workspaces. This is done by remembering the tag-order of the original
windowset and then restoring that at the end.
This is a breaking change, insofar as it changes the type signatures of
the exported functions `recentWS`, `cycleWindowSets`, and
`toggleWindowSets` to return a list of `WorkspaceId`s instead of a list
of `WindowSet`s.
Fixes: https://github.com/xmonad/xmonad-contrib/issues/504