vanadium/xmonad: use event handling to set master pane count

This commit is contained in:
Primrose 2026-01-06 22:22:57 +01:00
parent e65e37d3a9
commit 084261c58e
Signed by: primrose
GPG key ID: 4E887A4CA9714ADA
3 changed files with 64 additions and 21 deletions

View file

@ -25,6 +25,7 @@ library
hs-source-dirs: lib
exposed-modules:
XMonad.Layout.Reflect.Message
XMonad.Layout.SetMasterNTall
Data.Char.Greek
executable leanamonad

View file

@ -0,0 +1,30 @@
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
-- Wraps ResizableTall, allows setting master count to a number directly
module XMonad.Layout.SetMasterNTall
( SetMasterNTall(..)
, SetMasterN(..)
) where
import XMonad
import qualified XMonad.StackSet as W
import XMonad.Layout.ResizableTile
-- Message
data SetMasterN = SetMasterN Int
instance Message SetMasterN
-- Layout
newtype SetMasterNTall a = SetMasterNTall { unSetMasterNTall :: ResizableTall a }
deriving (Read, Show)
instance LayoutClass SetMasterNTall a where
runLayout (W.Workspace t l s) =
let ws' = W.Workspace t (unSetMasterNTall l) s
in (fmap . fmap . fmap) SetMasterNTall . runLayout ws'
handleMessage (SetMasterNTall l@(ResizableTall _n0 d f s)) mess
| Just (SetMasterN n) <- fromMessage mess = pure $ Just $ SetMasterNTall $ ResizableTall n d f s
| otherwise = (fmap . fmap) SetMasterNTall . handleMessage l $ mess
description (SetMasterNTall l) = description l

View file

@ -16,7 +16,6 @@ import XMonad.Hooks.OnPropertyChange
import XMonad.Hooks.RefocusLast
import XMonad.Hooks.StatusBar
import XMonad.Layout.FocusTracking
import XMonad.Layout.IfMax
import XMonad.Layout.Magnifier hiding (Toggle)
import qualified XMonad.Layout.Magnifier as Mag
import XMonad.Layout.NoBorders
@ -24,6 +23,7 @@ import XMonad.Layout.Reflect
import XMonad.Layout.Reflect.Message
import XMonad.Layout.Renamed
import XMonad.Layout.ResizableTile
import XMonad.Layout.SetMasterNTall
import XMonad.Layout.Spacing
import XMonad.Layout.ToggleLayouts
import qualified XMonad.StackSet as W
@ -71,23 +71,16 @@ main =
myLayout =
avoidStruts
$ smartBorders
$ toggleLayouts (mag tallr) full
$ toggleLayouts (magnifierOff tallr) full
where
mag = magnifierOff
full = focusTracking Full
mkTallrN n =
smartSpacingWithEdge 5
$ reflectMsg . reflectHoriz
$ ResizableTall n (1/10) (3/7) []
tallr =
renamed [ Replace "Tall" ]
$ ifMax 3 (mkTallrN 1)
$ ifMax 5 (mkTallrN 2)
$ ifMax 7 (mkTallrN 3)
$ mkTallrN 4
$ smartSpacingWithEdge 5
$ reflectMsg . reflectHoriz
$ SetMasterNTall
$ ResizableTall 1 (1/10) (3/7) []
isSioyek :: Query Bool
isSioyek = className =? "sioyek"
@ -202,14 +195,33 @@ myEventHandleHook =
-- Imagine Spotify playing in the background, a track change would focus that workspace.
-- We prevent this by checking if the window is in the current workspace
onTitleChange
$ (windowIsInCurrentWorkspace -->)
$ composeAll
[ isSpotify --> doShiftAndGreedyView multimediaWS
, isYouTube --> doShiftAndGreedyView multimediaWS
, isDiscord --> doShiftAndGreedyView chatWS
, isWhatsApp --> doShiftAndGreedyView chatWS
, isElement --> doShiftAndGreedyView chatWS
]
( windowIsInCurrentWorkspace --> composeAll
[ isSpotify --> doShiftAndGreedyView multimediaWS
, isYouTube --> doShiftAndGreedyView multimediaWS
, isDiscord --> doShiftAndGreedyView chatWS
, isWhatsApp --> doShiftAndGreedyView chatWS
, isElement --> doShiftAndGreedyView chatWS
]
)
<> setMasterNEventHandleHook
setMasterNEventHandleHook :: Event -> X All
setMasterNEventHandleHook ev =
let adjustMasterCount :: X ()
adjustMasterCount = do
count <- gets $ length . W.integrate' . W.stack . W.workspace . W.current . windowset
if count <= 3 then sendMessage (SetMasterN 1)
else if count <= 5 then sendMessage (SetMasterN 2)
else if count <= 7 then sendMessage (SetMasterN 3)
else pure ()
in do
case ev of
MapRequestEvent{} -> adjustMasterCount
ConfigureEvent{} -> adjustMasterCount
DestroyWindowEvent {} -> adjustMasterCount
_ -> pure ()
pure (All True)
doShiftAndGreedyView :: WorkspaceId -> Query (Endo WindowSet)
doShiftAndGreedyView n = doF . go =<< ask