2016-10-22 18:17:25 -06:00
|
|
|
{-# LANGUAGE TypeSynonymInstances, MultiParamTypeClasses #-}
|
2016-10-21 23:01:51 -06:00
|
|
|
import Control.Monad
|
|
|
|
import Data.Aeson
|
|
|
|
import qualified Data.ByteString.Lazy as B
|
|
|
|
import Data.List
|
|
|
|
import qualified Data.Map as M
|
|
|
|
import Data.Maybe
|
2016-10-05 04:23:40 -06:00
|
|
|
import Graphics.X11.ExtraTypes.XF86
|
2016-10-21 23:01:51 -06:00
|
|
|
import System.Directory
|
|
|
|
import System.FilePath.Posix
|
2016-10-26 17:47:18 -06:00
|
|
|
import System.Taffybar.Hooks.PagerHints
|
2016-10-21 17:37:26 -06:00
|
|
|
import Text.Printf
|
2016-09-16 15:38:11 -06:00
|
|
|
|
2016-09-15 22:47:23 -06:00
|
|
|
import XMonad hiding ( (|||) )
|
2016-10-05 02:30:30 -06:00
|
|
|
import XMonad.Actions.CycleWS
|
2016-10-23 02:57:08 -06:00
|
|
|
import qualified XMonad.Actions.DynamicWorkspaceOrder as DWO
|
2016-09-16 13:53:09 -06:00
|
|
|
import XMonad.Actions.WindowBringer
|
2016-10-24 20:41:21 -06:00
|
|
|
import XMonad.Actions.WindowGo
|
2016-10-22 18:16:52 -06:00
|
|
|
import XMonad.Actions.WorkspaceNames
|
2016-09-15 17:57:12 -06:00
|
|
|
import XMonad.Config ()
|
2016-09-13 03:50:25 -06:00
|
|
|
import XMonad.Hooks.EwmhDesktops
|
2016-09-13 13:51:06 -06:00
|
|
|
import XMonad.Hooks.ManageDocks
|
2016-09-27 18:25:36 -06:00
|
|
|
import XMonad.Hooks.FadeInactive
|
2016-10-03 15:57:58 -06:00
|
|
|
import XMonad.Layout.BoringWindows
|
2016-09-15 22:47:23 -06:00
|
|
|
import XMonad.Layout.LayoutCombinators
|
2016-10-22 18:17:25 -06:00
|
|
|
import XMonad.Layout.LayoutModifier
|
2016-10-03 15:57:58 -06:00
|
|
|
import XMonad.Layout.Minimize
|
2016-09-27 18:27:03 -06:00
|
|
|
import XMonad.Layout.MultiColumns
|
2016-09-15 02:49:15 -06:00
|
|
|
import XMonad.Layout.MultiToggle
|
|
|
|
import XMonad.Layout.MultiToggle.Instances
|
2016-09-14 17:56:37 -06:00
|
|
|
import XMonad.Layout.NoBorders
|
|
|
|
import XMonad.Layout.Spacing
|
2016-09-16 13:50:53 -06:00
|
|
|
import qualified XMonad.StackSet as W
|
2016-09-15 22:47:23 -06:00
|
|
|
import XMonad.Util.CustomKeys
|
2016-10-22 18:17:25 -06:00
|
|
|
import qualified XMonad.Util.ExtensibleState as XS
|
2016-10-14 04:52:09 -06:00
|
|
|
import XMonad.Util.NamedWindows (getName)
|
2016-09-14 17:56:37 -06:00
|
|
|
|
2016-10-26 17:47:18 -06:00
|
|
|
main = xmonad $ def
|
2016-10-26 14:23:44 -06:00
|
|
|
{ modMask = mod4Mask
|
|
|
|
, terminal = "urxvt"
|
|
|
|
, manageHook = manageDocks <+> myManageHook <+> manageHook def
|
|
|
|
, layoutHook = myLayoutHook
|
2016-10-27 01:17:42 -06:00
|
|
|
, logHook = toggleFadeInactiveLogHook 0.9 +++ ewmhWorkspaceNamesLogHook
|
2016-10-26 17:47:18 -06:00
|
|
|
, handleEventHook = docksEventHook <+> fullscreenEventHook +++ ewmhDesktopsEventHook +++ pagerHintsEventHook
|
2016-10-26 14:23:44 -06:00
|
|
|
, startupHook = myStartup +++ ewmhWorkspaceNamesLogHook
|
|
|
|
, keys = customKeys (const []) addKeys
|
|
|
|
} where
|
|
|
|
x +++ y = mappend y x
|
|
|
|
|
2016-10-26 16:19:49 -06:00
|
|
|
isHangoutsTitle = isPrefixOf "Google Hangouts"
|
|
|
|
|
|
|
|
chromeSelector = className =? "google-chrome" <&&> fmap (not . isHangoutsTitle) title
|
|
|
|
spotifySelector = className =? "Spotify"
|
|
|
|
emacsSelector = className =? "Emacs"
|
2016-10-26 17:47:18 -06:00
|
|
|
hangoutsSelector = className =? "google-chrome" <&&> fmap isHangoutsTitle title
|
2016-10-26 16:19:49 -06:00
|
|
|
|
|
|
|
-- Startup
|
|
|
|
|
|
|
|
myStartup = spawn "systemctl --user start wm.target"
|
|
|
|
|
|
|
|
-- Manage
|
|
|
|
|
|
|
|
myManageHook = composeAll . concat $
|
2016-10-27 02:47:17 -06:00
|
|
|
[ [ emacsSelector --> doShift "1" ]
|
|
|
|
, [ chromeSelector --> doShift "2" ]
|
|
|
|
, [ hangoutsSelector --> doShift "3"]
|
|
|
|
, [ spotifySelector --> doShift "4"]]
|
2016-10-26 16:19:49 -06:00
|
|
|
|
|
|
|
-- Layout
|
|
|
|
|
|
|
|
layouts = multiCol [1, 1] 2 0.01 (-0.5) ||| Full ||| Tall 1 (3/100) (1/2) ||| Tall 1 (3/100) (3/4)
|
|
|
|
|
2016-10-27 01:18:28 -06:00
|
|
|
myLayoutHook = avoidStruts . smartSpacing 10 . minimize . boringWindows .
|
|
|
|
mkToggle (MIRROR ?? EOT) . workspaceNamesHook . smartBorders .
|
|
|
|
noBorders $ layouts
|
2016-10-26 16:19:49 -06:00
|
|
|
|
|
|
|
-- WindowBringer
|
|
|
|
|
|
|
|
myWindowBringerConfig = WindowBringerConfig { menuCommand = "rofi"
|
|
|
|
, menuArgs = ["-dmenu", "-i"]
|
|
|
|
, windowTitler = myDecorateName
|
|
|
|
}
|
|
|
|
|
2016-10-21 22:58:14 -06:00
|
|
|
getClass w = do
|
|
|
|
classHint <- withDisplay $ \d -> io $ getClassHint d w
|
|
|
|
return $ resClass classHint
|
|
|
|
|
2016-10-20 18:58:25 -06:00
|
|
|
myDecorateName ws w = do
|
|
|
|
name <- show <$> getName w
|
2016-10-21 22:58:14 -06:00
|
|
|
classTitle <- getClass w
|
2016-10-22 18:16:52 -06:00
|
|
|
workspaceToName <- getWorkspaceNames
|
|
|
|
return $ printf "%-20s%-40s %+30s" classTitle (take 40 name) "in " ++ workspaceToName (W.tag ws)
|
2016-10-20 18:58:25 -06:00
|
|
|
|
2016-10-26 16:19:49 -06:00
|
|
|
-- Dynamic Workspace Renaming
|
2016-10-20 18:58:25 -06:00
|
|
|
|
2016-10-21 23:01:51 -06:00
|
|
|
getClassRemap = do
|
|
|
|
home <- getHomeDirectory
|
|
|
|
text <- B.readFile (home </> ".lib/class_remap.json")
|
|
|
|
return $ fromMaybe M.empty (decode text)
|
|
|
|
|
2016-10-22 18:17:25 -06:00
|
|
|
setWorkspaceNameToFocusedWindow workspace = do
|
|
|
|
namedWindows <- mapM getClass $ W.integrate' $ W.stack workspace
|
2016-10-21 23:01:51 -06:00
|
|
|
renamedWindows <- remapNames namedWindows
|
2016-10-22 18:17:25 -06:00
|
|
|
WorkspaceNames namesMap <- XS.get
|
|
|
|
let newName = intercalate "|" renamedWindows
|
|
|
|
currentName = M.findWithDefault "" (W.tag workspace) namesMap
|
|
|
|
when (currentName /= newName) $ setWorkspaceName (W.tag workspace) newName
|
2016-10-21 23:01:51 -06:00
|
|
|
|
|
|
|
remapNames namedWindows = do
|
|
|
|
remap <- io getClassRemap
|
|
|
|
return $ map (\original -> M.findWithDefault original original remap) namedWindows
|
2016-10-20 18:58:58 -06:00
|
|
|
|
2016-10-21 23:01:51 -06:00
|
|
|
setWorkspaceNames = do
|
2016-10-14 04:52:09 -06:00
|
|
|
ws <- gets windowset
|
|
|
|
mapM_ setWorkspaceNameToFocusedWindow (W.workspaces ws)
|
|
|
|
|
2016-10-22 18:17:25 -06:00
|
|
|
data WorkspaceNamesHook a = WorkspaceNamesHook deriving (Show, Read)
|
|
|
|
|
|
|
|
instance LayoutModifier WorkspaceNamesHook Window where
|
|
|
|
hook _ = setWorkspaceNames
|
|
|
|
|
|
|
|
workspaceNamesHook = ModifiedLayout WorkspaceNamesHook
|
|
|
|
|
2016-10-26 16:19:49 -06:00
|
|
|
-- EWMH support for workspace names
|
2016-09-16 13:50:53 -06:00
|
|
|
|
2016-10-26 16:19:49 -06:00
|
|
|
ewmhWorkspaceNamesLogHook = do
|
|
|
|
WorkspaceNames namesMap <- XS.get
|
2016-10-26 17:47:18 -06:00
|
|
|
let tagRemapping = getWorkspaceNameFromTag namesMap
|
|
|
|
pagerHintsLogHookCustom tagRemapping
|
|
|
|
ewmhDesktopsLogHookCustom id tagRemapping
|
2016-10-13 01:11:21 -06:00
|
|
|
|
2016-10-26 16:19:49 -06:00
|
|
|
getWorkspaceNameFromTag namesMap tag =
|
|
|
|
case M.lookup tag namesMap of
|
|
|
|
Nothing -> tag
|
|
|
|
Just label -> printf "%s: %s " tag label
|
2016-10-13 01:11:21 -06:00
|
|
|
|
2016-10-26 16:19:49 -06:00
|
|
|
shiftThenView i = W.greedyView i . W.shift i
|
2016-10-13 01:11:21 -06:00
|
|
|
|
2016-10-27 01:17:42 -06:00
|
|
|
-- Toggleable fade
|
|
|
|
|
|
|
|
newtype ToggleFade = ToggleFade (M.Map Window Bool)
|
|
|
|
deriving (Typeable, Read, Show)
|
|
|
|
|
|
|
|
instance ExtensionClass ToggleFade where
|
|
|
|
initialValue = ToggleFade M.empty
|
|
|
|
extensionType = PersistentExtension
|
|
|
|
|
|
|
|
fadeEnabledForWindow = ask >>= \w -> liftX (do
|
|
|
|
ToggleFade toggleMap <- XS.get
|
|
|
|
return $ M.findWithDefault True w toggleMap)
|
|
|
|
|
|
|
|
toggleFadeInactiveLogHook = fadeOutLogHook . fadeIf (isUnfocused <&&> fadeEnabledForWindow)
|
|
|
|
|
|
|
|
toggleFadingForActiveWindow = withWindowSet $ \windowSet -> do
|
|
|
|
ToggleFade toggleMap <- XS.get
|
|
|
|
let maybeWindow = W.peek windowSet
|
|
|
|
case maybeWindow of
|
|
|
|
Nothing -> return ()
|
|
|
|
Just window -> do
|
|
|
|
let existingValue = M.findWithDefault True window toggleMap
|
|
|
|
XS.put $ ToggleFade (M.insert window (not existingValue) toggleMap)
|
|
|
|
return ()
|
|
|
|
|
2016-10-23 18:32:27 -06:00
|
|
|
-- Use greedyView to switch to the correct workspace, and then focus on the
|
|
|
|
-- appropriate window within that workspace.
|
|
|
|
greedyFocusWindow w ws = W.focusWindow w $ W.greedyView
|
|
|
|
(fromMaybe (W.currentTag ws) $ W.findTag w ws) ws
|
2016-10-23 02:34:31 -06:00
|
|
|
|
2016-10-23 18:32:27 -06:00
|
|
|
shiftToEmptyAndView = doTo Next EmptyWS DWO.getSortByOrder
|
|
|
|
(windows . shiftThenView)
|
2016-10-23 02:57:08 -06:00
|
|
|
|
2016-10-26 19:11:18 -06:00
|
|
|
myRaiseNextMaybe = raiseNextMaybeCustomFocus greedyFocusWindow
|
|
|
|
myBringNextMaybe = raiseNextMaybeCustomFocus bringWindow
|
|
|
|
|
|
|
|
bindBringAndRaise :: KeyMask -> KeySym -> X () -> Query Bool -> [((KeyMask, KeySym), X ())]
|
|
|
|
bindBringAndRaise mask sym start query =
|
|
|
|
[ ((mask, sym), myRaiseNextMaybe start query)
|
|
|
|
, ((mask .|. controlMask, sym), myBringNextMaybe start query)]
|
|
|
|
|
|
|
|
bindBringAndRaiseMany :: [(KeyMask, KeySym, X (), Query Bool)] -> [((KeyMask, KeySym), X())]
|
|
|
|
bindBringAndRaiseMany = concatMap (\(a, b, c, d) -> bindBringAndRaise a b c d)
|
|
|
|
|
2016-09-16 13:50:53 -06:00
|
|
|
addKeys conf@XConfig {modMask = modm} =
|
2016-09-15 17:57:12 -06:00
|
|
|
[ ((modm, xK_p), spawn "rofi -show drun")
|
2016-09-19 12:07:03 -06:00
|
|
|
, ((modm .|. shiftMask, xK_p), spawn "rofi -show run")
|
2016-10-23 02:34:31 -06:00
|
|
|
, ((modm, xK_g), actionMenu myWindowBringerConfig greedyFocusWindow)
|
2016-10-20 18:58:25 -06:00
|
|
|
, ((modm, xK_b), bringMenuConfig myWindowBringerConfig)
|
2016-10-05 03:20:35 -06:00
|
|
|
, ((modm .|. controlMask, xK_t), spawn
|
|
|
|
"systemctl --user restart taffybar.service")
|
2016-10-03 18:49:44 -06:00
|
|
|
, ((modm, xK_v), spawn "copyq paste")
|
2016-10-05 02:30:30 -06:00
|
|
|
, ((modm, xK_s), swapNextScreen)
|
2016-09-15 22:47:23 -06:00
|
|
|
, ((modm .|. controlMask, xK_space), sendMessage $ JumpToLayout "Full")
|
|
|
|
, ((modm, xK_slash), sendMessage $ Toggle MIRROR)
|
2016-10-03 15:57:58 -06:00
|
|
|
, ((modm, xK_m), withFocused minimizeWindow)
|
2016-10-03 17:50:21 -06:00
|
|
|
, ((modm .|. shiftMask, xK_m), sendMessage RestoreNextMinimizedWin)
|
2016-10-24 18:17:35 -06:00
|
|
|
, ((modm, xK_backslash), toggleWS)
|
2016-10-05 03:20:35 -06:00
|
|
|
|
|
|
|
-- Hyper bindings
|
2016-10-27 01:17:42 -06:00
|
|
|
, ((mod3Mask, xK_1), toggleFadingForActiveWindow)
|
2016-10-23 02:57:08 -06:00
|
|
|
, ((mod3Mask, xK_e), moveTo Next EmptyWS )
|
|
|
|
, ((mod3Mask .|. shiftMask, xK_e), shiftToEmptyAndView)
|
2016-10-05 03:20:35 -06:00
|
|
|
, ((mod3Mask, xK_v), spawn "copyq_rofi.sh")
|
2016-10-13 01:08:49 -06:00
|
|
|
, ((mod3Mask, xK_p), spawn "system_password.sh")
|
2016-10-24 18:17:19 -06:00
|
|
|
, ((mod3Mask, xK_h), spawn "screenshot.sh")
|
2016-10-18 15:10:32 -06:00
|
|
|
, ((mod3Mask, xK_c), spawn "shell_command.sh")
|
2016-10-05 03:20:35 -06:00
|
|
|
|
|
|
|
-- playerctl
|
2016-10-05 04:23:40 -06:00
|
|
|
, ((mod3Mask, xK_f), spawn "playerctl play-pause")
|
|
|
|
, ((0, xF86XK_AudioPause), spawn "playerctl play-pause")
|
2016-10-05 03:20:35 -06:00
|
|
|
, ((mod3Mask, xK_d), spawn "playerctl next")
|
2016-10-05 04:23:40 -06:00
|
|
|
, ((0, xF86XK_AudioNext), spawn "playerctl next")
|
|
|
|
, ((mod3Mask, xK_a), spawn "playerctl previous")
|
|
|
|
, ((0, xF86XK_AudioPrev), spawn "playerctl previous")
|
|
|
|
|
|
|
|
-- volume control
|
2016-10-05 17:32:53 -06:00
|
|
|
, ((0, xF86XK_AudioRaiseVolume), spawn "pactl set-sink-volume 0 +05%")
|
|
|
|
, ((0, xF86XK_AudioLowerVolume), spawn "pactl set-sink-volume 0 -05%")
|
2016-10-05 04:23:40 -06:00
|
|
|
, ((0, xF86XK_AudioMute), spawn "pactl set-sink-mute 0 toggle")
|
2016-10-05 17:32:53 -06:00
|
|
|
, ((mod3Mask, xK_w), spawn "pactl set-sink-volume 0 +05%")
|
|
|
|
, ((mod3Mask, xK_s), spawn "pactl set-sink-volume 0 -05%")
|
2016-10-13 01:09:35 -06:00
|
|
|
|
2016-10-26 19:11:18 -06:00
|
|
|
] ++ bindBringAndRaiseMany
|
2016-10-13 01:09:35 -06:00
|
|
|
|
2016-10-26 19:11:18 -06:00
|
|
|
[ (modalt, xK_s, spawn "spotify", spotifySelector)
|
|
|
|
, (modalt, xK_e, spawn "emacsclient -c", emacsSelector)
|
2016-10-27 02:46:35 -06:00
|
|
|
, (modalt, xK_c, spawn "google-chrome-stable", chromeSelector)
|
2016-10-26 19:11:18 -06:00
|
|
|
, (modalt, xK_h, spawn "cool", hangoutsSelector)
|
|
|
|
] ++
|
2016-09-16 13:50:53 -06:00
|
|
|
-- Replace original moving stuff around + greedy view bindings
|
|
|
|
[((additionalMask .|. modm, key), windows $ function workspace)
|
|
|
|
| (workspace, key) <- zip (workspaces conf) [xK_1 .. xK_9]
|
|
|
|
, (function, additionalMask) <-
|
|
|
|
[ (W.greedyView, 0)
|
|
|
|
, (W.shift, shiftMask)
|
|
|
|
, (shiftThenView, controlMask)]]
|
2016-10-24 20:41:21 -06:00
|
|
|
where
|
|
|
|
modalt = modm .|. mod1Mask
|
2016-10-14 04:52:09 -06:00
|
|
|
|
|
|
|
-- Local Variables:
|
|
|
|
-- flycheck-ghc-args: ("-Wno-missing-signatures")
|
|
|
|
-- End:
|