From 064256e4ed147f3be3e7b3400c57d678b215b48f Mon Sep 17 00:00:00 2001 From: jasmine Date: Fri, 3 Oct 2025 17:30:29 +0800 Subject: [PATCH] feat: implement modal keybindings for layout and master pane control Add XMonad.Hooks.Modal to separate layout switching and master pane manipulation into distinct modal namespaces. This resolves keybinding conflicts and creates a more organized interaction model. Changes: - Layout mode (M-a l): one-shot layout selection (d/m/f) - Master mode (M-a m): persistent pane adjustments with arrow keys - Restore ppExtras with logMode to display active mode in xmobar - Remove conflicting Home/End/PageUp/PageDown bindings from master pane - Simplify navigation by moving screen focus back to Home/End --- src/xmonad.hs | 48 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/xmonad.hs b/src/xmonad.hs index 03864d7..13224fa 100644 --- a/src/xmonad.hs +++ b/src/xmonad.hs @@ -6,6 +6,7 @@ import XMonad.Actions.RotSlaves import XMonad.Hooks.DynamicLog import XMonad.Hooks.EwmhDesktops import XMonad.Hooks.ManageDocks +import XMonad.Hooks.Modal import XMonad.Hooks.StatusBar import XMonad.Layout.NoBorders import XMonad.Layout.Renamed @@ -30,6 +31,7 @@ main = xmonad . ewmhFullscreen . ewmh . withSB myXmobar + . modal [layoutMode, masterMode] $ myConfig myConfig = def @@ -74,10 +76,9 @@ myKeymap = , ("M-a t", spawn myFileManager) , ("M-a s", spawn myScrot ) - -- toggling layouts - , ("M-a d", sendMessage $ JumpToLayout "dynamic tiling") - , ("M-a m", sendMessage $ JumpToLayout "maximised" ) - , ("M-a f", sendMessage $ JumpToLayout "fullscreen" ) + -- modal modes + , ("M-a l", setMode "layout") + , ("M-a m", setMode "master") -- quit window , ("M-a q", kill) @@ -96,12 +97,12 @@ myKeymap = , ("M-", moveTo Next hiddenWS) -- window rotation - , ("M-S-", rotAllUp) - , ("M-S-", rotAllDown) + , ("M-" , rotAllUp) + , ("M-", rotAllDown) -- focus screens - , ("M-S-", prevScreen) - , ("M-S-", nextScreen) + , ("M-", prevScreen) + , ("M-" , nextScreen) -- switch workspaces , ("M-1", windows $ W.greedyView "code" ) @@ -117,12 +118,6 @@ myKeymap = , ("M-S-4", windows $ W.shift "games") , ("M-S-5", windows $ W.shift "misc" ) - -- master pane manipulation - , ("M-", sendMessage Shrink) -- shrink master pane width - , ("M-", sendMessage Expand) -- expand master pane width - , ("M-", sendMessage (IncMasterN 1)) -- more windows in master - , ("M-", sendMessage (IncMasterN (-1))) -- fewer windows in master - -- master window operations , ("M-", windows W.focusMaster) , ("M-S-", windows W.swapMaster ) @@ -141,6 +136,26 @@ myKeymap = ] +-- +-- Modal Modes +-- + +layoutMode :: Mode +layoutMode = mode "layout" $ mkKeysEz + [ ("d", sendMessage (JumpToLayout "dynamic tiling")) + , ("m", sendMessage (JumpToLayout "maximised" )) + , ("f", sendMessage (JumpToLayout "fullscreen" )) + ] + +masterMode :: Mode +masterMode = modeWithExit "master" $ mkKeysEz + [ ("", sendMessage Shrink) + , ("", sendMessage Expand) + , ("", sendMessage (IncMasterN 1)) + , ("", sendMessage (IncMasterN (-1))) + ] + + -- -- Layouts -- @@ -175,8 +190,11 @@ myXmobarPP = def , ppHiddenNoWindows = grey0 . wrap " " "" , ppUrgent = red . wrap " " "" , ppLayout = aqua . wrap (grey0 " [ ") (grey0 " ] ") - , ppOrder = \[ws, l, _] -> [ws, l] + , ppOrder = \case { [ws, l, title, mode] -> [ws, l, mode, title]; xs -> xs } + , ppExtras = [lMode] } + where + lMode = xmobarColorL "#d8a657" "#282828" . fixedWidthL AlignCenter "-" 4 $ logMode --