From d811643e1241d43dbb671802cbf62092f1a73976 Mon Sep 17 00:00:00 2001 From: philib <00philip00@gmail.com> Date: Wed, 18 Oct 2023 19:19:16 +0200 Subject: [PATCH] introduce single active scratchpad hook --- CHANGES.md | 4 ++++ XMonad/Util/NamedScratchpad.hs | 35 ++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 72d0fcefdf..6f3fdd2c05 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -83,6 +83,10 @@ ordered lexicographically, as before. Currently focused window will always be the topmost, meaning the last in the list. + * `XMonad.Util.NamedScratchpad` + + - Added a logHook to allow only one active scratchpad per workspace. + ### New Modules * `XMonad.Layout.CenterMainFluid` diff --git a/XMonad/Util/NamedScratchpad.hs b/XMonad/Util/NamedScratchpad.hs index 61a533827b..8f5489fe9e 100644 --- a/XMonad/Util/NamedScratchpad.hs +++ b/XMonad/Util/NamedScratchpad.hs @@ -31,6 +31,7 @@ module XMonad.Util.NamedScratchpad ( allNamedScratchpadAction, namedScratchpadManageHook, nsHideOnFocusLoss, + nsSingleScratchpadPerWorkspace, -- * Dynamic Scratchpads -- $dynamic-scratchpads @@ -298,6 +299,40 @@ nsHideOnFocusLoss scratches = withWindowSet $ \winSet -> do whenX (isNSP lastFocus scratches) $ shiftToNSP (W.workspaces winSet) ($ lastFocus) +-- | A @logHook@ to have only one active scratchpad on a workspace. This can be +-- useful when working with multiple floating scratchpads which would otherwise be stacked. 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 +-- > >> nsHideOnNewScratchpad myScratchpads +-- > -- enable hiding for all of @myScratchpads@ +-- > } +nsSingleScratchpadPerWorkspace :: NamedScratchpads -> X () +nsSingleScratchpadPerWorkspace scratches = withWindowSet $ \winSet -> do + let cur = W.currentTag winSet + let allWindowsOnCurrentWorkspace = W.index winSet + withRecentsIn cur () $ \lastFocus curFocus -> do + allScratchesOnCurrentWS <- filterM (`isNSP` scratches) allWindowsOnCurrentWorkspace + let allScratchesButCurrent = filter (/= curFocus) allScratchesOnCurrentWS + hideScratch = \s -> shiftToNSP (W.workspaces winSet) ($ s) + + let isWorthy = + -- Check for the window being on the current workspace; if there + -- is no history (i.e., curFocus ≡ lastFocus), don't do anything + -- because the potential scratchpad is definitely focused. + lastFocus `elem` W.index winSet && lastFocus /= curFocus + -- Don't do anything on the NSP workspace, lest the world explodes. + && cur /= scratchpadWorkspaceTag + when isWorthy $ + whenX (isNSP curFocus scratches) $ + for_ allScratchesButCurrent hideScratch + -- | Execute some action on a named scratchpad. -- -- This function /almost always/ ignores its third argument; see Note