From ff0ab6f977e6216e2163f4e83a22ff6f6d5190c9 Mon Sep 17 00:00:00 2001 From: mephory Date: Fri, 29 May 2020 15:47:46 +0200 Subject: [PATCH 1/2] X.U.DynamicScratchpads: Make any window a scratchpad --- CHANGES.md | 5 ++ XMonad/Util/DynamicScratchpads.hs | 96 +++++++++++++++++++++++++++++++ xmonad-contrib.cabal | 1 + 3 files changed, 102 insertions(+) create mode 100644 XMonad/Util/DynamicScratchpads.hs diff --git a/CHANGES.md b/CHANGES.md index 8f82fc86..7b4dc757 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -42,6 +42,11 @@ conditions on a window, basis. Useful for creating bindings that are excluded or exclusive for some windows. + * `XMonad.Util.DynamicScratchpads` + + Declare any window as a scratchpad on the fly. Once declared, the + scratchpad behaves like `XMonad.Util.NamedScratchpad`. + ### Bug Fixes and Minor Changes * `XMonad.Util.Run` diff --git a/XMonad/Util/DynamicScratchpads.hs b/XMonad/Util/DynamicScratchpads.hs new file mode 100644 index 00000000..9c45f793 --- /dev/null +++ b/XMonad/Util/DynamicScratchpads.hs @@ -0,0 +1,96 @@ +----------------------------------------------------------------------------- +-- | +-- Module : XMonad.Util.DynamicScratchpads +-- Copyright : (c) Robin Oberschweiber +-- License : BSD-style (see LICENSE) +-- +-- Maintainer : Robin Obercshweiber +-- Stability : unstable +-- Portability : unportable +-- +-- Dynamically declare any window as a scratchpad. +-- +----------------------------------------------------------------------------- + +module XMonad.Util.DynamicScratchpads ( + -- * Usage + -- $usage + makeDynamicSP, + spawnDynamicSP + ) where + +import Graphics.X11.Types +import XMonad.Core +import XMonad.Operations +import qualified Data.Map as M +import qualified XMonad.StackSet as W +import qualified XMonad.Util.ExtensibleState as XS + + +-- $usage +-- Allows you to dynamically declare windows as scratchpads. You can bind a key +-- to make a window start/stop being a scratchpad, and another key to +-- spawn/hide that scratchpad. +-- +-- Like with XMonad.Util.NamedScratchpad, you have to have a workspace called +-- NSP, where hidden scratchpads will be moved to. +-- +-- You can declare dynamic scrachpads in your xmonad.hs like so: +-- +-- import XMonad.Util.DynamicScratchpads +-- +-- , ((modm .|. shiftMask, xK_a), withFocused $ makeDynamicSP "dyn1") +-- , ((modm .|. shiftMask, xK_b), withFocused $ makeDynamicSP "dyn2") +-- , ((modm , xK_a), spawnDynamicSP "dyn1") +-- , ((modm , xK_b), spawnDynamicSP "dyn2") + +-- | Stores dynamic scratchpads as a map of name to window +data SPStorage = SPStorage (M.Map String Window) + deriving (Typeable,Read,Show) + +instance ExtensionClass SPStorage where + initialValue = SPStorage $ M.fromList [] + extensionType = PersistentExtension + +-- | Makes a window a dynamic scratchpad with the given name, or stop a window +-- | from being a dynamic scratchpad, if it already is. +makeDynamicSP :: String -- ^ Scratchpad name + -> Window -- ^ Window to be made a scratchpad + -> X () +makeDynamicSP s w = do + (SPStorage m) <- XS.get + case M.lookup s m of + Nothing -> addDynamicSP s w + Just ow -> if w == ow + then removeDynamicSP s + else (showWindow ow >> addDynamicSP s w) + +-- | Spawn the specified dynamic scratchpad +spawnDynamicSP :: String -- ^ Scratchpad name + -> X () +spawnDynamicSP s = do + (SPStorage m) <- XS.get + case M.lookup s m of + Nothing -> mempty + Just w -> spawnDynamicSP' w + +spawnDynamicSP' :: Window -> X () +spawnDynamicSP' w = withWindowSet $ \s -> do + let matchingWindows = filter (== w) ((maybe [] W.integrate . W.stack . W.workspace . W.current) s) + case matchingWindows of + [] -> showWindow w + _ -> hideWindow w + +-- | Make a window a dynamic scratchpad +addDynamicSP :: String -> Window -> X () +addDynamicSP s w = XS.modify $ alterSPStorage (\_ -> Just w) s + +-- | Make a window stop being a dynamic scratchpad +removeDynamicSP :: String -> X () +removeDynamicSP s = XS.modify $ alterSPStorage (\_ -> Nothing) s + +-- | Moves window to the scratchpad workspace, effectively hiding it +hideWindow :: Window -> X () +hideWindow = windows . W.shiftWin "NSP" + +-- vim:ts=4:shiftwidth=4:softtabstop=4:expandtab: diff --git a/xmonad-contrib.cabal b/xmonad-contrib.cabal index 01d6a964..e62d4cfd 100644 --- a/xmonad-contrib.cabal +++ b/xmonad-contrib.cabal @@ -319,6 +319,7 @@ library XMonad.Util.CustomKeys XMonad.Util.DebugWindow XMonad.Util.Dmenu + XMonad.Util.DynamicScratchpads XMonad.Util.Dzen XMonad.Util.EZConfig XMonad.Util.ExclusiveScratchpads From 1fdfb4b8d0a459f922e3b41c09cd19892220bf87 Mon Sep 17 00:00:00 2001 From: mephory Date: Fri, 29 May 2020 16:15:51 +0200 Subject: [PATCH 2/2] X.U.DynamicScratchpads: added missing functions --- XMonad/Util/DynamicScratchpads.hs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/XMonad/Util/DynamicScratchpads.hs b/XMonad/Util/DynamicScratchpads.hs index 9c45f793..bcad466f 100644 --- a/XMonad/Util/DynamicScratchpads.hs +++ b/XMonad/Util/DynamicScratchpads.hs @@ -93,4 +93,12 @@ removeDynamicSP s = XS.modify $ alterSPStorage (\_ -> Nothing) s hideWindow :: Window -> X () hideWindow = windows . W.shiftWin "NSP" +-- | Move window to current workspace and focus it +showWindow :: Window -> X () +showWindow w = windows $ \ws -> + (W.focusWindow w) . (W.shiftWin (W.currentTag ws) w) $ ws + +alterSPStorage :: (Maybe Window -> Maybe Window) -> String -> SPStorage -> SPStorage +alterSPStorage f k (SPStorage m) = SPStorage $ M.alter f k m + -- vim:ts=4:shiftwidth=4:softtabstop=4:expandtab: