From 51b28e8e4787c490164d68a2ad0a49076ea658f9 Mon Sep 17 00:00:00 2001 From: m1mir Date: Tue, 4 Feb 2025 23:14:33 +0100 Subject: [PATCH] X.H.EwmhDesktops: Added setEwmhMapHiddenWorkspaceToScreen function. --- CHANGES.md | 3 +++ XMonad/Hooks/EwmhDesktops.hs | 51 +++++++++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index f0c84dd89..11412d286 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -44,6 +44,9 @@ - Added a customization option for the action that gets executed when a client sends a **_NET_CURRENT_DESKTOP** request. It is now possible to change it using the `setEwmhSwitchDesktopHook`. + - Added a custimzation option for mapping hidden workspaces to screens + when setting the **_NET_DESKTOP_VIEWPORT**. This can be done using + the `setEwmhMappHiddenWorkspaceToScreen`. * `XMonad.Layout.IndependentScreens` diff --git a/XMonad/Hooks/EwmhDesktops.hs b/XMonad/Hooks/EwmhDesktops.hs index 9da99d583..95417abca 100644 --- a/XMonad/Hooks/EwmhDesktops.hs +++ b/XMonad/Hooks/EwmhDesktops.hs @@ -54,6 +54,9 @@ module XMonad.Hooks.EwmhDesktops ( -- $customManageDesktopViewport disableEwmhManageDesktopViewport, + -- $customHiddenWorkspaceMapper + setEwmhMapHiddenWorkspaceToScreen, + -- * Standalone hooks (deprecated) ewmhDesktopsStartup, ewmhDesktopsLogHook, @@ -122,6 +125,8 @@ data EwmhDesktopsConfig = -- ^ configurable action for handling _NET_CURRENT_DESKTOP , manageDesktopViewport :: Bool -- ^ manage @_NET_DESKTOP_VIEWPORT@? + , hiddenWorkspaceToScreen :: WindowSet -> WindowSpace -> WindowScreen + -- ^ map hidden workspaces to screens for @_NET_DESKTOP_VIEWPORT@ } instance Default EwmhDesktopsConfig where @@ -132,6 +137,8 @@ instance Default EwmhDesktopsConfig where , fullscreenHooks = (doFullFloat, doSink) , switchDesktopHook = W.view , manageDesktopViewport = True + -- Hidden workspaces are mapped to the current screen by default. + , hiddenWorkspaceToScreen = \winset _ -> W.current winset } @@ -316,6 +323,36 @@ disableEwmhManageDesktopViewport :: XConfig l -> XConfig l disableEwmhManageDesktopViewport = XC.modifyDef $ \c -> c{ manageDesktopViewport = False } +-- $customHiddenWorkspaceMapper +-- +-- Mapping the hidden workspaces to the current screen is a good default behavior, +-- but it makes the assumption that workspaces don't belong to a sepcific screen. +-- If the default behaviour is undesired, for example when using "XMonad.Layout.IndependentScreens" +-- it can be customized. +-- +-- The following example demonstrates a way to configure the mapping when using "XMonad.Layout.IndependentScreens": +-- +-- > import XMonad.Layout.IndependentScreens +-- > +-- > customMapper :: WindowSet -> (WindowSpace -> WindowScreen) +-- > customMapper winset (Workspace wsid _ _) = fromMaybe (W.current winset) screenOnMonitor +-- > where +-- > screenId = unmarshallS wsid +-- > screenOnMonitor :: Maybe WindowScreen +-- > screenOnMonitor = find ((screenId ==) . W.screen) (W.current winset : W.visible winset) +-- > +-- > +-- > main = xmonad $ ... . setEwmhMapHiddenWorkspaceToScreen customMapper . ewmh . ... $ def{...} + +-- | Set (replace) the function responsible for mapping the hidden workspaces to screens. +-- Having a hidden workspace associated with 0 or more than one screen is undefinded behaviour. +setEwmhMapHiddenWorkspaceToScreen :: (WindowSet -> (WindowSpace -> WindowScreen)) + -- ^ Function that given the current WindowSet + -- produces a function to maps a (hidden) workspace to a screen. + -> XConfig l -> XConfig l +setEwmhMapHiddenWorkspaceToScreen mapper = XC.modifyDef $ \c -> c{ hiddenWorkspaceToScreen = mapper } + + -- | Initializes EwmhDesktops and advertises EWMH support to the X server. {-# DEPRECATED ewmhDesktopsStartup "Use ewmh instead." #-} ewmhDesktopsStartup :: X () @@ -390,7 +427,7 @@ whenChanged :: (Eq a, ExtensionClass a) => a -> X () -> X () whenChanged = whenX . XS.modified . const ewmhDesktopsLogHook' :: EwmhDesktopsConfig -> X () -ewmhDesktopsLogHook' EwmhDesktopsConfig{workspaceSort, workspaceRename, manageDesktopViewport} = withWindowSet $ \s -> do +ewmhDesktopsLogHook' EwmhDesktopsConfig{workspaceSort, workspaceRename, manageDesktopViewport, hiddenWorkspaceToScreen} = withWindowSet $ \s -> do sort' <- workspaceSort let ws = sort' $ W.workspaces s @@ -455,18 +492,20 @@ ewmhDesktopsLogHook' EwmhDesktopsConfig{workspaceSort, workspaceRename, manageDe when manageDesktopViewport $ do let visibleScreens = W.current s : W.visible s currentTags = map (W.tag . W.workspace) visibleScreens - whenChanged (MonitorTags currentTags) $ mkViewPorts s (map W.tag ws) + whenChanged (MonitorTags currentTags) $ mkViewPorts s hiddenWorkspaceToScreen (map W.tag ws) -- | Create the viewports from the current 'WindowSet' and a list of -- already sorted workspace IDs. -mkViewPorts :: WindowSet -> [WorkspaceId] -> X () -mkViewPorts winset = setDesktopViewport . concat . mapMaybe (viewPorts M.!?) +mkViewPorts :: WindowSet -> (WindowSet -> WindowSpace -> WindowScreen) -> [WorkspaceId] -> X () +mkViewPorts winset hiddenWorkspaceMapper = setDesktopViewport . concat . mapMaybe (viewPorts M.!?) where foc = W.current winset - -- Hidden workspaces are mapped to the current screen's viewport. viewPorts :: M.Map WorkspaceId [Position] viewPorts = M.fromList $ map mkVisibleViewPort (foc : W.visible winset) - ++ map (mkViewPort foc) (W.hidden winset) + ++ map (uncurry mkViewPort) hiddenWorkspacesWithScreens + + hiddenWorkspacesWithScreens :: [(WindowScreen,WindowSpace)] + hiddenWorkspacesWithScreens = map (\x-> (hiddenWorkspaceMapper winset x,x)) (W.hidden winset) mkViewPort :: WindowScreen -> WindowSpace -> (WorkspaceId, [Position]) mkViewPort scr w = (W.tag w, mkPos scr)