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.Default
|
||||||
import Data.Monoid
|
import Data.Monoid
|
||||||
import Graphics.X11.ExtraTypes.XF86
|
import Graphics.X11.ExtraTypes.XF86
|
||||||
|
import Control.Monad (liftM2)
|
||||||
import XMonad
|
import XMonad
|
||||||
import XMonad.Actions.PhysicalScreens
|
import XMonad.Actions.PhysicalScreens
|
||||||
import XMonad.Hooks.DynamicLog
|
import XMonad.Hooks.DynamicLog
|
||||||
@@ -11,6 +12,7 @@ import XMonad.Hooks.FloatConfigureReq
|
|||||||
import XMonad.Hooks.InsertPosition
|
import XMonad.Hooks.InsertPosition
|
||||||
import XMonad.Hooks.ManageDocks
|
import XMonad.Hooks.ManageDocks
|
||||||
import XMonad.Hooks.ManageHelpers
|
import XMonad.Hooks.ManageHelpers
|
||||||
|
import XMonad.Hooks.Rescreen
|
||||||
import XMonad.Hooks.StatusBar
|
import XMonad.Hooks.StatusBar
|
||||||
import XMonad.Hooks.StatusBar.PP
|
import XMonad.Hooks.StatusBar.PP
|
||||||
import XMonad.Layout.Grid
|
import XMonad.Layout.Grid
|
||||||
@@ -36,7 +38,8 @@ main =
|
|||||||
xmonad
|
xmonad
|
||||||
. ewmhFullscreen
|
. ewmhFullscreen
|
||||||
. ewmh
|
. ewmh
|
||||||
. withEasySB (xmobar1 <> xmobar2) defToggleStrutsKey
|
. dynamicEasySBs myStatusBars
|
||||||
|
. addRandrChangeHook (spawn myScreenHotplug)
|
||||||
$ myConfig
|
$ myConfig
|
||||||
|
|
||||||
-- Variables
|
-- Variables
|
||||||
@@ -68,29 +71,46 @@ myScreenshotDir = "/home/fuxino/Pictures/Screenshots/"
|
|||||||
myScreenshotName :: String
|
myScreenshotName :: String
|
||||||
myScreenshotName = "Screenshot-%Y-%m-%d-%H%M%S.png"
|
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 :: String
|
||||||
myScreenSetup =
|
myScreenSetup =
|
||||||
"sleep 1 && xrandr --output HDMI-1-0 --preferred --primary --output eDP-1 --right-of HDMI-1-0 --preferred && ~/.fehbg"
|
"sleep 1; " ++ myScreenLayout ++ "; pgrep -x picom > /dev/null || picom -b -c; " ++ myTrayer
|
||||||
++ " && picom -b -c"
|
|
||||||
++ " && trayer -l --edge top --align right --SetDockType true \
|
-- Run when a monitor is (dis)connected; restarts trayer so it moves to the right screen
|
||||||
\--SetPartialStrut true --expand true --widthtype request \
|
myScreenHotplug :: String
|
||||||
\--tint 0x232634 --height 18 --monitor 1"
|
myScreenHotplug = myScreenLayout ++ "; " ++ myTrayer
|
||||||
|
|
||||||
myScratchpads :: [NamedScratchpad]
|
myScratchpads :: [NamedScratchpad]
|
||||||
myScratchpads =
|
myScratchpads =
|
||||||
[ NS "Riseup-vpn" "riseup-vpn" (className =? "RiseupVPN") (customFloating $ W.RationalRect 0.15 0.4 0.15 0.4),
|
[ 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 "Terminal" spawnTerminal (className =? "scratch-terminal") (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 "Music" spawnMusic (className =? "scratch-music") (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 "Mail" spawnMail (className =? "scratch-mail") (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 "Cal" spawnCal (className =? "scratch-cal") (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 "Btop" spawnBtop (className =? "scratch-btop") (customFloating $ W.RationalRect 0.2 0.2 0.6 0.6)
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
spawnTerminal = myTerminal ++ " -T kitty-float"
|
spawnTerminal = myTerminal ++ " --class scratch-terminal -T kitty-float"
|
||||||
spawnMusic = myTerminal ++ " -T ncmpcpp ncmpcpp"
|
spawnMusic = myTerminal ++ " --class scratch-music -T ncmpcpp ncmpcpp"
|
||||||
spawnMail = myTerminal ++ " -T mutt bash -c 'pushd ~/Downloads > /dev/null; mutt; popd > /dev/null'"
|
spawnMail = myTerminal ++ " --class scratch-mail -T mutt bash -c 'pushd ~/Downloads > /dev/null; mutt; popd > /dev/null'"
|
||||||
spawnCal = myTerminal ++ " -T calcurse calcurse"
|
spawnCal = myTerminal ++ " --class scratch-cal -T calcurse calcurse"
|
||||||
spawnBtop = myTerminal ++ " -T btop btop"
|
spawnBtop = myTerminal ++ " --class scratch-btop -T btop btop"
|
||||||
|
|
||||||
-- Config
|
-- Config
|
||||||
myConfig =
|
myConfig =
|
||||||
@@ -105,7 +125,8 @@ myConfig =
|
|||||||
manageHook = myManageHook,
|
manageHook = myManageHook,
|
||||||
handleEventHook = myHandleEventHook
|
handleEventHook = myHandleEventHook
|
||||||
}
|
}
|
||||||
`additionalKeysP` [ ("M-S-l", spawn "slock"),
|
`additionalKeysP` [ ("M-b", sendMessage ToggleStruts),
|
||||||
|
("M-S-l", spawn "slock"),
|
||||||
("<Print>", unGrab *> spawn ("scrot " ++ myScreenshotDir ++ myScreenshotName)),
|
("<Print>", unGrab *> spawn ("scrot " ++ myScreenshotDir ++ myScreenshotName)),
|
||||||
("S-<Print>", unGrab *> spawn ("scrot -s " ++ myScreenshotDir ++ myScreenshotName)),
|
("S-<Print>", unGrab *> spawn ("scrot -s " ++ myScreenshotDir ++ myScreenshotName)),
|
||||||
("M-S-<Print>", unGrab *> spawn ("scrot -u " ++ 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
|
delta = 3 / 100
|
||||||
|
|
||||||
-- Xmobar
|
-- Xmobar
|
||||||
xmobar1 = statusBarProp "xmobar -x 0 ~/.config/xmobar/xmobarrc_hdmi" (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.
|
||||||
xmobar2 = statusBarProp "xmobar -x 1 ~/.config/xmobar/xmobarrc_laptop" (pure myXmobarPP)
|
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 :: PP
|
||||||
myXmobarPP =
|
myXmobarPP =
|
||||||
@@ -211,6 +236,7 @@ myStartupHook = do
|
|||||||
spawnOnce "blueman-applet"
|
spawnOnce "blueman-applet"
|
||||||
spawnOnce "mousemove"
|
spawnOnce "mousemove"
|
||||||
spawnOnce "adb start-server"
|
spawnOnce "adb start-server"
|
||||||
|
spawnOnce "/home/fuxino/.local/bin/discover-overlay-wait"
|
||||||
|
|
||||||
-- Manage hook
|
-- Manage hook
|
||||||
myManageHook :: ManageHook
|
myManageHook :: ManageHook
|
||||||
@@ -236,8 +262,8 @@ myManageHook =
|
|||||||
className =? "libreoffice-calc" --> doShift "6:\xeb69 ",
|
className =? "libreoffice-calc" --> doShift "6:\xeb69 ",
|
||||||
className =? "libreoffice-writer" --> doShift "6:\xeb69 ",
|
className =? "libreoffice-writer" --> doShift "6:\xeb69 ",
|
||||||
className =? "mpv" --> doFullFloat,
|
className =? "mpv" --> doFullFloat,
|
||||||
className =? "mpv" --> doShift "5:\xead9 ",
|
className =? "mpv" --> viewShift "5:\xead9 ",
|
||||||
className =? "FreeTube" --> doShift "5:\xead9 ",
|
className =? "freetube" --> doShift "5:\xead9 ",
|
||||||
className =? myTerminal --> doShift "1:\xf489 ",
|
className =? myTerminal --> doShift "1:\xf489 ",
|
||||||
className =? "scrcpy" --> doShift "5:\xead9 ",
|
className =? "scrcpy" --> doShift "5:\xead9 ",
|
||||||
className =? "steam" --> doShift "3:\xf1b6 ",
|
className =? "steam" --> doShift "3:\xf1b6 ",
|
||||||
@@ -254,6 +280,7 @@ myManageHook =
|
|||||||
isFullscreen --> doFullFloat
|
isFullscreen --> doFullFloat
|
||||||
]
|
]
|
||||||
<+> namedScratchpadManageHook myScratchpads
|
<+> namedScratchpadManageHook myScratchpads
|
||||||
|
where viewShift = doF . liftM2 (.) W.greedyView W.shift
|
||||||
|
|
||||||
-- Handle event hook
|
-- Handle event hook
|
||||||
myHandleEventHook :: Event -> X All
|
myHandleEventHook :: Event -> X All
|
||||||
|
|||||||
Reference in New Issue
Block a user