diff --git a/CHANGES.md b/CHANGES.md index c56f9e48..cec6145e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -47,6 +47,12 @@ that are exclusive on the same screen. It also allows to remove this constraint of being mutually exclusive with another scratchpad. + * `XMonad.Actions.PerWindowKeys` + + Create actions that run on a `Query Bool`, usually associated with + conditions on a window, basis. Useful for creating bindings that are + excluded or exclusive for some windows. + ### Bug Fixes and Minor Changes * `XMonad.Layout.Tabbed` diff --git a/XMonad/Actions/PerWindowKeys.hs b/XMonad/Actions/PerWindowKeys.hs new file mode 100644 index 00000000..2c3e1fc2 --- /dev/null +++ b/XMonad/Actions/PerWindowKeys.hs @@ -0,0 +1,60 @@ +----------------------------------------------------------------------------- +-- | +-- Module : XMonad.Actions.PerWindowKeys +-- Copyright : (c) Wilson Sales, 2019 +-- License : BSD3-style (see LICENSE) +-- +-- Maintainer : Wilson Sales +-- Stability : unstable +-- Portability : unportable +-- +-- Define key-bindings on per-window basis. +-- +----------------------------------------------------------------------------- + +module XMonad.Actions.PerWindowKeys ( + -- * Usage + -- $usage + bindAll, + bindFirst + ) where + +import XMonad + +-- $usage +-- +-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: +-- +-- > import XMonad.Actions.PerWindowKeys +-- +-- > ,((0, xK_F2), bindFirst [(className =? "firefox", spawn "dmenu"), (isFloat, withFocused $ windows . W.sink)]) +-- +-- > ,((0, xK_F3), bindAll [(isDialog, kill), (pure True, doSomething)]) +-- +-- If you want an action that will always run, but also want to do something for +-- other queries, you can use @'bindAll' [(query1, action1), ..., (pure True, +-- alwaysDoThisAction)]@. +-- +-- Similarly, if you want a default action to be run if all the others failed, +-- you can use @'bindFirst' [(query1, action1), ..., (pure True, +-- doThisIfTheOthersFail)]@. +-- +-- For detailed instructions on editing your key bindings, see +-- "XMonad.Doc.Extending#Editing_key_bindings". + +-- | Run an action if a Query holds true. Doesn't stop at the first one that +-- does, however, and could potentially run all actions. +bindAll :: [(Query Bool, X ())] -> X () +bindAll = mapM_ choose where + choose (mh,action) = withFocused $ \w -> whenX (runQuery mh w) action + +-- | Run the action paired with the first Query that holds true. +bindFirst :: [(Query Bool, X ())] -> X () +bindFirst = withFocused . chooseOne + +chooseOne :: [(Query Bool, X ())] -> Window -> X () +chooseOne [] _ = return () +chooseOne ((mh,a):bs) w = do + c <- runQuery mh w + if c then a + else chooseOne bs w diff --git a/xmonad-contrib.cabal b/xmonad-contrib.cabal index 21accb8c..177635a8 100644 --- a/xmonad-contrib.cabal +++ b/xmonad-contrib.cabal @@ -116,6 +116,7 @@ library XMonad.Actions.Navigation2D XMonad.Actions.NoBorders XMonad.Actions.OnScreen + XMonad.Actions.PerWindowKeys XMonad.Actions.PerWorkspaceKeys XMonad.Actions.PhysicalScreens XMonad.Actions.Plane