1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 | -- HMIW's xmonad config
-- since i really struggled with this one, and i've been
-- raiding the dotfiles on gitlab, i've decided to put
-- mine there. i'll leave some bread crumbs best i can
-- but i'm still not as comfortable with this WM as i am
-- with awesome and qtile.
--
-- if you're reading this and actually know what you're
-- talking about, PLEASE feel free to correct me.
-- here are a few i've shamelessly pinched from.
--https://github.com/quarkQuark/dotfiles/
--https://gitlab.com/OldTechBloke/dotfiles/-/blob/master/.xmonad/xmonad.hs
--https://gitlab.com/dwt1/dotfiles/-/tree/master/.xmonad
import XMonad
import Data.Monoid
import System.Exit
import XMonad.Hooks.DynamicLog
import XMonad.Hooks.ManageDocks
import XMonad.Util.Run(spawnPipe)
--import XMonad.Util.EZConfig(additionalKeys)
import System.IO
import qualified XMonad.StackSet as W
import qualified Data.Map as M
import XMonad.Util.SpawnOnce
import XMonad.Hooks.SetWMName
import XMonad.Util.NamedScratchpad
--import XMonad.Hooks.EwmhDesktops
--import XMonad.Hooks.ManageHelpers
import XMonad.Layout.NoBorders
import XMonad.Layout.LayoutModifier
import XMonad.Layout.Spacing
--import qualified XMonad.Layout.ToggleLayouts as T (toggleLayouts, ToggleLayout(Toggle))
import XMonad.Layout.Renamed
import XMonad.Layout.ResizableTile
import XMonad.Layout.SimplestFloat
import XMonad.Layout.Fullscreen
----------------------------------------------------------------------
-- USER VARIABLES --
----------------------------------------------------------------------
myTerminal :: String
myTerminal = "urxvt"
myWBrowser :: String
myWBrowser = "firefox"
myFBrowser :: String
myFBrowser = "nemo"
myTEditor :: String
myTEditor = "subl3"
myMPlayer :: String
myMPlayer = "clementine"
myScreenShot :: String
myScreenShot = "flameshot gui"
myLauncher :: String
myLauncher = "/usr/bin/rofi -show drun -modi drun -theme Arc-Dark"
myQuitMenu :: String
myQuitMenu = "rofi -show power-menu -modi power-menu:~/.local/bin/rofi-power-menu"
myWorkspaces = ["a: net","s: edit","d: faff","z: vid","x: mus","c: trnt","v: opts"]
----------------------------------------------------------------------
-- KEYS --
----------------------------------------------------------------------
myKeys conf@(XConfig {XMonad.modMask = modm}) = M.fromList $
-- Quit menu
[ ((modm .|. controlMask .|. shiftMask, xK_q), spawn myQuitMenu)
-- Log out
, ((modm .|. controlMask, xK_q), io (exitWith ExitSuccess))
-- Reload Awesome
, ((modm .|. controlMask, xK_r), spawn "xmonad --recompile; xmonad --restart")
-- Capture a screenshot
, ((0, xK_Print), spawn myScreenShot)
---------------------------
-- Launcher
, ((modm, xK_Return), spawn myLauncher)
-- File browser
, ((modm, xK_f), spawn myFBrowser)
, ((modm .|. shiftMask, xK_f), spawn "termite -e ranger")
-- Web browser
, ((modm, xK_b), spawn myWBrowser)
-- Gimp
, ((modm, xK_g), spawn "gimp")
-- Music player
, ((modm, xK_period), spawn myMPlayer)
-- Terminal
, ((modm, xK_t), spawn $ XMonad.terminal conf)
-- Text editor
, ((modm .|. shiftMask, xK_t), spawn myTEditor)
--------------------------------------
-- Switch layout
, ((modm, xK_l ), sendMessage NextLayout)
-- Switch to layout defaults
, ((modm .|. shiftMask, xK_l ), setLayout $ XMonad.layoutHook conf)
-- Change focus
, ((modm, xK_Right), windows W.focusDown)
, ((modm, xK_Tab), windows W.focusDown)
-- Change focus
, ((modm, xK_Left), windows W.focusUp)
-- Swap windows
, ((modm .|. shiftMask, xK_Left ), windows W.swapUp)
-- Swap windows
, ((modm .|. shiftMask, xK_Right ), windows W.swapDown)
-- Jump to urgent
-- not mapped yet
-- Increase master window width
, ((modm .|. controlMask, xK_Up), sendMessage Expand)
-- Decrease master window width
, ((modm .|. controlMask, xK_Down), sendMessage Shrink)
-- increase / decrease current slave window size (from resizabletile)
, ((modm .|. controlMask, xK_Right), sendMessage MirrorShrink)
-- increase / decrease current slave window size (from resizabletile)
, ((modm .|. controlMask, xK_Left), sendMessage MirrorExpand)
-- Toggle struts
, ((modm .|. controlMask, xK_space), sendMessage ToggleStruts)
-- Kill window
, ((modm, xK_q), kill)
-- Sink a floating window back into tiling
, ((modm .|. shiftMask, xK_space), withFocused $ windows . W.sink)
-- Move focused client to master
, ((modm .|. shiftMask, xK_m), windows W.focusMaster)
-- scratchpads
-- bound to number keys
, ((modm, xK_1), namedScratchpadAction myScratchPads "term1")
, ((modm, xK_2), namedScratchpadAction myScratchPads "term2")
, ((modm, xK_3), namedScratchpadAction myScratchPads "fbrow")
----------------------------------------------------------
-- most of these keybinds will cause conflicts. if you --
-- want to use them, remap them. i've put them to --
-- one side for now --
----------------------------------------------------------
--
-- -- Resize viewed windows to the correct size
-- , ((modm, xK_n ), refresh)
-- -- Move focus to the master window
-- , ((modm, xK_m ), windows W.focusMaster )
-- -- Swap the focused window and the master window
-- , ((modm, xK_Return), windows W.swapMaster)
-- -- Increment the number of windows in the master area
-- , ((modm , xK_comma ), sendMessage (IncMasterN 1))
-- -- Deincrement the number of windows in the master area
-- , ((modm , xK_period), sendMessage (IncMasterN (-1)))
-- -- Run xmessage with a summary of the default keybindings (useful for beginners)
-- , ((modm .|. shiftMask, xK_slash ), spawn ("echo \"" ++ help ++ "\" | xmessage -file -"))
-----------------------------------------------------------------------------------------------
]
++
--------------------------------------
-- ??bind workspaces to mod + 1-9?? --
--------------------------------------
-- because i like having my workspaces bound to asdzxcv keys
-- i've commented out this bit (which is a fiarly standard
-- setting in all tiling WMs) so edit them back in if you like
-- and delete the almost identical replica
---------------------------------------------------------------
-- [((m .|. modm, k), windows $ f i)
-- | (i, k) <- zip (XMonad.workspaces conf) [xK_1 .. xK_9]
-- , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]]
-- ++
---------------------------------------------------------------
[((m .|. modm, k), windows $ f i)
| (i, k) <- zip (XMonad.workspaces conf) [xK_a, xK_s, xK_d, xK_z, xK_x, xK_c, xK_v ]
, (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 .|. modm, 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)]]
----------------------------------------------------------------------
-- LOOK AND FEEL --
----------------------------------------------------------------------
-- the next two lines just create the spacing. ripped from old tech bloke's
-- config. to actually set the size of the gaps use mySpacing in the layout
-- section.
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
myFocusFollowsMouse :: Bool
myFocusFollowsMouse = True
myClickJustFocuses :: Bool
myClickJustFocuses = True
myBorderWidth :: Dimension
myBorderWidth = 2
myNormalBorderColor = "#05070c"
myFocusedBorderColor = "#5294e2"
---------------------------------------------------------------------
-- LAYOUTS --
----------------------------------------------------------------------
-- i only really use two layouts, and one of them is the first
-- flipped on its side. resizable tall uses the mirror expand/shrink
-- to resize the slave windows, which unlike the master, must have
-- focus when resizing. also they work differently depending on which
-- of the slave windows you are resizing.
--
myLayout =
avoidStruts monadtall
||| avoidStruts monadwide
||| sfloat
||| full
where
monadtall =
renamed [Replace "Monad Tall"]
-- $ fullscreenFull
$ smartBorders
$ mySpacing 4 -- sets the gap size in px
$ ResizableTall 1 (10/100) (1/2) []
-- this layout takes all the values from previous
-- layout and flips by 90°
monadwide =
renamed [Replace "Monad Wide"]
$ Mirror monadtall
full =
renamed [Replace "Full Screen"]
$ noBorders
$ Full
sfloat =
renamed [Replace "Floating"]
$ simplestFloat
-- this isn't quite how i'd like it. i'd prefer gaps to act like
-- smart boarders, only appearing if there's more than one window.
-- there's probably a way of doing it. must find out how.
-----------------------------------------------------------------------
-- WINDOW RULES
-----------------------------------------------------------------------
-- i've added some hooks to make certain windows spawn below the
-- master window, rather than replacing it. at first i wanted
-- to work like every other WM and do this by default but actually
-- this is better. there is a way of doing that, see the FAQ
-- https://wiki.haskell.org/Xmonad/Frequently_asked_questions#Make_new_windows_appear_.27below.27_rather_than_.27above.27_the_current_window
myManageHook = composeAll
[ className =? "MPlayer" --> doFloat
, className =? "Gimp" --> doFloat
, className =? "KeePassXC" --> doFloat
-- Xmessage is the error you get when you do something
-- wrong in this config.
, className =? "Xmessage" --> doFloat
-- stops applications from spawning as master window
, className =? "Termite" --> doF W.swapDown
, className =? "URxvt" --> doF W.swapDown
, className =? "Thunar" --> doF W.swapDown
-- workspace hooks
, className =? "firefox" --> doShift "a: net"
, className =? "Brave-browser" --> doShift "a: net"
, className =? "Subl3" --> doShift "s: edit"
, className =? "Gimp" --> doShift "s: edit"
, className =? "vlc" --> doShift "z: vid"
, className =? "mpv" --> doShift "z: vid"
, className =? "Clementine" --> doShift "x: mus"
, className =? "qBittorrent" --> doShift "c: trnt"
, className =? "Transmission-gtk" --> doShift "c: trnt"
, className =? "Gucharmap" --> doShift "v: opts"
, className =? "Gnome-disks" --> doShift "v: opts"
, className =? "qt5ct" --> doShift "v: opts"
, className =? "Lxappearance" --> doShift "v: opts"
, className =? "Timeshift-gtk" --> doShift "v: opts"
, className =? "Kvantum Manager" --> doShift "v: opts"
, className =? "Pulseaudio-equalizer-gtk" --> doShift "v: opts"
-- i think, this means let applications do what the want
, resource =? "desktop_window" --> doIgnore
, resource =? "kdesktop" --> doIgnore
] <+> namedScratchpadManageHook myScratchPads
----------------------------------------------------------------------
-- SCRATCH PADS --
----------------------------------------------------------------------
-- ripped from distrotube's configs pretty much. it took me a while to
-- get my head around it, even after reading the docs.
-- i didn't realise that the title was something you set from the command
-- to launch the terminal.. despite it being written in right front of me.
-- use your terminal's man page to find the option for this.
-- you're on your own with the manage term bit. w & h refer to % of
-- screen. the other two, they are the distance from a fixed point.
-- where that fixed point is exactly... nobody knows.
myScratchPads :: [NamedScratchpad]
myScratchPads = [ NS "term1" spawnTerm1 findTerm1 manageTerm1
, NS "term2" spawnTerm2 findTerm2 manageTerm2
, NS "fbrow" spawnFbrow findFbrow manageFbrow
]
where
spawnTerm1 = myTerminal ++ " -t term1"
findTerm1 = title =? "term1"
manageTerm1 = customFloating $ W.RationalRect l t w h
where
h = 0.4
w = 0.75
t = 0.40 -h
l = 0.88 -w
spawnTerm2 = myTerminal ++ " -t term2"
findTerm2 = title =? "term2"
manageTerm2 = customFloating $ W.RationalRect l t w h
where
h = 0.15
w = 0.75
t = 0.99 -h
l = 0.88 -w
spawnFbrow = "thunar"
findFbrow = className =? "Thunar"
manageFbrow = customFloating $ W.RationalRect l t w h
where
h = 0.5
w = 0.80
t = 0.50 -h
l = 0.88 -w
-- you can sink scratchpads into tiled layouts and still toggle them
-- with their respective keys. i'd prefer it if toggling a scratchpad
-- would spawn a new one after sinking the old one. maybe that's
-- possible.
-----------------------------------------------------------------------
-- STARTUP HOOK
-----------------------------------------------------------------------
-- haven't had much luck with this trayer script, which supposedly
-- expands to accommodate icons. it just obscures the view of the other
-- widgets, so i think i disabled it and just put my widgets before
-- the tray.
myStartupHook = do
-- spawnOnce "feh --bg-scale /home/chris/.backgrounds/xmonad.jpg"
-- spawnOnce "picom"
-- spawnOnce "/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1"
-- spawnOnce "nm-applet"
-- spawnOnce "pa-applet"
-- spawnOnce "/home/chris/.local/bin/fixtouchpad.sh"
spawnOnce "/home/chris/.local/bin/startup.sh"
spawn "trayer --edge top --align right --widthtype request --padding 6 --distance 540 --distancefrom right --SetDockType true --SetPartialStrut false --expand true --monitor 1 --transparent true --alpha 0 --tint 0x000000 --height 18 &"
setWMName "LG3D"
-----------------------------------------------------------------------
-- MAIN
-----------------------------------------------------------------------
-- as i understand it, anything which differs from the default xmonad
-- config must be pipped through here. my mouse settings are the default
-- mouse settings, but if i were to change them, i'd add
-- ", mouseBindings = myMouseBindings," to this list, and provide my own
-- settings above.
main = do
xmproc <- spawnPipe "xmobar /home/chris/.config/xmobar/xmobarrc"
xmonad $ docks $ fullscreenSupport def
--{ layoutHook = avoidStruts $ layoutHook def
{ layoutHook = myLayout
-- ripped from distrotube
, logHook = dynamicLogWithPP xmobarPP
{ ppOutput = hPutStrLn xmproc
, ppCurrent = xmobarColor "#46a8c3" "" . wrap "[" "]" -- Current workspace in xmobar
, ppVisible = xmobarColor "#46a8c3" "" . wrap "" "" -- Visible but not current workspace
, ppHidden = xmobarColor "#5294e2" "" . wrap "" "" -- Hidden workspaces in xmobar
, ppHiddenNoWindows = xmobarColor "#2f343f" "" -- Hidden workspaces (no windows)
, ppTitle = xmobarColor "gray" "" . shorten 60 -- Title of active window in xmobar
, ppSep = "<fc=gray> | </fc>" -- Separators in xmobar
, ppUrgent = xmobarColor "#C45500" "" . wrap "!" "!" -- Urgent workspace
, ppOrder = \(ws:l:t:ex) -> [ws,l]++ex++[t]
}
, manageHook = myManageHook <+> fullscreenManageHook-- <+> manageHook defaultConfig
, keys = myKeys
, handleEventHook = fullscreenEventHook
, startupHook = myStartupHook
, workspaces = myWorkspaces
, terminal = myTerminal
, normalBorderColor = myNormalBorderColor
, focusedBorderColor = myFocusedBorderColor
, modMask = mod4Mask
, focusFollowsMouse = myFocusFollowsMouse
, clickJustFocuses = myClickJustFocuses
, borderWidth = myBorderWidth
}
|
x
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | -- i'll do my best to make notes but it's a bit of a mess
-- https://archives.haskell.org/projects.haskell.org/xmobar/#system-monitor-plugins
-- FYI xmobar and trayer will need to be killed before reloading
-- to be sure that it is in fact reloading. if it doesn't
-- run both from the terminal to see what's what. maybe set up an alias
-- in bashrc 'alias kxb="killall trayer xmobar"' (without single quotes)
Config { font = "xft:mononoki bold:pixelsize=14"
, bgColor = "black"
, fgColor = "grey"
, position = Top
, lowerOnStart = True
-- here the widgets are configured before being placed on the bar in template
, commands =
[ Run Cpu
[ "-L", "50"
, "-H", "75"
, "--normal", "orange"
, "--high", "red"
] 35
, Run Memory
[ "-t", "Mem: <used>MB"
] 50
-- cpu core temperature monitor
, Run CoreTemp
[ "--template" , "Temp: <core0>°C | <core1>°C"
, "--Low" , "70" -- units: °C
, "--High" , "80" -- units: °C
, "--low" , "green"
, "--normal" , "orange"
, "--high" , "red"
] 16
, Run Date "%d-%m-%y | %H:%M" "date" 10
-- trayer SET PATH TO TRAYER SCRIPT!!
, Run Com "/home/chris/.config/xmobar/trayer-padding-icon.sh" [] "trayerpad" 124
--left hand widgets
, Run StdinReader
, Run Swap [] 10
]
, sepChar = "%"
, alignSep = "}{"
-- inverted curly brackets dictate alignment. everything before } is on the left.
-- and everything after { is on the right.
-- trayer is a bit of a pain to set up, see startup hooks in xmonad.hs and
-- consult the man page for flags. i suggest wrapping the widget in colour
-- tags to match xmobar's BG colour, as the word "updating" appears underneath.
-- i don't seem to be having much luck with this auto expand script either.
, template = "%StdinReader% }{<fc=#000000>%trayerpad%</fc> %memory% %swap% | %coretemp% | %cpu% | %date% "
}
|
x
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #!/bin/sh
# Copied from https://github.com/jaor/xmobar/issues/239#issuecomment-233206552
# Detects the width of running trayer-srg window (xprop name 'panel')
# and creates an XPM icon of that width, 1px height, and transparent.
# Outputs an <icon>-tag for use in xmobar to display the generated
# XPM icon.
#
# Run script from xmobar:
# `Run Com "/where/ever/trayer-padding-icon.sh" [] "trayerpad" 10`
# and use `%trayerpad%` in your template.
# Function to create a transparent Wx1 px XPM icon
create_xpm_icon () {
timestamp=$(date)
pixels=$(for i in `seq $1`; do echo -n "."; done)
cat << EOF > "$2"
/* XPM *
static char * trayer_pad_xpm[] = {
/* This XPM icon is used for padding in xmobar to */
/* leave room for trayer-srg. It is dynamically */
/* updated by by trayer-padding-icon.sh which is run */
/* by xmobar. */
/* Created: ${timestamp} */
/* <w/cols> <h/rows> <colors> <chars per pixel> */
"$1 1 1 1",
/* Colors (none: transparent) */
". c none",
/* Pixels */
"$pixels"
};
EOF
}
# Width of the trayer window
width=$(xprop -name panel | grep 'program specified minimum size' | cut -d ' ' -f 5)
# Icon file name
iconfile="/tmp/trayer-padding-${width}px.xpm"
# If the desired icon does not exist create it
if [ ! -f $iconfile ]; then
create_xpm_icon $width $iconfile
fi
# Output the icon tag for xmobar
echo "<icon=${iconfile}/>"
|
x
Notes
XMonad config
This is one I really struggled with. It’s more or less complete, but there are several things I’d like to change. I’m not sure I’m doing full screen right either. There are a few issues that I’d like to iron out, for one the memory reported in the status bar is typically 200-300MBs higher than what is reported by htop.
Dependencies
- Xmonad
- Xmonad-contrib A few extras used in this configuration
- Xmobar The statusbar
- Trayer A system tray application
Not so important dependencies
Skipping these won’t break your config but grabbing them might make life easier for you.
- Rofi My preferred launcher, replace the relevant key binding if you want to use something else.
- Rofi power menu from jluttine
- Feh (The background is set in the startuphooks section of ~/.xmonad/xmonad.hs)
- noto-fonts
Installation
Just copy the relevant files to their directories
~/.xmonad/xmonad.hs
~/.config/xmobar/xmobarrc
~/.config/xmobar/trayer-padding-icon.sh
~/.loacl/bin/rofi-power-menu (optional)
Lastly, have a quick scan of the files in case there’s anything you might want to change, such as the applications set in my variables.
Useful Features
- Workspaces bound to letter keys (asdzxcv)
- Certain windows open below the master window.
- Named scratchpads
- Assigned workspaces for certain applications
- Layout-specific look and feel
- Resizable slave windows
Key Bindings
| Action | Key |
|———–|———————|
| Quit menu | mod, ctrl, shft + q |
| Log out | mod, ctrl + q |
| Reload XMonad | mod, ctrl + r |
| Capture a screenshot | print |
| View workspace | mod + a,s,d,z,x,c,v |
| Send window to workspace | mod, shift + a,s,d,z,x,c,v |
| Launch Rofi | mod + return |
| Launch File manager | mod + f |
| Launch Browser | mod + b |
| Launch Gimp | mod + g |
| Launch Clementine | mod + . |
| Launch terminal | mod + t |
| Switch layout | mod + l |
| Switch layout to default for ws | mod, shft + l |
| Focus previous client by | mod + tab / mod + right |
| Focus next client by | mod + left |
| Swap with next client by | mod, shft + left |
| Swap with previous client by | mod, shft + right |
| Increase/decrease master client’s width | mod, ctrl + up/down |
| Increase/decrease current slave window size | mod, ctrl + Right/Left |
| Toggle show/hide struts | mod, ctrl + space |
| Close client | mod + q |
| Sink floating window | mod, shft + space |
| Scratchpad 1 (Term 1) | mod + 1 |
| Scratchpad 2 (Term 2) | mod + 2 |
| Scratchpad 3 (File browser) | mod + 3 |