Okay, apparently the symlink somehow broke

So yeah. *Now* XMonad has been massively overhauled.
This commit is contained in:
Alexander Schmidt 2017-02-01 23:18:11 -06:00
parent 230845f938
commit 577301953a
1 changed files with 309 additions and 149 deletions

View File

@ -1,24 +1,73 @@
{-# OPTIONS -fno-warn-missing-signatures #-}
-- xmonad.hs
-- | Note: I copied the default configuration and (heavily) modified it
-- to ensure that everything was working correctly; I did this because I
-- was having issues with layouts not working correctly and I wanted to
-- ensure I was doing everything right. Also, nice comments explaining
-- what everything is doing is always a good thing.
import XMonad
import XMonad.Layout
import XMonad hiding ( (|||) )
import XMonad.Layout hiding ( (|||) )
import XMonad.Operations
import XMonad.ManageHook
import qualified XMonad.StackSet as W
import Data.Bits ((.|.))
import Data.Monoid
import qualified Data.Map as M
import System.Exit
import Graphics.X11.Xlib
import Graphics.X11.Xlib.Extras
-- Layout
import XMonad.Layout.IM
import XMonad.Layout.Gaps
import XMonad.Layout.Spacing
import XMonad.Layout.Reflect
import XMonad.Layout.NoBorders
import XMonad.Layout.ResizableTile
import XMonad.Layout.PerWorkspace
import XMonad.Layout.LayoutCombinators
import qualified XMonad.Layout.Renamed as R
-- Hooks
import XMonad.Hooks.DynamicLog
import XMonad.Hooks.DynamicBars
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.ManageHelpers
import XMonad.Hooks.EwmhDesktops
import XMonad.Hooks.ServerMode
import XMonad.Hooks.UrgencyHook
-- Actions
import XMonad.Actions.CycleWS
import XMonad.Actions.RotSlaves
import XMonad.Actions.Commands
import XMonad.Actions.PhysicalScreens
import XMonad.Actions.DynamicWorkspaces
import XMonad.Actions.Commands
import qualified XMonad.Actions.FlexibleResize as FR
import XMonad.Actions.FloatSnap
-- import XMonad.Actions.CopyWindow
-- import XMonad.Actions.Submap
-- import XMonad.Actions.GridSelect
-- import XMonad.Actions.CopyWindow
-- import XMonad.Actions.WindowMenu
-- Util
import XMonad.Util.Run
import XMonad.Util.SpawnOnce
import XMonad.Util.EZConfig
import XMonad.Util.WorkspaceCompare
import XMonad.Util.NamedScratchpad
import qualified XMonad.Util.ExtensibleState as XS
-- Prompt
import XMonad.Prompt
import XMonad.Prompt.Workspace
-- other
import qualified XMonad.StackSet as W
import qualified Data.Map as M
import Data.Monoid
import Data.Ratio ((%))
import System.IO
import System.Exit
import Graphics.X11.Types
import Graphics.X11.ExtraTypes.XF86
import qualified DBus as D
import qualified DBus.Client as D
import qualified Codec.Binary.UTF8.String as UTF8
-- | The default number of workspaces (virtual screens) and their names.
-- By default we use numeric strings, but any string may be used as a
@ -29,27 +78,41 @@ import Graphics.X11.Xlib.Extras
--
-- > workspaces = ["web", "irc", "code" ] ++ map show [4..9]
--
myWorkspaces :: [WorkspaceId]
myWorkspaces = map show [1 .. 9 :: Int]
-- workspaces' = map show [1 .. 9 :: Int]
workspaces' :: [WorkspaceId]
workspaces' = map show [ 1..9 :: Int]
-- | modMask lets you specify which modkey you want to use. The default
-- is mod1Mask ("left alt"). You may also consider using mod3Mask
-- ("right alt"), which does not conflict with emacs keybindings. The
-- "windows key" is usually mod4Mask.
--
myDefaultModMask :: KeyMask
myDefaultModMask = mod1Mask
modMask' :: KeyMask
modMask' = mod4Mask
-- | Width of the window border in pixels.
--
myBorderWidth :: Dimension
myBorderWidth = 1
borderWidth' :: Dimension
borderWidth' = 1
-- | Border colors for unfocused and focused windows, respectively.
--
myNormalBorderColor, myFocusedBorderColor :: String
myNormalBorderColor = "gray" -- "#dddddd"
myFocusedBorderColor = "red" -- "#ff0000" don't use hex, not <24 bit safe
normalBorderColor', focusedBorderColor' :: String
normalBorderColor' = "#1d1f21"
focusedBorderColor' = "#969896"
-- | The preferred terminal program, which is used in a binding below and by
-- certain contrib modules.
terminal' :: String
terminal' = "/usr/bin/termite"
-- | Whether focus follows the mouse pointer.
focusFollowsMouse' :: Bool
focusFollowsMouse' = False
-- | Whether a mouse click select the focus or is just passed to the window
clickJustFocuses' :: Bool
clickJustFocuses' = True
------------------------------------------------------------------------
-- Window rules
@ -62,11 +125,35 @@ myFocusedBorderColor = "red" -- "#ff0000" don't use hex, not <24 bit safe
-- To find the property name associated with a program, use
-- xprop | grep WM_CLASS
-- and click on the client you're interested in.
--
myManageHook :: ManageHook
myManageHook = composeAll
[ className =? "MPlayer" --> doFloat
, className =? "Gimp" --> doFloat ]
-- --
avoidMaster :: W.StackSet i l a s sd -> W.StackSet i l a s sd
avoidMaster = W.modify' $ modifyFunc
where modifyFunc c@(W.Stack t [] (r:rs)) = W.Stack t [r] rs
modifyFunc c@_ = c
manageHook' :: ManageHook
manageHook' = manageHooks'
<+> namedScratchpadManageHook scratchpads
<+> manageDocks
<+> transience'
manageHooks' :: ManageHook
manageHooks' = composeAll . concat $
[ [ className =? c --> doShift (workspaces' !! 0) | c <- browsers ]
, [ className =? c --> doShift (workspaces' !! 7) | c <- chatClients ]
, [ className =? c --> doCenterFloat | c <- scratchpadFloats ]
, [ className =? c --> doCenterFloat | c <- centerFloats ]
, [ windowRole =? d --> doCenterFloat | d <- dialogs ]
, [ fmap not isDialog --> doF avoidMaster
, isDialog --> doCenterFloat
, isFullscreen --> doFullFloat
] ]
where browsers = [ "Google-chrome" ]
chatClients = [ "TelegramDesktop", "discord", "Slack" ]
centerFloats = [ "Arandr", "VirtualBox" ]
dialogs = [ "GtkFileChooserDialog" ]
scratchpadFloats = [ "Zeal" ]
windowRole = stringProperty "WM_WINDOW_ROLE"
------------------------------------------------------------------------
-- Logging
@ -80,8 +167,42 @@ myManageHook = composeAll
--
-- See the 'DynamicLog' extension for examples.
--
myLogHook :: X ()
myLogHook = return ()
-- make a workspace clickable
clickable :: [Char] -> [Char]
clickable w = "<action=`xdotool key super+" ++ w ++ "`>" ++ w ++ "</action>"
xmobarCommand :: Show a => a -> [Char]
xmobarCommand s = "/usr/bin/xmobar ~/.xmonad/xmobarrc --screen=" ++ show s
statusBarCreator :: DynamicStatusBar
statusBarCreator (S sid) = do
spawnPipe . xmobarCommand $ sid
statusBarDestroyer :: DynamicStatusBarCleanup
statusBarDestroyer = do return ()
focusedStatusBarPP :: PP
focusedStatusBarPP = def
{ ppCurrent = xmobarColor "#81A2BE" "" . wrap "[" "]" . clickable
, ppHidden = xmobarColor "#707880" "" . clickable
, ppHiddenNoWindows = wrap "" "" . clickable
, ppTitle = shorten 40
, ppVisible = wrap "(" ")" . clickable
, ppUrgent = xmobarColor "#1d1f21" "#cc6666"
, ppWsSep = " "
, ppSep = " :: "
, ppOrder = \(ws:l:_:_) -> [ws, l]
}
unfocusedStatusBarPP :: PP
unfocusedStatusBarPP = def
{ ppCurrent = wrap "[" "]"
, ppWsSep = " "
}
logHook' = do
multiPP focusedStatusBarPP unfocusedStatusBarPP
------------------------------------------------------------------------
-- Event handling
@ -89,12 +210,20 @@ myLogHook = return ()
-- | Defines a custom handler function for X Events. The function should
-- return (All True) if the default handler is to be run afterwards.
-- To combine event hooks, use mappend or mconcat from Data.Monoid.
myHandleEventHook :: Event -> X All
myHandleEventHook _ = return (All True)
handleEventHook' :: Event -> X All
handleEventHook' =
serverModeEventHookCmd' defaultCommands'
<+> fullscreenEventHook
<+> docksEventHook
<+> dynStatusBarEventHook statusBarCreator statusBarDestroyer
-- | Perform an arbitrary action at xmonad startup.
myStartupHook :: X ()
myStartupHook = return ()
startupHook' :: X ()
startupHook' = do
dynStatusBarStartup statusBarCreator statusBarDestroyer
-- run startup script
spawnOnce "/home/alex/bin/xmonad-startup.sh"
------------------------------------------------------------------------
-- Extensible layouts
@ -107,146 +236,177 @@ myStartupHook = return ()
-- | The available layouts. Note that each layout is separated by |||, which
-- denotes layout choice.
myLayout = tiled ||| Mirror tiled ||| Full
where
-- default tiling algorithm partitions the screen into two panes
tiled = Tall nmaster delta ratio
-- The default number of windows in the master pane
nmaster = 1
layoutHook' = avoidStruts . smartBorders
. spacing 10 . gaps [(U, 15), (D, 20), (L, 20), (R, 20)]
$ onWorkspace(workspaces' !! 7) telegramLayout
$ layouts
where
layouts = resizable
||| Mirror resizable
||| noBorders Full
-- Default proportion of screen occupied by master pane
ratio = 1/2
-- resizable Tall layout
resizable = R.renamed [R.Replace "Tall"] $ ResizableTall nmaster delta ratio []
-- Percent of screen to increment by when resizing panes
delta = 3/100
-- The default number of windows in the master pane
nmaster = 1
------------------------------------------------------------------------
-- Key bindings:
-- Default proportion of screen occupied by master pane
ratio = toRational (2/(1 + sqrt 5 :: Double))
-- | The preferred terminal program, which is used in a binding below and by
-- certain contrib modules.
myTerminal :: String
myTerminal = "termite"
-- | Whether focus follows the mouse pointer.
myFocusFollowsMouse :: Bool
myFocusFollowsMouse = True
-- | Whether a mouse click select the focus or is just passed to the window
myClickJustFocuses :: Bool
myClickJustFocuses = True
-- Percent of screen to increment by when resizing panes
delta = 3/100
-- use 35% of the screen for telegram
telegramLayout = R.renamed [R.Replace "IM" ] $ reflectHoriz $ withIM (35%100) (ClassName "TelegramDesktop") ( reflectHoriz $ resizable ||| Mirror resizable)
-- | The xmonad key bindings. Add, modify or remove key bindings here.
--
-- (The comment formatting character is used when generating the manpage)
--
myKeys :: XConfig Layout -> M.Map (KeyMask, KeySym) (X ())
myKeys conf@(XConfig {XMonad.modMask = modMask}) = M.fromList $
-- launching and killing programs
[ ((modMask .|. shiftMask, xK_Return), spawn $ XMonad.terminal conf) -- %! Launch terminal
, ((modMask, xK_p ), spawn "dmenu_run") -- %! Launch dmenu
, ((modMask .|. shiftMask, xK_p ), spawn "gmrun") -- %! Launch gmrun
, ((modMask .|. shiftMask, xK_c ), kill) -- %! Close the focused window
-- myKeys :: XConfig Layout -> M.Map (KeyMask, KeySym) (X ())
-- myKeys conf@(XConfig {XMonad.modMask = modm}) = M.fromList $
, ((modMask, xK_space ), sendMessage NextLayout) -- %! Rotate through the available layout algorithms
, ((modMask .|. shiftMask, xK_space ), setLayout $ XMonad.layoutHook conf) -- %! Reset the layouts on the current workspace to default
keys' :: XConfig Layout -> M.Map (KeyMask, KeySym) (X ())
keys' conf@(XConfig {XMonad.modMask = modm}) = M.fromList $
[ ((modm .|. shiftMask, xK_Return), spawn $ XMonad.terminal conf) -- %! Launch terminal
, ((modm, xK_p ), spawn "dmenu_run") -- %! Launch dmenu
, ((modm .|. shiftMask, xK_p ), spawn "gmrun") -- %! Launch gmrun
, ((modm .|. shiftMask, xK_c ), kill) -- %! Close the focused window
, ((modMask, xK_n ), refresh) -- %! Resize viewed windows to the correct size
, ((modm, xK_space ), sendMessage NextLayout) -- %! Rotate through the available layout algorithms
, ((modm .|. shiftMask, xK_space ), setLayout $ XMonad.layoutHook conf) -- %! Reset the layouts on the current workspace to default
, ((modm, xK_n ), refresh) -- %! Resize viewed windows to the correct size
-- move focus up or down the window stack
, ((modMask, xK_Tab ), windows W.focusDown) -- %! Move focus to the next window
, ((modMask .|. shiftMask, xK_Tab ), windows W.focusUp ) -- %! Move focus to the previous window
, ((modMask, xK_j ), windows W.focusDown) -- %! Move focus to the next window
, ((modMask, xK_k ), windows W.focusUp ) -- %! Move focus to the previous window
, ((modMask, xK_m ), windows W.focusMaster ) -- %! Move focus to the master window
, ((modm, xK_Tab ), windows W.focusDown) -- %! Move focus to the next window
, ((modm .|. shiftMask, xK_Tab ), windows W.focusUp ) -- %! Move focus to the previous window
, ((modm, xK_j ), windows W.focusDown) -- %! Move focus to the next window
, ((modm, xK_k ), windows W.focusUp ) -- %! Move focus to the previous window
, ((modm, xK_m ), windows W.focusMaster ) -- %! Move focus to the master window
-- modifying the window order
, ((modMask, xK_Return), windows W.swapMaster) -- %! Swap the focused window and the master window
, ((modMask .|. shiftMask, xK_j ), windows W.swapDown ) -- %! Swap the focused window with the next window
, ((modMask .|. shiftMask, xK_k ), windows W.swapUp ) -- %! Swap the focused window with the previous window
, ((modm, xK_Return), windows W.swapMaster) -- %! Swap the focused window and the master window
, ((modm .|. shiftMask, xK_j ), windows W.swapDown ) -- %! Swap the focused window with the next window
, ((modm .|. shiftMask, xK_k ), windows W.swapUp ) -- %! Swap the focused window with the previous window
-- resizing the master/slave ratio
, ((modMask, xK_h ), sendMessage Shrink) -- %! Shrink the master area
, ((modMask, xK_l ), sendMessage Expand) -- %! Expand the master area
, ((modm, xK_h ), sendMessage Shrink) -- %! Shrink the master area
, ((modm, xK_l ), sendMessage Expand) -- %! Expand the master area
-- floating layer support
, ((modMask, xK_t ), withFocused $ windows . W.sink) -- %! Push window back into tiling
, ((modm, xK_t ), withFocused $ windows . W.sink) -- %! Push window back into tiling
-- increase or decrease number of windows in the master area
, ((modMask , xK_comma ), sendMessage (IncMasterN 1)) -- %! Increment the number of windows in the master area
, ((modMask , xK_period), sendMessage (IncMasterN (-1))) -- %! Deincrement the number of windows in the master area
, ((modm , xK_comma ), sendMessage (IncMasterN 1)) -- %! Increment the number of windows in the master area
, ((modm , xK_period), sendMessage (IncMasterN (-1))) -- %! Deincrement the number of windows in the master area
-- quit, or restart
, ((modMask .|. shiftMask, xK_q ), io (exitWith ExitSuccess)) -- %! Quit xmonad
, ((modMask , xK_q ), spawn "if type xmonad; then xmonad --recompile && xmonad --restart; else xmessage xmonad not in \\$PATH: \"$PATH\"; fi") -- %! Restart xmonad
, ((modm .|. shiftMask, xK_q ), io (exitWith ExitSuccess)) -- %! Quit xmonad
, ((modm , xK_q ), spawn "if type xmonad; then xmonad --recompile && xmonad --restart; else xmessage xmonad not in \\$PATH: \"$PATH\"; fi") -- %! Restart xmonad<Paste>
-- , ((modMask .|. shiftMask, xK_slash ), spawn ("echo \"" ++ help ++ "\" | xmessage -file -")) -- %! Run xmessage with a summary of the default keybindings (useful for beginners)
-- -- repeat the binding for non-American layout keyboards
-- , ((modMask , xK_question), spawn ("echo \"" ++ help ++ "\" | xmessage -file -"))
, ((0, xF86XK_AudioRaiseVolume), spawn "pactl set-sink-volume 1 +2%")
, ((0, xF86XK_AudioLowerVolume), spawn "pactl set-sink-volume 1 -2%")
-- media keys
, ((0, xF86XK_AudioMute), spawn "pactl set-sink-mute 1 toggle")
, ((0, xF86XK_AudioNext), spawn "mpc -q next")
, ((0, xF86XK_AudioPrev), spawn "mpc -q prev")
, ((0, xF86XK_AudioPlay), spawn "mpc toggle")
, ((0, xF86XK_AudioStop), spawn "mpc stop")
--
-- backlight
, ((0, xF86XK_MonBrightnessUp), spawn "light -A 1.5%")
, ((0, xF86XK_MonBrightnessDown), spawn "light -U 1.5%")
-- toggle struts 'n gaps
, ((modm, xK_b), sendMessage $ ToggleStruts)
, ((modm, xK_u), sendMessage $ ToggleGaps)
-- lock the screen
, ((controlMask .|. mod1Mask, xK_l), spawn "/home/alex/bin/lock")
-- resize windows vertically
, ((modm .|. shiftMask, xK_l), sendMessage MirrorShrink)
, ((modm .|. shiftMask, xK_h), sendMessage MirrorExpand)
-- rotate workspaces
, ((modm .|. shiftMask, xK_bracketleft ), rotAllUp)
, ((modm .|. shiftMask, xK_bracketright), rotAllDown)
-- move between workspaces
, ((modm, xK_bracketleft ), moveTo Prev (WSIs notNSP))
, ((modm, xK_bracketright ), moveTo Next (WSIs notNSP))
-- move between screens
, ((modm, xK_Right), nextScreen)
, ((modm, xK_Left), prevScreen)
-- shift windows between screens
, ((modm .|. shiftMask, xK_Right), shiftNextScreen)
, ((modm .|. shiftMask, xK_Left), shiftPrevScreen)
, ((mod1Mask .|. controlMask .|. shiftMask, xK_Right), shiftToNext >> nextWS)
, ((mod1Mask .|. controlMask .|. shiftMask, xK_Left), shiftToPrev >> prevWS)
-- swap current workspace with the previously displayed workspace
, ((modm, xK_z), namedScratchpadAction scratchpads "zeal")
, ((modm .|. shiftMask, xK_m ), workspacePrompt def (windows . W.shift))
, ((modm, xK_p), spawn "rofi -show run")
, ((modm .|. controlMask, xK_x), spawn "/home/alex/bin/lock")
]
++
-- mod-[1..9] %! Switch to workspace N
-- mod-shift-[1..9] %! Move client to workspace N
[((m .|. modMask, k), windows $ f i)
| (i, k) <- zip (XMonad.workspaces conf) [xK_1 .. xK_9]
, (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]]
++
-- mod-{w,e,r} %! Switch to physical/Xinerama screens 1, 2, or 3
-- mod-shift-{w,e,r} %! Move client to screen 1, 2, or 3
[((m .|. modMask, key), screenWorkspace sc >>= flip whenJust (windows . f))
| (key, sc) <- zip [xK_w, xK_e, xK_r] [0..]
, (f, m) <- [(W.view, 0), (W.shift, shiftMask)]]
++
[((mod4Mask .|. mask, key), f sc)
| (key, sc) <- zip [xK_w, xK_e] [0..]
, (f, mask) <- [(viewScreen, 0), (sendToScreen, shiftMask)]]
++
zip (zip (repeat (mod4Mask)) [xK_1..xK_9]) (map (withNthWorkspace W.greedyView) [0..])
++
zip (zip (repeat (mod4Mask .|. shiftMask)) [xK_1..xK_9]) (map (withNthWorkspace W.shift) [0..])
-- | Mouse bindings: default actions bound to mouse events
myMouseBindings :: XConfig Layout -> M.Map (KeyMask, Button) (Window -> X ())
myMouseBindings (XConfig {XMonad.modMask = modMask}) = M.fromList
-- mod-button1 %! Set the window to floating mode and move by dragging
[ ((modMask, button1), \w -> focus w >> mouseMoveWindow w
>> windows W.shiftMaster)
-- mod-button2 %! Raise the window to the top of the stack
, ((modMask, button2), windows . (W.shiftMaster .) . W.focusWindow)
-- mod-button3 %! Set the window to floating mode and resize by dragging
, ((modMask, button3), \w -> focus w >> mouseResizeWindow w
>> windows W.shiftMaster)
-- you may also bind events to the mouse scroll wheel (button4 and button5)
mouseBindings' (XConfig {XMonad.modMask = modm}) = M.fromList $
[ ((modm, button1), (\w -> focus w >> mouseMoveWindow w >> afterDrag (snapMagicMove (Just 50) (Just 50) w )))
, ((modm, button2), (\w -> focus w >> windows W.swapMaster >> afterDrag (snapMagicResize [L,R,U,D] (Just 50) (Just 50) w )))
, ((modm, button3), (\w -> focus w >> FR.mouseResizeWindow w >> afterDrag (snapMagicResize [L,R,U,D] (Just 50) (Just 50) w )))
]
--named scratchpads
scratchpads = [ NS "zeal" "zeal" (className =? "Zeal") defaultFloating ]
-- -- | The default set of configuration values itself
-- { borderWidth = borderWidth
-- , workspaces = workspaces
-- , layoutHook = layout
-- , terminal = terminal
-- , normalBorderColor = normalBorderColor
-- , focusedBorderColor = focusedBorderColor
-- , modMask = defaultModMask
-- , keys = keys
-- , logHook = logHook
-- , startupHook = startupHook
-- , mouseBindings = mouseBindings
-- , manageHook = manageHook
-- , handleEventHook = handleEventHook
-- , focusFollowsMouse = focusFollowsMouse
-- , clickJustFocuses = clickJustFocuses
-- }
-- Filter out the NSP workspace
notNSP = (return $ ("NSP" /=) . W.tag) :: X (WindowSpace -> Bool)
main = xmonad $ defaultConfig
{ borderWidth = myBorderWidth
, workspaces = myWorkspaces
, layoutHook = myLayout
, terminal = myTerminal
, normalBorderColor = myNormalBorderColor
, focusedBorderColor = myFocusedBorderColor
, modMask = myDefaultModMask
, keys = myKeys
, logHook = myLogHook
, startupHook = myStartupHook
, mouseBindings = myMouseBindings
, manageHook = myManageHook
, handleEventHook = myHandleEventHook
, focusFollowsMouse = myFocusFollowsMouse
, clickJustFocuses = myClickJustFocuses
}
-- custom command list
defaultCommands' :: X [(String, X ())]
defaultCommands' = do
return $ otherCommands
where
otherCommands =
[
("next-ws", moveTo Next (WSIs notNSP))
, ("prev-ws", moveTo Prev (WSIs notNSP))
]
main :: IO ()
main = do
xmonad $ withUrgencyHook NoUrgencyHook $ ewmh $ def
{ terminal = terminal'
, modMask = modMask'
, borderWidth = borderWidth'
, normalBorderColor = normalBorderColor'
, focusedBorderColor = focusedBorderColor'
, focusFollowsMouse = focusFollowsMouse'
, clickJustFocuses = clickJustFocuses'
, workspaces = workspaces'
, layoutHook = layoutHook'
, logHook = logHook'
, manageHook = manageHook'
, handleEventHook = handleEventHook'
, startupHook = startupHook'
, keys = keys'
, mouseBindings = mouseBindings'
}