X.U.NamedScratchpad: Add nsHideOnFocusLoss

This adds a new logHook, nsHideOnFocusLoss, that hides the given
scratchpads when they lose focus.  This is akin to the functionality
provided by a lot of dropdown terminals.
This commit is contained in:
slotThe 2021-06-22 13:33:39 +02:00
parent 67c9d7fe90
commit 361a34d797

View File

@ -27,15 +27,17 @@ module XMonad.Util.NamedScratchpad (
allNamedScratchpadAction,
namedScratchpadManageHook,
namedScratchpadFilterOutWorkspace,
namedScratchpadFilterOutWorkspacePP
namedScratchpadFilterOutWorkspacePP,
nsHideOnFocusLoss,
) where
import XMonad
import XMonad.Prelude (filterM, find, unless)
import XMonad.Hooks.ManageHelpers (doRectFloat)
import XMonad.Actions.DynamicWorkspaces (addHiddenWorkspace)
import XMonad.Hooks.DynamicLog (PP, ppSort)
import XMonad.Actions.SpawnOn (spawnHere)
import XMonad.Hooks.DynamicLog (PP, ppSort)
import XMonad.Hooks.ManageHelpers (doRectFloat)
import XMonad.Hooks.RefocusLast (withRecentsIn)
import XMonad.Prelude (filterM, find, unless, when)
import qualified Data.List.NonEmpty as NE
@ -93,6 +95,11 @@ import qualified XMonad.StackSet as W
-- 'XMonad.Util.WorkspaceCompare.filterOutWs'. See the documentation of these
-- functions for examples.
--
-- Further, there is also a @logHook@ that you can use to hide
-- scratchpads when they lose focus; this is functionality akin to what
-- some dropdown terminals provide. See the documentation of
-- 'nsHideOnFocusLoss' for an example how to set this up.
--
-- | Single named scratchpad configuration
data NamedScratchpad = NS { name :: String -- ^ Scratchpad name
@ -152,6 +159,31 @@ allNamedScratchpadAction :: NamedScratchpads
-> X ()
allNamedScratchpadAction = someNamedScratchpadAction mapM_ runApplication
-- | A @logHook@ to hide scratchpads when they lose focus. This can be
-- useful for e.g. dropdown terminals. Note that this also requires you
-- to use the 'XMonad.Hooks.RefocusLast.refocusLastLogHook'.
--
-- ==== __Example__
--
-- > import XMonad.Hooks.RefocusLast (refocusLastLogHook)
-- > import XMonad.Util.NamedScratchpad
-- >
-- > main = xmonad $ def
-- > { logHook = refocusLastLogHook
-- > >> nsHideOnFocusLoss myScratchpads
-- > -- enable hiding for all of @myScratchpads@
-- > }
nsHideOnFocusLoss :: NamedScratchpads -> X ()
nsHideOnFocusLoss scratches = withWindowSet $ \winSet -> do
let cur = W.currentTag winSet
withRecentsIn cur () $ \lastFocus _ ->
when (lastFocus `elem` W.index winSet && cur /= scratchpadWorkspaceTag) $
whenX (isNS lastFocus) $
shiftToNSP (W.workspaces winSet) ($ lastFocus)
where
isNS :: Window -> X Bool
isNS w = or <$> traverse ((`runQuery` w) . query) scratches
-- | execute some action on a named scratchpad
someNamedScratchpadAction :: ((Window -> X ()) -> NE.NonEmpty Window -> X ())
-> (NamedScratchpad -> X ())
@ -173,11 +205,7 @@ someNamedScratchpadAction f runApp scratchpadConfig scratchpadName =
Just wins -> f (windows . W.shiftWin (W.currentTag winSet)) wins
-- matching window running on current workspace -> window should be shifted to scratchpad workspace
Just wins -> do
unless (any (\wsp -> scratchpadWorkspaceTag == W.tag wsp) (W.workspaces winSet))
(addHiddenWorkspace scratchpadWorkspaceTag)
f (windows . W.shiftWin scratchpadWorkspaceTag) wins
Just wins -> shiftToNSP (W.workspaces winSet) (`f` wins)
Nothing -> return ()
-- | Tag of the scratchpad workspace
@ -189,6 +217,14 @@ namedScratchpadManageHook :: NamedScratchpads -- ^ Named scratchpads configurati
-> ManageHook
namedScratchpadManageHook = composeAll . fmap (\c -> query c --> hook c)
-- | Shift some windows to the scratchpad workspace according to the
-- given function. The workspace is created if necessary.
shiftToNSP :: [WindowSpace] -> ((Window -> X ()) -> X ()) -> X ()
shiftToNSP ws f = do
unless (any ((scratchpadWorkspaceTag ==) . W.tag) ws) $
addHiddenWorkspace scratchpadWorkspaceTag
f (windows . W.shiftWin scratchpadWorkspaceTag)
-- | Transforms a workspace list containing the NSP workspace into one that
-- doesn't contain it. Intended for use with logHooks.
namedScratchpadFilterOutWorkspace :: [WindowSpace] -> [WindowSpace]