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, allNamedScratchpadAction,
namedScratchpadManageHook, namedScratchpadManageHook,
namedScratchpadFilterOutWorkspace, namedScratchpadFilterOutWorkspace,
namedScratchpadFilterOutWorkspacePP namedScratchpadFilterOutWorkspacePP,
nsHideOnFocusLoss,
) where ) where
import XMonad import XMonad
import XMonad.Prelude (filterM, find, unless)
import XMonad.Hooks.ManageHelpers (doRectFloat)
import XMonad.Actions.DynamicWorkspaces (addHiddenWorkspace) import XMonad.Actions.DynamicWorkspaces (addHiddenWorkspace)
import XMonad.Hooks.DynamicLog (PP, ppSort)
import XMonad.Actions.SpawnOn (spawnHere) 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 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 -- 'XMonad.Util.WorkspaceCompare.filterOutWs'. See the documentation of these
-- functions for examples. -- 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 -- | Single named scratchpad configuration
data NamedScratchpad = NS { name :: String -- ^ Scratchpad name data NamedScratchpad = NS { name :: String -- ^ Scratchpad name
@ -152,6 +159,31 @@ allNamedScratchpadAction :: NamedScratchpads
-> X () -> X ()
allNamedScratchpadAction = someNamedScratchpadAction mapM_ runApplication 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 -- | execute some action on a named scratchpad
someNamedScratchpadAction :: ((Window -> X ()) -> NE.NonEmpty Window -> X ()) someNamedScratchpadAction :: ((Window -> X ()) -> NE.NonEmpty Window -> X ())
-> (NamedScratchpad -> X ()) -> (NamedScratchpad -> X ())
@ -173,11 +205,7 @@ someNamedScratchpadAction f runApp scratchpadConfig scratchpadName =
Just wins -> f (windows . W.shiftWin (W.currentTag winSet)) wins Just wins -> f (windows . W.shiftWin (W.currentTag winSet)) wins
-- matching window running on current workspace -> window should be shifted to scratchpad workspace -- matching window running on current workspace -> window should be shifted to scratchpad workspace
Just wins -> do Just wins -> shiftToNSP (W.workspaces winSet) (`f` wins)
unless (any (\wsp -> scratchpadWorkspaceTag == W.tag wsp) (W.workspaces winSet))
(addHiddenWorkspace scratchpadWorkspaceTag)
f (windows . W.shiftWin scratchpadWorkspaceTag) wins
Nothing -> return () Nothing -> return ()
-- | Tag of the scratchpad workspace -- | Tag of the scratchpad workspace
@ -189,6 +217,14 @@ namedScratchpadManageHook :: NamedScratchpads -- ^ Named scratchpads configurati
-> ManageHook -> ManageHook
namedScratchpadManageHook = composeAll . fmap (\c -> query c --> hook c) 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 -- | Transforms a workspace list containing the NSP workspace into one that
-- doesn't contain it. Intended for use with logHooks. -- doesn't contain it. Intended for use with logHooks.
namedScratchpadFilterOutWorkspace :: [WindowSpace] -> [WindowSpace] namedScratchpadFilterOutWorkspace :: [WindowSpace] -> [WindowSpace]