xmonad-contrib- Community-maintained extensions for xmonad
Copyright(c) Konstantin Sobolev <konstantin.sobolev@gmail.com>
LicenseBSD-style (see LICENSE)
MaintainerKonstantin Sobolev <konstantin.sobolev@gmail.com>
Safe HaskellSafe-Inferred



Named scratchpads that support several arbitrary applications at the same time.



Allows to have several floating scratchpads running different applications. Bind a key to namedScratchpadSpawnAction. Pressing it will spawn configured application, or bring it to the current workspace if it already exists. Pressing the key with the application on the current workspace will send it to a hidden workspace called NSP.

If you already have a workspace called NSP, it will use that. NSP will also appear in xmobar and dzen status bars. You can tweak your dynamicLog settings to filter it out if you like.

Create named scratchpads configuration in your xmonad.hs like this:

import XMonad.StackSet as W
import XMonad.ManageHook
import XMonad.Util.NamedScratchpad

scratchpads = [
-- run htop in xterm, find it by title, use default floating window placement
    NS "htop" "xterm -e htop" (title =? "htop") defaultFloating ,

-- run stardict, find it by class name, place it in the floating window
-- 1/6 of screen width from the left, 1/6 of screen height
-- from the top, 2/3 of screen width by 2/3 of screen height
    NS "stardict" "stardict" (className =? "Stardict")
        (customFloating $ W.RationalRect (1/6) (1/6) (2/3) (2/3)) ,

-- run gvim, find by role, don't float
    NS "notes" "gvim --role notes ~/notes.txt" (role =? "notes") nonFloating
] where role = stringProperty "WM_WINDOW_ROLE"

Add keybindings:

 , ((modm .|. controlMask .|. shiftMask, xK_t), namedScratchpadAction scratchpads "htop")
 , ((modm .|. controlMask .|. shiftMask, xK_s), namedScratchpadAction scratchpads "stardict")
 , ((modm .|. controlMask .|. shiftMask, xK_n), namedScratchpadAction scratchpads "notes")

... and a manage hook:

 , manageHook = namedScratchpadManageHook scratchpads

For detailed instruction on editing the key binding see XMonad.Doc.Extending

For some applications (like displaying your workspaces in a status bar) it is convenient to filter out the NSP workspace when looking at all workspaces. For this, you can use filterOutWsPP, or filterOutWs together with addEwmhWorkspaceSort if your status bar gets the list of workspaces from EWMH. 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.

data NamedScratchpad Source #

Single named scratchpad configuration




  • name :: String

    Scratchpad name

  • cmd :: String

    Command used to run application

  • query :: Query Bool

    Query to find already running application

  • hook :: ManageHook

    Manage hook called for application window, use it to define the placement. See nonFloating, defaultFloating and customFloating

scratchpadWorkspaceTag :: String Source #

Tag of the scratchpad workspace

nonFloating :: ManageHook Source #

Manage hook that makes the window non-floating

defaultFloating :: ManageHook Source #

Manage hook that makes the window floating with the default placement

customFloating :: RationalRect -> ManageHook Source #

Manage hook that makes the window floating with custom placement

type NamedScratchpads = [NamedScratchpad] Source #

Named scratchpads configuration

namedScratchpadAction Source #


:: NamedScratchpads

Named scratchpads configuration

-> String

Scratchpad name

-> X () 

Action to pop up specified named scratchpad

NOTE: Ignores its first argument and uses NSPState instead.

spawnHereNamedScratchpadAction Source #


:: NamedScratchpads

Named scratchpads configuration

-> String

Scratchpad name

-> X () 

Action to pop up specified named scratchpad, initially starting it on the current workspace.

NOTE: Ignores its first argument and uses NSPState instead.

customRunNamedScratchpadAction Source #


:: (NamedScratchpad -> X ())

Function initially running the application, given the configured scratchpad cmd

-> NamedScratchpads

Named scratchpads configuration

-> String

Scratchpad name

-> X () 

Action to pop up specified named scratchpad, given a custom way to initially start the application.

NOTE: Ignores its second argument and uses NSPState instead.

allNamedScratchpadAction :: NamedScratchpads -> String -> X () Source #

Like namedScratchpadAction, but execute the action for all scratchpads that match the query.

NOTE: Ignores its first argument and uses NSPState instead.

namedScratchpadManageHook Source #


:: NamedScratchpads

Named scratchpads configuration

-> ManageHook 

Manage hook to use with named scratchpads

nsHideOnFocusLoss :: NamedScratchpads -> X () Source #

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 refocusLastLogHook.


import XMonad.Hooks.RefocusLast (refocusLastLogHook)
import XMonad.Util.NamedScratchpad

main = xmonad $ def
  { logHook = refocusLastLogHook
           >> nsHideOnFocusLoss myScratchpads
              -- enable hiding for all of @myScratchpads@

Dynamic Scratchpads

Dynamic scratchpads allow you to declare existing windows as scratchpads. You can bind a key to make a window start/stop being a scratchpad, and another key to toggle its visibility. Because dynamic scratchpads are based on existing windows, they have some caveats in comparison to "normal" scratchpads:

  • xmonad has no way of knowing how windows were spawned and thus one is not able to "start" dynamic scratchpads again after the associated window has been closed.
  • If you already have an active dynamic scratchpad "dyn1" and you call toggleDynamicNSP with another window, that window will henceforth occupy the "dyn1" scratchpad. If you still need the old window, you might have to travel to your scratchpad workspace (scratchpadWorkspaceTag) in order to retrieve it.

As an example, the following snippet contains keybindings for two dynamic scratchpads, called "dyn1" and "dyn2":

import XMonad.Util.NamedScratchpads

, ("M-s-a", withFocused $ toggleDynamicNSP "dyn1")
, ("M-s-b", withFocused $ toggleDynamicNSP "dyn2")
, ("M-a"  , dynamicNSPAction "dyn1")
, ("M-b"  , dynamicNSPAction "dyn2")

dynamicNSPAction :: String -> X () Source #

Toggle the visibility of a dynamic scratchpad.

toggleDynamicNSP :: String -> Window -> X () Source #

Either create a dynamic scratchpad out of the given window, or stop a window from being one if it already is.


namedScratchpadFilterOutWorkspace :: [WindowSpace] -> [WindowSpace] Source #

Deprecated: Use XMonad.Util.WorkspaceCompare.filterOutWs [scratchpadWorkspaceTag] instead

Transforms a workspace list containing the NSP workspace into one that doesn't contain it. Intended for use with logHooks.

namedScratchpadFilterOutWorkspacePP :: PP -> PP Source #

Deprecated: Use XMonad.Hooks.StatusBar.PP.filterOutWsPP [scratchpadWorkspaceTag] instead

Transforms a pretty-printer into one not displaying the NSP workspace.

A simple use could be:

logHook = dynamicLogWithPP . namedScratchpadFilterOutWorkspace $ def

Here is another example, when using XMonad.Layout.IndependentScreens. If you have handles hLeft and hRight for bars on the left and right screens, respectively, and pp is a pretty-printer function that takes a handle, you could write

logHook = let log screen handle = dynamicLogWithPP . namedScratchpadFilterOutWorkspacePP . marshallPP screen . pp $ handle
          in log 0 hLeft >> log 1 hRight