Make XMonad screen setup adapt to connected monitors
- Match scratchpads by WM_CLASS instead of title, so they no longer get shifted to workspace 1 or lose track of their window - Spawn one xmobar per connected screen (dynamicEasySBs) - Pick the xrandr layout and tray monitor based on whether HDMI is connected, and re-run it on monitor hotplug - Don't let one failed startup step block the rest - Make the startup command safe to re-run (no duplicate trayer/picom)
This commit is contained in:
+49
-22
@@ -3,6 +3,7 @@
|
||||
import Data.Default
|
||||
import Data.Monoid
|
||||
import Graphics.X11.ExtraTypes.XF86
|
||||
import Control.Monad (liftM2)
|
||||
import XMonad
|
||||
import XMonad.Actions.PhysicalScreens
|
||||
import XMonad.Hooks.DynamicLog
|
||||
@@ -11,6 +12,7 @@ import XMonad.Hooks.FloatConfigureReq
|
||||
import XMonad.Hooks.InsertPosition
|
||||
import XMonad.Hooks.ManageDocks
|
||||
import XMonad.Hooks.ManageHelpers
|
||||
import XMonad.Hooks.Rescreen
|
||||
import XMonad.Hooks.StatusBar
|
||||
import XMonad.Hooks.StatusBar.PP
|
||||
import XMonad.Layout.Grid
|
||||
@@ -36,7 +38,8 @@ main =
|
||||
xmonad
|
||||
. ewmhFullscreen
|
||||
. ewmh
|
||||
. withEasySB (xmobar1 <> xmobar2) defToggleStrutsKey
|
||||
. dynamicEasySBs myStatusBars
|
||||
. addRandrChangeHook (spawn myScreenHotplug)
|
||||
$ myConfig
|
||||
|
||||
-- Variables
|
||||
@@ -68,29 +71,46 @@ myScreenshotDir = "/home/fuxino/Pictures/Screenshots/"
|
||||
myScreenshotName :: String
|
||||
myScreenshotName = "Screenshot-%Y-%m-%d-%H%M%S.png"
|
||||
|
||||
-- Sets up the outputs and the wallpaper, and leaves the tray's monitor in $tray
|
||||
myScreenLayout :: String
|
||||
myScreenLayout =
|
||||
"if xrandr --query | grep -q '^HDMI-1-0 connected'; then"
|
||||
++ " xrandr --output HDMI-1-0 --preferred --primary --output eDP-1 --right-of HDMI-1-0 --preferred; tray=1;"
|
||||
++ " else xrandr --output eDP-1 --preferred --primary --output HDMI-1-0 --off; tray=0; fi"
|
||||
++ "; ~/.fehbg"
|
||||
|
||||
-- Replaces any running trayer, so there's never more than one
|
||||
myTrayer :: String
|
||||
myTrayer =
|
||||
"pkill -x trayer; while pgrep -x trayer > /dev/null; do sleep 0.1; done; \
|
||||
\trayer -l --edge top --align right --SetDockType true \
|
||||
\--SetPartialStrut true --expand true --widthtype request \
|
||||
\--tint 0x232634 --height 18 --monitor $tray"
|
||||
|
||||
-- Safe to re-run (e.g. spawnOnce after this string changes and xmonad restarts)
|
||||
myScreenSetup :: String
|
||||
myScreenSetup =
|
||||
"sleep 1 && xrandr --output HDMI-1-0 --preferred --primary --output eDP-1 --right-of HDMI-1-0 --preferred && ~/.fehbg"
|
||||
++ " && picom -b -c"
|
||||
++ " && trayer -l --edge top --align right --SetDockType true \
|
||||
\--SetPartialStrut true --expand true --widthtype request \
|
||||
\--tint 0x232634 --height 18 --monitor 1"
|
||||
"sleep 1; " ++ myScreenLayout ++ "; pgrep -x picom > /dev/null || picom -b -c; " ++ myTrayer
|
||||
|
||||
-- Run when a monitor is (dis)connected; restarts trayer so it moves to the right screen
|
||||
myScreenHotplug :: String
|
||||
myScreenHotplug = myScreenLayout ++ "; " ++ myTrayer
|
||||
|
||||
myScratchpads :: [NamedScratchpad]
|
||||
myScratchpads =
|
||||
[ NS "Riseup-vpn" "riseup-vpn" (className =? "RiseupVPN") (customFloating $ W.RationalRect 0.15 0.4 0.15 0.4),
|
||||
NS "Terminal" spawnTerminal (title =? "kitty-float") (customFloating $ W.RationalRect 0.2 0.2 0.6 0.6),
|
||||
NS "Music" spawnMusic (title =? "ncmpcpp") (customFloating $ W.RationalRect 0.2 0.2 0.6 0.6),
|
||||
NS "Mail" spawnMail (title =? "mutt") (customFloating $ W.RationalRect 0.2 0.2 0.6 0.6),
|
||||
NS "Cal" spawnCal (title =? "calcurse") (customFloating $ W.RationalRect 0.2 0.2 0.6 0.6),
|
||||
NS "Btop" spawnBtop (title =? "btop") (customFloating $ W.RationalRect 0.2 0.2 0.6 0.6)
|
||||
NS "Terminal" spawnTerminal (className =? "scratch-terminal") (customFloating $ W.RationalRect 0.2 0.2 0.6 0.6),
|
||||
NS "Music" spawnMusic (className =? "scratch-music") (customFloating $ W.RationalRect 0.2 0.2 0.6 0.6),
|
||||
NS "Mail" spawnMail (className =? "scratch-mail") (customFloating $ W.RationalRect 0.2 0.2 0.6 0.6),
|
||||
NS "Cal" spawnCal (className =? "scratch-cal") (customFloating $ W.RationalRect 0.2 0.2 0.6 0.6),
|
||||
NS "Btop" spawnBtop (className =? "scratch-btop") (customFloating $ W.RationalRect 0.2 0.2 0.6 0.6)
|
||||
]
|
||||
where
|
||||
spawnTerminal = myTerminal ++ " -T kitty-float"
|
||||
spawnMusic = myTerminal ++ " -T ncmpcpp ncmpcpp"
|
||||
spawnMail = myTerminal ++ " -T mutt bash -c 'pushd ~/Downloads > /dev/null; mutt; popd > /dev/null'"
|
||||
spawnCal = myTerminal ++ " -T calcurse calcurse"
|
||||
spawnBtop = myTerminal ++ " -T btop btop"
|
||||
spawnTerminal = myTerminal ++ " --class scratch-terminal -T kitty-float"
|
||||
spawnMusic = myTerminal ++ " --class scratch-music -T ncmpcpp ncmpcpp"
|
||||
spawnMail = myTerminal ++ " --class scratch-mail -T mutt bash -c 'pushd ~/Downloads > /dev/null; mutt; popd > /dev/null'"
|
||||
spawnCal = myTerminal ++ " --class scratch-cal -T calcurse calcurse"
|
||||
spawnBtop = myTerminal ++ " --class scratch-btop -T btop btop"
|
||||
|
||||
-- Config
|
||||
myConfig =
|
||||
@@ -105,7 +125,8 @@ myConfig =
|
||||
manageHook = myManageHook,
|
||||
handleEventHook = myHandleEventHook
|
||||
}
|
||||
`additionalKeysP` [ ("M-S-l", spawn "slock"),
|
||||
`additionalKeysP` [ ("M-b", sendMessage ToggleStruts),
|
||||
("M-S-l", spawn "slock"),
|
||||
("<Print>", unGrab *> spawn ("scrot " ++ myScreenshotDir ++ myScreenshotName)),
|
||||
("S-<Print>", unGrab *> spawn ("scrot -s " ++ myScreenshotDir ++ myScreenshotName)),
|
||||
("M-S-<Print>", unGrab *> spawn ("scrot -u " ++ myScreenshotDir ++ myScreenshotName)),
|
||||
@@ -164,9 +185,13 @@ myLayoutHook = onWorkspace "2:\xe743 " myWebLayout $ onWorkspace "3:\xf1b6 " myG
|
||||
delta = 3 / 100
|
||||
|
||||
-- Xmobar
|
||||
xmobar1 = statusBarProp "xmobar -x 0 ~/.config/xmobar/xmobarrc_hdmi" (pure myXmobarPP)
|
||||
|
||||
xmobar2 = statusBarProp "xmobar -x 1 ~/.config/xmobar/xmobarrc_laptop" (pure myXmobarPP)
|
||||
-- One bar per connected screen. The laptop config leaves room for trayer, so it
|
||||
-- goes on the laptop screen, which is screen 1 with HDMI and screen 0 without.
|
||||
myStatusBars :: ScreenId -> X StatusBarConfig
|
||||
myStatusBars (S i) = do
|
||||
nScreens <- gets (length . W.screens . windowset)
|
||||
let rc = if nScreens > 1 && i /= 1 then "xmobarrc_hdmi" else "xmobarrc_laptop"
|
||||
pure $ statusBarProp ("xmobar -x " ++ show i ++ " ~/.config/xmobar/" ++ rc) (pure myXmobarPP)
|
||||
|
||||
myXmobarPP :: PP
|
||||
myXmobarPP =
|
||||
@@ -211,6 +236,7 @@ myStartupHook = do
|
||||
spawnOnce "blueman-applet"
|
||||
spawnOnce "mousemove"
|
||||
spawnOnce "adb start-server"
|
||||
spawnOnce "/home/fuxino/.local/bin/discover-overlay-wait"
|
||||
|
||||
-- Manage hook
|
||||
myManageHook :: ManageHook
|
||||
@@ -236,8 +262,8 @@ myManageHook =
|
||||
className =? "libreoffice-calc" --> doShift "6:\xeb69 ",
|
||||
className =? "libreoffice-writer" --> doShift "6:\xeb69 ",
|
||||
className =? "mpv" --> doFullFloat,
|
||||
className =? "mpv" --> doShift "5:\xead9 ",
|
||||
className =? "FreeTube" --> doShift "5:\xead9 ",
|
||||
className =? "mpv" --> viewShift "5:\xead9 ",
|
||||
className =? "freetube" --> doShift "5:\xead9 ",
|
||||
className =? myTerminal --> doShift "1:\xf489 ",
|
||||
className =? "scrcpy" --> doShift "5:\xead9 ",
|
||||
className =? "steam" --> doShift "3:\xf1b6 ",
|
||||
@@ -254,6 +280,7 @@ myManageHook =
|
||||
isFullscreen --> doFullFloat
|
||||
]
|
||||
<+> namedScratchpadManageHook myScratchpads
|
||||
where viewShift = doF . liftM2 (.) W.greedyView W.shift
|
||||
|
||||
-- Handle event hook
|
||||
myHandleEventHook :: Event -> X All
|
||||
|
||||
Reference in New Issue
Block a user