diff --git a/.config/xmonad/README.org b/.config/xmonad/README.org
index f2d5364..6e3483c 100644
--- a/.config/xmonad/README.org
+++ b/.config/xmonad/README.org
@@ -2,42 +2,83 @@
#+author: Phil Bajsicki
#+PROPERTY: header-args :tangle xmonad.hs
-* Info:
+
+* Table of Contents :toc:
+- [[#info][Info]]
+- [[#imports][Imports]]
+ - [[#base][Base]]
+ - [[#actions][Actions]]
+ - [[#data][Data]]
+ - [[#hooks][Hooks]]
+ - [[#layouts][Layouts]]
+ - [[#layout-modifiers][Layout Modifiers]]
+ - [[#xmonadprompt][XMonad.Prompt]]
+ - [[#utilities][Utilities]]
+ - [[#colorschemes][Colorschemes]]
+- [[#window-management-and-layouts][Window Management and Layouts]]
+ - [[#border-width-and-spacing][Border Width and Spacing]]
+ - [[#layouts-1][Layouts]]
+ - [[#theming-for-tabs-sublayout][Theming for tabs (sub)layout]]
+ - [[#clickable-workspaces-in-xmobar][Clickable workspaces in XMobar]]
+ - [[#workspace-definitions][Workspace definitions]]
+ - [[#manage-hook][Manage Hook]]
+ - [[#startup-hook][Startup Hook]]
+- [[#main-xmonad-loop][Main XMonad loop]]
+ - [[#xmobar][XMobar]]
+ - [[#xmonad--managehook][XMonad & manageHook]]
+- [[#keybinds][Keybinds]]
+ - [[#workspaces][Workspaces]]
+ - [[#window-focus-and-movement][Window focus and movement]]
+ - [[#sublayouts][Sublayouts]]
+ - [[#xmonad-and-apps][XMonad and apps]]
+
+* Info
This is my XMonad config. It's heavily based on Derek Taylor's config from DTOS.
+The notable things I changed are noted in their specific sections.
+
* Imports
+** Base
+
#+begin_src haskell
--- Base
import XMonad
import System.Directory
import System.IO (hClose, hPutStr, hPutStrLn)
import System.Exit (exitSuccess)
import qualified XMonad.StackSet as W
+#+end_src
- -- Actions
+
+** Actions
+#+begin_src haskell
import XMonad.Actions.CopyWindow (kill1)
import XMonad.Actions.CycleWS
import XMonad.Actions.GridSelect
import XMonad.Actions.MouseResize
import XMonad.Actions.Promote
import XMonad.Actions.RotSlaves (rotSlavesDown, rotAllDown)
+import XMonad.Actions.SpawnOn
import XMonad.Actions.UpdatePointer
import XMonad.Actions.WindowGo (runOrRaise)
import XMonad.Actions.WithAll (sinkAll, killAll)
import qualified XMonad.Actions.Search as S
+#+end_src
- -- Data
+** Data
+#+begin_src haskell
import Data.Char (isSpace, toUpper)
import Data.Maybe (fromJust)
import Data.Monoid
import Data.Maybe (isJust)
import Data.Tree
import qualified Data.Map as M
+#+end_src
- -- Hooks
+** Hooks
+#+begin_src haskell
import XMonad.Hooks.DynamicLog (dynamicLogWithPP, wrap, xmobarPP, xmobarColor, shorten, PP(..))
import XMonad.Hooks.EwmhDesktops -- for some fullscreen events, also for xcomposite in obs.
import XMonad.Hooks.ManageDocks (avoidStruts, docks, manageDocks, ToggleStruts(..))
@@ -48,8 +89,10 @@ import XMonad.Hooks.StatusBar
import XMonad.Hooks.StatusBar.PP
import XMonad.Hooks.WindowSwallowing
import XMonad.Hooks.WorkspaceHistory
+#+end_src
- -- Layouts
+** Layouts
+#+begin_src haskell
import XMonad.Layout.Accordion
import XMonad.Layout.GridVariants (Grid(Grid))
import XMonad.Layout.SimplestFloat
@@ -57,8 +100,10 @@ import XMonad.Layout.Spiral
import XMonad.Layout.ResizableTile
import XMonad.Layout.Tabbed
import XMonad.Layout.ThreeColumns
+#+end_src
- -- Layouts modifiers
+** Layout Modifiers
+#+begin_src haskell
import XMonad.Layout.LayoutModifier
import XMonad.Layout.LimitWindows (limitWindows, increaseLimit, decreaseLimit)
import XMonad.Layout.MultiToggle (mkToggle, single, EOT(EOT), (??))
@@ -73,11 +118,17 @@ import XMonad.Layout.WindowArranger (windowArrange, WindowArrangerMsg(..))
import XMonad.Layout.WindowNavigation
import qualified XMonad.Layout.ToggleLayouts as T (toggleLayouts, ToggleLayout(Toggle))
import qualified XMonad.Layout.MultiToggle as MT (Toggle(..))
+#+end_src
+** XMonad.Prompt
+#+begin_src haskell
import XMonad.Prompt
import XMonad.Prompt.OrgMode
+#+end_src
--- Utilities
+
+** Utilities
+#+begin_src haskell
import XMonad.Util.Dmenu
import XMonad.Util.EZConfig
import XMonad.Util.NamedActions
@@ -85,40 +136,48 @@ import XMonad.Util.NamedScratchpad
import XMonad.Util.Run (runProcessWithInput, safeSpawn, spawnPipe)
import XMonad.Util.SpawnOnce
import XMonad.Util.ClickableWorkspaces
+#+end_src
- -- ColorScheme module (SET ONLY ONE!)
- -- Possible choice are:
- -- DoomOne
- -- Dracula
- -- GruvboxDark
- -- MonokaiPro
- -- Nord
- -- OceanicNext
- -- Palenight
- -- SolarizedDark
- -- SolarizedLight
- -- TomorrowNight
+** Colorschemes
+DT's ColorScheme module. Possible choice are:
+- DoomOne
+- Dracula
+- GruvboxDark
+- MonokaiPro
+- Nord
+- OceanicNext
+- Palenight
+- SolarizedDark
+- SolarizedLight
+- TomorrowNight
+
+#+begin_src haskell
import Colors.DoomOne
-
#+end_src
* Window Management and Layouts
+** Border Width and Spacing
#+begin_src haskell
+myBorderWidth :: Dimension
+myBorderWidth = 2
-myBorderWidth :: Dimension --used in 2 places
-myBorderWidth = 2 -- Sets border width for windows
-
-windowCount :: X (Maybe String) --used in 2 places
+windowCount :: X (Maybe String)
windowCount = gets $ Just . show . length . W.integrate' . W.stack . W.workspace . W.current . windowset
--Makes setting the spacingRaw simpler to write. The spacingRaw module adds a configurable amount of space around windows.
mySpacing :: Integer -> l a -> XMonad.Layout.LayoutModifier.ModifiedLayout Spacing l a
mySpacing i = spacingRaw False (Border i i i i) True (Border i i i i) True
+#+end_src
+
+
+** Layouts
+- limitWindows n sets maximum number of windows displayed for layout.
+- mySpacing n sets the gap size around the windows.
+
+#+begin_src haskell
+
--- Defining a bunch of layouts, many that I don't use.
--- limitWindows n sets maximum number of windows displayed for layout.
--- mySpacing n sets the gap size around the windows.
tall = renamed [Replace "tall"]
$ smartBorders
-- $ windowNavigation
@@ -137,37 +196,30 @@ tabs = renamed [Replace "tabs"]
-- I cannot add spacing to this layout because it will
-- add spacing between window and tabs which looks bad.
$ tabbed shrinkText myTabTheme
+#+end_src
+
+** Theming for tabs (sub)layout
+#+begin_src haskell
+
--- setting colors for tabs layout and tabs sublayout.
myTabTheme = def { fontName = "xft:Iosevka-9"
, activeColor = color15
, inactiveColor = colorBack
, activeBorderColor = color15
, inactiveBorderColor = colorFore
, activeTextColor = colorBack
- , inactiveTextColor = colorFore
- }
+ , inactiveTextColor = colorFore }
+#+end_src
-myManageHook = composeAll
- [ className =? "confirm" --> doFloat
- , className =? "file_progress" --> doFloat
- , className =? "dialog" --> doFloat
- , className =? "download" --> doFloat
- , className =? "error" --> doFloat
- , className =? "Gimp" --> doFloat
- , className =? "notification" --> doFloat
- , className =? "pinentry-gtk-2" --> doFloat
- , className =? "splash" --> doFloat
- , className =? "toolbar" --> doFloat
- , className =? "zoom" --> doFloat
- , className =? "Yad" --> doCenterFloat
- , (className =? "firefox" <&&> resource =? "Dialog") --> doFloat -- Float Firefox Dialog
- , isFullscreen --> doFullFloat
- ]
--- myWorkspaceIndices = M.fromList $ zipWith (,) workspaces [1..] -- (,) == \x y -> (x,y)
+** Clickable workspaces in XMobar
+#+begin_src haskell
mySB = statusBarProp "xmobar" (clickablePP xmobarPP)
+#+end_src
+** Workspace definitions
+
+#+begin_src haskell
myWorkspaces = ["1", "2", "3", "4", "5", "6", "7", "8", "9",
"e",
"w", "g", "d", "b", "j", "f", "o", "u",
@@ -176,52 +228,118 @@ myWorkspaces = ["1", "2", "3", "4", "5", "6", "7", "8", "9",
]
myWorkspaceIndices = M.fromList $ zipWith (,) myWorkspaces [1..] -- (,) == \x y -> (x,y)
+
clickable ws = ""++ws++""
where i = fromJust $ M.lookup ws myWorkspaceIndices
-
#+end_src
+** Manage Hook
+#+begin_src haskell
+myManageHook = manageSpawn <> composeAll
+ [ className =? "confirm" --> doFloat
+ , className =? "file_progress" --> doFloat
+ , className =? "dialog" --> doFloat
+ , className =? "download" --> doFloat
+ , className =? "error" --> doFloat
+ , className =? "Gimp" --> doFloat
+ , className =? "notification" --> doFloat
+ , className =? "pinentry-gtk-2" --> doFloat
+ , className =? "splash" --> doFloat
+ , className =? "toolbar" --> doFloat
+ , className =? "zoom" --> doFloat
+ , className =? "Yad" --> doCenterFloat
+ , (className =? "firefox" <&&> resource =? "Dialog") --> doFloat -- Float Firefox Dialog
+ , isFullscreen --> doFullFloat
+ ]
+#+end_src
+** Startup Hook
+
+Set the WMName and session type so applications which check for it don't bug out.
+*** Settings applied on login
+#+begin_src haskell
+myStartupHook = do
+ setWMName "LG3D"
+ spawnOnce "lxsession"
+#+end_src
+**** Keyboard layout
+I'm Polish, so I type on a Polish layout. I also extensively use the compose key, so I have it handy.
+#+begin_src haskell
+ spawnOnce "setxkbmap -model pc104 -layout pl -option compose:rctrl"
+#+end_src
+**** Mount encrypted container
+#+begin_src haskell
+ spawnOnce "gocryptfs ~/.bajsicki enc --extpass lxqt-openssh-askpass"
+#+end_src
+**** Wallpaper
+Randomize wallpaper. Requires /feh/. You can change the path to any directory with wallpapers for consistent variety.
+#+begin_src haskell
+ spawnOnce "feh --randomize --bg-fill /usr/share/backgrounds/archlinux/*"
+#+end_src
+**** Trayer
+Trayer is a system tray, which works well with XMobar. This restarts it every time XMonad is reinitialized to avoid weirdness.
+#+begin_src haskell
+ spawn "killall trayer" -- kill current trayer on each
+ spawn ("sleep 2 && trayer --edge top --align right --widthtype request --padding 6 --SetDockType true --SetPartialStrut true --expand true --monitor 1 --transparent true --alpha 0 " ++ colorTrayer ++ " --height 20")
+#+end_src
+
+**** Daemons
+***** Dunst
+Dunst for notifications.
+#+begin_src haskell
+ spawnOnce "dunst"
+#+end_src
+***** Activity Watch
+I like looking back on the way I spend my time every once in a while. Local time tracking is really helpful, so I run AW in the background.
+#+begin_src haskell
+ spawnOnce "aw-server"
+ spawnOnce "aw-watcher-afk"
+ spawnOnce "aw-watcher-window"
+ spawnOnce "poetry run aw-watcher-spotify"
+#+end_src
+***** Emacs
+Emacs daemon for emacsclient.
+#+begin_src haskell
+ spawnOnce "/usr/bin/emacs --daemon"
+#+end_src
+*** Startup applications
+#+begin_src haskell
+ spawnOn "1" "firefox-developer-edition"
+ spawnOn "2" "evolution"
+ spawnOn "9" "steam"
+ spawnOn "3" "discord"
+ spawnOn "6" "google-chrome-stable"
+ spawnOn "e" "/usr/bin/emacsclient"
+ spawnOn "j" "keepassxc"
+#+end_src
* Main XMonad loop
#+begin_src haskell
-
-
main :: IO ()
main = do
- -- Launching three instances of xmobar on their monitors.
+#+end_src
+** XMobar
+Launching three instances of xmobar on their monitors.
+#+begin_src haskell
xmproc0 <- spawnPipe ("xmobar -x 0 $HOME/.config/xmobar/tomorrow-night-xmobarrc")
xmproc1 <- spawnPipe ("xmobar -x 1 $HOME/.config/xmobar/tomorrow-night-xmobarrc")
xmproc2 <- spawnPipe ("xmobar -x 2 $HOME/.config/xmobar/tomorrow-night-xmobarrc")
- -- the xmonad, ya know...what the WM is named after!
+
+#+end_src
+** XMonad & manageHook
+#+begin_src haskell
xmonad $ ewmh $ docks $ def
{ manageHook = myManageHook <+> manageDocks
+#+end_src
+*** handleEventHook
+This lets alacritty be swallowed when it opens a GUI application.
+#+begin_src haskell
, handleEventHook = swallowEventHook (className =? "Alacritty" <||> className =? "st-256color" <||> className =? "XTerm") (return True)
- -- docks
- -- Uncomment this line to enable fullscreen support on things like YouTube/Netflix.
- -- This works perfect on SINGLE monitor systems. On multi-monitor systems,
- -- it adds a border around the window if screen does not have focus. So, solution
- -- is to use a keybinding to toggle fullscreen noborders instead. (M-)
- -- <+> fullscreenEventHook
+#+end_src
+*** Pulling settings together
+#+begin_src haskell
, modMask = mod4Mask
, terminal = "alacritty"
- , startupHook = do
- setWMName "LG3D"
- spawnOnce "feh --randomize --bg-fill /usr/share/backgrounds/archlinux/*" -- feh set random wallpaper"
- spawnOnce "lxsession"
- spawnOnce "nm-applet"
- spawnOnce "picom"
- spawnOnce "volumeicon"
- spawn "~/.screenalyout/3-laptop-center.sh"
- spawn "setxkbmap -model pc104 -layout pl"
- spawn "dunst"
- spawnOnce "python tech/source/aw-watcher-spotify/aw_watcher_spotify/main.py"
- spawnOnce "aw-watcher-afk"
- spawnOnce "aw-watcher-window"
-
- spawn "killall conky" -- kill current conky on each restart
- spawn "/usr/bin/emacs --daemon" -- emacs daemon for the emacsclient
- spawn "killall trayer" -- kill current trayer on each
- spawn ("sleep 2 && trayer --edge top --align right --widthtype request --padding 6 --SetDockType true --SetPartialStrut true --expand true --monitor 1 --transparent true --alpha 0 " ++ colorTrayer ++ " --height 20")
+ , startupHook = myStartupHook
, layoutHook = avoidStruts
$ windowNavigation
$ subTabbed
@@ -234,19 +352,26 @@ main = do
, borderWidth = myBorderWidth
, normalBorderColor = colorBack
, focusedBorderColor = color15
+#+end_src
+*** logHook
+Define logHook. ppOutput streams into the three instances of XMobar.
+#+begin_src haskell
, logHook = dynamicLogWithPP xmobarPP
- { ppOutput = \x -> hPutStrLn xmproc0 x -- xmobar on monitor 1
- >> hPutStrLn xmproc1 x -- xmobar on monitor 2
- >> hPutStrLn xmproc2 x -- xmobar on monitor 3
+ { ppOutput = \x -> hPutStrLn xmproc0 x
+ >> hPutStrLn xmproc1 x
+ >> hPutStrLn xmproc2 x
+#+end_src
+**** Colors/ clicks
+#+begin_src haskell
, ppCurrent = xmobarColor color06 "" . wrap
("") ""
- -- Visible but not current workspace
, ppVisible = xmobarColor color06 "" . clickable
- -- Hidden workspace
, ppHidden = xmobarColor color05 "" . wrap
("") "" . clickable
- -- Hidden workspaces (no windows)
, ppHiddenNoWindows = xmobarColor color05 "" . clickable
+#+end_src
+**** Window Title, Separators, etc.
+#+begin_src haskell
-- Title of active window
, ppTitle = xmobarColor colorFore "" . shorten 48
-- Separator character
@@ -258,16 +383,14 @@ main = do
-- order of things in xmobar
, ppOrder = \(ws:l:t:ex) -> [ws,l]++ex++[t]
} >> updatePointer (0.5, 0.5) (0.0, 0.0) }
-
#+end_src
* Keybinds
-
+** Workspaces
+This is the bulk of my changes. I use /a lot/ of workspaces.
+They're all under two chords. M-s /shows/ a workspace, and M-t /throws/ a window to a workspace. Easy mnemonics, yay.
#+begin_src haskell
-
`additionalKeysP`
-
--- subKeys "Switch to workspace"
[ ("M-s 1", (windows $ W.greedyView $ myWorkspaces !! 0))
, ("M-s 2", (windows $ W.greedyView $ myWorkspaces !! 1))
, ("M-s 3", (windows $ W.greedyView $ myWorkspaces !! 2))
@@ -304,7 +427,6 @@ main = do
, ("M-s z", (windows $ W.greedyView $ myWorkspaces !! 33))
, ("M-s p", (windows $ W.greedyView $ myWorkspaces !! 34))
- -- ^++^ subKeys "Throw to workspace"
, ("M-t 1", (windows $ W.shift $ myWorkspaces !! 0))
, ("M-t 2", (windows $ W.shift $ myWorkspaces !! 1))
, ("M-t 3", (windows $ W.shift $ myWorkspaces !! 2))
@@ -341,7 +463,10 @@ main = do
, ("M-t z", (windows $ W.shift $ myWorkspaces !! 33))
, ("M-t p", (windows $ W.shift $ myWorkspaces !! 34))
-
+#+end_src
+** Window focus and movement
+Pretty self-explanatory. /ToggleStruts/ is fullscreen. /sinkAll/ tiles floating windows.
+#+begin_src haskell
, ("M-o", windows W.focusUp)
, ("M-a", windows W.focusDown)
@@ -357,21 +482,17 @@ main = do
, ("M-.", nextScreen)
, ("M-,", prevScreen)
- -- Switch layouts
, ("M-", sendMessage NextLayout)
, ("M-f", sendMessage (MT.Toggle NBFULL) >> sendMessage ToggleStruts)
- -- Window resizing
, ("M-y", sendMessage Shrink)
, ("M-l", sendMessage Expand)
- -- , ("M-M1-j", addName "Shrink window vertically" $ sendMessage MirrorShrink)
- -- , ("M-M1-k", addName "Expand window vertically" $ sendMessage MirrorExpand)
-
- -- Floating windows
- -- ("M-f", addName "Toggle float layout" $ sendMessage (T.Toggle "floats"))
- -- , ("M-S-t", addName "Sink a floating window" $ withFocused $ windows . W.sink)
, ("M-b", sinkAll)
+#+end_src
+** Sublayouts
+This lets me 'collect' windows into a tiled group if it starts getting crowded on the screen.
+#+begin_src haskell
-- Sublayouts
-- This is used to push windows to tabbed sublayouts, or pull them out of it.
, ("C-S-M1-n",sendMessage $ pullGroup L)
@@ -383,50 +504,54 @@ main = do
, ("C-S-M1-u", withFocused (sendMessage . UnMergeAll))
, ("C-S-M1-j", onGroup W.focusUp')
, ("C-S-M1-y", onGroup W.focusDown')
-
-
- -- XMonad and apps
+#+end_src
+** XMonad and apps
+Notes: I use a ZSA Moonlander so a lot of the 4-5 key sequences are actually just two keys.
+*** XMonad
+#+begin_src haskell
, ("C-M1-S-0", sequence_ [spawn "xmonad --restart", spawn "xmonad --recompile"])
, ("M-S-M1-C-0", io exitSuccess)
, ("S-C-M1-q", kill1)
, ("M-S-C-M1-q", killAll)
- , ("M-S-", spawn "~/.local/bin/dm-run")
, ("M-d", spawn "rofi -show drun")
-
+#+end_src
+*** Some common keybinds:
+#+begin_src haskell
, ("M-e", spawn "emacsclient -c -a 'emacs'")
, ("M-", spawn "alacritty")
, ("M-S-", spawn "feh --randomize --bg-fill /usr/share/backgrounds/archlinux/*")
, ("M-", spawn "dm-maim")
, ("", spawn "flameshot gui")
- -- ORG PROMPTS
+#+end_src
+*** XMonad.Prompt.OrgMode
+#+begin_src haskell
, ("M-c i", orgPrompt def "TODO" "~/enc/org/inbox.org")
, ("M-c l", orgPromptPrimary def "LINK" "~/enc/org/inbox.org")
, ("M-c n", orgPrompt def "NOTE" "~/enc/org/inbox.org")
, ("M-c p", orgPromptRefile def "TODO" "~/enc/org/phil.org")
-
- -- , ("", spawn "maim -so | xclip -selection clipboard -t image/png")
-
+#+end_src
+*** Timestamp chords
+For local time, EST, and PST.
+#+begin_src haskell
-- Time! Timestamps!
, ("M-w l", spawn "sleep 0.5 && xdotool type \"$(date +'%Y.%m.%d %H:%M:%S %Z')\"")
, ("M-w e", spawn "sleep 0.5 && xdotool type \"$(TZ=America/New_York date +'%Y.%m.%d %H:%M:%S %Z')\"")
, ("M-w m", spawn "sleep 0.5 && xdotool type \"$(TZ=America/Denver date +'%Y.%m.%d %H:%M:%S %Z')\"")
-
- -- Multimedia Keys
+#+end_src
+*** Multimedia keys
+#+begin_src haskell
, ("", spawn "mpc toggle")
, ("", spawn "mpc prev")
, ("", spawn "mpc next")
, ("", spawn "amixer set Master toggle")
, ("", spawn "pactl set-sink-volume \"bluez_output.E8_EE_CC_02_F6_8A.1\" -5%")
, ("", spawn "pactl set-sink-volume \"bluez_output.E8_EE_CC_02_F6_8A.1\" +5%")
- -- , ("", addName "Open home page" $ spawn (myBrowser ++ " https://www.youtube.com/c/DistroTube"))
- , ("", spawn "dm-websearch")
- , ("", runOrRaise "evolution" (resource =? "evolution"))
- , ("", runOrRaise "qalculate-gtk" (resource =? "qalculate-gtk"))
--- , ("", spawn "eject /dev/cdrom")
]
+#+end_src
+*** Mouse wheel to switch workspaces.
+#+begin_src haskell
`additionalMouseBindings`
[ ((mod4Mask, button4), \w -> focus w >> prevWS)
, ((mod4Mask, button5), \w -> focus w >> nextWS)]
-
#+end_src