xmonad.hs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. {-# LANGUAGE OverloadedStrings #-}
  2. {-# LANGUAGE PackageImports #-}
  3. import XMonad
  4. import XMonad.Config.Desktop
  5. import XMonad.Hooks.DynamicLog
  6. import XMonad.Hooks.ManageDocks
  7. import XMonad.Util.Run(spawnPipe, hPutStrLn, runProcessWithInput)
  8. -- Layouts
  9. import XMonad.Layout.Spacing(smartSpacing)
  10. import XMonad.Layout.Tabbed
  11. import XMonad.Layout.NoBorders
  12. -- Shutdown commands and keys
  13. import Data.Map(fromList)
  14. import XMonad.Prompt
  15. import XMonad.Prompt.XMonad
  16. import System.Exit(ExitCode(ExitSuccess), exitWith)
  17. import XMonad.Util.EZConfig(additionalKeys, removeKeys)
  18. -- Brightness and audio keys
  19. import Graphics.X11.ExtraTypes.XF86
  20. import Data.List(elemIndex, foldl1')
  21. -- kde
  22. import XMonad.Config.Kde
  23. import XMonad.Hooks.EwmhDesktops
  24. import Control.Exception
  25. import "DBus" DBus
  26. import "DBus" DBus.Connection as DC
  27. import "DBus" DBus.Message
  28. import qualified Codec.Binary.UTF8.String as UTF8
  29. prettyPrinter :: DC.Connection -> PP
  30. prettyPrinter dbus = defaultPP
  31. { ppOutput = dbusOutput dbus
  32. , ppCurrent = wrap "[" "]"
  33. , ppSep = " | "
  34. }
  35. getWellKnownName :: DC.Connection -> IO ()
  36. getWellKnownName dbus = tryGetName `catch` (\(DBus.Error _ _) -> getWellKnownName dbus)
  37. where
  38. tryGetName = do
  39. namereq <- newMethodCall serviceDBus pathDBus interfaceDBus "RequestName"
  40. addArgs namereq [String "org.xmonad.Log", Word32 5]
  41. sendWithReplyAndBlock dbus namereq 0
  42. return ()
  43. dbusOutput :: DC.Connection -> String -> IO ()
  44. dbusOutput dbus str = do
  45. msg <- newSignal "/org/xmonad/Log" "org.xmonad.Log" "Update"
  46. addArgs msg [String (UTF8.decodeString str)]
  47. -- If the send fails, ignore it.
  48. send dbus msg 0 `catch` (\(DBus.Error _ _) -> return 0)
  49. return ()
  50. main :: IO ()
  51. -- main = do
  52. main = withConnection Session $ \dbus -> do
  53. getWellKnownName dbus
  54. xmonad $ ewmh $ docks kde4Config
  55. { manageHook = manageHook kdeConfig <+> myManageHook
  56. , logHook = dynamicLogWithPP (prettyPrinter dbus)
  57. , layoutHook = smartBorders $ avoidStruts $
  58. (smartSpacing 5 $ withBorder 2 $ Tall 1 (3/100) (1/2)) |||
  59. (smartSpacing 5 $ withBorder 2 $ Mirror (Tall 1 (3/100) (1/2))) |||
  60. -- Full |||
  61. -- Tabs are bugged/don't work in ewmh. On the
  62. -- bright side, it makes a window float over KDE's
  63. -- bar, which is what I want fullscreen to do.
  64. -- It's not a bug, it's a feature.
  65. simpleTabbed
  66. , startupHook = startup
  67. , handleEventHook = handleEventHook def <+> fullscreenEventHook
  68. , modMask = mod4Mask
  69. } `additionalKeys` myKeys `removeKeys` myRemoveKeys
  70. myRemoveKeys =
  71. [ (mod4Mask, xK_Tab)
  72. , (mod4Mask .|. shiftMask, xK_Tab)
  73. , (mod4Mask, xK_p)
  74. ]
  75. myManageHook = composeAll . concat $
  76. [ [ className =? c --> doFloat | c <- myFloats]
  77. , [ title =? p --> doFloat | p <- plasmaWindows]
  78. ]
  79. where myFloats = ["Gimp"]
  80. plasmaWindows =
  81. [ "yakuake"
  82. , "Yakuake"
  83. , "Kmix"
  84. , "kmix"
  85. , "plasma"
  86. , "Plasma"
  87. , "plasma-desktop"
  88. , "Plasma-desktop"
  89. , "krunner"
  90. , "ksplashsimple"
  91. , "ksplashqml"
  92. , "ksplashx"
  93. ]
  94. startupList :: [String]
  95. startupList =
  96. [ "compton"
  97. , "owncloud"
  98. ]
  99. startup :: X ()
  100. startup = do
  101. foldl1' (>>) $ map (spawn . ifNotRunning) startupList
  102. -- Wrap a command in Bash that checks if it's running.
  103. ifNotRunning :: String -> String
  104. ifNotRunning s = "if [ `pgrep -c " ++ (basename s) ++ "` == 0 ]; then " ++ s ++ "; fi"
  105. -- Grab the program name from a command (everything up to the space,
  106. -- if there's a space). Doesn't work with escaped spaces.
  107. basename :: String -> String
  108. basename s = case elemIndex ' ' s of
  109. (Just n) -> take n s
  110. Nothing -> s
  111. myKeys = [
  112. -- extra programs
  113. ((mod4Mask, xK_x),
  114. spawn "emacsclient -c")
  115. , ((mod4Mask, xK_z),
  116. spawn "firefox-nightly")
  117. , ((mod4Mask, xK_m),
  118. spawn ":"
  119. -- TODO put social stuff here (Discord, Riot) and open it on a particular workspace
  120. )
  121. ]