{-# OPTIONS_GHC -Wno-name-shadowing #-} -- | -- Module : XMonad.Custom.Bindings -- Description : Key bindings and keys configuration -- Copyright : (c) Azat Bahawi 2018-2022 -- SPDX-License-Identifier : GPL-3.0-or-later -- Maintainer : azat@bahawi.net -- Stability : experimental -- Portability : non-portable -- module XMonad.Custom.Bindings ( ngKeys , ngModMask , ngMouseBindings ) where import qualified Data.Map as M import System.Exit import XMonad import XMonad.Actions.CopyWindow import XMonad.Actions.CycleWS import XMonad.Actions.DynamicProjects import XMonad.Actions.DynamicWorkspaces import qualified XMonad.Actions.FlexibleManipulate as F import XMonad.Actions.FloatSnap import XMonad.Actions.MessageFeedback import XMonad.Actions.Navigation2D import XMonad.Actions.Promote import XMonad.Actions.UpdatePointer import XMonad.Actions.WithAll import qualified XMonad.Custom.Misc as C import XMonad.Custom.Scratchpads import XMonad.Custom.Theme import XMonad.Hooks.UrgencyHook import XMonad.Layout.BinarySpacePartition import XMonad.Layout.Hidden import XMonad.Layout.ResizableTile import XMonad.Layout.SubLayouts import XMonad.Prompt.ConfirmPrompt import XMonad.Prompt.Shell import XMonad.Prompt.Window import XMonad.Prompt.Workspace import qualified XMonad.StackSet as S import XMonad.Util.EZConfig import XMonad.Util.NamedScratchpad ngModMask :: KeyMask ngModMask = mod4Mask ngKeys :: XConfig Layout -> M.Map (KeyMask, KeySym) (X ()) ngKeys c = mkKeymap c (rawKeys c) ngMouseBindings :: XConfig Layout -> M.Map (KeyMask, Button) (Window -> X ()) ngMouseBindings XConfig { XMonad.modMask = ngModMask } = M.fromList [ ( (ngModMask, button1) , \w -> focus w >> F.mouseWindow F.position w >> ifClick (snapMagicMove (Just 50) (Just 50) w) >> windows S.shiftMaster ) , ( (ngModMask, button3) , \w -> focus w >> F.mouseWindow F.linear w >> ifClick (snapMagicResize [L, R, U, D] (Just 50) (Just 50) w) >> windows S.shiftMaster ) ] zipKeys :: [a] -> [[a]] -> [t1] -> (t1 -> b) -> [([a], b)] zipKeys m ks as f = zipWith (\k d -> (m ++ k, f d)) ks as zipKeys' :: [a] -> [[a]] -> [t1] -> (t1 -> t2 -> b) -> t2 -> [([a], b)] zipKeys' m ks as f b = zipWith (\k d -> (m ++ k, f d b)) ks as rawKeys :: XConfig Layout -> [(String, X ())] rawKeys c = withUpdatePointer $ concatMap ($ c) keymaps where keymaps = [ keysBase , keysSystem , keysMedia , keysWorkspaces , keysSpawnables , keysWindows , keysLayout , keysResize ] withUpdatePointer :: [(String, X ())] -> [(String, X ())] withUpdatePointer = map addAction where addAction :: (String, X ()) -> (String, X ()) addAction (key, action) = (key, action >> updatePointer (0.98, 0.01) (0, 0)) keysBase :: XConfig Layout -> [(String, X ())] keysBase _ = [ ("M-S-q", confirmPrompt hotPromptTheme "Quit?" $ io exitSuccess) , ("M-x" , shellPrompt promptTheme) , ("M-w" , windowPrompt promptTheme Goto allWindows) , ("M-S-w", windowPrompt promptTheme Bring allWindows) ] keysSystem :: XConfig Layout -> [(String, X ())] keysSystem _ = [("M-C-g", return ())] keysMedia :: XConfig Layout -> [(String, X ())] keysMedia _ = [ ("", spawn "pactl set-source-mute 1 toggle") , ("" , spawn "pactl set-sink-mute 0 toggle") , ( "" , spawn "pactl set-sink-mute 0 false && pactl set-sink-volume 0 -10%" ) , ( "" , spawn "pactl set-sink-mute 0 false && pactl set-sink-volume 0 +10%" ) , ("", spawn "mpc toggle") , ("", spawn "mpc stop") , ("", spawn "mpc prev") , ("", spawn "mpc next") ] keysWorkspaces :: XConfig Layout -> [(String, X ())] keysWorkspaces _ = [ ("M-S-o", switchProjectPrompt promptTheme) , ("M-S-p", shiftToProjectPrompt promptTheme) , ("M-i" , toggleWS' ["NSP"]) , ("M-n" , workspacePrompt promptTheme $ windows . S.shift) ] ++ zipKeys "M-" wsKeys [0 ..] (withNthWorkspace S.greedyView) ++ zipKeys "M-S-" wsKeys [0 ..] (withNthWorkspace S.shift) ++ zipKeys "M-C-S-" wsKeys [0 ..] (withNthWorkspace copy) where wsKeys = map show [1 .. 9 :: Int] keysSpawnables :: XConfig Layout -> [(String, X ())] keysSpawnables _ = [ ("M-", spawn (C.term C.applications)) , ("M-c" , namedScratchpadAction scratchpads "console") , ("M-m" , namedScratchpadAction scratchpads "music") , ("M-t" , namedScratchpadAction scratchpads "top") , ("M-v" , namedScratchpadAction scratchpads "volume") ] keysWindows :: XConfig Layout -> [(String, X ())] keysWindows _ = [ ("M-d" , kill) , ("M-S-d", confirmPrompt hotPromptTheme "Kill all" killAll) , ("M-e" , withFocused hideWindow) , ("M-S-e", popOldestHiddenWindow) , ("M-p" , promote) , ("M-g", withFocused $ sendMessage . MergeAll) , ("M-S-g", withFocused $ sendMessage . UnMerge) , ("M-u" , focusUrgent) , ("M-s" , windows S.focusMaster) , ("M-S-'", windows S.swapDown) , ("M-S-;", windows S.swapUp) ] ++ zipKeys' "M-" vimKeys directions windowGo True -- TODO W moving ++ zipKeys' "M-S-" vimKeys directions windowSwap True ++ zipKeys "M-C-" vimKeys directions (sendMessage . pullGroup) ++ zipKeys' "M-" arrowKeys directions screenGo True ++ zipKeys' "M-S-" arrowKeys directions windowToScreen True ++ zipKeys' "M-C-" arrowKeys directions screenSwap True where directions = [D, U, L, R] arrowKeys = ["", "", "", ""] vimKeys = ["j", "k", "h", "l"] keysLayout :: XConfig Layout -> [(String, X ())] keysLayout c = [ ("M-" , sendMessage NextLayout) , ("M-C-", toSubl NextLayout) , ("M-S-", setLayout $ XMonad.layoutHook c) , ("M-S-," , sendMessage $ IncMasterN (-1)) , ("M-S-." , sendMessage $ IncMasterN 1) ] keysResize :: XConfig Layout -> [(String, X ())] keysResize _ = [ ("M-[" , tryMessageR_ (ExpandTowards L) Shrink) , ("M-]" , tryMessageR_ (ExpandTowards R) Expand) , ("M-S-[" , tryMessageR_ (ExpandTowards U) MirrorShrink) , ("M-S-]" , tryMessageR_ (ExpandTowards D) MirrorExpand) , ("M-C-[" , tryMessageR_ (ShrinkFrom R) Shrink) , ("M-C-]" , tryMessageR_ (ShrinkFrom L) Expand) , ("M-S-C-[", tryMessageR_ (ShrinkFrom D) MirrorShrink) , ("M-S-C-]", tryMessageR_ (ShrinkFrom U) MirrorExpand) ] where tryMessageR_ :: (Message a, Message b) => a -> b -> X () tryMessageR_ x y = sequence_ [tryMessageWithNoRefreshToCurrent x y, refresh]