X.A.CycleRecentWS: Simplify/fix unView

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.
This commit is contained in:
Tomas Janousek 2021-05-14 00:35:30 +01:00 committed by slotThe
parent 24786c6d04
commit 12b30c393c
2 changed files with 25 additions and 32 deletions

View File

@ -38,8 +38,7 @@ import XMonad hiding (workspaces)
import XMonad.StackSet hiding (filter) import XMonad.StackSet hiding (filter)
import Control.Arrow ((&&&)) import Control.Arrow ((&&&))
import Data.List (find) import Data.Function (on)
import Data.Maybe (fromJust)
-- $usage -- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file: -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file:
@ -140,38 +139,29 @@ cycleWindowSets genOptions mods keyNext keyPrev = do
-- new 'WindowSet' may have accumulated. -- new 'WindowSet' may have accumulated.
unView :: forall i l a s sd. Eq i unView :: forall i l a s sd. Eq i
=> StackSet i l a s sd -> StackSet i l a s sd -> StackSet i l a s sd => StackSet i l a s sd -> StackSet i l a s sd -> StackSet i l a s sd
unView origW w unView w0 w
| -- The focused screen changed; the old focus is on a visible screen | currentTag w0 == currentTag w = w
newFocT `elem` visT =
w { current = (current origW){ workspace = findFoc (workspace <$> visible w) } | v1 : vs <- visible w
, visible = zipWith (\v ws -> v{ workspace = ws }) vis (updateNewFoc visW) , currentTag w0 == (tag . workspace) v1
} = w { current = v1
| -- The focused screen didn't change; the old focus is hidden , visible = insertAt (commonPrefixV (visible w0) vs) (current w) vs }
newFocT `elem` hidT =
w { current = (current origW){ workspace = findFoc (hidden w) } | h1 : hs <- hidden w
, hidden = updateNewFoc hid , currentTag w0 == tag h1
} = w { current = (current w){ workspace = h1 }
, hidden = insertAt (commonPrefixH (hidden w0) hs) (workspace (current w)) hs }
| otherwise = w | otherwise = w
where where
-- Foci, old and new commonPrefixV = commonPrefix `on` fmap (tag . workspace)
focT = tag . workspace . current $ origW commonPrefixH = commonPrefix `on` fmap tag
(newFoc, newFocT) = id &&& tag $ workspace (current w)
-- Workspaces in the _original_ windowset insertAt :: Int -> x -> [x] -> [x]
(hid, hidT) = id &&& map tag $ hidden origW insertAt n x xs = let (l, r) = splitAt n xs in l ++ [x] ++ r
(vis, (visW, visT)) = id &&& map workspace &&& map (tag . workspace)
$ visible origW
-- | Given a list of new workspaces that contain the old focus, commonPrefix :: Eq x => [x] -> [x] -> Int
-- return that workspace. commonPrefix a b = length $ takeWhile id $ zipWith (==) a b
findFoc :: [Workspace i l a] -> Workspace i l a
findFoc ws = fromJust $ find ((== focT) . tag) ws
-- | Given a list of old workspaces that contain the new focus,
-- update the state of the focus.
updateNewFoc :: [Workspace i l a] -> [Workspace i l a]
updateNewFoc ws = before ++ newFoc : after
where (before, after) = drop 1 <$> break ((== newFocT) . tag) ws
-- | Given some function that generates a list of workspaces from a -- | Given some function that generates a list of workspaces from a
-- given 'WindowSet', switch to the first generated workspace. -- given 'WindowSet', switch to the first generated workspace.

View File

@ -6,7 +6,7 @@ import Test.Hspec.QuickCheck
import Test.QuickCheck import Test.QuickCheck
import XMonad.Actions.CycleRecentWS (unView) import XMonad.Actions.CycleRecentWS (unView)
import XMonad.StackSet (view) import XMonad.StackSet (view, mapLayout)
import Instances import Instances
import Utils (tags) import Utils (tags)
@ -17,4 +17,7 @@ spec = do
prop_unView :: T -> Property prop_unView :: T -> Property
prop_unView ss = conjoin prop_unView ss = conjoin
[ counterexample (show t) (unView ss (view t ss) === ss) | t <- tags ss ] [ counterexample (show t) (unView ss (state (view t ss)) === state ss)
| t <- tags ss ]
where
state = mapLayout succ