    {-# LANGUAGE PatternGuards #-}
    {-# LANGUAGE RecordWildCards #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Actions.CopyWindow
    -- Description :  Duplicate a window on multiple workspaces.
    -- Copyright   :  (c) David Roundy <droundy@darcs.net>, Ivan Veselov <veselov@gmail.com>, Lanny Ripple <lan3ny@gmail.com>
    -- License     :  BSD3-style (see LICENSE)
    --
    -- Maintainer  :  ???
    -- Stability   :  unstable
    -- Portability :  unportable
    --
    -- Provides bindings to duplicate a window on multiple workspaces,
    -- providing dwm-like tagging functionality.
    --
    -----------------------------------------------------------------------------

    module XMonad.Actions.CopyWindow (
                                     -- * Usage
                                     -- $usage
                                     copy, copyToAll, copyWindow, runOrCopy
                                     , killAllOtherCopies, kill1, taggedWindows, copiesOfOn
                                     -- * Highlight workspaces containing copies in logHook
                                     -- $logHook
                                     , wsContainingCopies, copiesPP
                                    ) where

    import XMonad
    import XMonad.Prelude
    import Control.Arrow ((&&&))
    import qualified Data.List as L

    import XMonad.Actions.WindowGo
    import XMonad.Hooks.StatusBar.PP (PP(..), WS(..), isHidden)
    import qualified XMonad.StackSet as W

    -- $usage
    --
    -- You can use this module with the following in your @xmonad.hs@ file:
    --
    -- > import XMonad.Actions.CopyWindow
    --
    -- Then add something like this to your keybindings:
    --
    -- > -- mod-[1..9] @@ Switch to workspace N
    -- > -- mod-shift-[1..9] @@ Move client to workspace N
    -- > -- mod-control-shift-[1..9] @@ Copy client to workspace N
    -- > [((m .|. modm, k), windows $ f i)
    -- >     | (i, k) <- zip (workspaces x) [xK_1 ..]
    -- >     , (f, m) <- [(W.view, 0), (W.shift, shiftMask), (copy, shiftMask .|. controlMask)]]
    --
    -- To use the above key bindings you need also to import
    -- "XMonad.StackSet":
    --
    -- > import qualified XMonad.StackSet as W
    --
    -- You may also wish to redefine the binding to kill a window so it only
    -- removes it from the current workspace, if it's present elsewhere:
    --
    -- >  , ((modm .|. shiftMask, xK_c     ), kill1) -- @@ Close the focused window
    --
    -- Instead of copying a window from one workspace to another maybe you don't
    -- want to have to remember where you placed it.  For that consider:
    --
    -- >  , ((modm, xK_b    ), runOrCopy "firefox" (className =? "Firefox")) -- @@ run or copy firefox
    --
    -- Another possibility which this extension provides is 'making window
    -- always visible' (i.e. always on current workspace), similar to corresponding
    -- metacity functionality. This behaviour is emulated through copying given
    -- window to all the workspaces and then removing it when it's unneeded on
    -- all workspaces any more.
    --
    -- Here is the example of keybindings which provide these actions:
    --
    -- >  , ((modm, xK_v ), windows copyToAll) -- @@ Make focused window always visible
    -- >  , ((modm .|. shiftMask, xK_v ),  killAllOtherCopies) -- @@ Toggle window state back
    --
    -- For detailed instructions on editing your key bindings, see
    -- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.

    -- $logHook
    --
    -- To distinguish workspaces containing copies of the focused window, use 'copiesPP'.
    -- 'copiesPP' takes a pretty printer and makes it aware of copies of the focused window.
    -- It can be applied when creating a 'XMonad.Hooks.StatusBar.StatusBarConfig'.
    --
    -- A sample config looks like this:
    --
    -- > mySB = statusBarProp "xmobar" (copiesPP (pad . xmobarColor "red" "black") xmobarPP)
    -- > main = xmonad $ withEasySB mySB defToggleStrutsKey def

    -- | Take a pretty printer and make it aware of copies by using the provided function
    -- to show hidden workspaces that contain copies of the focused window.
    copiesPP :: (WorkspaceId -> String) -> PP -> X PP
    copiesPP :: (WorkspaceId -> WorkspaceId) -> PP -> X PP
    copiesPP WorkspaceId -> WorkspaceId
    wtoS PP
    pp = do
        [WorkspaceId]
    copies <- X [WorkspaceId]
    wsContainingCopies
        let check :: WS -> Bool
    check WS{[Window]
    WindowSpace
    WindowSet
    PP
    wsUrgents :: [Window]
    wsWindowSet :: WindowSet
    wsWS :: WindowSpace
    wsPP :: PP
    wsUrgents :: WS -> [Window]
    wsWindowSet :: WS -> WindowSet
    wsWS :: WS -> WindowSpace
    wsPP :: WS -> PP
    ..} = WindowSpace -> WorkspaceId
    forall i l a. Workspace i l a -> i
    W.tag WindowSpace
    wsWS WorkspaceId -> [WorkspaceId] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [WorkspaceId]
    copies
        let printer :: ReaderT WS Maybe (WorkspaceId -> WorkspaceId)
    printer = ((WS -> Bool) -> ReaderT WS Maybe Bool
    forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
    asks (WS -> Bool
    isHidden (WS -> Bool) -> (WS -> Bool) -> WS -> Bool
    forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
    <&&> WS -> Bool
    check) ReaderT WS Maybe Bool
    -> (Bool -> ReaderT WS Maybe ()) -> ReaderT WS Maybe ()
    forall a b.
    ReaderT WS Maybe a
    -> (a -> ReaderT WS Maybe b) -> ReaderT WS Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Bool -> ReaderT WS Maybe ()
    forall (f :: * -> *). Alternative f => Bool -> f ()
    guard) ReaderT WS Maybe ()
    -> (WorkspaceId -> WorkspaceId)
    -> ReaderT WS Maybe (WorkspaceId -> WorkspaceId)
    forall (f :: * -> *) a b. Functor f => f a -> b -> f b
    $> WorkspaceId -> WorkspaceId
    wtoS
        PP -> X PP
    forall a. a -> X a
    forall (m :: * -> *) a. Monad m => a -> m a
    return PP
    pp{ ppPrinters = printer <|> ppPrinters pp }

    -- | Copy the focused window to a workspace.
    copy :: (Eq s, Eq i, Eq a) => i -> W.StackSet i l a s sd -> W.StackSet i l a s sd
    copy :: forall s i a l sd.
    (Eq s, Eq i, Eq a) =>
    i -> StackSet i l a s sd -> StackSet i l a s sd
    copy i
    n StackSet i l a s sd
    s | Just a
    w <- StackSet i l a s sd -> Maybe a
    forall i l a s sd. StackSet i l a s sd -> Maybe a
    W.peek StackSet i l a s sd
    s = a -> i -> StackSet i l a s sd -> StackSet i l a s sd
    forall a i s l sd.
    (Eq a, Eq i, Eq s) =>
    a -> i -> StackSet i l a s sd -> StackSet i l a s sd
    copyWindow a
    w i
    n StackSet i l a s sd
    s
             | Bool
    otherwise = StackSet i l a s sd
    s

    -- | Copy the focused window to all workspaces.
    copyToAll :: (Eq s, Eq i, Eq a) => W.StackSet i l a s sd -> W.StackSet i l a s sd
    copyToAll :: forall s i a l sd.
    (Eq s, Eq i, Eq a) =>
    StackSet i l a s sd -> StackSet i l a s sd
    copyToAll StackSet i l a s sd
    s = (Workspace i l a -> StackSet i l a s sd -> StackSet i l a s sd)
    -> StackSet i l a s sd -> [Workspace i l a] -> StackSet i l a s sd
    forall a b. (a -> b -> b) -> b -> [a] -> b
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr (i -> StackSet i l a s sd -> StackSet i l a s sd
    forall s i a l sd.
    (Eq s, Eq i, Eq a) =>
    i -> StackSet i l a s sd -> StackSet i l a s sd
    copy (i -> StackSet i l a s sd -> StackSet i l a s sd)
    -> (Workspace i l a -> i)
    -> Workspace i l a
    -> StackSet i l a s sd
    -> StackSet i l a s sd
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Workspace i l a -> i
    forall i l a. Workspace i l a -> i
    W.tag) StackSet i l a s sd
    s (StackSet i l a s sd -> [Workspace i l a]
    forall i l a s sd. StackSet i l a s sd -> [Workspace i l a]
    W.workspaces StackSet i l a s sd
    s)

    -- | Copy an arbitrary window to a workspace.
    copyWindow :: (Eq a, Eq i, Eq s) => a -> i -> W.StackSet i l a s sd -> W.StackSet i l a s sd
    copyWindow :: forall a i s l sd.
    (Eq a, Eq i, Eq s) =>
    a -> i -> StackSet i l a s sd -> StackSet i l a s sd
    copyWindow a
    w i
    n = StackSet i l a s sd -> StackSet i l a s sd
    forall {s} {l} {sd}.
    Eq s =>
    StackSet i l a s sd -> StackSet i l a s sd
    copy'
        where copy' :: StackSet i l a s sd -> StackSet i l a s sd
    copy' StackSet i l a s sd
    s = if i
    n i -> StackSet i l a s sd -> Bool
    forall i l a s sd. Eq i => i -> StackSet i l a s sd -> Bool
    `W.tagMember` StackSet i l a s sd
    s
                        then i -> StackSet i l a s sd -> StackSet i l a s sd
    forall s i l a sd.
    (Eq s, Eq i) =>
    i -> StackSet i l a s sd -> StackSet i l a s sd
    W.view (StackSet i l a s sd -> i
    forall i l a s sd. StackSet i l a s sd -> i
    W.currentTag StackSet i l a s sd
    s) (StackSet i l a s sd -> StackSet i l a s sd)
    -> StackSet i l a s sd -> StackSet i l a s sd
    forall a b. (a -> b) -> a -> b
    $ a -> StackSet i l a s sd -> StackSet i l a s sd
    forall {a} {i} {l} {s} {sd}.
    Eq a =>
    a -> StackSet i l a s sd -> StackSet i l a s sd
    insertUp' a
    w (StackSet i l a s sd -> StackSet i l a s sd)
    -> StackSet i l a s sd -> StackSet i l a s sd
    forall a b. (a -> b) -> a -> b
    $ i -> StackSet i l a s sd -> StackSet i l a s sd
    forall s i l a sd.
    (Eq s, Eq i) =>
    i -> StackSet i l a s sd -> StackSet i l a s sd
    W.view i
    n StackSet i l a s sd
    s
                        else StackSet i l a s sd
    s
              insertUp' :: a -> StackSet i l a s sd -> StackSet i l a s sd
    insertUp' a
    a = Maybe (Stack a)
    -> (Stack a -> Maybe (Stack a))
    -> StackSet i l a s sd
    -> StackSet i l a s sd
    forall a i l s sd.
    Maybe (Stack a)
    -> (Stack a -> Maybe (Stack a))
    -> StackSet i l a s sd
    -> StackSet i l a s sd
    W.modify (Stack a -> Maybe (Stack a)
    forall a. a -> Maybe a
    Just (Stack a -> Maybe (Stack a)) -> Stack a -> Maybe (Stack a)
    forall a b. (a -> b) -> a -> b
    $ a -> [a] -> [a] -> Stack a
    forall a. a -> [a] -> [a] -> Stack a
    W.Stack a
    a [] [])
                              (\(W.Stack a
    t [a]
    l [a]
    r) -> if a
    a a -> [a] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` a
    ta -> [a] -> [a]
    forall a. a -> [a] -> [a]
    :[a]
    l[a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++[a]
    r
                                                 then Stack a -> Maybe (Stack a)
    forall a. a -> Maybe a
    Just (Stack a -> Maybe (Stack a)) -> Stack a -> Maybe (Stack a)
    forall a b. (a -> b) -> a -> b
    $ a -> [a] -> [a] -> Stack a
    forall a. a -> [a] -> [a] -> Stack a
    W.Stack a
    t [a]
    l [a]
    r
                                                 else Stack a -> Maybe (Stack a)
    forall a. a -> Maybe a
    Just (Stack a -> Maybe (Stack a)) -> Stack a -> Maybe (Stack a)
    forall a b. (a -> b) -> a -> b
    $ a -> [a] -> [a] -> Stack a
    forall a. a -> [a] -> [a] -> Stack a
    W.Stack a
    a (a -> [a] -> [a]
    forall a. Eq a => a -> [a] -> [a]
    L.delete a
    a [a]
    l) (a -> [a] -> [a]
    forall a. Eq a => a -> [a] -> [a]
    L.delete a
    a (a
    ta -> [a] -> [a]
    forall a. a -> [a] -> [a]
    :[a]
    r)))

    -- | runOrCopy will run the provided shell command unless it can
    --  find a specified window in which case it will copy the window to
    --  the current workspace.  Similar to (i.e., stolen from) "XMonad.Actions.WindowGo".
    runOrCopy :: String -> Query Bool -> X ()
    runOrCopy :: WorkspaceId -> Query Bool -> X ()
    runOrCopy = X () -> Query Bool -> X ()
    copyMaybe (X () -> Query Bool -> X ())
    -> (WorkspaceId -> X ()) -> WorkspaceId -> Query Bool -> X ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . WorkspaceId -> X ()
    forall (m :: * -> *). MonadIO m => WorkspaceId -> m ()
    spawn

    -- | Copy a window if it exists, run the first argument otherwise.
    copyMaybe :: X () -> Query Bool -> X ()
    copyMaybe :: X () -> Query Bool -> X ()
    copyMaybe X ()
    f Query Bool
    qry = Query Bool -> ManageHook -> X () -> X ()
    ifWindow Query Bool
    qry ManageHook
    forall {l} {sd}.
    Query (Endo (StackSet WorkspaceId l Window ScreenId sd))
    copyWin X ()
    f
        where copyWin :: Query (Endo (StackSet WorkspaceId l Window ScreenId sd))
    copyWin = Query Window
    forall r (m :: * -> *). MonadReader r m => m r
    ask Query Window
    -> (Window
        -> Query (Endo (StackSet WorkspaceId l Window ScreenId sd)))
    -> Query (Endo (StackSet WorkspaceId l Window ScreenId sd))
    forall a b. Query a -> (a -> Query b) -> Query b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \Window
    w -> (StackSet WorkspaceId l Window ScreenId sd
     -> StackSet WorkspaceId l Window ScreenId sd)
    -> Query (Endo (StackSet WorkspaceId l Window ScreenId sd))
    forall s. (s -> s) -> Query (Endo s)
    doF (\StackSet WorkspaceId l Window ScreenId sd
    ws -> Window
    -> WorkspaceId
    -> StackSet WorkspaceId l Window ScreenId sd
    -> StackSet WorkspaceId l Window ScreenId sd
    forall a i s l sd.
    (Eq a, Eq i, Eq s) =>
    a -> i -> StackSet i l a s sd -> StackSet i l a s sd
    copyWindow Window
    w (StackSet WorkspaceId l Window ScreenId sd -> WorkspaceId
    forall i l a s sd. StackSet i l a s sd -> i
    W.currentTag StackSet WorkspaceId l Window ScreenId sd
    ws) StackSet WorkspaceId l Window ScreenId sd
    ws)

    -- | Remove the focused window from this workspace.  If it's present in no
    -- other workspace, then kill it instead. If we do kill it, we'll get a
    -- delete notify back from X.
    --
    -- There are two ways to delete a window. Either just kill it, or if it
    -- supports the delete protocol, send a delete event (e.g. firefox).
    kill1 :: X ()
    kill1 :: X ()
    kill1 = do WindowSet
    ss <- (XState -> WindowSet) -> X WindowSet
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets XState -> WindowSet
    windowset
               Maybe Window -> (Window -> X ()) -> X ()
    forall (m :: * -> *) a. Monad m => Maybe a -> (a -> m ()) -> m ()
    whenJust (WindowSet -> Maybe Window
    forall i l a s sd. StackSet i l a s sd -> Maybe a
    W.peek WindowSet
    ss) ((Window -> X ()) -> X ()) -> (Window -> X ()) -> X ()
    forall a b. (a -> b) -> a -> b
    $ \Window
    w -> if Window -> WindowSet -> Bool
    forall a i l s sd. Eq a => a -> StackSet i l a s sd -> Bool
    W.member Window
    w (WindowSet -> Bool) -> WindowSet -> Bool
    forall a b. (a -> b) -> a -> b
    $ Window -> WindowSet -> WindowSet
    forall {a} {i} {l} {s} {sd}.
    Eq a =>
    a -> StackSet i l a s sd -> StackSet i l a s sd
    delete'' Window
    w WindowSet
    ss
                                          then (WindowSet -> WindowSet) -> X ()
    windows ((WindowSet -> WindowSet) -> X ())
    -> (WindowSet -> WindowSet) -> X ()
    forall a b. (a -> b) -> a -> b
    $ Window -> WindowSet -> WindowSet
    forall {a} {i} {l} {s} {sd}.
    Eq a =>
    a -> StackSet i l a s sd -> StackSet i l a s sd
    delete'' Window
    w
                                          else X ()
    kill
        where delete'' :: a -> StackSet i l a s sd -> StackSet i l a s sd
    delete'' a
    w = Maybe (Stack a)
    -> (Stack a -> Maybe (Stack a))
    -> StackSet i l a s sd
    -> StackSet i l a s sd
    forall a i l s sd.
    Maybe (Stack a)
    -> (Stack a -> Maybe (Stack a))
    -> StackSet i l a s sd
    -> StackSet i l a s sd
    W.modify Maybe (Stack a)
    forall a. Maybe a
    Nothing ((a -> Bool) -> Stack a -> Maybe (Stack a)
    forall a. (a -> Bool) -> Stack a -> Maybe (Stack a)
    W.filter (a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    /= a
    w))

    -- | Kill all other copies of focused window (if they're present).
    -- 'All other' means here 'copies which are not on the current workspace'.
    killAllOtherCopies :: X ()
    killAllOtherCopies :: X ()
    killAllOtherCopies = do WindowSet
    ss <- (XState -> WindowSet) -> X WindowSet
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets XState -> WindowSet
    windowset
                            Maybe Window -> (Window -> X ()) -> X ()
    forall (m :: * -> *) a. Monad m => Maybe a -> (a -> m ()) -> m ()
    whenJust (WindowSet -> Maybe Window
    forall i l a s sd. StackSet i l a s sd -> Maybe a
    W.peek WindowSet
    ss) ((Window -> X ()) -> X ()) -> (Window -> X ()) -> X ()
    forall a b. (a -> b) -> a -> b
    $ \Window
    w -> (WindowSet -> WindowSet) -> X ()
    windows ((WindowSet -> WindowSet) -> X ())
    -> (WindowSet -> WindowSet) -> X ()
    forall a b. (a -> b) -> a -> b
    $
                                                       WorkspaceId -> WindowSet -> WindowSet
    forall s i l a sd.
    (Eq s, Eq i) =>
    i -> StackSet i l a s sd -> StackSet i l a s sd
    W.view (WindowSet -> WorkspaceId
    forall i l a s sd. StackSet i l a s sd -> i
    W.currentTag WindowSet
    ss) (WindowSet -> WindowSet)
    -> (WindowSet -> WindowSet) -> WindowSet -> WindowSet
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
                                                       Window -> WindowSet -> WindowSet
    forall {b} {sid} {a} {l} {sd}.
    (Eq b, Eq sid, Eq a) =>
    a -> StackSet b l a sid sd -> StackSet b l a sid sd
    delFromAllButCurrent Window
    w
        where
          delFromAllButCurrent :: a -> StackSet b l a sid sd -> StackSet b l a sid sd
    delFromAllButCurrent a
    w StackSet b l a sid sd
    ss = (Workspace b l a -> StackSet b l a sid sd -> StackSet b l a sid sd)
    -> StackSet b l a sid sd
    -> [Workspace b l a]
    -> StackSet b l a sid sd
    forall a b. (a -> b -> b) -> b -> [a] -> b
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr (a -> b -> StackSet b l a sid sd -> StackSet b l a sid sd
    forall {i} {s} {a} {l} {sd}.
    (Eq i, Eq s, Eq a) =>
    a -> i -> StackSet i l a s sd -> StackSet i l a s sd
    delWinFromWorkspace a
    w (b -> StackSet b l a sid sd -> StackSet b l a sid sd)
    -> (Workspace b l a -> b)
    -> Workspace b l a
    -> StackSet b l a sid sd
    -> StackSet b l a sid sd
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Workspace b l a -> b
    forall i l a. Workspace i l a -> i
    W.tag)
                                      StackSet b l a sid sd
    ss
                                      (StackSet b l a sid sd -> [Workspace b l a]
    forall i l a s sd. StackSet i l a s sd -> [Workspace i l a]
    W.hidden StackSet b l a sid sd
    ss [Workspace b l a] -> [Workspace b l a] -> [Workspace b l a]
    forall a. [a] -> [a] -> [a]
    ++ (Screen b l a sid sd -> Workspace b l a)
    -> [Screen b l a sid sd] -> [Workspace b l a]
    forall a b. (a -> b) -> [a] -> [b]
    map Screen b l a sid sd -> Workspace b l a
    forall i l a sid sd. Screen i l a sid sd -> Workspace i l a
    W.workspace (StackSet b l a sid sd -> [Screen b l a sid sd]
    forall i l a sid sd. StackSet i l a sid sd -> [Screen i l a sid sd]
    W.visible StackSet b l a sid sd
    ss))
          delWinFromWorkspace :: a -> i -> StackSet i l a s sd -> StackSet i l a s sd
    delWinFromWorkspace a
    w i
    wid = 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
    forall {s} {i} {s} {l} {a} {sd} {l} {a} {sd}.
    (Eq s, Eq i, Eq s) =>
    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
    viewing i
    wid ((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)
    -> StackSet i l a s sd
    -> StackSet i l a s sd
    forall a b. (a -> b) -> a -> b
    $ Maybe (Stack a)
    -> (Stack a -> Maybe (Stack a))
    -> StackSet i l a s sd
    -> StackSet i l a s sd
    forall a i l s sd.
    Maybe (Stack a)
    -> (Stack a -> Maybe (Stack a))
    -> StackSet i l a s sd
    -> StackSet i l a s sd
    W.modify Maybe (Stack a)
    forall a. Maybe a
    Nothing ((a -> Bool) -> Stack a -> Maybe (Stack a)
    forall a. (a -> Bool) -> Stack a -> Maybe (Stack a)
    W.filter (a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    /= a
    w))

          viewing :: 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
    viewing i
    wis StackSet i l a s sd -> StackSet i l a s sd
    f StackSet i l a s sd
    ss = i -> StackSet i l a s sd -> StackSet i l a s sd
    forall s i l a sd.
    (Eq s, Eq i) =>
    i -> StackSet i l a s sd -> StackSet i l a s sd
    W.view (StackSet i l a s sd -> i
    forall i l a s sd. StackSet i l a s sd -> i
    W.currentTag StackSet i l a s sd
    ss) (StackSet i l a s sd -> StackSet i l a s sd)
    -> StackSet i l a s sd -> StackSet i l a s sd
    forall a b. (a -> b) -> a -> b
    $ StackSet i l a s sd -> StackSet i l a s sd
    f (StackSet i l a s sd -> StackSet i l a s sd)
    -> StackSet i l a s sd -> StackSet i l a s sd
    forall a b. (a -> b) -> a -> b
    $ i -> StackSet i l a s sd -> StackSet i l a s sd
    forall s i l a sd.
    (Eq s, Eq i) =>
    i -> StackSet i l a s sd -> StackSet i l a s sd
    W.view i
    wis StackSet i l a s sd
    ss

    -- | A list of hidden workspaces containing a copy of the focused window.
    wsContainingCopies :: X [WorkspaceId]
    wsContainingCopies :: X [WorkspaceId]
    wsContainingCopies = do
        WindowSet
    ws <- (XState -> WindowSet) -> X WindowSet
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets XState -> WindowSet
    windowset
        [WorkspaceId] -> X [WorkspaceId]
    forall a. a -> X a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([WorkspaceId] -> X [WorkspaceId])
    -> [WorkspaceId] -> X [WorkspaceId]
    forall a b. (a -> b) -> a -> b
    $ Maybe Window -> [(WorkspaceId, [Window])] -> [WorkspaceId]
    forall a i. Eq a => Maybe a -> [(i, [a])] -> [i]
    copiesOfOn (WindowSet -> Maybe Window
    forall i l a s sd. StackSet i l a s sd -> Maybe a
    W.peek WindowSet
    ws) ([WindowSpace] -> [(WorkspaceId, [Window])]
    forall i l a. [Workspace i l a] -> [(i, [a])]
    taggedWindows ([WindowSpace] -> [(WorkspaceId, [Window])])
    -> [WindowSpace] -> [(WorkspaceId, [Window])]
    forall a b. (a -> b) -> a -> b
    $ WindowSet -> [WindowSpace]
    forall i l a s sd. StackSet i l a s sd -> [Workspace i l a]
    W.hidden WindowSet
    ws)

    -- | Get a list of tuples (tag, [Window]) for each workspace.
    taggedWindows :: [W.Workspace i l a] -> [(i, [a])]
    taggedWindows :: forall i l a. [Workspace i l a] -> [(i, [a])]
    taggedWindows = (Workspace i l a -> (i, [a])) -> [Workspace i l a] -> [(i, [a])]
    forall a b. (a -> b) -> [a] -> [b]
    map ((Workspace i l a -> (i, [a])) -> [Workspace i l a] -> [(i, [a])])
    -> (Workspace i l a -> (i, [a])) -> [Workspace i l a] -> [(i, [a])]
    forall a b. (a -> b) -> a -> b
    $ Workspace i l a -> i
    forall i l a. Workspace i l a -> i
    W.tag (Workspace i l a -> i)
    -> (Workspace i l a -> [a]) -> Workspace i l a -> (i, [a])
    forall b c c'. (b -> c) -> (b -> c') -> b -> (c, c')
    forall (a :: * -> * -> *) b c c'.
    Arrow a =>
    a b c -> a b c' -> a b (c, c')
    &&& Maybe (Stack a) -> [a]
    forall a. Maybe (Stack a) -> [a]
    W.integrate' (Maybe (Stack a) -> [a])
    -> (Workspace i l a -> Maybe (Stack a)) -> Workspace i l a -> [a]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Workspace i l a -> Maybe (Stack a)
    forall i l a. Workspace i l a -> Maybe (Stack a)
    W.stack

    -- | Get tags with copies of the focused window (if present.)
    copiesOfOn :: (Eq a) => Maybe a -> [(i, [a])] -> [i]
    copiesOfOn :: forall a i. Eq a => Maybe a -> [(i, [a])] -> [i]
    copiesOfOn Maybe a
    foc [(i, [a])]
    tw = [i] -> (a -> [i]) -> Maybe a -> [i]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe [] a -> [i]
    hasCopyOf Maybe a
    foc
      where hasCopyOf :: a -> [i]
    hasCopyOf a
    f = ((i, [a]) -> i) -> [(i, [a])] -> [i]
    forall a b. (a -> b) -> [a] -> [b]
    map (i, [a]) -> i
    forall a b. (a, b) -> a
    fst ([(i, [a])] -> [i]) -> [(i, [a])] -> [i]
    forall a b. (a -> b) -> a -> b
    $ ((i, [a]) -> Bool) -> [(i, [a])] -> [(i, [a])]
    forall a. (a -> Bool) -> [a] -> [a]
    filter ((a
    f a -> [a] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` ) ([a] -> Bool) -> ((i, [a]) -> [a]) -> (i, [a]) -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (i, [a]) -> [a]
    forall a b. (a, b) -> b
    snd) [(i, [a])]
    tw