199 lines
8.8 KiB
Haskell
199 lines
8.8 KiB
Haskell
import XMonad
|
|
import XMonad.Util.EZConfig
|
|
import XMonad.Layout.ThreeColumns
|
|
import XMonad.Layout.WindowNavigation
|
|
import XMonad.Layout.MultiToggle.Instances
|
|
import XMonad.Layout.MultiToggle
|
|
import XMonad.Layout.NoBorders
|
|
import XMonad.Layout.IndependentScreens
|
|
import XMonad.Actions.CopyWindow
|
|
import XMonad.Actions.CycleWS
|
|
import XMonad.Actions.EasyMotion (selectWindow)
|
|
import XMonad.Hooks.EwmhDesktops
|
|
import XMonad.Hooks.DynamicLog
|
|
import XMonad.Hooks.StatusBar
|
|
import XMonad.Hooks.StatusBar.PP
|
|
import qualified XMonad.Layout.Magnifier as Mag
|
|
import qualified Data.Map as M
|
|
import qualified XMonad.StackSet as W
|
|
import System.Exit
|
|
import XMonad.Util.Loggers
|
|
|
|
-- TODO: xmobar
|
|
|
|
myWorkspaceNames = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]
|
|
myScreens = 2
|
|
conf = def { layoutHook = myLayout
|
|
, workspaces = withScreens myScreens myWorkspaceNames
|
|
, modMask = mod4Mask
|
|
}
|
|
`additionalKeysP`
|
|
myKeys
|
|
|
|
-- main :: IO ()
|
|
main =
|
|
xmonad $ ewmh $ withEasySB (statusBarProp "xmobar" (pure myXmobarPP)) defToggleStrutsKey conf
|
|
|
|
-- Define the status bars for each screen
|
|
-- myStatusBars :: [StatusBarConfig]
|
|
-- myStatusBars = [ statusBarProp ("xmobar -x " ++ show sc) (pure myXmobarPP) | sc <- [0..myScreens - 1] ]
|
|
|
|
-- main :: IO ()
|
|
-- main = xmonad . ewmh $ dynamicSBs myStatusBars conf
|
|
|
|
myXmobarPP :: PP
|
|
myXmobarPP = def
|
|
{ ppSep = magenta " • "
|
|
, ppTitleSanitize = xmobarStrip
|
|
, ppCurrent = xmobarBorder "Top" borderColor 2 . xmobarBorder "Bottom" borderColor 2
|
|
, ppUrgent = red . wrap (yellow "!") (yellow "!")
|
|
, ppOrder = \[ws, l, _, wins] -> [ws, l, wins]
|
|
, ppExtras = [logTitles formatFocused formatUnfocused]
|
|
}
|
|
where
|
|
formatFocused = wrap (white "[") (white "]") . magenta . ppWindow
|
|
formatUnfocused = wrap (lowWhite "[") (lowWhite "]") . blue . ppWindow
|
|
|
|
-- | Windows should have *some* title, which should not not exceed a
|
|
-- sane length.
|
|
ppWindow :: String -> String
|
|
ppWindow = xmobarRaw . (\w -> if null w then "untitled" else w) . shorten 30
|
|
|
|
blue, lowWhite, magenta, red, white, yellow :: String -> String
|
|
magenta = xmobarColor "#ff79c6" ""
|
|
blue = xmobarColor "#bd93f9" ""
|
|
white = xmobarColor "#f8f8f2" ""
|
|
yellow = xmobarColor "#f1fa8c" ""
|
|
red = xmobarColor "#ff5555" ""
|
|
lowWhite = xmobarColor "#bbbbbb" ""
|
|
borderColor = "#8be9fd"
|
|
|
|
myKeys :: [(String, X ())]
|
|
myKeys = [
|
|
-- Screen lock & suspend
|
|
("C-M1-l" , spawn "i3lock" )
|
|
, ("C-M1-S-l" , spawn "i3lock" *> spawn "systemctl suspend")
|
|
-- Terminal
|
|
, ("M4-<Return>", spawn "kitty -1")
|
|
-- Frequent programs
|
|
, ("M4-q", spawn "firefox" )
|
|
, ("M4-a", runOrCopy "emacs" (className =? "Emacs"))
|
|
, ("M4-d", spawn "discord" )
|
|
, ("M4-g", spawn "dolphin" )
|
|
-- Program launcher
|
|
, ("M4-r", spawn "rofi -show drun -theme Paper" )
|
|
-- Exit
|
|
, ("M4-M1-C-q", io (exitWith ExitSuccess) )
|
|
-- Manipulate current client
|
|
, ("M4-w", kill1 )
|
|
, ("M4-s", toggleFloat )
|
|
-- focus client
|
|
, ("M4-h", sendMessage (Go L) )
|
|
, ("M4-j", sendMessage (Go D) )
|
|
, ("M4-k", sendMessage (Go U) )
|
|
, ("M4-l", sendMessage (Go R) )
|
|
-- focus client (easymotion)
|
|
, ("M4-;", selectWindow def >>= (`whenJust` windows . W.focusWindow))
|
|
-- Swap client
|
|
, ("M4-S-h", sendMessage $ Swap L)
|
|
, ("M4-S-j", sendMessage $ Swap D)
|
|
, ("M4-S-k", sendMessage $ Swap U)
|
|
, ("M4-S-l", sendMessage $ Swap R)
|
|
, ("M4-S-<Return>", windows $ W.swapMaster)
|
|
-- Move client
|
|
, ("M4-M1-S-h", sendMessage (Move L) )
|
|
, ("M4-M1-S-j", sendMessage (Move D) )
|
|
, ("M4-M1-S-k", sendMessage (Move U) )
|
|
, ("M4-M1-S-l", sendMessage (Move R) )
|
|
-- Fullscreen
|
|
, ("M4-f", sendMessage (Toggle FULL) )
|
|
-- Magnification
|
|
, ("M4-m", sendMessage (Mag.Toggle) )
|
|
, ("M4-[", sendMessage (Mag.MagnifyLess) )
|
|
, ("M4-]", sendMessage (Mag.MagnifyMore) )
|
|
-- Modify number of master windows
|
|
, ("M4-M1-j", sendMessage (IncMasterN (-1)))
|
|
, ("M4-M1-k", sendMessage (IncMasterN 1 ))
|
|
-- Resize master area
|
|
, ("M4-C-h", sendMessage Shrink)
|
|
, ("M4-C-l", sendMessage Expand)
|
|
-- Cycle through workspaces
|
|
, ("M4-<Left>", moveTo Prev spacesOnCurrentScreen )
|
|
, ("M4-<Right>", moveTo Next spacesOnCurrentScreen )
|
|
-- Cycle through empty workspaces
|
|
, ("M4-M1-<Left>", moveTo Prev emptySpacesOnCurrentScreen)
|
|
, ("M4-M1-<Right>", moveTo Next emptySpacesOnCurrentScreen)
|
|
-- Send window through workspaces
|
|
, ("M4-S-<Left>", shiftTo Prev spacesOnCurrentScreen )
|
|
, ("M4-S-<Right>", shiftTo Next spacesOnCurrentScreen )
|
|
-- Music player control (void)
|
|
, ("<XF86AudioPlay>", spawn "playerctl play-pause" )
|
|
, ("<Scroll_Lock>", spawn "playerctl previous" )
|
|
, ("<XF86AudioNext>", spawn "playerctl next" )
|
|
, ("<Pause>", spawn "cmus-remote -C player-next-album")
|
|
-- Music player control (t470)
|
|
, ("<XF86Bluetooth>", spawn "playerctl play-pause")
|
|
, ("<XF86Tools>", spawn "playerctl previous")
|
|
, ("<XF86Keyboard>", spawn "playerctl next") -- Potentially broken key
|
|
, ("<XF86Favorites>", spawn "cmus-remote -C player-next-album")
|
|
-- Audio control
|
|
, ("<XF86AudioMute>", spawn "wpctl set-mute @DEFAULT_SINK@ toggle")
|
|
, ("<XF86AudioLowerVolume>", spawn "wpctl set-volume @DEFAULT_SINK@ 1%-")
|
|
, ("<XF86AudioRaiseVolume>", spawn "wpctl set-volume @DEFAULT_SINK@ 1%+")
|
|
-- Mic control
|
|
, ("<XF86AudioMicMute>", spawn "wpctl set-mute @DEFAULT_SOURCE@ toggle")
|
|
, ("M1-<XF86AudioLowerVolume>", spawn "wpctl set-volume @DEFAULT_SOURCE@ 1%-")
|
|
, ("M1-<XF86AudioRaiseVolume>", spawn "wpctl set-volume @DEFAULT_SOURCE@ 1%+")
|
|
-- backlight control (t470)
|
|
, ("<XF86MonBrightnessDown>", spawn "brightnessctl set 1%-")
|
|
, ("<XF86MonBrightnessUp>", spawn "brightnessctl set 1%+")
|
|
-- backlight control (void)
|
|
, ("M4-<Prior>", spawn "ddcutil setvcp 10 + 10")
|
|
, ("M4-<Next>", spawn "ddcutil setvcp 10 - 10")
|
|
-- Reload configuration
|
|
, ("M4-<Escape>", spawn "xmonad --recompile; xmonad --restart")
|
|
] ++ concat [
|
|
-- Workspace switching
|
|
[ ("M4-" ++ i, windows $ onCurrentScreen W.view $ i)
|
|
-- Move window to workspace
|
|
, ("M4-S-" ++ i, windows $ onCurrentScreen W.shift $ i)
|
|
-- Copy window to workspace
|
|
, ("M4-M1-S-" ++ i, windows $ onCurrentScreen copy $ i) ]
|
|
| i <- myWorkspaceNames
|
|
]
|
|
|
|
-- https://stackoverflow.com/questions/33547168/xmonad-combine-dwm-style-workspaces-per-physical-screen-with-cycling-function
|
|
isOnScreen :: ScreenId -> WindowSpace -> Bool
|
|
isOnScreen s ws = s == unmarshallS (W.tag ws)
|
|
|
|
currentScreen :: X ScreenId
|
|
currentScreen = gets (W.screen . W.current . windowset)
|
|
|
|
spacesOnCurrentScreen :: WSType
|
|
spacesOnCurrentScreen = WSIs (isOnScreen <$> currentScreen)
|
|
|
|
emptySpacesOnCurrentScreen :: WSType
|
|
emptySpacesOnCurrentScreen = spacesOnCurrentScreen :&: emptyWS
|
|
|
|
myLayout = smartBorders
|
|
$ windowNavigation
|
|
$ mkToggle (single FULL)
|
|
$ (Mag.magnifiercz' 1.3 $ ThreeColMid 1 (3/100) (2/3))
|
|
||| Tall 1 (3/100) (2/3)
|
|
|
|
-- https://www.reddit.com/r/xmonad/comments/hm2tg0/how_to_toggle_floating_state_on_a_window/
|
|
-- Centre and float a window (retain size)
|
|
centreFloat win = do
|
|
(_, W.RationalRect x y w h) <- floatLocation win
|
|
windows $ W.float win (W.RationalRect ((1 - w) / 2) ((1 - h) / 2) w h)
|
|
return ()
|
|
|
|
-- If the window is floating then (f), if tiled then (n)
|
|
floatOrNot f n = withFocused $ \windowId -> do
|
|
floats <- gets (W.floating . windowset)
|
|
if windowId `M.member` floats -- if the current window is floating...
|
|
then f
|
|
else n
|
|
|
|
-- Float and centre a tiled window, sink a floating window
|
|
toggleFloat = floatOrNot (withFocused $ windows . W.sink) (withFocused float)
|