Merge pull request #926 from m1mir/feat/ewmh-hidden-viewport

X.H.EwmhDesktops: Add setEwmhHiddenWorkspaceToScreenMapping function.
This commit is contained in:
Tony Zorman 2025-03-18 06:38:02 +00:00 committed by GitHub
commit 0517c94960
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 49 additions and 8 deletions

View File

@ -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 customization option for mapping hidden workspaces to screens
when setting the **_NET_DESKTOP_VIEWPORT**. This can be done using
the `setEwmhHiddenWorkspaceToScreenMapping`.
* `XMonad.Layout.IndependentScreens`
@ -51,6 +54,7 @@
belong to.
- Added `doFocus'` hook as an alternative for `doFocus` when using
IndependentScreens.
- Added `screenOnMonitor` for getting the active screen for a monitor.
* `XMonad.Util.NamedScratchPad`

View File

@ -54,6 +54,9 @@ module XMonad.Hooks.EwmhDesktops (
-- $customManageDesktopViewport
disableEwmhManageDesktopViewport,
-- $customHiddenWorkspaceMapper
setEwmhHiddenWorkspaceToScreenMapping,
-- * 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,34 @@ 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) maybeMappedScreen
-- > where
-- > screenId = unmarshallS wsid
-- > maybeMappedScreen = screenOnMonitor screenId winset
-- >
-- >
-- > main = xmonad $ ... . setEwmhHiddenWorkspaceToScreenMapping customMapper . ewmh . ... $ def{...}
-- | Set (replace) the function responsible for mapping the hidden workspaces to screens.
setEwmhHiddenWorkspaceToScreenMapping :: (WindowSet -> (WindowSpace -> WindowScreen))
-- ^ Function that given the current WindowSet
-- produces a function to maps a (hidden) workspace to a screen.
-> XConfig l -> XConfig l
setEwmhHiddenWorkspaceToScreenMapping 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 +425,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 +490,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)

View File

@ -26,7 +26,7 @@ module XMonad.Layout.IndependentScreens (
marshallPP,
whenCurrentOn,
countScreens,
workspacesOn,
workspacesOn, screenOnMonitor,
workspaceOnScreen, focusWindow', doFocus', focusScreen, focusWorkspace, nthWorkspace, withWspOnScreen,
-- * Converting between virtual and physical workspaces
-- $converting
@ -148,7 +148,7 @@ withWspOnScreen screenId operation ws = case workspaceOnScreen screenId ws of
Just wsp -> operation wsp ws
Nothing -> ws
-- | Get the workspace that is active on a given screen.
-- | Get the screen that is active on a given monitor.
screenOnMonitor :: ScreenId -> WindowSet -> Maybe WindowScreen
screenOnMonitor screenId ws = find ((screenId ==) . W.screen) (W.current ws : W.visible ws)