xmonad.hs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. import XMonad
  2. import XMonad.Hooks.DynamicLog(dynamicLogWithPP
  3. , xmobarPP
  4. , ppOutput
  5. , ppLayout
  6. , ppTitle)
  7. import XMonad.Hooks.ManageDocks(docks, docksEventHook, manageDocks, avoidStruts)
  8. import XMonad.Util.Run(spawnPipe, hPutStrLn, runProcessWithInput)
  9. import XMonad.Util.SpawnOnce(spawnOnce)
  10. -- Layouts
  11. import XMonad.Layout.Spacing(smartSpacing)
  12. import XMonad.Layout.Tabbed(simpleTabbed)
  13. import XMonad.Layout.NoBorders(withBorder, smartBorders)
  14. import XMonad.Layout.IndependentScreens(countScreens)
  15. -- Shutdown commands and keys
  16. import Data.Map(fromList)
  17. import XMonad.Util.EZConfig(removeKeys)
  18. -- For starting up a list of programs
  19. import Data.List(elemIndex, foldl1')
  20. import qualified XMonad.StackSet as W
  21. import qualified Data.Map as M
  22. import XMonad.Config.Kde(kde4Config, desktopLayoutModifiers)
  23. import XMonad.Hooks.EwmhDesktops(ewmh, fullscreenEventHook)
  24. myModMask = mod4Mask
  25. myTerminal = "konsole"
  26. -- Only show workspaces on xmobar, as everything else will be on KDE's panels
  27. myPP = xmobarPP { ppTitle = \_ -> ""
  28. , ppLayout = \_ -> ""}
  29. -- Make xmobar workspaces clickable
  30. xmobarEscape = concatMap doubleLts
  31. where doubleLts '<' = "<<"
  32. doubleLts x = [x]
  33. myWorkspaces = clickable . (map xmobarEscape) $ map show [1..9]
  34. where
  35. clickable l = [ "<action=xdotool key super+" ++ show (n) ++ ">" ++ ws ++ "</action>" |
  36. (i,ws) <- zip [1..9] l,
  37. let n = i ]
  38. main = do
  39. -- Spawn an xmobar on each screen
  40. nScreen <- countScreens
  41. xmprocs <- mapM (\dis -> spawnPipe ("xmobar -x " ++ show dis)) [0..nScreen-1]
  42. xmonad $ ewmh $ docks $ kde4Config {
  43. manageHook = manageDocks <+> myManageHook <+> manageHook kde4Config
  44. , workspaces = myWorkspaces
  45. , layoutHook = avoidStruts $ desktopLayoutModifiers $ smartBorders $
  46. (smartSpacing 5 $ withBorder 2 $ Tall 1 (3/100) (1/2)) |||
  47. (smartSpacing 5 $ withBorder 2 $ Mirror (Tall 1 (3/100) (1/2))) |||
  48. -- Full |||
  49. -- Tabs are bugged/don't work in ewmh. On the
  50. -- bright side, it makes a window float over KDE's
  51. -- bar, which is what I want fullscreen to do.
  52. -- It's not a bug, it's a feature.
  53. simpleTabbed
  54. -- Write signals to all xmobars.
  55. , logHook = dynamicLogWithPP myPP {
  56. ppOutput = \s -> sequence_ [hPutStrLn h s | h <- xmprocs]
  57. }
  58. , startupHook = sequence_ [spawnOnce s | s <- startupList]
  59. , handleEventHook = handleEventHook kde4Config <+> fullscreenEventHook <+> docksEventHook
  60. , modMask = mod4Mask
  61. , keys = \c -> myKeys c `M.union` keys kde4Config c
  62. }
  63. `removeKeys` myRemoveKeys
  64. myKeys conf@(XConfig {XMonad.modMask = myModMask}) = M.fromList $
  65. -- extra programs
  66. [ ((myModMask, xK_x),
  67. spawn "emacsclient -c")
  68. , ((myModMask, xK_z),
  69. spawn "firefox-nightly")
  70. , ((myModMask, xK_p),
  71. spawn "krunner")
  72. , ((myModMask, xK_m),
  73. spawn ":")
  74. -- TODO put social stuff here (Discord, Riot) and open it on a particular workspace
  75. -- defaults
  76. -- Spawn terminal.
  77. , ((myModMask .|. shiftMask, xK_Return),
  78. spawn myTerminal)
  79. -- Close focused window.
  80. , ((myModMask .|. shiftMask, xK_c),
  81. kill)
  82. -- Cycle through the available layout algorithms.
  83. , ((myModMask, xK_space),
  84. sendMessage NextLayout)
  85. -- Reset the layouts on the current workspace to default.
  86. , ((myModMask .|. shiftMask, xK_space),
  87. setLayout $ XMonad.layoutHook conf)
  88. -- Resize viewed windows to the correct size.
  89. , ((myModMask, xK_n),
  90. refresh)
  91. -- Move focus to the next window.
  92. , ((myModMask, xK_Tab),
  93. windows W.focusDown)
  94. -- Move focus to the next window.
  95. , ((myModMask, xK_j),
  96. windows W.focusDown)
  97. -- Move focus to the previous window.
  98. , ((myModMask, xK_k),
  99. windows W.focusUp )
  100. -- Move focus to the master window.
  101. , ((myModMask, xK_m),
  102. windows W.focusMaster )
  103. -- Swap the focused window and the master window.
  104. , ((myModMask, xK_Return),
  105. windows W.swapMaster)
  106. -- Swap the focused window with the next window.
  107. , ((myModMask .|. shiftMask, xK_j),
  108. windows W.swapDown )
  109. -- Swap the focused window with the previous window.
  110. , ((myModMask .|. shiftMask, xK_k),
  111. windows W.swapUp )
  112. -- Shrink the master area.
  113. , ((myModMask, xK_h),
  114. sendMessage Shrink)
  115. -- Expand the master area.
  116. , ((myModMask, xK_l),
  117. sendMessage Expand)
  118. -- Push window back into tiling.
  119. , ((myModMask, xK_t),
  120. withFocused $ windows . W.sink)
  121. -- Increment the number of windows in the master area.
  122. , ((myModMask, xK_comma),
  123. sendMessage (IncMasterN 1))
  124. -- Decrement the number of windows in the master area.
  125. , ((myModMask, xK_period),
  126. sendMessage (IncMasterN (-1)))
  127. -- Toggle the status bar gap.
  128. -- Restart xmonad.
  129. , ((myModMask, xK_q),
  130. restart "xmonad" True)
  131. ]
  132. ++
  133. -- mod-[1..9], Switch to workspace N
  134. -- mod-shift-[1..9], Move client to workspace N
  135. [ ((m .|. myModMask, k), windows $ f i)
  136. | (i, k) <- zip (XMonad.workspaces conf) [xK_1 .. xK_9]
  137. , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]
  138. ]
  139. ++
  140. -- mod-{w,e,r}, Switch to physical/Xinerama screens 1, 2, or 3
  141. -- mod-shift-{w,e,r}, Move client to screen 1, 2, or 3
  142. [ ((m .|. myModMask, key), screenWorkspace sc >>= flip whenJust (windows . f))
  143. | (key, sc) <- zip [xK_w, xK_e, xK_r] [0..]
  144. , (f, m) <- [(W.view, 0), (W.shift, shiftMask)]
  145. ]
  146. myRemoveKeys =
  147. [ (mod4Mask, xK_Tab)
  148. , (mod4Mask .|. shiftMask, xK_Tab)
  149. ]
  150. myManageHook = composeAll . concat $
  151. [ [ className =? c --> doFloat | c <- myFloats]
  152. , [ title =? p --> doFloat | p <- plasmaWindows]
  153. , [ className =? "plasmashell" --> doIgnore ]
  154. ]
  155. where myFloats = ["Gimp"]
  156. plasmaWindows =
  157. [ "yakuake"
  158. , "Yakuake"
  159. , "Kmix"
  160. , "kmix"
  161. , "plasma"
  162. , "Plasma"
  163. , "plasma-desktop"
  164. , "Plasma-desktop"
  165. , "krunner"
  166. , "ksplashsimple"
  167. , "ksplashqml"
  168. , "ksplashx"
  169. ]
  170. startupList :: [String]
  171. startupList =
  172. [ "compton"
  173. , "nextcloud"
  174. -- TODO find a way around this dirty hack
  175. , "sleep 5 && for i in `xdotool search --all --name xmobar`; do xdotool windowraise $i; done"
  176. ]